;(function ($, window, document, undefined) { 'use strict'; Foundation.libs.interchange = { name : 'interchange', version : '5.0.3', cache : {}, images_loaded : false, nodes_loaded : false, settings : { load_attr : 'interchange', named_queries : { 'default' : 'only screen', small : Foundation.media_queries.small, medium : Foundation.media_queries.medium, large : Foundation.media_queries.large, xlarge : Foundation.media_queries.xlarge, xxlarge: Foundation.media_queries.xxlarge, landscape : 'only screen and (orientation: landscape)', portrait : 'only 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)' }, directives : { replace: function (el, path, trigger) { // The trigger argument, if called within the directive, fires // an event named after the directive on the element, passing // any parameters along to the event that you pass to trigger. // // ex. trigger(), trigger([a, b, c]), or trigger(a, b, c) // // This allows you to bind a callback like so: // $('#interchangeContainer').on('replace', function (e, a, b, c) { // console.log($(this).html(), a, b, c); // }); if (/IMG/.test(el[0].nodeName)) { var orig_path = el[0].src; if (new RegExp(path, 'i').test(orig_path)) return; el[0].src = path; return trigger(el[0].src); } var last_path = el.data('interchange-last-path'); if (last_path == path) return; return $.get(path, function (response) { el.html(response); el.data('interchange-last-path', path); trigger(); }); } } }, init : function (scope, method, options) { Foundation.inherit(this, 'throttle'); this.data_attr = 'data-' + this.settings.load_attr; $.extend(true, this.settings, method, options); this.bindings(method, options); this.load('images'); this.load('nodes'); }, events : function () { var self = this; $(window) .off('.interchange') .on('resize.fndtn.interchange', self.throttle(function () { self.resize.call(self); }, 50)); return this; }, resize : function () { var cache = this.cache; if(!this.images_loaded || !this.nodes_loaded) { setTimeout($.proxy(this.resize, this), 50); return; } for (var uuid in cache) { if (cache.hasOwnProperty(uuid)) { var passed = this.results(uuid, cache[uuid]); if (passed) { this.settings.directives[passed .scenario[1]](passed.el, passed.scenario[0], function () { if (arguments[0] instanceof Array) { var args = arguments[0]; } else { var args = Array.prototype.slice.call(arguments, 0); } passed.el.trigger(passed.scenario[1], args); }); } } } }, results : function (uuid, scenarios) { var count = scenarios.length; if (count > 0) { var el = this.S('[data-uuid="' + uuid + '"]'); for (var i = count - 1; i >= 0; i--) { var mq, rule = scenarios[i][2]; if (this.settings.named_queries.hasOwnProperty(rule)) { mq = matchMedia(this.settings.named_queries[rule]); } else { mq = matchMedia(rule); } if (mq.matches) { return {el: el, scenario: scenarios[i]}; } } } return false; }, load : function (type, force_update) { if (typeof this['cached_' + type] === 'undefined' || force_update) { this['update_' + type](); } return this['cached_' + type]; }, update_images : function () { var images = this.S('img[' + this.data_attr + ']'), count = images.length, loaded_count = 0, data_attr = this.data_attr; this.cache = {}; this.cached_images = []; this.images_loaded = (count === 0); for (var i = count - 1; i >= 0; i--) { loaded_count++; if (images[i]) { var str = images[i].getAttribute(data_attr) || ''; if (str.length > 0) { this.cached_images.push(images[i]); } } if(loaded_count === count) { this.images_loaded = true; this.enhance('images'); } } return this; }, update_nodes : function () { var nodes = this.S('[' + this.data_attr + ']').not('img'), count = nodes.length, loaded_count = 0, data_attr = this.data_attr; this.cached_nodes = []; // Set nodes_loaded to true if there are no nodes // this.nodes_loaded = false; this.nodes_loaded = (count === 0); for (var i = count - 1; i >= 0; i--) { loaded_count++; var str = nodes[i].getAttribute(data_attr) || ''; if (str.length > 0) { this.cached_nodes.push(nodes[i]); } if(loaded_count === count) { this.nodes_loaded = true; this.enhance('nodes'); } } return this; }, enhance : function (type) { var count = this['cached_' + type].length; for (var i = count - 1; i >= 0; i--) { this.object($(this['cached_' + type][i])); } return $(window).trigger('resize'); }, parse_params : function (path, directive, mq) { return [this.trim(path), this.convert_directive(directive), this.trim(mq)]; }, convert_directive : function (directive) { var trimmed = this.trim(directive); if (trimmed.length > 0) { return trimmed; } return 'replace'; }, object : function(el) { var raw_arr = this.parse_data_attr(el), scenarios = [], count = raw_arr.length; if (count > 0) { for (var i = count - 1; i >= 0; i--) { var split = raw_arr[i].split(/\((.*?)(\))$/); if (split.length > 1) { var cached_split = split[0].split(','), params = this.parse_params(cached_split[0], cached_split[1], split[1]); scenarios.push(params); } } } return this.store(el, scenarios); }, uuid : function (separator) { var delim = separator || "-"; function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + delim + S4() + delim + S4() + delim + S4() + delim + S4() + S4() + S4()); }, store : function (el, scenarios) { var uuid = this.uuid(), current_uuid = el.data('uuid'); if (this.cache[current_uuid]) return this.cache[current_uuid]; el.attr('data-uuid', uuid); return this.cache[uuid] = scenarios; }, trim : function(str) { if (typeof str === 'string') { return $.trim(str); } return str; }, parse_data_attr : function (el) { var raw = el.data(this.settings.load_attr).split(/\[(.*?)\]/), count = raw.length, output = []; for (var i = count - 1; i >= 0; i--) { if (raw[i].replace(/[\W\d]+/, '').length > 4) { output.push(raw[i]); } } return output; }, reflow : function () { this.load('images', true); this.load('nodes', true); } }; }(jQuery, this, this.document));