2d9836f7ae25771b101229457d4cc3f857865091
[yaffs-website] / web / modules / contrib / blazy / js / blazy.load.js
1 /**
2  * @file
3  * Provides bLazy loader.
4  */
5
6 (function (Drupal, drupalSettings, _db, window, document) {
7
8   'use strict';
9
10   /**
11    * Blazy public methods.
12    *
13    * @namespace
14    */
15   Drupal.blazy = Drupal.blazy || {
16     init: null,
17     windowWidth: 0,
18     done: false,
19     globals: function () {
20       var me = this;
21       var settings = drupalSettings.blazy || {};
22       var commons = {
23         success: me.clearing,
24         error: me.clearing
25       };
26
27       return _db.extend(settings, commons);
28     },
29
30     clearing: function (el) {
31       // The .b-lazy element can be attached to IMG, or DIV as CSS background.
32       el.className = el.className.replace(/(\S+)loading/, '');
33
34       // The .is-loading can be .grid, .slide__content, .box__content, etc.
35       var loaders = [
36         _db.closest(el, '.is-loading'),
37         _db.closest(el, '[class*="loading"]')
38       ];
39
40       // Also cleans up closest containers containing loading class.
41       _db.forEach(loaders, function (wrapEl) {
42         if (wrapEl !== null) {
43           wrapEl.className = wrapEl.className.replace(/(\S+)loading/, '');
44         }
45       });
46     }
47   };
48
49   /**
50    * Blazy utility functions.
51    *
52    * @param {HTMLElement} elm
53    *   The Blazy HTML element.
54    */
55   function doBlazy(elm) {
56     var me = Drupal.blazy;
57     var dataAttr = elm.getAttribute('data-blazy');
58     var empty = dataAttr === '' || dataAttr === '[]';
59     var data = empty ? false : _db.parse(dataAttr);
60     var opts = !data ? me.globals() : _db.extend({}, me.globals(), data);
61     var ratios = elm.querySelectorAll('[data-dimensions]');
62     var loopRatio = ratios.length > 0;
63
64     /**
65      * Updates the dynamic multi-breakpoint aspect ratio.
66      *
67      * This only applies to multi-serving images with aspect ratio fluid if
68      * each element contains [data-dimensions] attribute.
69      * Static single aspect ratio, e.g. `media--ratio--169`, will be ignored,
70      * and will use CSS instead.
71      *
72      * @param {HTMLElement} el
73      *   The .media--ratio HTML element.
74      */
75     function updateRatio(el) {
76       var dimensions = !el.getAttribute('data-dimensions') ? false : _db.parse(el.getAttribute('data-dimensions'));
77
78       if (!dimensions) {
79         return;
80       }
81
82       var keys = Object.keys(dimensions);
83       var xs = keys[0];
84       var xl = keys[keys.length - 1];
85       var mw = function (w) {
86         return w >= me.windowWidth;
87       };
88       var pad = keys.filter(mw).map(function (v) {
89         return dimensions[v];
90       }).shift();
91
92       if (pad === 'undefined') {
93         pad = dimensions[me.windowWidth >= xl ? xl : xs];
94       }
95
96       if (pad !== 'undefined') {
97         el.style.paddingBottom = pad + '%';
98       }
99     }
100
101     // Initializes Blazy instance.
102     me.init = new Blazy(opts);
103
104     // Reacts on resizing.
105     if (!me.done) {
106       _db.resize(function () {
107         me.windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
108
109         if (loopRatio) {
110           _db.forEach(ratios, updateRatio, elm);
111         }
112
113         // Dispatch resizing event.
114         _db.trigger(elm, 'resizing', {windowWidth: me.windowWidth});
115       })();
116
117       me.done = true;
118     }
119
120     elm.className += ' blazy--on';
121   }
122
123   /**
124    * Attaches blazy behavior to HTML element identified by [data-blazy].
125    *
126    * @type {Drupal~behavior}
127    */
128   Drupal.behaviors.blazy = {
129     attach: function (context) {
130       var me = Drupal.blazy;
131       var el = context.querySelector('[data-blazy]');
132
133       // Runs basic Blazy if no [data-blazy] found, probably a single image.
134       // Cannot use .contains(), as IE11 doesn't support method 'contains'.
135       if (el === null) {
136         me.init = new Blazy(me.globals());
137         return;
138       }
139
140       // Runs Blazy with multi-serving images, and aspect ratio supports.
141       var blazies = context.querySelectorAll('.blazy:not(.blazy--on)');
142       _db.once(_db.forEach(blazies, doBlazy));
143     }
144   };
145
146 }(Drupal, drupalSettings, dBlazy, this, this.document));