govlab-styleguide
Version:
A styleguide / lightweight frontend framework for GovLab websites
185 lines (161 loc) • 5.06 kB
JavaScript
/**
* Interchange module.
* @module foundation.interchange
* @requires foundation.util.mediaQuery
* @requires foundation.util.timerAndImageLoader
*/
!function(Foundation, $) {
'use strict';
/**
* Creates a new instance of Interchange.
* @class
* @fires Interchange#init
* @param {Object} element - jQuery object to add the trigger to.
* @param {Object} options - Overrides to the default plugin settings.
*/
function Interchange(element, options) {
this.$element = element;
this.options = $.extend({}, Interchange.defaults, options);
this.rules = [];
this.currentPath = '';
this._init();
this._events();
Foundation.registerPlugin(this, 'Interchange');
}
/**
* Default settings for plugin
*/
Interchange.defaults = {
/**
* Rules to be applied to Interchange elements. Set with the `data-interchange` array notation.
* @option
*/
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)'
};
/**
* Initializes the Interchange plugin and calls functions to get interchange functioning on load.
* @function
* @private
*/
Interchange.prototype._init = function() {
this._addBreakpoints();
this._generateRules();
this._reflow();
};
/**
* Initializes events for Interchange.
* @function
* @private
*/
Interchange.prototype._events = function() {
$(window).on('resize.zf.interchange', Foundation.util.throttle(this._reflow.bind(this), 50));
};
/**
* Calls necessary functions to update Interchange upon DOM change
* @function
* @private
*/
Interchange.prototype._reflow = function() {
var match;
// Iterate through each rule, but only save the last match
for (var i in this.rules) {
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
*/
Interchange.prototype._addBreakpoints = function() {
for (var i in Foundation.MediaQuery.queries) {
var query = Foundation.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
*/
Interchange.prototype._generateRules = function() {
var rulesList = [];
var rules;
if (this.options.rules) {
rules = this.options.rules;
}
else {
rules = this.$element.data('interchange').match(/\[.*?\]/g);
}
for (var i in rules) {
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
*/
Interchange.prototype.replace = function(path) {
if (this.currentPath === path) return;
var _this = this;
// Replacing images
if (this.$element[0].nodeName === 'IMG') {
this.$element.attr('src', path).load(function() {
_this.currentPath = path;
});
}
// Replacing background images
else if (path.match(/\.(gif|jpg|jpeg|tiff|png)([?#].*)?/i)) {
this.$element.css({ 'background-image': 'url('+path+')' });
}
// Replacing HTML
else {
$.get(path, function(response) {
_this.$element.html(response);
$(response).foundation();
_this.currentPath = path;
});
}
this.$element.trigger('replaced.zf.interchange');
};
/**
* Destroys an instance of interchange.
* @function
*/
Interchange.prototype.destroy = function(){
//TODO this.
};
Foundation.plugin(Interchange, 'Interchange');
// Exports for AMD/Browserify
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined')
module.exports = Interchange;
if (typeof define === 'function')
define(['foundation'], function() {
return Interchange;
});
}(Foundation, jQuery);