211 lines
5.3 KiB
JavaScript
211 lines
5.3 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
import $ from 'jquery';
|
||
|
import { MediaQuery } from './foundation.util.mediaQuery';
|
||
|
import { Plugin } from './foundation.core.plugin';
|
||
|
import { GetYoDigits } from './foundation.core.utils';
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Interchange module.
|
||
|
* @module foundation.interchange
|
||
|
* @requires foundation.util.mediaQuery
|
||
|
*/
|
||
|
|
||
|
class Interchange extends Plugin {
|
||
|
/**
|
||
|
* Creates a new instance of Interchange.
|
||
|
* @class
|
||
|
* @name Interchange
|
||
|
* @fires Interchange#init
|
||
|
* @param {Object} element - jQuery object to add the trigger to.
|
||
|
* @param {Object} options - Overrides to the default plugin settings.
|
||
|
*/
|
||
|
_setup(element, options) {
|
||
|
this.$element = element;
|
||
|
this.options = $.extend({}, Interchange.defaults, options);
|
||
|
this.rules = [];
|
||
|
this.currentPath = '';
|
||
|
this.className = 'Interchange'; // ie9 back compat
|
||
|
|
||
|
this._init();
|
||
|
this._events();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initializes the Interchange plugin and calls functions to get interchange functioning on load.
|
||
|
* @function
|
||
|
* @private
|
||
|
*/
|
||
|
_init() {
|
||
|
MediaQuery._init();
|
||
|
|
||
|
var id = this.$element[0].id || GetYoDigits(6, 'interchange');
|
||
|
this.$element.attr({
|
||
|
'data-resize': id,
|
||
|
'id': id
|
||
|
});
|
||
|
|
||
|
this._addBreakpoints();
|
||
|
this._generateRules();
|
||
|
this._reflow();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initializes events for Interchange.
|
||
|
* @function
|
||
|
* @private
|
||
|
*/
|
||
|
_events() {
|
||
|
this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', () => this._reflow());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Calls necessary functions to update Interchange upon DOM change
|
||
|
* @function
|
||
|
* @private
|
||
|
*/
|
||
|
_reflow() {
|
||
|
var match;
|
||
|
|
||
|
// Iterate through each rule, but only save the last match
|
||
|
for (var i in this.rules) {
|
||
|
if(this.rules.hasOwnProperty(i)) {
|
||
|
var rule = this.rules[i];
|
||
|
if (window.matchMedia(rule.query).matches) {
|
||
|
match = rule;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (match) {
|
||
|
this.replace(match.path);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the Foundation breakpoints and adds them to the Interchange.SPECIAL_QUERIES object.
|
||
|
* @function
|
||
|
* @private
|
||
|
*/
|
||
|
_addBreakpoints() {
|
||
|
for (var i in MediaQuery.queries) {
|
||
|
if (MediaQuery.queries.hasOwnProperty(i)) {
|
||
|
var query = MediaQuery.queries[i];
|
||
|
Interchange.SPECIAL_QUERIES[query.name] = query.value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks the Interchange element for the provided media query + content pairings
|
||
|
* @function
|
||
|
* @private
|
||
|
* @param {Object} element - jQuery object that is an Interchange instance
|
||
|
* @returns {Array} scenarios - Array of objects that have 'mq' and 'path' keys with corresponding keys
|
||
|
*/
|
||
|
_generateRules(element) {
|
||
|
var rulesList = [];
|
||
|
var rules;
|
||
|
|
||
|
if (this.options.rules) {
|
||
|
rules = this.options.rules;
|
||
|
}
|
||
|
else {
|
||
|
rules = this.$element.data('interchange');
|
||
|
}
|
||
|
|
||
|
rules = typeof rules === 'string' ? rules.match(/\[.*?, .*?\]/g) : rules;
|
||
|
|
||
|
for (var i in rules) {
|
||
|
if(rules.hasOwnProperty(i)) {
|
||
|
var rule = rules[i].slice(1, -1).split(', ');
|
||
|
var path = rule.slice(0, -1).join('');
|
||
|
var query = rule[rule.length - 1];
|
||
|
|
||
|
if (Interchange.SPECIAL_QUERIES[query]) {
|
||
|
query = Interchange.SPECIAL_QUERIES[query];
|
||
|
}
|
||
|
|
||
|
rulesList.push({
|
||
|
path: path,
|
||
|
query: query
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.rules = rulesList;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the `src` property of an image, or change the HTML of a container, to the specified path.
|
||
|
* @function
|
||
|
* @param {String} path - Path to the image or HTML partial.
|
||
|
* @fires Interchange#replaced
|
||
|
*/
|
||
|
replace(path) {
|
||
|
if (this.currentPath === path) return;
|
||
|
|
||
|
var _this = this,
|
||
|
trigger = 'replaced.zf.interchange';
|
||
|
|
||
|
// Replacing images
|
||
|
if (this.$element[0].nodeName === 'IMG') {
|
||
|
this.$element.attr('src', path).on('load', function() {
|
||
|
_this.currentPath = path;
|
||
|
})
|
||
|
.trigger(trigger);
|
||
|
}
|
||
|
// Replacing background images
|
||
|
else if (path.match(/\.(gif|jpg|jpeg|png|svg|tiff)([?#].*)?/i)) {
|
||
|
path = path.replace(/\(/g, '%28').replace(/\)/g, '%29');
|
||
|
this.$element.css({ 'background-image': 'url('+path+')' })
|
||
|
.trigger(trigger);
|
||
|
}
|
||
|
// Replacing HTML
|
||
|
else {
|
||
|
$.get(path, function(response) {
|
||
|
_this.$element.html(response)
|
||
|
.trigger(trigger);
|
||
|
$(response).foundation();
|
||
|
_this.currentPath = path;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Fires when content in an Interchange element is done being loaded.
|
||
|
* @event Interchange#replaced
|
||
|
*/
|
||
|
// this.$element.trigger('replaced.zf.interchange');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Destroys an instance of interchange.
|
||
|
* @function
|
||
|
*/
|
||
|
_destroy() {
|
||
|
this.$element.off('resizeme.zf.trigger')
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Default settings for plugin
|
||
|
*/
|
||
|
Interchange.defaults = {
|
||
|
/**
|
||
|
* Rules to be applied to Interchange elements. Set with the `data-interchange` array notation.
|
||
|
* @option
|
||
|
* @type {?array}
|
||
|
* @default null
|
||
|
*/
|
||
|
rules: null
|
||
|
};
|
||
|
|
||
|
Interchange.SPECIAL_QUERIES = {
|
||
|
'landscape': 'screen and (orientation: landscape)',
|
||
|
'portrait': 'screen and (orientation: portrait)',
|
||
|
'retina': 'only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)'
|
||
|
};
|
||
|
|
||
|
export {Interchange};
|