Вход Регистрация
Файл: sngine-v2.8/Documentation/assets/plugins/lightbox/ekko-lightbox.js
Строк: 788
<?php
const Lightbox = (($) => {

    const 
NAME 'ekkoLightbox'
    
const JQUERY_NO_CONFLICT = $.fn[NAME]

    const Default = {
        
title'',
        
footer'',
        
maxWidth9999,
        
maxHeight9999,
        
showArrowstrue//display the left / right arrows or not
        
wrappingtrue//if true, gallery loops infinitely
        
typenull//force the lightbox into image / youtube mode. if null, or not image|youtube|vimeo; detect it
        
alwaysShowClosefalse//always show the close button, even if there is no title
        
loadingMessage'<div class="ekko-lightbox-loader"><div><div></div><div></div></div></div>'// http://tobiasahlin.com/spinkit/
        
leftArrow'<span>&#10094;</span>',
        
rightArrow'<span>&#10095;</span>',
        
strings: {
            
close'Close',
            
fail'Failed to load image:',
            
type'Could not detect remote target type. Force the type using data-type',
        },
        
docdocument// if in an iframe can specify top.document
        
onShow() {},
        
onShown() {},
        
onHide() {},
        
onHidden() {},
        
onNavigate() {},
        
onContentLoaded() {}
    }

    class 
Lightbox {

        
/**

        Class properties:

         _$element: null -> the <a> element currently being displayed
         _$modal: The bootstrap modal generated
            _$modalDialog: The .modal-dialog
            _$modalContent: The .modal-content
            _$modalBody: The .modal-body
            _$modalHeader: The .modal-header
            _$modalFooter: The .modal-footer
         _$lightboxContainerOne: Container of the first lightbox element
         _$lightboxContainerTwo: Container of the second lightbox element
         _$lightboxBody: First element in the container
         _$modalArrows: The overlayed arrows container

         _$galleryItems: Other <a>'s available for this gallery
         _galleryName: Name of the current data('gallery') showing
         _galleryIndex: The current index of the _$galleryItems being shown

         _config: {} the options for the modal
         _modalId: unique id for the current lightbox
         _padding / _border: CSS properties for the modal container; these are used to calculate the available space for the content

         */

        
static get Default() {
            return Default
        }

        
constructor($elementconfig) {
            
this._config = $.extend({}, Default, config)
            
this._$modalArrows null
            this
._galleryIndex 0
            this
._galleryName null
            this
._padding null
            this
._border null
            this
._titleIsShown false
            this
._footerIsShown false
            this
._wantedWidth 0
            this
._wantedHeight 0
            this
._touchstartX 0
            this
._touchendX 0

            this
._modalId = `ekkoLightbox-${Math.floor((Math.random() * 1000) + 1)}`;
            
this._$element $element instanceof jQuery $element : $($element)

            
this._isBootstrap3 = $.fn.modal.Constructor.VERSION[0] == 3;

            
let h4 = `<h4 class="modal-title">${this._config.title || "&nbsp;"}</h4>`;
            
let btn = `<button type="button" class="close" data-dismiss="modal" aria-label="${this._config.strings.close}"><span aria-hidden="true">&times;</span></button>`;

            
let header = `<div class="modal-header${this._config.title || this._config.alwaysShowClose '' ' hide'}">`+(this._isBootstrap3 btn+h4 h4+btn)+`</div>`;
            
let footer = `<div class="modal-footer${this._config.footer '' ' hide'}">${this._config.footer || "&nbsp;"}</div>`;
            
let body '<div class="modal-body"><div class="ekko-lightbox-container"><div class="ekko-lightbox-item fade in show"></div><div class="ekko-lightbox-item fade"></div></div></div>'
            
let dialog = `<div class="modal-dialog" role="document"><div class="modal-content">${header}${body}${footer}</div></div>`
            $(
this._config.doc.body).append(`<div id="${this._modalId}" class="ekko-lightbox modal fade" tabindex="-1" tabindex="-1" role="dialog" aria-hidden="true">${dialog}</div>`)

            
this._$modal = $(`#${this._modalId}`, this._config.doc)
            
this._$modalDialog this._$modal.find('.modal-dialog').first()
            
this._$modalContent this._$modal.find('.modal-content').first()
            
this._$modalBody this._$modal.find('.modal-body').first()
            
this._$modalHeader this._$modal.find('.modal-header').first()
            
this._$modalFooter this._$modal.find('.modal-footer').first()

            
this._$lightboxContainer this._$modalBody.find('.ekko-lightbox-container').first()
            
this._$lightboxBodyOne this._$lightboxContainer.find('> div:first-child').first()
            
this._$lightboxBodyTwo this._$lightboxContainer.find('> div:last-child').first()

            
this._border this._calculateBorders()
            
this._padding this._calculatePadding()

            
this._galleryName this._$element.data('gallery')
            if (
this._galleryName) {
                
this._$galleryItems = $(document.body).find(`*[data-gallery="${this._galleryName}"]`)
                
this._galleryIndex this._$galleryItems.index(this._$element)
                $(
document).on('keydown.ekkoLightbox'this._navigationalBinder.bind(this))

                
// add the directional arrows to the modal
                
if (this._config.showArrows && this._$galleryItems.length 1) {
                    
this._$lightboxContainer.append(`<div class="ekko-lightbox-nav-overlay"><a href="#">${this._config.leftArrow}</a><a href="#">${this._config.rightArrow}</a></div>`)
                    
this._$modalArrows this._$lightboxContainer.find('div.ekko-lightbox-nav-overlay').first()
                    
this._$lightboxContainer.on('click''a:first-child'event => {
                        
event.preventDefault()
                        return 
this.navigateLeft()
                    })
                    
this._$lightboxContainer.on('click''a:last-child'event => {
                        
event.preventDefault()
                        return 
this.navigateRight()
                    })
                    
this.updateNavigation()
                }
            }

            
this._$modal
            
.on('show.bs.modal'this._config.onShow.bind(this))
            .
on('shown.bs.modal', () => {
                
this._toggleLoading(true)
                
this._handle()
                return 
this._config.onShown.call(this)
            })
            .
on('hide.bs.modal'this._config.onHide.bind(this))
            .
on('hidden.bs.modal', () => {
                if (
this._galleryName) {
                    $(
document).off('keydown.ekkoLightbox')
                    $(
window).off('resize.ekkoLightbox')
                }
                
this._$modal.remove()
                return 
this._config.onHidden.call(this)
            })
            .
modal(this._config)

            $(
window).on('resize.ekkoLightbox', () => {
                
this._resize(this._wantedWidththis._wantedHeight)
            })
            
this._$lightboxContainer
            
.on('touchstart', () => {
                
this._touchstartX event.changedTouches[0].screenX;

            })
            .
on('touchend', () => {
                
this._touchendX event.changedTouches[0].screenX;
                
this._swipeGesure();
            })
        }

        
element() {
            return 
this._$element;
        }

        
modal() {
            return 
this._$modal;
        }

        
navigateTo(index) {

            if (
index || index this._$galleryItems.length-1)
                return 
this

            this
._galleryIndex index

            this
.updateNavigation()

            
this._$element = $(this._$galleryItems.get(this._galleryIndex))
            
this._handle();
        }

        
navigateLeft() {

            if(!
this._$galleryItems)
                return;

            if (
this._$galleryItems.length === 1)
                return

            if (
this._galleryIndex === 0) {
                if (
this._config.wrapping)
                    
this._galleryIndex this._$galleryItems.length 1
                
else
                    return
            }
            else 
//circular
                
this._galleryIndex--

            
this._config.onNavigate.call(this'left'this._galleryIndex)
            return 
this.navigateTo(this._galleryIndex)
        }

        
navigateRight() {

            if(!
this._$galleryItems)
                return;

            if (
this._$galleryItems.length === 1)
                return

            if (
this._galleryIndex === this._$galleryItems.length 1) {
                if (
this._config.wrapping)
                    
this._galleryIndex 0
                
else
                    return
            }
            else 
//circular
                
this._galleryIndex++

            
this._config.onNavigate.call(this'right'this._galleryIndex)
            return 
this.navigateTo(this._galleryIndex)
        }

        
updateNavigation() {
            if (!
this._config.wrapping) {
                
let $nav this._$lightboxContainer.find('div.ekko-lightbox-nav-overlay')
                if (
this._galleryIndex === 0)
                    
$nav.find('a:first-child').addClass('disabled')
                else
                    
$nav.find('a:first-child').removeClass('disabled')

                if (
this._galleryIndex === this._$galleryItems.length 1)
                    
$nav.find('a:last-child').addClass('disabled')
                else
                    
$nav.find('a:last-child').removeClass('disabled')
            }
        }

        
close() {
            return 
this._$modal.modal('hide');
        }

        
// helper private methods
        
_navigationalBinder(event) {
            
event event || window.event;
            if (
event.keyCode === 39)
                return 
this.navigateRight()
            if (
event.keyCode === 37)
                return 
this.navigateLeft()
        }

        
// type detection private methods
        
_detectRemoteType(srctype) {

            
type type || false;

            if(!
type && this._isImage(src))
                
type 'image';
            if(!
type && this._getYoutubeId(src))
                
type 'youtube';
            if(!
type && this._getVimeoId(src))
                
type 'vimeo';
            if(!
type && this._getInstagramId(src))
                
type 'instagram';
            if(
type == 'audio' || type == 'video' || (!type && this._isMedia(src)))
                
type 'media';
            if(!
type || ['image''youtube''vimeo''instagram''media''url'].indexOf(type) < 0)
                
type 'url';

            return 
type;
        }

        
_getRemoteContentType(src) {
            
let response = $.ajax({
                
type'HEAD',
                
urlsrc,
                
asyncfalse
            
});
            
let contentType response.getResponseHeader('Content-Type')
            return 
contentType;
        }

        
_isImage(string) {
            return 
string && string.match(/(^data:image/.*,)|(.(jp(e|g|eg)|gif|png|bmp|webp|svg)((?|#).*)?$)/i)
        
}

        
_isMedia(string) {
            return 
string && string.match(/(.(mp3|mp4|ogg|webm|wav)((?|#).*)?$)/i)
        
}

        
_containerToUse() {
            
// if currently showing an image, fade it out and remove
            
let $toUse this._$lightboxBodyTwo
            let $current 
this._$lightboxBodyOne

            
if(this._$lightboxBodyTwo.hasClass('in')) {
                
$toUse this._$lightboxBodyOne
                $current 
this._$lightboxBodyTwo
            
}

            
$current.removeClass('in show')
            
setTimeout(() => {
                if(!
this._$lightboxBodyTwo.hasClass('in'))
                    
this._$lightboxBodyTwo.empty()
                if(!
this._$lightboxBodyOne.hasClass('in'))
                    
this._$lightboxBodyOne.empty()
            }, 
500)

            
$toUse.addClass('in show')
            return 
$toUse
        
}

        
_handle() {

            
let $toUse this._containerToUse()
            
this._updateTitleAndFooter()

            
let currentRemote this._$element.attr('data-remote') || this._$element.attr('href')
            
let currentType this._detectRemoteType(currentRemotethis._$element.attr('data-type') || false)

            if([
'image''youtube''vimeo''instagram''media''url'].indexOf(currentType) < 0)
                return 
this._error(this._config.strings.type)

            switch(
currentType) {
                case 
'image':
                    
this._preloadImage(currentRemote$toUse)
                    
this._preloadImageByIndex(this._galleryIndex3)
                    break;
                case 
'youtube':
                    
this._showYoutubeVideo(currentRemote$toUse);
                    break;
                case 
'vimeo':
                    
this._showVimeoVideo(this._getVimeoId(currentRemote), $toUse);
                    break;
                case 
'instagram':
                    
this._showInstagramVideo(this._getInstagramId(currentRemote), $toUse);
                    break;
                case 
'media':
                    
this._showHtml5Media(currentRemote$toUse);
                    break;
                default: 
// url
                    
this._loadRemoteContent(currentRemote$toUse);
                    break;
            }

            return 
this;
        }

        
_getYoutubeId(string) {
            if(!
string)
                return 
false;
            
let matches string.match(/^.*(youtu.be/|v/|u/w/|embed/|watch?v=|&v=)([^#&?]*).*/)
            
return (matches && matches[2].length === 11) ? matches[2] : false
        
}

        
_getVimeoId(string) {
            return 
string && string.indexOf('vimeo') > string false
        
}

        
_getInstagramId(string) {
            return 
string && string.indexOf('instagram') > string false
        
}

        
// layout private methods
        
_toggleLoading(show) {
            
show show || false
            
if(show) {
                
this._$modalDialog.css('display''none')
                
this._$modal.removeClass('in show')
                $(
'.modal-backdrop').append(this._config.loadingMessage)
            }
            else {
                
this._$modalDialog.css('display''block')
                
this._$modal.addClass('in show')
                $(
'.modal-backdrop').find('.ekko-lightbox-loader').remove()
            }
            return 
this;
        }

        
_calculateBorders() {
            return {
                
topthis._totalCssByAttribute('border-top-width'),
                
rightthis._totalCssByAttribute('border-right-width'),
                
bottomthis._totalCssByAttribute('border-bottom-width'),
                
leftthis._totalCssByAttribute('border-left-width'),
            }
        }

        
_calculatePadding() {
            return {
                
topthis._totalCssByAttribute('padding-top'),
                
rightthis._totalCssByAttribute('padding-right'),
                
bottomthis._totalCssByAttribute('padding-bottom'),
                
leftthis._totalCssByAttribute('padding-left'),
            }
        }

        
_totalCssByAttribute(attribute) {
            return 
parseInt(this._$modalDialog.css(attribute), 10) +
                
parseInt(this._$modalContent.css(attribute), 10) +
                
parseInt(this._$modalBody.css(attribute), 10)
        }

        
_updateTitleAndFooter() {
            
let title this._$element.data('title') || ""
            
let caption this._$element.data('footer') || ""

            
this._titleIsShown false
            
if (title || this._config.alwaysShowClose) {
                
this._titleIsShown true
                this
._$modalHeader.css('display''').find('.modal-title').html(title || "&nbsp;")
            }
            else
                
this._$modalHeader.css('display''none')

            
this._footerIsShown false
            
if (caption) {
                
this._footerIsShown true
                this
._$modalFooter.css('display''').html(caption)
            }
            else
                
this._$modalFooter.css('display''none')

            return 
this;
        }

        
_showYoutubeVideo(remote$containerForElement) {
            
let id this._getYoutubeId(remote)
            
let query remote.indexOf('&') > remote.substr(remote.indexOf('&')) : ''
            
let width this._$element.data('width') || 560
            let height 
this._$element.data('height') ||  width / ( 560/315 )
            return 
this._showVideoIframe(
                `
//www.youtube.com/embed/${id}?badge=0&autoplay=1&html5=1${query}`,
                
width,
                
height,
                
$containerForElement
            
);
        }

        
_showVimeoVideo(id$containerForElement) {
            
let width this._$element.data('width') || 500
            let height 
this._$element.data('height') ||  width / ( 560/315 )
            return 
this._showVideoIframe(id '?autoplay=1'widthheight$containerForElement)
        }

        
_showInstagramVideo(id$containerForElement) {
            
// instagram load their content into iframe's so this can be put straight into the element
            
let width this._$element.data('width') || 612
            let height 
width 80;
            
id id.substr(-1) !== '/' id '/' id// ensure id has trailing slash
            
$containerForElement.html(`<iframe width="${width}" height="${height}" src="${id}embed/" frameborder="0" allowfullscreen></iframe>`);
            
this._resize(widthheight);
            
this._config.onContentLoaded.call(this);
            if (
this._$modalArrows//hide the arrows when showing video
                
this._$modalArrows.css('display''none');
            
this._toggleLoading(false);
            return 
this;
        }

        
_showVideoIframe(urlwidthheight$containerForElement) { // should be used for videos only. for remote content use loadRemoteContent (data-type=url)
            
height height || width// default to square
            
$containerForElement.html(`<div class="embed-responsive embed-responsive-16by9"><iframe width="${width}" height="${height}" src="${url}" frameborder="0" allowfullscreen class="embed-responsive-item"></iframe></div>`);
            
this._resize(widthheight);
            
this._config.onContentLoaded.call(this);
            if (
this._$modalArrows)
                
this._$modalArrows.css('display''none'); //hide the arrows when showing video
            
this._toggleLoading(false);
            return 
this;
        }
                
        
_showHtml5Media(url$containerForElement) { // should be used for videos only. for remote content use loadRemoteContent (data-type=url)
            
let contentType this._getRemoteContentType(url);
            if(!
contentType){
                return 
this._error(this._config.strings.type)
            }
            
let mediaType '';
            if(
contentType.indexOf('audio') > 0){
                
mediaType 'audio';
            }else{
                
mediaType 'video';
            }
            
let width this._$element.data('width') || 560
            let height 
this._$element.data('height') ||  width / ( 560/315 )
            
$containerForElement.html(`<div class="embed-responsive embed-responsive-16by9"><${mediaType} width="${width}" height="${height}" preload="auto" autoplay controls class="embed-responsive-item"><source src="${url}" type="${contentType}">${this._config.strings.type}</${mediaType}></div>`);
            
this._resize(widthheight);
            
this._config.onContentLoaded.call(this);
            if (
this._$modalArrows)
                
this._$modalArrows.css('display''none'); //hide the arrows when showing video
            
this._toggleLoading(false);
            return 
this;
        }

        
_loadRemoteContent(url$containerForElement) {
            
let width this._$element.data('width') || 560;
            
let height this._$element.data('height') || 560;

            
let disableExternalCheck this._$element.data('disableExternalCheck') || false;
            
this._toggleLoading(false);

            
// external urls are loading into an iframe
            // local ajax can be loaded into the container itself
            
if (!disableExternalCheck && !this._isExternal(url)) {
                
$containerForElement.load(url, $.proxy(() => {
                    return 
this._$element.trigger('loaded.bs.modal');
                }));

            } else {
                
$containerForElement.html(`<iframe src="${url}" frameborder="0" allowfullscreen></iframe>`);
                
this._config.onContentLoaded.call(this);
            }

            if (
this._$modalArrows//hide the arrows when remote content
                
this._$modalArrows.css('display''none')

            
this._resize(widthheight);
            return 
this;
        }

        
_isExternal(url) {
            
let match url.match(/^([^:/?#]+:)?(?://([^/?#]*))?([^?#]+)?(?[^#]*)?(#.*)?/);
            
if (typeof match[1] === "string" && match[1].length && match[1].toLowerCase() !== location.protocol)
                return 
true;

            if (
typeof match[2] === "string" && match[2].length && match[2].replace(new RegExp(`:(${{
                    
"http:"80,
                    
"https:"443
                
}[location.protocol]})?$`), "") !== location.host)
                return 
true;

            return 
false;
        }

        
_errormessage ) {
            
console.error(message);
            
this._containerToUse().html(message);
            
this._resize(300300);
            return 
this;
        }

        
_preloadImageByIndex(startIndexnumberOfTimes) {

            if(!
this._$galleryItems)
                return;

            
let next = $(this._$galleryItems.get(startIndex), false)
            if(
typeof next == 'undefined')
                return

            
let src next.attr('data-remote') || next.attr('href')
            if (
next.attr('data-type') === 'image' || this._isImage(src))
                
this._preloadImage(srcfalse)

            if(
numberOfTimes 0)
                return 
this._preloadImageByIndex(startIndex 1numberOfTimes-1);
        }

        
_preloadImagesrc$containerForImage) {

            
$containerForImage $containerForImage || false

            let img 
= new Image();
            if (
$containerForImage) {

                
// if loading takes > 200ms show a loader
                
let loadingTimeout setTimeout(() => {
                    
$containerForImage.append(this._config.loadingMessage)
                }, 
200)

                
img.onload = () => {
                    if(
loadingTimeout)
                        
clearTimeout(loadingTimeout)
                    
loadingTimeout null;
                    
let image = $('<img />');
                    
image.attr('src'img.src);
                    
image.addClass('img-fluid');

                    
// backward compatibility for bootstrap v3
                    
image.css('width''100%');

                    
$containerForImage.html(image);
                    if (
this._$modalArrows)
                        
this._$modalArrows.css('display'''// remove display to default to css property

                    
this._resize(img.widthimg.height);
                    
this._toggleLoading(false);
                    return 
this._config.onContentLoaded.call(this);
                };
                
img.onerror = () => {
                    
this._toggleLoading(false);
                    return 
this._error(this._config.strings.fail+`  ${src}`);
                };
            }

            
img.src src;
            return 
img;
        }

        
_swipeGesure() {
            if (
this._touchendX this._touchstartX) {
                return 
this.navigateRight();
            }
            if (
this._touchendX this._touchstartX) {
                return 
this.navigateLeft();
            }
        }

        
_resizewidthheight ) {

            
height height || width
            this
._wantedWidth width
            this
._wantedHeight height

            let imageAspecRatio 
width height;

            
// if width > the available space, scale down the expected width and height
            
let widthBorderAndPadding this._padding.left this._padding.right this._border.left this._border.right

            
// force 10px margin if window size > 575px
            
let addMargin this._config.doc.body.clientWidth 575 20 0
            let discountMargin 
this._config.doc.body.clientWidth 575 20

            let maxWidth 
Math.min(width widthBorderAndPaddingthis._config.doc.body.clientWidth addMarginthis._config.maxWidth)

            if((
width widthBorderAndPadding) > maxWidth) {
                
height = (maxWidth widthBorderAndPadding discountMargin) / imageAspecRatio;
                
width maxWidth
            
} else
                
width = (width widthBorderAndPadding)

            
let headerHeight 0,
                
footerHeight 0

            
// as the resize is performed the modal is show, the calculate might fail
            // if so, default to the default sizes
            
if (this._footerIsShown)
                
footerHeight this._$modalFooter.outerHeight(true) || 55

            
if (this._titleIsShown)
                
headerHeight this._$modalHeader.outerHeight(true) || 67

            let borderPadding 
this._padding.top this._padding.bottom this._border.bottom this._border.top

            
//calculated each time as resizing the window can cause them to change due to Bootstraps fluid margins
            
let margins parseFloat(this._$modalDialog.css('margin-top')) + parseFloat(this._$modalDialog.css('margin-bottom'));

            
let maxHeight Math.min(height, $(window).height() - borderPadding margins headerHeight footerHeightthis._config.maxHeight borderPadding headerHeight footerHeight);

            if(
height maxHeight) {
                
// if height > the available height, scale down the width
                
width Math.ceil(maxHeight imageAspecRatio) + widthBorderAndPadding;
            }

            
this._$lightboxContainer.css('height'maxHeight)
            
this._$modalDialog.css('flex'1).css('maxWidth'width);

            
let modal this._$modal.data('bs.modal');
            if (
modal) {
                
// v4 method is mistakenly protected
                
try {
                    
modal._handleUpdate();
                } catch(
Exception) {
                    
modal.handleUpdate();
                }
            }
            return 
this;
        }

        static 
_jQueryInterface(config) {
            
config config || {}
            return 
this.each(() => {
                
let $this = $(this)
                
let _config = $.extend(
                    {},
                    
Lightbox.Default,
                    
$this.data(),
                    
typeof config === 'object' && config
                
)

                new 
Lightbox(this_config)
            })
        }
    }



    $.
fn[NAME]             = Lightbox._jQueryInterface
    
$.fn[NAME].Constructor Lightbox
    
$.fn[NAME].noConflict  = () => {
        $.
fn[NAME] = JQUERY_NO_CONFLICT
        
return Lightbox._jQueryInterface
    
}

    return 
Lightbox

})(jQuery)

export default Lightbox
?>
Онлайн: 0
Реклама