345 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			345 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | ;(function ($, window, document, undefined) { | ||
|  |   'use strict'; | ||
|  | 
 | ||
|  |   Foundation.libs.interchange = { | ||
|  |     name : 'interchange', | ||
|  | 
 | ||
|  |     version : '5.4.7', | ||
|  | 
 | ||
|  |     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(this.data_attr + '-last-path'), | ||
|  |               self = this; | ||
|  | 
 | ||
|  |           if (last_path == path) return; | ||
|  | 
 | ||
|  |           if (/\.(gif|jpg|jpeg|tiff|png)([?#].*)?/i.test(path)) { | ||
|  |             $(el).css('background-image', 'url('+path+')'); | ||
|  |             el.data('interchange-last-path', path); | ||
|  |             return trigger(path); | ||
|  |           } | ||
|  | 
 | ||
|  |           return $.get(path, function (response) { | ||
|  |             el.html(response); | ||
|  |             el.data(self.data_attr + '-last-path', path); | ||
|  |             trigger(); | ||
|  |           }); | ||
|  | 
 | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  | 
 | ||
|  |     init : function (scope, method, options) { | ||
|  |       Foundation.inherit(this, 'throttle random_str'); | ||
|  | 
 | ||
|  |       this.data_attr = this.set_data_attr(); | ||
|  |       $.extend(true, this.settings, method, options); | ||
|  |       this.bindings(method, options); | ||
|  |       this.load('images'); | ||
|  |       this.load('nodes'); | ||
|  |     }, | ||
|  | 
 | ||
|  |     get_media_hash : function() { | ||
|  |         var mediaHash=''; | ||
|  |         for (var queryName in this.settings.named_queries ) { | ||
|  |             mediaHash += matchMedia(this.settings.named_queries[queryName]).matches.toString(); | ||
|  |         } | ||
|  |         return mediaHash; | ||
|  |     }, | ||
|  | 
 | ||
|  |     events : function () { | ||
|  |       var self = this, prevMediaHash; | ||
|  | 
 | ||
|  |       $(window) | ||
|  |         .off('.interchange') | ||
|  |         .on('resize.fndtn.interchange', self.throttle(function () { | ||
|  |             var currMediaHash = self.get_media_hash(); | ||
|  |             if (currMediaHash !== prevMediaHash) { | ||
|  |                 self.resize(); | ||
|  |             } | ||
|  |             prevMediaHash = currMediaHash; | ||
|  |         }, 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]].call(this, 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('[' + this.add_namespace('data-uuid') + '="' + uuid + '"]'); | ||
|  | 
 | ||
|  |         while (count--) { | ||
|  |           var mq, rule = scenarios[count][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[count]}; | ||
|  |           } | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       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, | ||
|  |           i = count, | ||
|  |           loaded_count = 0, | ||
|  |           data_attr = this.data_attr; | ||
|  | 
 | ||
|  |       this.cache = {}; | ||
|  |       this.cached_images = []; | ||
|  |       this.images_loaded = (count === 0); | ||
|  | 
 | ||
|  |       while (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, | ||
|  |           i = count, | ||
|  |           loaded_count = 0, | ||
|  |           data_attr = this.data_attr; | ||
|  | 
 | ||
|  |       this.cached_nodes = []; | ||
|  |       this.nodes_loaded = (count === 0); | ||
|  | 
 | ||
|  | 
 | ||
|  |       while (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 i = this['cached_' + type].length; | ||
|  | 
 | ||
|  |       while (i--) { | ||
|  |         this.object($(this['cached_' + type][i])); | ||
|  |       } | ||
|  | 
 | ||
|  |       return $(window).trigger('resize').trigger('resize.fndtn.interchange'); | ||
|  |     }, | ||
|  | 
 | ||
|  |     convert_directive : function (directive) { | ||
|  | 
 | ||
|  |       var trimmed = this.trim(directive); | ||
|  | 
 | ||
|  |       if (trimmed.length > 0) { | ||
|  |         return trimmed; | ||
|  |       } | ||
|  | 
 | ||
|  |       return 'replace'; | ||
|  |     }, | ||
|  | 
 | ||
|  |     parse_scenario : function (scenario) { | ||
|  |       // This logic had to be made more complex since some users were using commas in the url path
 | ||
|  |       // So we cannot simply just split on a comma
 | ||
|  |       var directive_match = scenario[0].match(/(.+),\s*(\w+)\s*$/), | ||
|  |       media_query         = scenario[1]; | ||
|  | 
 | ||
|  |       if (directive_match) { | ||
|  |         var path  = directive_match[1], | ||
|  |         directive = directive_match[2]; | ||
|  |       } | ||
|  |       else { | ||
|  |         var cached_split = scenario[0].split(/,\s*$/), | ||
|  |         path             = cached_split[0], | ||
|  |         directive        = '';                | ||
|  |       } | ||
|  | 
 | ||
|  |       return [this.trim(path), this.convert_directive(directive), this.trim(media_query)]; | ||
|  |     }, | ||
|  | 
 | ||
|  |     object : function(el) { | ||
|  |       var raw_arr = this.parse_data_attr(el), | ||
|  |           scenarios = [],  | ||
|  |           i = raw_arr.length; | ||
|  | 
 | ||
|  |       if (i > 0) { | ||
|  |         while (i--) { | ||
|  |           var split = raw_arr[i].split(/\((.*?)(\))$/); | ||
|  | 
 | ||
|  |           if (split.length > 1) { | ||
|  |             var params = this.parse_scenario(split); | ||
|  |             scenarios.push(params); | ||
|  |           } | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       return this.store(el, scenarios); | ||
|  |     }, | ||
|  | 
 | ||
|  |     store : function (el, scenarios) { | ||
|  |       var uuid = this.random_str(), | ||
|  |           current_uuid = el.data(this.add_namespace('uuid', true)); | ||
|  | 
 | ||
|  |       if (this.cache[current_uuid]) return this.cache[current_uuid]; | ||
|  | 
 | ||
|  |       el.attr(this.add_namespace('data-uuid'), uuid); | ||
|  | 
 | ||
|  |       return this.cache[uuid] = scenarios; | ||
|  |     }, | ||
|  | 
 | ||
|  |     trim : function(str) { | ||
|  | 
 | ||
|  |       if (typeof str === 'string') { | ||
|  |         return $.trim(str); | ||
|  |       } | ||
|  | 
 | ||
|  |       return str; | ||
|  |     }, | ||
|  | 
 | ||
|  |     set_data_attr: function (init) { | ||
|  |       if (init) { | ||
|  |         if (this.namespace.length > 0) { | ||
|  |           return this.namespace + '-' + this.settings.load_attr; | ||
|  |         } | ||
|  | 
 | ||
|  |         return this.settings.load_attr; | ||
|  |       } | ||
|  | 
 | ||
|  |       if (this.namespace.length > 0) { | ||
|  |         return 'data-' + this.namespace + '-' + this.settings.load_attr; | ||
|  |       } | ||
|  | 
 | ||
|  |       return 'data-' + this.settings.load_attr; | ||
|  |     }, | ||
|  | 
 | ||
|  |     parse_data_attr : function (el) { | ||
|  |       var raw = el.attr(this.attr_name()).split(/\[(.*?)\]/), | ||
|  |           i = raw.length,  | ||
|  |           output = []; | ||
|  | 
 | ||
|  |       while (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, window, window.document)); |