3 * Provides Slick loader.
6 (function ($, Drupal, drupalSettings) {
11 * Slick utility functions.
14 * The index of the current element.
15 * @param {HTMLElement} elm
16 * The slick HTML element.
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;
25 // Populate defaults + globals into each breakpoint.
28 if (r.hasOwnProperty(b) && r[b].settings !== 'unslick') {
29 r[b].settings = $.extend({}, drupalSettings.slick, globals(o), r[b].settings);
34 // Update the slick settings object.
39 * The event must be bound prior to slick being called.
41 function beforeSlick() {
42 if (o.randomize && !t.hasClass('slick-initiliazed')) {
46 t.on('setPosition.sl', function (e, slick) {
50 $('.media--loading', t).closest('.slide__content').addClass('is-loading');
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);
59 // Enforces lazyload ahead to smoothen the UX.
60 Drupal.blazy.init.load($src);
67 * The event must be bound after slick being called.
69 function afterSlick() {
70 var slick = t.slick('getSlick');
71 var media = t.find('.media--player').length;
74 t.parent().on('click.sl', '.slick-down', function (e) {
77 $('html, body').stop().animate({
78 scrollTop: $(b.data('target')).offset().top - (b.data('offset') || 0)
79 }, 800, o.easing || 'swing');
83 t.on('mousewheel.sl', function (e, delta) {
85 return t.slick(delta < 0 ? 'slickNext' : 'slickPrev');
89 t.on('lazyLoaded lazyLoadError', function (e, slick, img) {
93 // Turns off any video if any change to the slider.
95 t.on('afterChange.sl', closeOut);
96 t.on('click.sl', '.media__icon--close', closeOut);
97 t.on('click.sl', '.media__icon--play', pause);
102 * Turns images into CSS background if so configured.
104 * @param {HTMLElement} img
105 * The image HTML element.
107 function setBackground(img) {
109 var $bg = $img.closest('.media--background');
110 var p = $img.closest('.slide') || $img.closest('.unslick');
112 $img.parentsUntil(p).removeClass(function (index, css) {
113 return (css.match(/(\S+)loading/g) || []).join(' ');
117 $bg.css('background-image', 'url(' + $img.attr('src') + ')');
118 $bg.find('> img').remove();
119 $bg.removeAttr('data-lazy');
124 * Randomize slide orders, for ads/products rotation within cached blocks.
126 function randomize() {
127 t.children().sort(function () {
128 return 0.5 - Math.random();
136 * Updates arrows visibility based on available options.
138 * @param {Object} slick
139 * The slick instance object.
142 * The visibility of slick arrows controlled by CSS class visually-hidden.
144 function setPosition(slick) {
145 var less = slick.slideCount <= o.slidesToShow;
146 var hide = less || o.arrows === false;
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', '');
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: ''});
163 // Do not remove arrows, to allow responsive have different options.
164 return a[hide ? 'addClass' : 'removeClass']('visually-hidden');
169 * Trigger the media close.
171 function closeOut() {
172 // Clean up any pause marker at slider container.
173 t.removeClass('is-paused');
175 if (t.find('.is-playing').length) {
176 t.find('.is-playing').removeClass('is-playing').find('.media__icon--close').click();
181 * Trigger pause on slick instance when media playing a video.
184 t.addClass('is-paused').slick('slickPause');
188 * Declare global options explicitly to copy into responsive settings.
191 * The slick options object.
194 * The global options common for both main and responsive displays.
196 function globals(o) {
199 lazyLoad: o.lazyLoad,
200 dotsClass: o.dotsClass,
202 appendDots: o.appendDots === '.slick__arrow'
203 ? a : (o.appendDots || $(t)),
204 prevArrow: $('.slick-prev', a),
205 nextArrow: $('.slick-next', 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);
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')) {
229 // Add helper class for arrow visibility as they are outside slider.
230 $(elm).addClass('slick--initialized');
234 * Attaches slick behavior to HTML element identified by CSS selector .slick.
236 * @type {Drupal~behavior}
238 Drupal.behaviors.slick = {
239 attach: function (context) {
240 $('.slick', context).once('slick').each(doSlick);
244 })(jQuery, Drupal, drupalSettings);