2 (function ($, window
, document
, undefined) {
5 Foundation
.libs
.interchange
= {
16 load_attr
: 'interchange',
19 'default': 'only screen',
20 'small': Foundation
.media_queries
['small'],
21 'small-only': Foundation
.media_queries
['small-only'],
22 'medium': Foundation
.media_queries
['medium'],
23 'medium-only': Foundation
.media_queries
['medium-only'],
24 'large': Foundation
.media_queries
['large'],
25 'large-only': Foundation
.media_queries
['large-only'],
26 'xlarge': Foundation
.media_queries
['xlarge'],
27 'xlarge-only': Foundation
.media_queries
['xlarge-only'],
28 'xxlarge': Foundation
.media_queries
['xxlarge'],
29 'landscape': 'only screen and (orientation: landscape)',
30 'portrait': 'only screen and (orientation: portrait)',
31 'retina': 'only screen and (-webkit-min-device-pixel-ratio: 2),' +
32 'only screen and (min--moz-device-pixel-ratio: 2),' +
33 'only screen and (-o-min-device-pixel-ratio: 2/1),' +
34 'only screen and (min-device-pixel-ratio: 2),' +
35 'only screen and (min-resolution: 192dpi),' +
36 'only screen and (min-resolution: 2dppx)'
40 replace: function (el
, path
, trigger
) {
41 // The trigger argument, if called within the directive, fires
42 // an event named after the directive on the element, passing
43 // any parameters along to the event that you pass to trigger.
45 // ex. trigger(), trigger([a, b, c]), or trigger(a, b, c)
47 // This allows you to bind a callback like so:
48 // $('#interchangeContainer').on('replace', function (e, a, b, c) {
49 // console.log($(this).html(), a, b, c);
52 if (/IMG/.test(el
[0].nodeName
)) {
53 var orig_path
= el
[0].src
;
55 if (new RegExp(path
, 'i').test(orig_path
)) return;
59 return trigger(el
[0].src
);
61 var last_path
= el
.data(this.data_attr
+ '-last-path'),
64 if (last_path
== path
) return;
66 if (/\.(gif|jpg|jpeg|tiff|png)([?#].*)?/i.test(path
)) {
67 $(el
).css('background-image', 'url(' + path
+ ')');
68 el
.data('interchange-last-path', path
);
72 return $.get(path
, function (response
) {
74 el
.data(self
.data_attr
+ '-last-path', path
);
82 init: function (scope
, method
, options
) {
83 Foundation
.inherit(this, 'throttle random_str');
85 this.data_attr
= this.set_data_attr();
86 $.extend(true, this.settings
, method
, options
);
87 this.bindings(method
, options
);
92 get_media_hash: function () {
94 for (var queryName
in this.settings
.named_queries
) {
95 mediaHash
+= matchMedia(this.settings
.named_queries
[queryName
]).matches
.toString();
100 events: function () {
101 var self
= this, prevMediaHash
;
105 .on('resize.fndtn.interchange', self
.throttle(function () {
106 var currMediaHash
= self
.get_media_hash();
107 if (currMediaHash
!== prevMediaHash
) {
110 prevMediaHash
= currMediaHash
;
116 resize: function () {
117 var cache
= this.cache
;
119 if (!this.images_loaded
|| !this.nodes_loaded
) {
120 setTimeout($.proxy(this.resize
, this), 50);
124 for (var uuid
in cache
) {
125 if (cache
.hasOwnProperty(uuid
)) {
126 var passed
= this.results(uuid
, cache
[uuid
]);
129 this.settings
.directives
[passed
130 .scenario
[1]].call(this, passed
.el
, passed
.scenario
[0], function () {
131 if (arguments
[0] instanceof Array
) {
132 var args
= arguments
[0];
134 var args
= Array
.prototype.slice
.call(arguments
, 0);
137 passed
.el
.trigger(passed
.scenario
[1], args
);
145 results: function (uuid
, scenarios
) {
146 var count
= scenarios
.length
;
149 var el
= this.S('[' + this.add_namespace('data-uuid') + '="' + uuid
+ '"]');
152 var mq
, rule
= scenarios
[count
][2];
153 if (this.settings
.named_queries
.hasOwnProperty(rule
)) {
154 mq
= matchMedia(this.settings
.named_queries
[rule
]);
156 mq
= matchMedia(rule
);
159 return {el
: el
, scenario
: scenarios
[count
]};
167 load: function (type
, force_update
) {
168 if (typeof this['cached_' + type
] === 'undefined' || force_update
) {
169 this['update_' + type
]();
172 return this['cached_' + type
];
175 update_images: function () {
176 var images
= this.S('img[' + this.data_attr
+ ']'),
177 count
= images
.length
,
180 data_attr
= this.data_attr
;
183 this.cached_images
= [];
184 this.images_loaded
= (count
=== 0);
189 var str
= images
[i
].getAttribute(data_attr
) || '';
191 if (str
.length
> 0) {
192 this.cached_images
.push(images
[i
]);
196 if (loaded_count
=== count
) {
197 this.images_loaded
= true;
198 this.enhance('images');
205 update_nodes: function () {
206 var nodes
= this.S('[' + this.data_attr
+ ']').not('img'),
207 count
= nodes
.length
,
210 data_attr
= this.data_attr
;
212 this.cached_nodes
= [];
213 this.nodes_loaded
= (count
=== 0);
218 var str
= nodes
[i
].getAttribute(data_attr
) || '';
220 if (str
.length
> 0) {
221 this.cached_nodes
.push(nodes
[i
]);
224 if (loaded_count
=== count
) {
225 this.nodes_loaded
= true;
226 this.enhance('nodes');
233 enhance: function (type
) {
234 var i
= this['cached_' + type
].length
;
237 this.object($(this['cached_' + type
][i
]));
240 return $(window
).trigger('resize').trigger('resize.fndtn.interchange');
243 convert_directive: function (directive
) {
245 var trimmed
= this.trim(directive
);
247 if (trimmed
.length
> 0) {
254 parse_scenario: function (scenario
) {
255 // This logic had to be made more complex since some users were using commas in the url path
256 // So we cannot simply just split on a comma
257 var directive_match
= scenario
[0].match(/(.+),\s*(\w+)\s*$/),
258 media_query
= scenario
[1];
260 if (directive_match
) {
261 var path
= directive_match
[1],
262 directive
= directive_match
[2];
265 var cached_split
= scenario
[0].split(/,\s*$/),
266 path
= cached_split
[0],
270 return [this.trim(path
), this.convert_directive(directive
), this.trim(media_query
)];
273 object: function (el
) {
274 var raw_arr
= this.parse_data_attr(el
),
280 var split
= raw_arr
[i
].split(/\((.*?)(\))$/);
282 if (split
.length
> 1) {
283 var params
= this.parse_scenario(split
);
284 scenarios
.push(params
);
289 return this.store(el
, scenarios
);
292 store: function (el
, scenarios
) {
293 var uuid
= this.random_str(),
294 current_uuid
= el
.data(this.add_namespace('uuid', true));
296 if (this.cache
[current_uuid
]) return this.cache
[current_uuid
];
298 el
.attr(this.add_namespace('data-uuid'), uuid
);
300 return this.cache
[uuid
] = scenarios
;
303 trim: function (str
) {
305 if (typeof str
=== 'string') {
312 set_data_attr: function (init
) {
314 if (this.namespace.length
> 0) {
315 return this.namespace + '-' + this.settings
.load_attr
;
318 return this.settings
.load_attr
;
321 if (this.namespace.length
> 0) {
322 return 'data-' + this.namespace + '-' + this.settings
.load_attr
;
325 return 'data-' + this.settings
.load_attr
;
328 parse_data_attr: function (el
) {
329 var raw
= el
.attr(this.attr_name()).split(/\[(.*?)\]/),
334 if (raw
[i
].replace(/[\W\d]+/, '').length
> 4) {
342 reflow: function () {
343 this.load('images', true);
344 this.load('nodes', true);
349 }(jQuery
, window
, window
.document
));