wow.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. (function() {
  2. var MutationObserver, Util, WeakMap, getComputedStyle, getComputedStyleRX,
  3. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  4. __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  5. Util = (function() {
  6. function Util() {}
  7. Util.prototype.extend = function(custom, defaults) {
  8. var key, value;
  9. for (key in defaults) {
  10. value = defaults[key];
  11. if (custom[key] == null) {
  12. custom[key] = value;
  13. }
  14. }
  15. return custom;
  16. };
  17. Util.prototype.isMobile = function(agent) {
  18. return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent);
  19. };
  20. Util.prototype.addEvent = function(elem, event, fn) {
  21. if (elem.addEventListener != null) {
  22. return elem.addEventListener(event, fn, false);
  23. } else if (elem.attachEvent != null) {
  24. return elem.attachEvent("on" + event, fn);
  25. } else {
  26. return elem[event] = fn;
  27. }
  28. };
  29. Util.prototype.removeEvent = function(elem, event, fn) {
  30. if (elem.removeEventListener != null) {
  31. return elem.removeEventListener(event, fn, false);
  32. } else if (elem.detachEvent != null) {
  33. return elem.detachEvent("on" + event, fn);
  34. } else {
  35. return delete elem[event];
  36. }
  37. };
  38. Util.prototype.innerHeight = function() {
  39. if ('innerHeight' in window) {
  40. return window.innerHeight;
  41. } else {
  42. return document.documentElement.clientHeight;
  43. }
  44. };
  45. return Util;
  46. })();
  47. WeakMap = this.WeakMap || this.MozWeakMap || (WeakMap = (function() {
  48. function WeakMap() {
  49. this.keys = [];
  50. this.values = [];
  51. }
  52. WeakMap.prototype.get = function(key) {
  53. var i, item, _i, _len, _ref;
  54. _ref = this.keys;
  55. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  56. item = _ref[i];
  57. if (item === key) {
  58. return this.values[i];
  59. }
  60. }
  61. };
  62. WeakMap.prototype.set = function(key, value) {
  63. var i, item, _i, _len, _ref;
  64. _ref = this.keys;
  65. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  66. item = _ref[i];
  67. if (item === key) {
  68. this.values[i] = value;
  69. return;
  70. }
  71. }
  72. this.keys.push(key);
  73. return this.values.push(value);
  74. };
  75. return WeakMap;
  76. })());
  77. MutationObserver = this.MutationObserver || this.WebkitMutationObserver || this.MozMutationObserver || (MutationObserver = (function() {
  78. function MutationObserver() {
  79. if (typeof console !== "undefined" && console !== null) {
  80. console.warn('MutationObserver is not supported by your browser.');
  81. }
  82. if (typeof console !== "undefined" && console !== null) {
  83. console.warn('WOW.js cannot detect dom mutations, please call .sync() after loading new content.');
  84. }
  85. }
  86. MutationObserver.notSupported = true;
  87. MutationObserver.prototype.observe = function() {};
  88. return MutationObserver;
  89. })());
  90. getComputedStyle = this.getComputedStyle || function(el, pseudo) {
  91. this.getPropertyValue = function(prop) {
  92. var _ref;
  93. if (prop === 'float') {
  94. prop = 'styleFloat';
  95. }
  96. if (getComputedStyleRX.test(prop)) {
  97. prop.replace(getComputedStyleRX, function(_, _char) {
  98. return _char.toUpperCase();
  99. });
  100. }
  101. return ((_ref = el.currentStyle) != null ? _ref[prop] : void 0) || null;
  102. };
  103. return this;
  104. };
  105. getComputedStyleRX = /(\-([a-z]){1})/g;
  106. this.WOW = (function() {
  107. WOW.prototype.defaults = {
  108. boxClass: 'wow',
  109. animateClass: 'animated',
  110. offset: 0,
  111. mobile: true,
  112. live: true,
  113. callback: null
  114. };
  115. function WOW(options) {
  116. if (options == null) {
  117. options = {};
  118. }
  119. this.scrollCallback = __bind(this.scrollCallback, this);
  120. this.scrollHandler = __bind(this.scrollHandler, this);
  121. this.start = __bind(this.start, this);
  122. this.scrolled = true;
  123. this.config = this.util().extend(options, this.defaults);
  124. this.animationNameCache = new WeakMap();
  125. }
  126. WOW.prototype.init = function() {
  127. var _ref;
  128. this.element = window.document.documentElement;
  129. if ((_ref = document.readyState) === "interactive" || _ref === "complete") {
  130. this.start();
  131. } else {
  132. this.util().addEvent(document, 'DOMContentLoaded', this.start);
  133. }
  134. return this.finished = [];
  135. };
  136. WOW.prototype.start = function() {
  137. var box, _i, _len, _ref;
  138. this.stopped = false;
  139. this.boxes = (function() {
  140. var _i, _len, _ref, _results;
  141. _ref = this.element.querySelectorAll("." + this.config.boxClass);
  142. _results = [];
  143. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  144. box = _ref[_i];
  145. _results.push(box);
  146. }
  147. return _results;
  148. }).call(this);
  149. this.all = (function() {
  150. var _i, _len, _ref, _results;
  151. _ref = this.boxes;
  152. _results = [];
  153. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  154. box = _ref[_i];
  155. _results.push(box);
  156. }
  157. return _results;
  158. }).call(this);
  159. if (this.boxes.length) {
  160. if (this.disabled()) {
  161. this.resetStyle();
  162. } else {
  163. _ref = this.boxes;
  164. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  165. box = _ref[_i];
  166. this.applyStyle(box, true);
  167. }
  168. }
  169. }
  170. if (!this.disabled()) {
  171. this.util().addEvent(window, 'scroll', this.scrollHandler);
  172. this.util().addEvent(window, 'resize', this.scrollHandler);
  173. this.interval = setInterval(this.scrollCallback, 50);
  174. }
  175. if (this.config.live) {
  176. return new MutationObserver((function(_this) {
  177. return function(records) {
  178. var node, record, _j, _len1, _results;
  179. _results = [];
  180. for (_j = 0, _len1 = records.length; _j < _len1; _j++) {
  181. record = records[_j];
  182. _results.push((function() {
  183. var _k, _len2, _ref1, _results1;
  184. _ref1 = record.addedNodes || [];
  185. _results1 = [];
  186. for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
  187. node = _ref1[_k];
  188. _results1.push(this.doSync(node));
  189. }
  190. return _results1;
  191. }).call(_this));
  192. }
  193. return _results;
  194. };
  195. })(this)).observe(document.body, {
  196. childList: true,
  197. subtree: true
  198. });
  199. }
  200. };
  201. WOW.prototype.stop = function() {
  202. this.stopped = true;
  203. this.util().removeEvent(window, 'scroll', this.scrollHandler);
  204. this.util().removeEvent(window, 'resize', this.scrollHandler);
  205. if (this.interval != null) {
  206. return clearInterval(this.interval);
  207. }
  208. };
  209. WOW.prototype.sync = function(element) {
  210. if (MutationObserver.notSupported) {
  211. return this.doSync(this.element);
  212. }
  213. };
  214. WOW.prototype.doSync = function(element) {
  215. var box, _i, _len, _ref, _results;
  216. if (element == null) {
  217. element = this.element;
  218. }
  219. if (element.nodeType !== 1) {
  220. return;
  221. }
  222. element = element.parentNode || element;
  223. _ref = element.querySelectorAll("." + this.config.boxClass);
  224. _results = [];
  225. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  226. box = _ref[_i];
  227. if (__indexOf.call(this.all, box) < 0) {
  228. this.boxes.push(box);
  229. this.all.push(box);
  230. if (this.stopped || this.disabled()) {
  231. this.resetStyle();
  232. } else {
  233. this.applyStyle(box, true);
  234. }
  235. _results.push(this.scrolled = true);
  236. } else {
  237. _results.push(void 0);
  238. }
  239. }
  240. return _results;
  241. };
  242. WOW.prototype.show = function(box) {
  243. this.applyStyle(box);
  244. box.className = "" + box.className + " " + this.config.animateClass;
  245. if (this.config.callback != null) {
  246. return this.config.callback(box);
  247. }
  248. };
  249. WOW.prototype.applyStyle = function(box, hidden) {
  250. var delay, duration, iteration;
  251. duration = box.getAttribute('data-wow-duration');
  252. delay = box.getAttribute('data-wow-delay');
  253. iteration = box.getAttribute('data-wow-iteration');
  254. return this.animate((function(_this) {
  255. return function() {
  256. return _this.customStyle(box, hidden, duration, delay, iteration);
  257. };
  258. })(this));
  259. };
  260. WOW.prototype.animate = (function() {
  261. if ('requestAnimationFrame' in window) {
  262. return function(callback) {
  263. return window.requestAnimationFrame(callback);
  264. };
  265. } else {
  266. return function(callback) {
  267. return callback();
  268. };
  269. }
  270. })();
  271. WOW.prototype.resetStyle = function() {
  272. var box, _i, _len, _ref, _results;
  273. _ref = this.boxes;
  274. _results = [];
  275. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  276. box = _ref[_i];
  277. _results.push(box.style.visibility = 'visible');
  278. }
  279. return _results;
  280. };
  281. WOW.prototype.customStyle = function(box, hidden, duration, delay, iteration) {
  282. if (hidden) {
  283. this.cacheAnimationName(box);
  284. }
  285. box.style.visibility = hidden ? 'hidden' : 'visible';
  286. if (duration) {
  287. this.vendorSet(box.style, {
  288. animationDuration: duration
  289. });
  290. }
  291. if (delay) {
  292. this.vendorSet(box.style, {
  293. animationDelay: delay
  294. });
  295. }
  296. if (iteration) {
  297. this.vendorSet(box.style, {
  298. animationIterationCount: iteration
  299. });
  300. }
  301. this.vendorSet(box.style, {
  302. animationName: hidden ? 'none' : this.cachedAnimationName(box)
  303. });
  304. return box;
  305. };
  306. WOW.prototype.vendors = ["moz", "webkit"];
  307. WOW.prototype.vendorSet = function(elem, properties) {
  308. var name, value, vendor, _results;
  309. _results = [];
  310. for (name in properties) {
  311. value = properties[name];
  312. elem["" + name] = value;
  313. _results.push((function() {
  314. var _i, _len, _ref, _results1;
  315. _ref = this.vendors;
  316. _results1 = [];
  317. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  318. vendor = _ref[_i];
  319. _results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value);
  320. }
  321. return _results1;
  322. }).call(this));
  323. }
  324. return _results;
  325. };
  326. WOW.prototype.vendorCSS = function(elem, property) {
  327. var result, style, vendor, _i, _len, _ref;
  328. style = getComputedStyle(elem);
  329. result = style.getPropertyCSSValue(property);
  330. _ref = this.vendors;
  331. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  332. vendor = _ref[_i];
  333. result = result || style.getPropertyCSSValue("-" + vendor + "-" + property);
  334. }
  335. return result;
  336. };
  337. WOW.prototype.animationName = function(box) {
  338. var animationName;
  339. try {
  340. animationName = this.vendorCSS(box, 'animation-name').cssText;
  341. } catch (_error) {
  342. animationName = getComputedStyle(box).getPropertyValue('animation-name');
  343. }
  344. if (animationName === 'none') {
  345. return '';
  346. } else {
  347. return animationName;
  348. }
  349. };
  350. WOW.prototype.cacheAnimationName = function(box) {
  351. return this.animationNameCache.set(box, this.animationName(box));
  352. };
  353. WOW.prototype.cachedAnimationName = function(box) {
  354. return this.animationNameCache.get(box);
  355. };
  356. WOW.prototype.scrollHandler = function() {
  357. return this.scrolled = true;
  358. };
  359. WOW.prototype.scrollCallback = function() {
  360. var box;
  361. if (this.scrolled) {
  362. this.scrolled = false;
  363. this.boxes = (function() {
  364. var _i, _len, _ref, _results;
  365. _ref = this.boxes;
  366. _results = [];
  367. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  368. box = _ref[_i];
  369. if (!(box)) {
  370. continue;
  371. }
  372. if (this.isVisible(box)) {
  373. this.show(box);
  374. continue;
  375. }
  376. _results.push(box);
  377. }
  378. return _results;
  379. }).call(this);
  380. if (!(this.boxes.length || this.config.live)) {
  381. return this.stop();
  382. }
  383. }
  384. };
  385. WOW.prototype.offsetTop = function(element) {
  386. var top;
  387. while (element.offsetTop === void 0) {
  388. element = element.parentNode;
  389. }
  390. top = element.offsetTop;
  391. while (element = element.offsetParent) {
  392. top += element.offsetTop;
  393. }
  394. return top;
  395. };
  396. WOW.prototype.isVisible = function(box) {
  397. var bottom, offset, top, viewBottom, viewTop;
  398. offset = box.getAttribute('data-wow-offset') || this.config.offset;
  399. viewTop = window.pageYOffset;
  400. viewBottom = viewTop + Math.min(this.element.clientHeight, this.util().innerHeight()) - offset;
  401. top = this.offsetTop(box);
  402. bottom = top + box.clientHeight;
  403. return top <= viewBottom && bottom >= viewTop;
  404. };
  405. WOW.prototype.util = function() {
  406. return this._util != null ? this._util : this._util = new Util();
  407. };
  408. WOW.prototype.disabled = function() {
  409. return !this.config.mobile && this.util().isMobile(navigator.userAgent);
  410. };
  411. return WOW;
  412. })();
  413. }).call(this);