parallax.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /*!
  2. * Name : Just Another Parallax [Jarallax]
  3. * Version : 1.8.0
  4. * Author : _nK https://nkdev.info
  5. * GitHub : https://github.com/nk-o/jarallax
  6. */
  7. (function (window) {
  8. 'use strict';
  9. // Adapted from https://gist.github.com/paulirish/1579671
  10. if(!Date.now) {
  11. Date.now = function () { return new Date().getTime(); };
  12. }
  13. if(!window.requestAnimationFrame) {
  14. (function () {
  15. var vendors = ['webkit', 'moz'];
  16. for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
  17. var vp = vendors[i];
  18. window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
  19. window.cancelAnimationFrame = window[vp+'CancelAnimationFrame']
  20. || window[vp+'CancelRequestAnimationFrame'];
  21. }
  22. if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
  23. || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
  24. var lastTime = 0;
  25. window.requestAnimationFrame = function (callback) {
  26. var now = Date.now();
  27. var nextTime = Math.max(lastTime + 16, now);
  28. return setTimeout(function () { callback(lastTime = nextTime); },
  29. nextTime - now);
  30. };
  31. window.cancelAnimationFrame = clearTimeout;
  32. }
  33. }());
  34. }
  35. // test if css property supported by browser
  36. // like "transform"
  37. var tempDiv = document.createElement('div');
  38. function isPropertySupported (property) {
  39. var prefixes = ['O','Moz','ms','Ms','Webkit'];
  40. var i = prefixes.length;
  41. if (tempDiv.style[property] !== undefined) {
  42. return true;
  43. }
  44. property = property.charAt(0).toUpperCase() + property.substr(1);
  45. while (--i > -1 && tempDiv.style[prefixes[i] + property] === undefined) { }
  46. return i >= 0;
  47. }
  48. var supportTransform = isPropertySupported('transform');
  49. var supportTransform3D = isPropertySupported('perspective');
  50. var ua = navigator.userAgent;
  51. var isAndroid = ua.toLowerCase().indexOf('android') > -1;
  52. var isIOs = /iPad|iPhone|iPod/.test(ua) && !window.MSStream;
  53. var isFirefox = ua.toLowerCase().indexOf('firefox') > -1;
  54. var isIE = ua.indexOf('MSIE ') > -1 // IE 10 or older
  55. || ua.indexOf('Trident/') > -1 // IE 11
  56. || ua.indexOf('Edge/') > -1; // Edge
  57. var isIElt10 = document.all && !window.atob; // IE 9 or older
  58. var wndW;
  59. var wndH;
  60. function updateWndVars () {
  61. wndW = window.innerWidth || document.documentElement.clientWidth;
  62. wndH = window.innerHeight || document.documentElement.clientHeight;
  63. }
  64. updateWndVars();
  65. // list with all jarallax instances
  66. // need to render all in one scroll/resize event
  67. var jarallaxList = [];
  68. // Jarallax instance
  69. var Jarallax = (function () {
  70. var instanceID = 0;
  71. function Jarallax_inner (item, userOptions) {
  72. var _this = this,
  73. dataOptions;
  74. _this.$item = item;
  75. _this.defaults = {
  76. type : 'scroll', // type of parallax: scroll, scale, opacity, scale-opacity, scroll-opacity
  77. speed : 0.5, // supported value from -1 to 2
  78. imgSrc : null,
  79. imgWidth : null,
  80. imgHeight : null,
  81. elementInViewport : null,
  82. zIndex : -100,
  83. noAndroid : false,
  84. noIos : true,
  85. // events
  86. onScroll : null, // function(calculations) {}
  87. onInit : null, // function() {}
  88. onDestroy : null, // function() {}
  89. onCoverImage : null // function() {}
  90. };
  91. dataOptions = JSON.parse(_this.$item.getAttribute('data-jarallax') || '{}');
  92. _this.options = _this.extend({}, _this.defaults, dataOptions, userOptions);
  93. // stop init if android or ios
  94. if(!supportTransform || isAndroid && _this.options.noAndroid || isIOs && _this.options.noIos) {
  95. return;
  96. }
  97. // fix speed option [-1.0, 2.0]
  98. _this.options.speed = Math.min(2, Math.max(-1, parseFloat(_this.options.speed)));
  99. // custom element to check if parallax in viewport
  100. var elementInVP = _this.options.elementInViewport;
  101. // get first item from array
  102. if(elementInVP && typeof elementInVP === 'object' && typeof elementInVP.length !== 'undefined') {
  103. elementInVP = elementInVP[0];
  104. }
  105. // check if dom element
  106. if(!elementInVP instanceof Element) {
  107. elementInVP = null;
  108. }
  109. _this.options.elementInViewport = elementInVP;
  110. _this.instanceID = instanceID++;
  111. _this.image = {
  112. src : _this.options.imgSrc || null,
  113. $container : null,
  114. $item : null,
  115. width : _this.options.imgWidth || null,
  116. height : _this.options.imgHeight || null,
  117. // fix for some devices
  118. // use <img> instead of background image - more smoothly
  119. useImgTag : isIOs || isAndroid || isIE,
  120. // position absolute is needed on IE9 and FireFox because fixed position have glitches
  121. position : !supportTransform3D || isFirefox ? 'absolute' : 'fixed'
  122. };
  123. if(_this.initImg()) {
  124. _this.init();
  125. }
  126. }
  127. return Jarallax_inner;
  128. }());
  129. // add styles to element
  130. Jarallax.prototype.css = function (el, styles) {
  131. if(typeof styles === 'string') {
  132. if(window.getComputedStyle) {
  133. return window.getComputedStyle(el).getPropertyValue(styles);
  134. }
  135. return el.style[styles];
  136. }
  137. // add transform property with vendor prefixes
  138. if(styles.transform) {
  139. if (supportTransform3D) {
  140. styles.transform += ' translateZ(0)';
  141. }
  142. styles.WebkitTransform = styles.MozTransform = styles.msTransform = styles.OTransform = styles.transform;
  143. }
  144. for(var k in styles) {
  145. el.style[k] = styles[k];
  146. }
  147. return el;
  148. };
  149. // Extend like jQuery.extend
  150. Jarallax.prototype.extend = function (out) {
  151. out = out || {};
  152. for (var i = 1; i < arguments.length; i++) {
  153. if (!arguments[i]) {
  154. continue;
  155. }
  156. for (var key in arguments[i]) {
  157. if (arguments[i].hasOwnProperty(key)) {
  158. out[key] = arguments[i][key];
  159. }
  160. }
  161. }
  162. return out;
  163. };
  164. // Jarallax functions
  165. Jarallax.prototype.initImg = function () {
  166. var _this = this;
  167. // get image src
  168. if(_this.image.src === null) {
  169. _this.image.src = _this.css(_this.$item, 'background-image').replace(/^url\(['"]?/g,'').replace(/['"]?\)$/g,'');
  170. }
  171. return !(!_this.image.src || _this.image.src === 'none');
  172. };
  173. Jarallax.prototype.init = function () {
  174. var _this = this,
  175. containerStyles = {
  176. position : 'absolute',
  177. top : 0,
  178. left : 0,
  179. width : '100%',
  180. height : '100%',
  181. overflow : 'hidden',
  182. pointerEvents : 'none'
  183. },
  184. imageStyles = {};
  185. // save default user styles
  186. _this.$item.setAttribute('data-jarallax-original-styles', _this.$item.getAttribute('style'));
  187. // set relative position and z-index to the parent
  188. if (_this.css(_this.$item, 'position') === 'static') {
  189. _this.css(_this.$item, {
  190. position: 'relative'
  191. });
  192. }
  193. if (_this.css(_this.$item, 'z-index') === 'auto') {
  194. _this.css(_this.$item, {
  195. zIndex: 0
  196. });
  197. }
  198. // container for parallax image
  199. _this.image.$container = document.createElement('div');
  200. _this.css(_this.image.$container, containerStyles);
  201. _this.css(_this.image.$container, {
  202. visibility : 'hidden',
  203. 'z-index' : _this.options.zIndex
  204. });
  205. _this.image.$container.setAttribute('id', 'jarallax-container-' + _this.instanceID);
  206. _this.$item.appendChild(_this.image.$container);
  207. // use img tag
  208. if(_this.image.useImgTag) {
  209. _this.image.$item = document.createElement('img');
  210. _this.image.$item.setAttribute('src', _this.image.src);
  211. imageStyles = _this.extend({
  212. 'max-width' : 'none'
  213. }, containerStyles, imageStyles);
  214. }
  215. // use div with background image
  216. else {
  217. _this.image.$item = document.createElement('div');
  218. imageStyles = _this.extend({
  219. 'background-position' : '50% 50%',
  220. 'background-size' : '100% auto',
  221. 'background-repeat' : 'no-repeat no-repeat',
  222. 'background-image' : 'url("' + _this.image.src + '")'
  223. }, containerStyles, imageStyles);
  224. }
  225. // check if one of parents have transform style (without this check, scroll transform will be inverted)
  226. // discussion - https://github.com/nk-o/jarallax/issues/9
  227. var parentWithTransform = 0;
  228. var $itemParents = _this.$item;
  229. while ($itemParents !== null && $itemParents !== document && parentWithTransform === 0) {
  230. var parent_transform = _this.css($itemParents, '-webkit-transform') || _this.css($itemParents, '-moz-transform') || _this.css($itemParents, 'transform');
  231. if(parent_transform && parent_transform !== 'none') {
  232. parentWithTransform = 1;
  233. // add transform on parallax container if there is parent with transform
  234. _this.css(_this.image.$container, {
  235. transform: 'translateX(0) translateY(0)'
  236. });
  237. }
  238. $itemParents = $itemParents.parentNode;
  239. }
  240. // absolute position if one of parents have transformations or parallax without scroll
  241. if (parentWithTransform || _this.options.type === 'opacity'|| _this.options.type === 'scale' || _this.options.type === 'scale-opacity') {
  242. _this.image.position = 'absolute';
  243. }
  244. // add position to parallax block
  245. imageStyles.position = _this.image.position;
  246. // parallax image
  247. _this.css(_this.image.$item, imageStyles);
  248. _this.image.$container.appendChild(_this.image.$item);
  249. // cover image if width and height is ready
  250. function initAfterReady () {
  251. _this.coverImage();
  252. _this.clipContainer();
  253. _this.onScroll(true);
  254. // call onInit event
  255. if(_this.options.onInit) {
  256. _this.options.onInit.call(_this);
  257. }
  258. // timeout to fix IE blinking
  259. setTimeout(function () {
  260. if(_this.$item) {
  261. // remove default user background
  262. _this.css(_this.$item, {
  263. 'background-image' : 'none',
  264. 'background-attachment' : 'scroll',
  265. 'background-size' : 'auto'
  266. });
  267. }
  268. }, 0);
  269. }
  270. if(_this.image.width && _this.image.height) {
  271. // init if width and height already exists
  272. initAfterReady();
  273. } else {
  274. // load image and get width and height
  275. _this.getImageSize(_this.image.src, function (width, height) {
  276. _this.image.width = width;
  277. _this.image.height = height;
  278. initAfterReady();
  279. });
  280. }
  281. jarallaxList.push(_this);
  282. };
  283. Jarallax.prototype.destroy = function () {
  284. var _this = this;
  285. // remove from instances list
  286. for(var k = 0, len = jarallaxList.length; k < len; k++) {
  287. if(jarallaxList[k].instanceID === _this.instanceID) {
  288. jarallaxList.splice(k, 1);
  289. break;
  290. }
  291. }
  292. // return styles on container as before jarallax init
  293. var originalStylesTag = _this.$item.getAttribute('data-jarallax-original-styles');
  294. _this.$item.removeAttribute('data-jarallax-original-styles');
  295. // null occurs if there is no style tag before jarallax init
  296. if(originalStylesTag === 'null') {
  297. _this.$item.removeAttribute('style');
  298. } else {
  299. _this.$item.setAttribute('style', originalStylesTag);
  300. }
  301. // remove additional dom elements
  302. if(_this.$clipStyles) {
  303. _this.$clipStyles.parentNode.removeChild(_this.$clipStyles);
  304. }
  305. _this.image.$container.parentNode.removeChild(_this.image.$container);
  306. // call onDestroy event
  307. if(_this.options.onDestroy) {
  308. _this.options.onDestroy.call(_this);
  309. }
  310. // delete jarallax from item
  311. delete _this.$item.jarallax;
  312. // delete all variables
  313. for(var n in _this) {
  314. delete _this[n];
  315. }
  316. };
  317. Jarallax.prototype.getImageSize = function (src, callback) {
  318. if(!src || !callback) {
  319. return;
  320. }
  321. var tempImg = new Image();
  322. tempImg.onload = function () {
  323. callback(tempImg.width, tempImg.height);
  324. };
  325. tempImg.src = src;
  326. };
  327. // it will remove some image overlapping
  328. // overlapping occur due to an image position fixed inside absolute position element (webkit based browsers works without any fix)
  329. Jarallax.prototype.clipContainer = function () {
  330. // clip is not working properly on real IE9 and less
  331. if(isIElt10) {
  332. return;
  333. }
  334. var _this = this,
  335. rect = _this.image.$container.getBoundingClientRect(),
  336. width = rect.width,
  337. height = rect.height;
  338. if(!_this.$clipStyles) {
  339. _this.$clipStyles = document.createElement('style');
  340. _this.$clipStyles.setAttribute('type', 'text/css');
  341. _this.$clipStyles.setAttribute('id', '#jarallax-clip-' + _this.instanceID);
  342. var head = document.head || document.getElementsByTagName('head')[0];
  343. head.appendChild(_this.$clipStyles);
  344. }
  345. var styles = [
  346. '#jarallax-container-' + _this.instanceID + ' {',
  347. ' clip: rect(0 ' + width + 'px ' + height + 'px 0);',
  348. ' clip: rect(0, ' + width + 'px, ' + height + 'px, 0);',
  349. '}'
  350. ].join('\n');
  351. // add clip styles inline (this method need for support IE8 and less browsers)
  352. if (_this.$clipStyles.styleSheet){
  353. _this.$clipStyles.styleSheet.cssText = styles;
  354. } else {
  355. _this.$clipStyles.innerHTML = styles;
  356. }
  357. };
  358. Jarallax.prototype.coverImage = function () {
  359. var _this = this;
  360. if(!_this.image.width || !_this.image.height) {
  361. return;
  362. }
  363. var rect = _this.image.$container.getBoundingClientRect(),
  364. contW = rect.width,
  365. contH = rect.height,
  366. contL = rect.left,
  367. imgW = _this.image.width,
  368. imgH = _this.image.height,
  369. speed = _this.options.speed,
  370. isScroll = _this.options.type === 'scroll' || _this.options.type === 'scroll-opacity',
  371. scrollDist = 0,
  372. resultW = 0,
  373. resultH = contH,
  374. resultML = 0,
  375. resultMT = 0;
  376. // scroll parallax
  377. if(isScroll) {
  378. // scroll distance and height for image
  379. if (speed < 0) {
  380. scrollDist = speed * Math.max(contH, wndH);
  381. } else {
  382. scrollDist = speed * (contH + wndH);
  383. }
  384. // size for scroll parallax
  385. if (speed > 1) {
  386. resultH = Math.abs(scrollDist - wndH);
  387. } else if (speed < 0) {
  388. resultH = scrollDist / speed + Math.abs(scrollDist);
  389. } else {
  390. resultH += Math.abs(wndH - contH) * (1 - speed);
  391. }
  392. scrollDist /= 2;
  393. }
  394. // calculate width relative to height and image size
  395. resultW = resultH * imgW / imgH;
  396. if(resultW < contW) {
  397. resultW = contW;
  398. resultH = resultW * imgH / imgW;
  399. }
  400. // center parallax image
  401. if(isScroll) {
  402. resultML = contL + (contW - resultW) / 2;
  403. resultMT = (wndH - resultH) / 2;
  404. } else {
  405. resultML = (contW - resultW) / 2;
  406. resultMT = (contH - resultH) / 2;
  407. }
  408. // fix if parallax block in absolute position
  409. if(_this.image.position === 'absolute') {
  410. resultML -= contL;
  411. }
  412. // store scroll distance
  413. _this.parallaxScrollDistance = scrollDist;
  414. // apply result to item
  415. _this.css(_this.image.$item, {
  416. width: resultW + 'px',
  417. height: resultH + 'px',
  418. marginLeft: resultML + 'px',
  419. marginTop: resultMT + 'px'
  420. });
  421. // call onCoverImage event
  422. if(_this.options.onCoverImage) {
  423. _this.options.onCoverImage.call(_this);
  424. }
  425. };
  426. Jarallax.prototype.isVisible = function () {
  427. return this.isElementInViewport || false;
  428. };
  429. Jarallax.prototype.onScroll = function (force) {
  430. var _this = this;
  431. if(!_this.image.width || !_this.image.height) {
  432. return;
  433. }
  434. var rect = _this.$item.getBoundingClientRect(),
  435. contT = rect.top,
  436. contH = rect.height,
  437. styles = {
  438. visibility : 'visible',
  439. backgroundPosition : '50% 50%'
  440. };
  441. // check if in viewport
  442. var viewportRect = rect;
  443. if(_this.options.elementInViewport) {
  444. viewportRect = _this.options.elementInViewport.getBoundingClientRect();
  445. }
  446. _this.isElementInViewport =
  447. viewportRect.bottom >= 0 &&
  448. viewportRect.right >= 0 &&
  449. viewportRect.top <= wndH &&
  450. viewportRect.left <= wndW;
  451. // stop calculations if item is not in viewport
  452. if (force ? false : !_this.isElementInViewport) {
  453. return;
  454. }
  455. // calculate parallax helping variables
  456. var beforeTop = Math.max(0, contT),
  457. beforeTopEnd = Math.max(0, contH + contT),
  458. afterTop = Math.max(0, -contT),
  459. beforeBottom = Math.max(0, contT + contH - wndH),
  460. beforeBottomEnd = Math.max(0, contH - (contT + contH - wndH)),
  461. afterBottom = Math.max(0, -contT + wndH - contH),
  462. fromViewportCenter = 1 - 2 * (wndH - contT) / (wndH + contH);
  463. // calculate on how percent of section is visible
  464. var visiblePercent = 1;
  465. if(contH < wndH) {
  466. visiblePercent = 1 - (afterTop || beforeBottom) / contH;
  467. } else {
  468. if(beforeTopEnd <= wndH) {
  469. visiblePercent = beforeTopEnd / wndH;
  470. } else if (beforeBottomEnd <= wndH) {
  471. visiblePercent = beforeBottomEnd / wndH;
  472. }
  473. }
  474. // opacity
  475. if(_this.options.type === 'opacity' || _this.options.type === 'scale-opacity' || _this.options.type === 'scroll-opacity') {
  476. styles.transform = ''; // empty to add translateZ(0) where it is possible
  477. styles.opacity = visiblePercent;
  478. }
  479. // scale
  480. if(_this.options.type === 'scale' || _this.options.type === 'scale-opacity') {
  481. var scale = 1;
  482. if(_this.options.speed < 0) {
  483. scale -= _this.options.speed * visiblePercent;
  484. } else {
  485. scale += _this.options.speed * (1 - visiblePercent);
  486. }
  487. styles.transform = 'scale(' + scale + ')';
  488. }
  489. // scroll
  490. if(_this.options.type === 'scroll' || _this.options.type === 'scroll-opacity') {
  491. var positionY = _this.parallaxScrollDistance * fromViewportCenter;
  492. // fix if parallax block in absolute position
  493. if(_this.image.position === 'absolute') {
  494. positionY -= contT;
  495. }
  496. styles.transform = 'translateY(' + positionY + 'px)';
  497. }
  498. _this.css(_this.image.$item, styles);
  499. // call onScroll event
  500. if(_this.options.onScroll) {
  501. _this.options.onScroll.call(_this, {
  502. section: rect,
  503. beforeTop: beforeTop,
  504. beforeTopEnd: beforeTopEnd,
  505. afterTop: afterTop,
  506. beforeBottom: beforeBottom,
  507. beforeBottomEnd: beforeBottomEnd,
  508. afterBottom: afterBottom,
  509. visiblePercent: visiblePercent,
  510. fromViewportCenter: fromViewportCenter
  511. });
  512. }
  513. };
  514. // init events
  515. function addEventListener (el, eventName, handler) {
  516. if (el.addEventListener) {
  517. el.addEventListener(eventName, handler);
  518. } else {
  519. el.attachEvent('on' + eventName, function (){
  520. handler.call(el);
  521. });
  522. }
  523. }
  524. function update (e) {
  525. window.requestAnimationFrame(function () {
  526. if(e.type !== 'scroll') {
  527. updateWndVars();
  528. }
  529. for(var k = 0, len = jarallaxList.length; k < len; k++) {
  530. // cover image and clip needed only when parallax container was changed
  531. if(e.type !== 'scroll') {
  532. jarallaxList[k].coverImage();
  533. jarallaxList[k].clipContainer();
  534. }
  535. jarallaxList[k].onScroll();
  536. }
  537. });
  538. }
  539. addEventListener(window, 'scroll', update);
  540. addEventListener(window, 'resize', update);
  541. addEventListener(window, 'orientationchange', update);
  542. addEventListener(window, 'load', update);
  543. // global definition
  544. var plugin = function (items) {
  545. // check for dom element
  546. // thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
  547. if(typeof HTMLElement === "object" ? items instanceof HTMLElement : items && typeof items === "object" && items !== null && items.nodeType === 1 && typeof items.nodeName==="string") {
  548. items = [items];
  549. }
  550. var options = arguments[1],
  551. args = Array.prototype.slice.call(arguments, 2),
  552. len = items.length,
  553. k = 0,
  554. ret;
  555. for (k; k < len; k++) {
  556. if (typeof options === 'object' || typeof options === 'undefined') {
  557. if(!items[k].jarallax) {
  558. items[k].jarallax = new Jarallax(items[k], options);
  559. }
  560. }
  561. else if(items[k].jarallax) {
  562. ret = items[k].jarallax[options].apply(items[k].jarallax, args);
  563. }
  564. if (typeof ret !== 'undefined') {
  565. return ret;
  566. }
  567. }
  568. return items;
  569. };
  570. plugin.constructor = Jarallax;
  571. // no conflict
  572. var oldPlugin = window.jarallax;
  573. window.jarallax = plugin;
  574. window.jarallax.noConflict = function () {
  575. window.jarallax = oldPlugin;
  576. return this;
  577. };
  578. // jQuery support
  579. if(typeof jQuery !== 'undefined') {
  580. var jQueryPlugin = function () {
  581. var args = arguments || [];
  582. Array.prototype.unshift.call(args, this);
  583. var res = plugin.apply(window, args);
  584. return typeof res !== 'object' ? res : this;
  585. };
  586. jQueryPlugin.constructor = Jarallax;
  587. // no conflict
  588. var oldJqPlugin = jQuery.fn.jarallax;
  589. jQuery.fn.jarallax = jQueryPlugin;
  590. jQuery.fn.jarallax.noConflict = function () {
  591. jQuery.fn.jarallax = oldJqPlugin;
  592. return this;
  593. };
  594. }
  595. // data-jarallax initialization
  596. addEventListener(window, 'DOMContentLoaded', function () {
  597. plugin(document.querySelectorAll('[data-jarallax], [data-jarallax-video]'));
  598. });
  599. }(window));