foundation.interchange.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*jslint unparam: true, browser: true, indent: 2 */
  2. ;(function ($, window, document, undefined) {
  3. 'use strict';
  4. Foundation.libs.interchange = {
  5. name : 'interchange',
  6. version : '4.2.1',
  7. cache : {},
  8. settings : {
  9. load_attr : 'interchange',
  10. named_queries : {
  11. 'default' : 'only screen and (min-width: 1px)',
  12. small : 'only screen and (min-width: 768px)',
  13. medium : 'only screen and (min-width: 1280px)',
  14. large : 'only screen and (min-width: 1440px)',
  15. landscape : 'only screen and (orientation: landscape)',
  16. portrait : 'only screen and (orientation: portrait)',
  17. retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),'
  18. + 'only screen and (min--moz-device-pixel-ratio: 2),'
  19. + 'only screen and (-o-min-device-pixel-ratio: 2/1),'
  20. + 'only screen and (min-device-pixel-ratio: 2),'
  21. + 'only screen and (min-resolution: 192dpi),'
  22. + 'only screen and (min-resolution: 2dppx)'
  23. },
  24. directives : {
  25. replace : function (el, path) {
  26. if (/IMG/.test(el[0].nodeName)) {
  27. var path_parts = path.split('/'),
  28. path_file = path_parts[path_parts.length - 1],
  29. orig_path = el[0].src;
  30. if (new RegExp(path_file, 'i').test(el[0].src)) return;
  31. el[0].src = path;
  32. return el.trigger('replace', [el[0].src, orig_path]);
  33. }
  34. }
  35. }
  36. },
  37. init : function (scope, method, options) {
  38. Foundation.inherit(this, 'throttle');
  39. if (typeof method === 'object') {
  40. $.extend(true, this.settings, method);
  41. }
  42. this.events();
  43. this.images();
  44. if (typeof method != 'string') {
  45. return this.settings.init;
  46. } else {
  47. return this[method].call(this, options);
  48. }
  49. },
  50. events : function () {
  51. var self = this;
  52. $(window).on('resize.fndtn.interchange', self.throttle(function () {
  53. self.resize.call(self);
  54. }, 50));
  55. },
  56. resize : function () {
  57. var cache = this.cache;
  58. for (var uuid in cache) {
  59. if (cache.hasOwnProperty(uuid)) {
  60. var passed = this.results(uuid, cache[uuid]);
  61. if (passed) {
  62. this.settings.directives[passed
  63. .scenario[1]](passed.el, passed.scenario[0]);
  64. }
  65. }
  66. }
  67. },
  68. results : function (uuid, scenarios) {
  69. var count = scenarios.length,
  70. results_arr = [];
  71. if (count > 0) {
  72. var el = $('[data-uuid="' + uuid + '"]');
  73. for (var i = count - 1; i >= 0; i--) {
  74. var rule = scenarios[i][2];
  75. if (this.settings.named_queries.hasOwnProperty(rule)) {
  76. var mq = matchMedia(this.settings.named_queries[rule]);
  77. } else {
  78. var mq = matchMedia(scenarios[i][2]);
  79. }
  80. if (mq.matches) {
  81. return {el: el, scenario: scenarios[i]};
  82. }
  83. }
  84. }
  85. return false;
  86. },
  87. images : function (force_update) {
  88. if (typeof this.cached_images === 'undefined' || force_update) {
  89. return this.update_images();
  90. }
  91. return this.cached_images;
  92. },
  93. update_images : function () {
  94. var images = document.getElementsByTagName('img'),
  95. count = images.length,
  96. data_attr = 'data-' + this.settings.load_attr;
  97. this.cached_images = [];
  98. for (var i = count - 1; i >= 0; i--) {
  99. this.loaded($(images[i]), (i === 0), function (image, last) {
  100. if (image) {
  101. var str = image.getAttribute(data_attr) || '';
  102. if (str.length > 0) {
  103. this.cached_images.push(image);
  104. }
  105. }
  106. if (last) this.enhance();
  107. }.bind(this));
  108. }
  109. return 'deferred';
  110. },
  111. // based on jquery.imageready.js
  112. // @weblinc, @jsantell, (c) 2012
  113. loaded : function (image, last, callback) {
  114. function loaded () {
  115. callback(image[0], last);
  116. }
  117. function bindLoad () {
  118. this.one('load', loaded);
  119. if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
  120. var src = this.attr( 'src' ),
  121. param = src.match( /\?/ ) ? '&' : '?';
  122. param += 'random=' + (new Date()).getTime();
  123. this.attr('src', src + param);
  124. }
  125. }
  126. if (!image.attr('src')) {
  127. loaded();
  128. return;
  129. }
  130. if (image[0].complete || image[0].readyState === 4) {
  131. loaded();
  132. } else {
  133. bindLoad.call(image);
  134. }
  135. },
  136. enhance : function () {
  137. var count = this.images().length;
  138. for (var i = count - 1; i >= 0; i--) {
  139. this._object($(this.images()[i]));
  140. }
  141. return $(window).trigger('resize');
  142. },
  143. parse_params : function (path, directive, mq) {
  144. return [this.trim(path), this.convert_directive(directive), this.trim(mq)];
  145. },
  146. convert_directive : function (directive) {
  147. var trimmed = this.trim(directive);
  148. if (trimmed.length > 0) {
  149. return trimmed;
  150. }
  151. return 'replace';
  152. },
  153. _object : function(el) {
  154. var raw_arr = this.parse_data_attr(el),
  155. scenarios = [], count = raw_arr.length;
  156. if (count > 0) {
  157. for (var i = count - 1; i >= 0; i--) {
  158. var split = raw_arr[i].split(/\((.*?)(\))$/);
  159. if (split.length > 1) {
  160. var cached_split = split[0].split(','),
  161. params = this.parse_params(cached_split[0],
  162. cached_split[1], split[1]);
  163. scenarios.push(params);
  164. }
  165. }
  166. }
  167. return this.store(el, scenarios);
  168. },
  169. uuid : function (separator) {
  170. var delim = separator || "-";
  171. function S4() {
  172. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  173. }
  174. return (S4() + S4() + delim + S4() + delim + S4()
  175. + delim + S4() + delim + S4() + S4() + S4());
  176. },
  177. store : function (el, scenarios) {
  178. var uuid = this.uuid(),
  179. current_uuid = el.data('uuid');
  180. if (current_uuid) return this.cache[current_uuid];
  181. el.attr('data-uuid', uuid);
  182. return this.cache[uuid] = scenarios;
  183. },
  184. trim : function(str) {
  185. if (typeof str === 'string') {
  186. return $.trim(str);
  187. }
  188. return str;
  189. },
  190. parse_data_attr : function (el) {
  191. var raw = el.data(this.settings.load_attr).split(/\[(.*?)\]/),
  192. count = raw.length, output = [];
  193. for (var i = count - 1; i >= 0; i--) {
  194. if (raw[i].replace(/[\W\d]+/, '').length > 4) {
  195. output.push(raw[i]);
  196. }
  197. }
  198. return output;
  199. },
  200. reflow : function () {
  201. this.images(true);
  202. }
  203. };
  204. }(Foundation.zj, this, this.document));