123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- /*! Lity - v2.4.0 - 2019-08-10
- * http://sorgalla.com/lity/
- * Copyright (c) 2015-2019 Jan Sorgalla; Licensed MIT */
- (function(window, factory) {
- if (typeof define === 'function' && define.amd) {
- define(['jquery'], function($) {
- return factory(window, $);
- });
- } else if (typeof module === 'object' && typeof module.exports === 'object') {
- module.exports = factory(window, require('jquery'));
- } else {
- window.lity = factory(window, window.jQuery || window.Zepto);
- }
- }(typeof window !== "undefined" ? window : this, function(window, $) {
- 'use strict';
- var document = window.document;
- var _win = $(window);
- var _deferred = $.Deferred;
- var _html = $('html');
- var _instances = [];
- var _attrAriaHidden = 'aria-hidden';
- var _dataAriaHidden = 'lity-' + _attrAriaHidden;
- 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^="-"])';
- var _defaultOptions = {
- esc: true,
- handler: null,
- handlers: {
- image: imageHandler,
- inline: inlineHandler,
- youtube: youtubeHandler,
- vimeo: vimeoHandler,
- googlemaps: googlemapsHandler,
- facebookvideo: facebookvideoHandler,
- iframe: iframeHandler
- },
- 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>×</button></div></div></div>'
- };
- var _imageRegexp = /(^data:image\/)|(\.(png|jpe?g|gif|svg|webp|bmp|ico|tiff?)(\?\S*)?$)/i;
- var _youtubeRegex = /(youtube(-nocookie)?\.com|youtu\.be)\/(watch\?v=|v\/|u\/|embed\/?)?([\w-]{11})(.*)?/i;
- var _vimeoRegex = /(vimeo(pro)?.com)\/(?:[^\d]+)?(\d+)\??(.*)?$/;
- var _googlemapsRegex = /((maps|www)\.)?google\.([^\/\?]+)\/?((maps\/?)?\?)(.*)/i;
- var _facebookvideoRegex = /(facebook\.com)\/([a-z0-9_-]*)\/videos\/([0-9]*)(.*)?$/i;
- var _transitionEndEvent = (function() {
- var el = document.createElement('div');
- var transEndEventNames = {
- WebkitTransition: 'webkitTransitionEnd',
- MozTransition: 'transitionend',
- OTransition: 'oTransitionEnd otransitionend',
- transition: 'transitionend'
- };
- for (var name in transEndEventNames) {
- if (el.style[name] !== undefined) {
- return transEndEventNames[name];
- }
- }
- return false;
- })();
- function transitionEnd(element) {
- var deferred = _deferred();
- if (!_transitionEndEvent || !element.length) {
- deferred.resolve();
- } else {
- element.one(_transitionEndEvent, deferred.resolve);
- setTimeout(deferred.resolve, 500);
- }
- return deferred.promise();
- }
- function settings(currSettings, key, value) {
- if (arguments.length === 1) {
- return $.extend({}, currSettings);
- }
- if (typeof key === 'string') {
- if (typeof value === 'undefined') {
- return typeof currSettings[key] === 'undefined'
- ? null
- : currSettings[key];
- }
- currSettings[key] = value;
- } else {
- $.extend(currSettings, key);
- }
- return this;
- }
- function parseQueryParams(params) {
- var pairs = decodeURI(params.split('#')[0]).split('&');
- var obj = {}, p;
- for (var i = 0, n = pairs.length; i < n; i++) {
- if (!pairs[i]) {
- continue;
- }
- p = pairs[i].split('=');
- obj[p[0]] = p[1];
- }
- return obj;
- }
- function appendQueryParams(url, params) {
- return url + (url.indexOf('?') > -1 ? '&' : '?') + $.param(params);
- }
- function transferHash(originalUrl, newUrl) {
- var pos = originalUrl.indexOf('#');
- if (-1 === pos) {
- return newUrl;
- }
- if (pos > 0) {
- originalUrl = originalUrl.substr(pos);
- }
- return newUrl + originalUrl;
- }
- function error(msg) {
- return $('<span class="lity-error"/>').append(msg);
- }
- function imageHandler(target, instance) {
- var desc = (instance.opener() && instance.opener().data('lity-desc')) || 'Image with no description';
- var img = $('<img src="' + target + '" alt="' + desc + '"/>');
- var deferred = _deferred();
- var failed = function() {
- deferred.reject(error('Failed loading image'));
- };
- img
- .on('load', function() {
- if (this.naturalWidth === 0) {
- return failed();
- }
- deferred.resolve(img);
- })
- .on('error', failed)
- ;
- return deferred.promise();
- }
- imageHandler.test = function(target) {
- return _imageRegexp.test(target);
- };
- function inlineHandler(target, instance) {
- var el, placeholder, hasHideClass;
- try {
- el = $(target);
- } catch (e) {
- return false;
- }
- if (!el.length) {
- return false;
- }
- placeholder = $('<i style="display:none !important"/>');
- hasHideClass = el.hasClass('lity-hide');
- instance
- .element()
- .one('lity:remove', function() {
- placeholder
- .before(el)
- .remove()
- ;
- if (hasHideClass && !el.closest('.lity-content').length) {
- el.addClass('lity-hide');
- }
- })
- ;
- return el
- .removeClass('lity-hide')
- .after(placeholder)
- ;
- }
- function youtubeHandler(target) {
- var matches = _youtubeRegex.exec(target);
- if (!matches) {
- return false;
- }
- return iframeHandler(
- transferHash(
- target,
- appendQueryParams(
- 'https://www.youtube' + (matches[2] || '') + '.com/embed/' + matches[4],
- $.extend(
- {
- autoplay: 1
- },
- parseQueryParams(matches[5] || '')
- )
- )
- )
- );
- }
- function vimeoHandler(target) {
- var matches = _vimeoRegex.exec(target);
- if (!matches) {
- return false;
- }
- return iframeHandler(
- transferHash(
- target,
- appendQueryParams(
- 'https://player.vimeo.com/video/' + matches[3],
- $.extend(
- {
- autoplay: 1
- },
- parseQueryParams(matches[4] || '')
- )
- )
- )
- );
- }
- function facebookvideoHandler(target) {
- var matches = _facebookvideoRegex.exec(target);
- if (!matches) {
- return false;
- }
- if (0 !== target.indexOf('http')) {
- target = 'https:' + target;
- }
- return iframeHandler(
- transferHash(
- target,
- appendQueryParams(
- 'https://www.facebook.com/plugins/video.php?href=' + target,
- $.extend(
- {
- autoplay: 1
- },
- parseQueryParams(matches[4] || '')
- )
- )
- )
- );
- }
- function googlemapsHandler(target) {
- var matches = _googlemapsRegex.exec(target);
- if (!matches) {
- return false;
- }
- return iframeHandler(
- transferHash(
- target,
- appendQueryParams(
- 'https://www.google.' + matches[3] + '/maps?' + matches[6],
- {
- output: matches[6].indexOf('layer=c') > 0 ? 'svembed' : 'embed'
- }
- )
- )
- );
- }
- function iframeHandler(target) {
- return '<div class="lity-iframe-container"><iframe frameborder="0" allowfullscreen allow="autoplay; fullscreen" src="' + target + '"/></div>';
- }
- function winHeight() {
- return document.documentElement.clientHeight
- ? document.documentElement.clientHeight
- : Math.round(_win.height());
- }
- function keydown(e) {
- var current = currentInstance();
- if (!current) {
- return;
- }
- // ESC key
- if (e.keyCode === 27 && !!current.options('esc')) {
- current.close();
- }
- // TAB key
- if (e.keyCode === 9) {
- handleTabKey(e, current);
- }
- }
- function handleTabKey(e, instance) {
- var focusableElements = instance.element().find(_focusableElementsSelector);
- var focusedIndex = focusableElements.index(document.activeElement);
- if (e.shiftKey && focusedIndex <= 0) {
- focusableElements.get(focusableElements.length - 1).focus();
- e.preventDefault();
- } else if (!e.shiftKey && focusedIndex === focusableElements.length - 1) {
- focusableElements.get(0).focus();
- e.preventDefault();
- }
- }
- function resize() {
- $.each(_instances, function(i, instance) {
- instance.resize();
- });
- }
- function registerInstance(instanceToRegister) {
- if (1 === _instances.unshift(instanceToRegister)) {
- _html.addClass('lity-active');
- _win
- .on({
- resize: resize,
- keydown: keydown
- })
- ;
- }
- $('body > *').not(instanceToRegister.element())
- .addClass('lity-hidden')
- .each(function() {
- var el = $(this);
- if (undefined !== el.data(_dataAriaHidden)) {
- return;
- }
- el.data(_dataAriaHidden, el.attr(_attrAriaHidden) || null);
- })
- .attr(_attrAriaHidden, 'true')
- ;
- }
- function removeInstance(instanceToRemove) {
- var show;
- instanceToRemove
- .element()
- .attr(_attrAriaHidden, 'true')
- ;
- if (1 === _instances.length) {
- _html.removeClass('lity-active');
- _win
- .off({
- resize: resize,
- keydown: keydown
- })
- ;
- }
- _instances = $.grep(_instances, function(instance) {
- return instanceToRemove !== instance;
- });
- if (!!_instances.length) {
- show = _instances[0].element();
- } else {
- show = $('.lity-hidden');
- }
- show
- .removeClass('lity-hidden')
- .each(function() {
- var el = $(this), oldAttr = el.data(_dataAriaHidden);
- if (!oldAttr) {
- el.removeAttr(_attrAriaHidden);
- } else {
- el.attr(_attrAriaHidden, oldAttr);
- }
- el.removeData(_dataAriaHidden);
- })
- ;
- }
- function currentInstance() {
- if (0 === _instances.length) {
- return null;
- }
- return _instances[0];
- }
- function factory(target, instance, handlers, preferredHandler) {
- var handler = 'inline', content;
- var currentHandlers = $.extend({}, handlers);
- if (preferredHandler && currentHandlers[preferredHandler]) {
- content = currentHandlers[preferredHandler](target, instance);
- handler = preferredHandler;
- } else {
- // Run inline and iframe handlers after all other handlers
- $.each(['inline', 'iframe'], function(i, name) {
- delete currentHandlers[name];
- currentHandlers[name] = handlers[name];
- });
- $.each(currentHandlers, function(name, currentHandler) {
- // Handler might be "removed" by setting callback to null
- if (!currentHandler) {
- return true;
- }
- if (
- currentHandler.test &&
- !currentHandler.test(target, instance)
- ) {
- return true;
- }
- content = currentHandler(target, instance);
- if (false !== content) {
- handler = name;
- return false;
- }
- });
- }
- return {handler: handler, content: content || ''};
- }
- function Lity(target, options, opener, activeElement) {
- var self = this;
- var result;
- var isReady = false;
- var isClosed = false;
- var element;
- var content;
- options = $.extend(
- {},
- _defaultOptions,
- options
- );
- element = $(options.template);
- // -- API --
- self.element = function() {
- return element;
- };
- self.opener = function() {
- return opener;
- };
- self.options = $.proxy(settings, self, options);
- self.handlers = $.proxy(settings, self, options.handlers);
- self.resize = function() {
- if (!isReady || isClosed) {
- return;
- }
- content
- .css('max-height', winHeight() + 'px')
- .trigger('lity:resize', [self])
- ;
- };
- self.close = function() {
- if (!isReady || isClosed) {
- return;
- }
- isClosed = true;
- removeInstance(self);
- var deferred = _deferred();
- // We return focus only if the current focus is inside this instance
- if (
- activeElement &&
- (
- document.activeElement === element[0] ||
- $.contains(element[0], document.activeElement)
- )
- ) {
- try {
- activeElement.focus();
- } catch (e) {
- // Ignore exceptions, eg. for SVG elements which can't be
- // focused in IE11
- }
- }
- content.trigger('lity:close', [self]);
- element
- .removeClass('lity-opened')
- .addClass('lity-closed')
- ;
- transitionEnd(content.add(element))
- .always(function() {
- content.trigger('lity:remove', [self]);
- element.remove();
- element = undefined;
- deferred.resolve();
- })
- ;
- return deferred.promise();
- };
- // -- Initialization --
- result = factory(target, self, options.handlers, options.handler);
- element
- .attr(_attrAriaHidden, 'false')
- .addClass('lity-loading lity-opened lity-' + result.handler)
- .appendTo('body')
- .focus()
- .on('click', '[data-lity-close]', function(e) {
- if ($(e.target).is('[data-lity-close]')) {
- self.close();
- }
- })
- .trigger('lity:open', [self])
- ;
- registerInstance(self);
- $.when(result.content)
- .always(ready)
- ;
- function ready(result) {
- content = $(result)
- .css('max-height', winHeight() + 'px')
- ;
- element
- .find('.lity-loader')
- .each(function() {
- var loader = $(this);
- transitionEnd(loader)
- .always(function() {
- loader.remove();
- })
- ;
- })
- ;
- element
- .removeClass('lity-loading')
- .find('.lity-content')
- .empty()
- .append(content)
- ;
- isReady = true;
- content
- .trigger('lity:ready', [self])
- ;
- }
- }
- function lity(target, options, opener) {
- if (!target.preventDefault) {
- opener = $(opener);
- } else {
- target.preventDefault();
- opener = $(this);
- target = opener.data('lity-target') || opener.attr('href') || opener.attr('src');
- }
- var instance = new Lity(
- target,
- $.extend(
- {},
- opener.data('lity-options') || opener.data('lity'),
- options
- ),
- opener,
- document.activeElement
- );
- if (!target.preventDefault) {
- return instance;
- }
- }
- lity.version = '2.4.0';
- lity.options = $.proxy(settings, lity, _defaultOptions);
- lity.handlers = $.proxy(settings, lity, _defaultOptions.handlers);
- lity.current = currentInstance;
- $(document).on('click.lity', '[data-lity]', lity);
- return lity;
- }));
|