Further modules included.
[yaffs-website] / web / modules / contrib / slick / js / slick.load.js
1 /**
2  * @file
3  * Provides Slick loader.
4  */
5
6 (function ($, Drupal, drupalSettings) {
7
8   'use strict';
9
10   /**
11    * Slick utility functions.
12    *
13    * @param {int} i
14    *   The index of the current element.
15    * @param {HTMLElement} elm
16    *   The slick HTML element.
17    */
18   function doSlick(i, elm) {
19     var t = $('> .slick__slider', elm).length ? $('> .slick__slider', elm) : $(elm);
20     var a = $('> .slick__arrow', elm);
21     var o = t.data('slick') ? $.extend({}, drupalSettings.slick, t.data('slick')) : drupalSettings.slick;
22     var r = $.type(o.responsive) === 'array' && o.responsive.length ? o.responsive : false;
23     var b;
24
25     // Populate defaults + globals into each breakpoint.
26     if (r) {
27       for (b in r) {
28         if (r.hasOwnProperty(b) && r[b].settings !== 'unslick') {
29           r[b].settings = $.extend({}, drupalSettings.slick, globals(o), r[b].settings);
30         }
31       }
32     }
33
34     // Update the slick settings object.
35     t.data('slick', o);
36     o = t.data('slick');
37
38     /**
39      * The event must be bound prior to slick being called.
40      */
41     function beforeSlick() {
42       if (o.randomize && !t.hasClass('slick-initiliazed')) {
43         randomize();
44       }
45
46       t.on('setPosition.sl', function (e, slick) {
47         setPosition(slick);
48       });
49
50       $('.media--loading', t).closest('.slide__content').addClass('is-loading');
51
52       // Blazy integration.
53       if (o.lazyLoad === 'blazy' && Drupal.blazy) {
54         t.on('beforeChange.sl', function () {
55           // .b-lazy can be attached to IMG, or DIV as CSS background.
56           var $src = $('.b-lazy:not(.b-loaded)', t);
57
58           if ($src.length) {
59             // Enforces lazyload ahead to smoothen the UX.
60             Drupal.blazy.init.load($src);
61           }
62         });
63       }
64     }
65
66     /**
67      * The event must be bound after slick being called.
68      */
69     function afterSlick() {
70       var slick = t.slick('getSlick');
71       var media = t.find('.media--player').length;
72
73       // Arrow down jumper.
74       t.parent().on('click.sl', '.slick-down', function (e) {
75         e.preventDefault();
76         var b = $(this);
77         $('html, body').stop().animate({
78           scrollTop: $(b.data('target')).offset().top - (b.data('offset') || 0)
79         }, 800, o.easing || 'swing');
80       });
81
82       if (o.mouseWheel) {
83         t.on('mousewheel.sl', function (e, delta) {
84           e.preventDefault();
85           return t.slick(delta < 0 ? 'slickNext' : 'slickPrev');
86         });
87       }
88
89       t.on('lazyLoaded lazyLoadError', function (e, slick, img) {
90         setBackground(img);
91       });
92
93       // Turns off any video if any change to the slider.
94       if (media) {
95         t.on('afterChange.sl', closeOut);
96         t.on('click.sl', '.media__icon--close', closeOut);
97         t.on('click.sl', '.media__icon--play', pause);
98       }
99     }
100
101     /**
102      * Turns images into CSS background if so configured.
103      *
104      * @param {HTMLElement} img
105      *   The image HTML element.
106      */
107     function setBackground(img) {
108       var $img = $(img);
109       var $bg = $img.closest('.media--background');
110       var p = $img.closest('.slide') || $img.closest('.unslick');
111
112       $img.parentsUntil(p).removeClass(function (index, css) {
113         return (css.match(/(\S+)loading/g) || []).join(' ');
114       });
115
116       if ($bg.length) {
117         $bg.css('background-image', 'url(' + $img.attr('src') + ')');
118         $bg.find('> img').remove();
119         $bg.removeAttr('data-lazy');
120       }
121     }
122
123     /**
124      * Randomize slide orders, for ads/products rotation within cached blocks.
125      */
126     function randomize() {
127       t.children().sort(function () {
128         return 0.5 - Math.random();
129       })
130       .each(function () {
131         t.append(this);
132       });
133     }
134
135     /**
136      * Updates arrows visibility based on available options.
137      *
138      * @param {Object} slick
139      *   The slick instance object.
140      *
141      * @return {String}
142      *   The visibility of slick arrows controlled by CSS class visually-hidden.
143      */
144     function setPosition(slick) {
145       var less = slick.slideCount <= o.slidesToShow;
146       var hide = less || o.arrows === false;
147
148       // Be sure the most complex slicks are taken care of as well, e.g.:
149       // asNavFor with the main display containing nested slicks.
150       if (t.attr('id') === slick.$slider.attr('id')) {
151         // Removes padding rules, if no value is provided to allow non-inline.
152         if (!o.centerPadding || o.centerPadding === '0') {
153           slick.$list.css('padding', '');
154         }
155
156         // @todo: Remove temp fix for when total <= slidesToShow at 1.6.1+.
157         // Ensures the fix doesn't break responsive options.
158         // @see https://github.com/kenwheeler/slick/issues/262
159         if (less && slick.$slideTrack.width() <= slick.$slider.width()) {
160           slick.$slideTrack.css({left: '', transform: ''});
161         }
162
163         // Do not remove arrows, to allow responsive have different options.
164         return a[hide ? 'addClass' : 'removeClass']('visually-hidden');
165       }
166     }
167
168     /**
169      * Trigger the media close.
170      */
171     function closeOut() {
172       // Clean up any pause marker at slider container.
173       t.removeClass('is-paused');
174
175       if (t.find('.is-playing').length) {
176         t.find('.is-playing').removeClass('is-playing').find('.media__icon--close').click();
177       }
178     }
179
180     /**
181      * Trigger pause on slick instance when media playing a video.
182      */
183     function pause() {
184       t.addClass('is-paused').slick('slickPause');
185     }
186
187     /**
188      * Declare global options explicitly to copy into responsive settings.
189      *
190      * @param {Object} o
191      *   The slick options object.
192      *
193      * @return {Object}
194      *   The global options common for both main and responsive displays.
195      */
196     function globals(o) {
197       return {
198         slide: o.slide,
199         lazyLoad: o.lazyLoad,
200         dotsClass: o.dotsClass,
201         rtl: o.rtl,
202         appendDots: o.appendDots === '.slick__arrow'
203           ? a : (o.appendDots || $(t)),
204         prevArrow: $('.slick-prev', a),
205         nextArrow: $('.slick-next', a),
206         appendArrows: a,
207         customPaging: function (slick, i) {
208           var tn = slick.$slides.eq(i).find('[data-thumb]') || null;
209           var img = '<img alt="' + Drupal.t(tn.attr('alt')) + '" src="' + tn.data('thumb') + '">';
210           var dotsThumb = tn.length && o.dotsClass.indexOf('thumbnail') > 0 ?
211             '<div class="slick-dots__thumbnail">' + img + '</div>' : '';
212           return slick.defaults.customPaging(slick, i).add(dotsThumb);
213         }
214       };
215     }
216
217     // Build the Slick.
218     beforeSlick();
219     t.slick(globals(o));
220     afterSlick();
221
222     // Destroy Slick if it is an enforced unslick.
223     // This allows Slick lazyload to run, but prevents further complication.
224     // Should use lazyLoaded event, but images are not always there.
225     if (t.hasClass('unslick')) {
226       t.slick('unslick');
227     }
228
229     // Add helper class for arrow visibility as they are outside slider.
230     $(elm).addClass('slick--initialized');
231   }
232
233   /**
234    * Attaches slick behavior to HTML element identified by CSS selector .slick.
235    *
236    * @type {Drupal~behavior}
237    */
238   Drupal.behaviors.slick = {
239     attach: function (context) {
240       $('.slick', context).once('slick').each(doSlick);
241     }
242   };
243
244 })(jQuery, Drupal, drupalSettings);