PageSourceSearch

https://contextxxi.org/plugins-dist/mediabox/lib/lity/lity.js?1788350574

js contextxxi.org collected 2026-09-24 10:09:51 UTC 16,249 bytes, 590 lines download raw bytes

vendor: 16,249 bytes, lines 1-590
1/*! Lity - v3.0.0-dev - 2020-04-26
2* http://sorgalla.com/lity/
3* Copyright (c) 2015-2020 Jan Sorgalla; Licensed MIT */
4(function(window, factory) {
5    if (typeof define === 'function' && define.amd) {
6        define(['jquery'], function($) {
7            return factory(window, $);
8        });
9    } else if (typeof module === 'object' && typeof module.exports === 'object') {
10        module.exports = factory(window, require('jquery'));
11    } else {
12        window.lity = factory(window, window.jQuery || window.Zepto);
13    }
14}(typeof window !== "undefined" ? window : this, function(window, $) {
15    'use strict';
16
17    var document = window.document;
18
19    var _win = $(window);
20    var _deferred = $.Deferred;
21    var _html = $('html');
22    var _instances = [];
23
24    var _attrAriaHidden = 'aria-hidden';
25    var _dataAriaHidden = 'lity-' + _attrAriaHidden;
26
27    var _focusableElementsSelector = 'a[href],area[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),iframe,object,embed,[contenteditable],[tabindex]:not([tabindex^="-"])';
28
29    var _defaultOptions = {
30        esc: true,
31        handler: null,
32        handlers: {
33            image: imageHandler,
34            inline: inlineHandler,
35            iframe: iframeHandler
36        },
37        forceFocusInside: false,
38        template: '<div class="lity" role="dialog" aria-label="Dialog Window (Press escape to close)" tabindex="-1"><div class="lity-wrap" data-lity-close role="document"><div class="lity-loader" aria-hidden="true">Loading...</div><div class="lity-container"><div class="lity-content"></div><button class="lity-close" type="button" aria-label="Close (Press escape to close)" data-lity-close>&times;</button></div></div></div>'
39    };
40
41    var _imageRegexp = /(^data:image\/)|(\.(png|jpe?g|gif|svg|webp|bmp|ico|tiff?)(\?\S*)?$)/i;
42
43    var _transitionEndEvent = (function() {
44        var el = document.createElement('div');
45
46        var transEndEventNames = {
47            WebkitTransition: 'webkitTransitionEnd',
48            MozTransition: 'transitionend',
49            OTransition: 'oTransitionEnd otransitionend',
50            transition: 'transitionend'
51        };
52
53        for (var name in transEndEventNames) {
54            if (el.style[name] !== undefined) {
55                return transEndEventNames[name];
56            }
57        }
58
59        return false;
60    })();
61
62    function transitionEnd(element) {
63        var deferred = _deferred();
64
65        if (!_transitionEndEvent || !element.length) {
66            deferred.resolve();
67        } else {
68            element.one(_transitionEndEvent, deferred.resolve);
69            setTimeout(deferred.resolve, 500);
70        }
71
72        return deferred.promise();
73    }
74
75    function settings(currSettings, key, value) {
76        if (arguments.length === 1) {
77            return $.extend({}, currSettings);
78        }
79
80        if (typeof key === 'string') {
81            if (typeof value === 'undefined') {
82                return typeof currSettings[key] === 'undefined'
83                    ? null
84                    : currSettings[key];
85            }
86
87            currSettings[key] = value;
88        } else {
89            $.extend(currSettings, key);
90        }
91
92        return this;
93    }
94
95    function parseQueryParams(params) {
96        var pos = params.indexOf('?');
97
98        if (pos > -1) {
99            params = params.substr(pos + 1);
100        }
101
102        var pairs = decodeURI(params.split('#')[0]).split('&');
103        var obj = {}, p;
104
105        for (var i = 0, n = pairs.length; i < n; i++) {
106            if (!pairs[i]) {
107                continue;
108            }
109
110            p = pairs[i].split('=');
111            obj[p[0]] = p[1];
112        }
113
114        return obj;
115    }
116
117    function appendQueryParams(url, params) {
118        if (!params) {
119            return url;
120        }
121
122        if ('string' === $.type(params)) {
123            params = parseQueryParams(params);
124        }
125
126        if (url.indexOf('?') > -1) {
127            var split = url.split('?');
128            url = split.shift();
129
130            params = $.extend(
131                {},
132                parseQueryParams(split[0]),
133                params
134            )
135        }
136
137        return url + '?' + $.param(params);
138    }
139
140    function transferHash(originalUrl, newUrl) {
141        var pos = originalUrl.indexOf('#');
142
143        if (-1 === pos) {
144            return newUrl;
145        }
146
147        if (pos > 0) {
148            originalUrl = originalUrl.substr(pos);
149        }
150
151        return newUrl + originalUrl;
152    }
153
154    function iframe(iframeUrl, instance, queryParams, hashUrl) {
155        instance && instance.element().addClass('lity-iframe');
156
157        if (queryParams) {
158            iframeUrl = appendQueryParams(iframeUrl, queryParams);
159        }
160
161        if (hashUrl) {
162            iframeUrl = transferHash(hashUrl, iframeUrl);
163        }
164
165        return '<div class="lity-iframe-container"><iframe frameborder="0" allowfullscreen allow="autoplay; fullscreen" src="' + iframeUrl + '"/></div>';
166    }
167
168    function error(msg) {
169        return $('<span class="lity-error"></span>').append(msg);
170    }
171
172    function imageHandler(target, instance) {
173        var desc = (instance.opener() && instance.opener().data('lity-desc')) || 'Image with no description';
174        var img = $('<img src="' + target + '" alt="' + desc + '"/>');
175        var deferred = _deferred();
176        var failed = function() {
177            deferred.reject(error('Failed loading image'));
178        };
179
180        img
181            .on('load', function() {
182                if (this.naturalWidth === 0) {
183                    return failed();
184                }
185
186                deferred.resolve(img);
187            })
188            .on('error', failed)
189        ;
190
191        return deferred.promise();
192    }
193
194    imageHandler.test = function(target) {
195        return _imageRegexp.test(target);
196    };
197
198    function inlineHandler(target, instance) {
199        var el, placeholder, hasHideClass;
200
201        try {
202            el = $(target);
203        } catch (e) {
204            return false;
205        }
206
207        if (!el.length) {
208            return false;
209        }
210
211        placeholder = $('<i style="display:none !important"></i>');
212        hasHideClass = el.hasClass('lity-hide');
213
214        instance
215            .element()
216            .one('lity:remove', function() {
217                placeholder
218                    .before(el)
219                    .remove()
220                ;
221
222                if (hasHideClass && !el.closest('.lity-content').length) {
223                    el.addClass('lity-hide');
224                }
225            })
226        ;
227
228        return el
229            .removeClass('lity-hide')
230            .after(placeholder)
231        ;
232    }
233
234    function iframeHandler(target, instance) {
235        return iframe(target, instance);
236    }
237
238    function winHeight() {
239        return document.documentElement.clientHeight
240            ? document.documentElement.clientHeight
241            : Math.round(_win.height());
242    }
243
244    function keydown(e) {
245        var current = currentInstance();
246
247        if (!current) {
248            return;
249        }
250
251        // ESC key
252        if (e.keyCode === 27 && !!current.options('esc')) {
253            current.close();
254        }
255
256        // TAB key
257        if (e.keyCode === 9) {
258            handleTabKey(e, current);
259        }
260    }
261
262    function handleTabKey(e, instance) {
263        var focusableElements = instance.element().find(_focusableElementsSelector);
264        var focusedIndex = focusableElements.index(document.activeElement);
265
266        if (e.shiftKey && focusedIndex <= 0) {
267            focusableElements.get(focusableElements.length - 1).focus();
268            e.preventDefault();
269        } else if (!e.shiftKey && focusedIndex === focusableElements.length - 1) {
270            focusableElements.get(0).focus();
271            e.preventDefault();
272        }
273        if (focusedIndex === -1 && instance.options().forceFocusInside) {
274            focusableElements.get(0).focus();
275            e.preventDefault();
276        }
277    }
278
279    function resize() {
280        $.each(_instances, function(i, instance) {
281            instance.resize();
282        });
283    }
284
285    function registerInstance(instanceToRegister) {
286        if (1 === _instances.unshift(instanceToRegister)) {
287            _html.addClass('lity-active');
288
289            _win
290                .on({
291                    resize: resize,
292                    keydown: keydown
293                })
294            ;
295        }
296
297        $('body > *').not(instanceToRegister.element())
298            .addClass('lity-hidden')
299            .each(function() {
300                var el = $(this);
301
302                if (undefined !== el.data(_dataAriaHidden)) {
303                    return;
304                }
305
306                el.data(_dataAriaHidden, el.attr(_attrAriaHidden) || null);
307            })
308            .attr(_attrAriaHidden, 'true')
309        ;
310    }
311
312    function removeInstance(instanceToRemove) {
313        var show;
314
315        instanceToRemove
316            .element()
317            .attr(_attrAriaHidden, 'true')
318        ;
319
320        if (1 === _instances.length) {
321            _html.removeClass('lity-active');
322
323            _win
324                .off({
325                    resize: resize,
326                    keydown: keydown
327                })
328            ;
329        }
330
331        _instances = $.grep(_instances, function(instance) {
332            return instanceToRemove !== instance;
333        });
334
335        if (!!_instances.length) {
336            show = _instances[0].element();
337        } else {
338            show = $('.lity-hidden');
339        }
340
341        show
342            .removeClass('lity-hidden')
343            .each(function() {
344                var el = $(this), oldAttr = el.data(_dataAriaHidden);
345
346                if (!oldAttr) {
347                    el.removeAttr(_attrAriaHidden);
348                } else {
349                    el.attr(_attrAriaHidden, oldAttr);
350                }
351
352                el.removeData(_dataAriaHidden);
353            })
354        ;
355    }
356
357    function currentInstance() {
358        if (0 === _instances.length) {
359            return null;
360        }
361
362        return _instances[0];
363    }
364
365    function factory(target, instance, handlers, preferredHandler) {
366        var handler = 'inline', content;
367
368        var currentHandlers = $.extend({}, handlers);
369
370        if (preferredHandler && currentHandlers[preferredHandler]) {
371            content = currentHandlers[preferredHandler](target, instance);
372            handler = preferredHandler;
373        } else {
374            // Run inline and iframe handlers after all other handlers
375            $.each(['inline', 'iframe'], function(i, name) {
376                delete currentHandlers[name];
377
378                currentHandlers[name] = handlers[name];
379            });
380
381            $.each(currentHandlers, function(name, currentHandler) {
382                // Handler might be "removed" by setting callback to null
383                if (!currentHandler) {
384                    return true;
385                }
386
387                if (
388                    currentHandler.test &&
389                    !currentHandler.test(target, instance)
390                ) {
391                    return true;
392                }
393
394                content = currentHandler(target, instance);
395
396                if (false !== content) {
397                    handler = name;
398                    return false;
399                }
400            });
401        }
402
403        return {handler: handler, content: content || ''};
404    }
405
406    function Lity(target, options, opener, activeElement) {
407        var self = this;
408        var result;
409        var isReady = false;
410        var isClosed = false;
411        var element;
412        var content;
413
414        options = $.extend(
415            {},
416            _defaultOptions,
417            options
418        );
419
420        element = $(options.template);
421
422        // -- API --
423
424        self.element = function() {
425            return element;
426        };
427
428        self.opener = function() {
429            return opener;
430        };
431
432        self.content = function() {
433            return content;
434        };
435
436        self.options  = $.proxy(settings, self, options);
437        self.handlers = $.proxy(settings, self, options.handlers);
438
439        self.resize = function() {
440            if (!isReady || isClosed) {
441                return;
442            }
443
444            content
445                .css('max-height', winHeight() + 'px')
446                .trigger('lity:resize', [self])
447            ;
448        };
449
450        self.close = function() {
451            if (isClosed) {
452                return;
453            }
454
455            isClosed = true;
456
457            removeInstance(self);
458
459            var deferred = _deferred();
460
461            // We return focus only if the current focus is inside this instance
462            if (
463                activeElement &&
464                (
465                    document.activeElement === element[0] ||
466                    $.contains(element[0], document.activeElement)
467                )
468            ) {
469                try {
470                    activeElement.focus();
471                } catch (e) {
472                    // Ignore exceptions, eg. for SVG elements which can't be
473                    // focused in IE11
474                }
475            }
476
477            var trigerable = (content ? content : element);
478            trigerable.trigger('lity:close', [self]);
479
480            element
481                .removeClass('lity-opened')
482                .addClass('lity-closed')
483            ;
484
485            transitionEnd(trigerable.add(element))
486                .always(function() {
487                    trigerable.trigger('lity:remove', [self]);
488                    element.remove();
489                    element = undefined;
490                    deferred.resolve();
491                })
492            ;
493
494            return deferred.promise();
495        };
496
497        // -- Initialization --
498
499        result = factory(target, self, options.handlers, options.handler);
500
501        element
502            .attr(_attrAriaHidden, 'false')
503            .addClass('lity-loading lity-opened lity-' + result.handler)
504            .appendTo('body')
505            .focus()
506            .on('click', '[data-lity-close]', function(e) {
507                if ($(e.target).is('[data-lity-close]')) {
508                    self.close();
509                }
510            })
511            .trigger('lity:open', [self])
512        ;
513
514        registerInstance(self);
515
516        $.when(result.content)
517            .always(ready)
518        ;
519
520        function ready(result) {
521            if (isClosed) {
522                return;
523            }
524            content = $(result)
525                .css('max-height', winHeight() + 'px')
526            ;
527
528            element
529                .find('.lity-loader')
530                .each(function() {
531                    var loader = $(this);
532
533                    transitionEnd(loader)
534                        .always(function() {
535                            loader.remove();
536                        })
537                    ;
538                })
539            ;
540
541            element
542                .removeClass('lity-loading')
543                .find('.lity-content')
544                .empty()
545                .append(content)
546            ;
547
548            isReady = true;
549
550            content
551                .trigger('lity:ready', [self])
552            ;
553        }
554    }
555
556    function lity(target, options, opener) {
557        if (!target.preventDefault) {
558            opener = $(opener);
559        } else {
560            target.preventDefault();
561            opener = $(this);
562            target = opener.data('lity-target') || opener.attr('href') || opener.attr('src');
563        }
564
565        var instance = new Lity(
566            target,
567            $.extend(
568                {},
569                opener.data('lity-options') || opener.data('lity'),
570                options
571            ),
572            opener,
573            document.activeElement
574        );
575
576        if (!target.preventDefault) {
577            return instance;
578        }
579    }
580
581    lity.version  = '3.0.0-dev';
582    lity.options  = $.proxy(settings, lity, _defaultOptions);
583    lity.handlers = $.proxy(settings, lity, _defaultOptions.handlers);
584    lity.current  = currentInstance;
585    lity.iframe   = iframe;
586
587    $(document).on('click.lity', '[data-lity]', lity);
588
589    return lity;
590}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.