UNPKG

uix-kit

Version:

A free web kits for fast web design and development, compatible with Bootstrap v5.

795 lines (517 loc) 23.8 kB
/* ************************************* * <!-- Custom Lightbox --> ************************************* */ import { UixModuleInstance, UixGUID, } from '@uixkit/core/_global/js'; import UixApplyAsyncScripts from '@uixkit/core/_global/js/fn/UixApplyAsyncScripts'; import '@uixkit/plugins/Miscellaneous/scrollLock'; import '../scss/_style.scss'; export const LIGHTBOX = ( ( module, $, window, document ) => { if ( window.LIGHTBOX === null ) return false; module.LIGHTBOX = module.LIGHTBOX || {}; module.LIGHTBOX.version = '0.2.3'; module.LIGHTBOX.pageLoaded = function() { if ( $( '.uix-lightbox__container' ).length == 0 ) { $( 'body' ).prepend( '<div class="uix-lightbox__loading is-loaded uix-t-c"><i class="fa fa-spinner fa-spin"></i> Loading...</div><a class="uix-lightbox__original__close" href="javascript:void(0);"></a><div class="uix-lightbox__container"><div class="uix-lightbox__inner"><div class="uix-lightbox__html"></div><p class="title"></p></div></div><div class="uix-lightbox__container-mask"></div><div class="uix-lightbox__close"><button type="button"></button></div>' ); } // To display the template tag content. $( 'template' ).each( function() { const _content = $( this ).html( function( index,html ) { return html.replace(/[\r\n]/g, '' ); }).html(), _id = $( this ).attr( 'id' ); //If it is dialog, clone the contents of the <template> into the body if ( typeof _id !== typeof undefined && ! $( 'body' ).hasClass( _id ) && $( '<div>' + _content + '</div>' ).find( '[role="dialog"]' ).length > 0 ) { //reset id $( this ).removeAttr( 'id' ); $( 'body' ).addClass( _id ); //append content to body $( _content.replace(/role=[\'\"]dialog[\'\"]/, 'role="dialog" id="'+_id+'"' ) ).appendTo( 'body' ); } }); const innerEl = '.uix-lightbox__inner', wrapperEl = '.uix-lightbox__container', loaderEl = '.uix-lightbox__loading', maskEl = '.uix-lightbox__container-mask', closeEl = '.uix-lightbox__close', largeImgCloseEl = '.uix-lightbox__original__close', triggerEl = '.uix-lightbox__trigger', docURL = window.location.href, $content = $( innerEl ).find( '.uix-lightbox__html' ), customWidth = 1000; //Match the width in the css file; //Detect URL change & Fire click event window.addEventListener( 'popstate', function( e ) { let eleTarget = null; $( '[data-lb-ajax]' ).each( function() { let prevURL = decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent( 'uix-lightbox-ajaxURL' ).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null; if ( $( this ).attr( 'href' ) === prevURL ) { eleTarget = this; } }); const backURL = $( eleTarget ).data( 'lb-ajax-doc-url' ); if ( typeof backURL != typeof undefined ) { lightboxClose( backURL ); } }); $( document ).off( 'click.LIGHTBOX_TRIGGER' ).on( 'click.LIGHTBOX_TRIGGER', triggerEl, function() { const $this = $( this ); let dataPhoto = $this.data( 'lb-src' ), dataHtmlID = $this.data( 'lb-html' ), dataFixed = $this.data( 'lb-fixed' ), dataMaskClose = $this.data( 'lb-mask-close' ), dataAjax = $this.data( 'lb-ajax' ), htmlContent = '', imgSrcStr = '', imgSrcStrToW = ''; if ( typeof dataFixed === typeof undefined ) { dataFixed = true; } if ( typeof dataMaskClose === typeof undefined ) { dataMaskClose = false; } if ( typeof dataAjax === typeof undefined ) { dataAjax = false; } if ( dataAjax ) { $( wrapperEl ).addClass( 'js-uix-ajax' ); //Record current page URL for history if ( typeof $this.data( 'lb-ajax-doc-url' ) === typeof undefined ) $this.data( 'lb-ajax-doc-url', docURL ); } //Display loading $( loaderEl ).removeClass( 'is-loaded' ); //Reset the wrapper position $( wrapperEl ).css( 'margin-top', 0 ); if ( !dataFixed ) { $( wrapperEl ).addClass( 'js-uix-no-fixed' ); $( closeEl ).addClass( 'is-active' ); //Initialize the wrapper position $( wrapperEl ).css( 'margin-top', $( window ).scrollTop() + 'px' ); } //Reset current container type $( innerEl ).removeClass( 'js-uix-custom js-uix-pure-image' ); // Locks the page if ( !$( wrapperEl ).hasClass( 'js-uix-no-fixed' ) ) { $.scrollLock( true ); //Add class for body //When scrollLock is used, scrollTop value will change $( 'body' ).addClass( 'scrollLock' ); } // Show the lightbox const showLightbox = function() { $( closeEl ).addClass( 'is-active' ); $( wrapperEl ).show(); $( maskEl ).show(); $( innerEl ).show(); }; // hide the content container const hideLightboxContent = function() { TweenMax.set( $content, { css : { 'display' : 'none' } }); }; // show the content container const showLightboxContent = function() { TweenMax.set( $content, { css : { 'display' : 'block' }, onComplete : function() { TweenMax.to( this.target, 0.5, { alpha : 1 }); } }); }; hideLightboxContent(); //////////////////////// //////// PHOTOS /////// //////////////////////// if ( typeof dataPhoto != typeof undefined && dataPhoto != '' ) { //show the lightbox showLightbox(); if ( dataPhoto.indexOf( '[' ) >= 0 && dataPhoto.indexOf( ']' ) >= 0 ) { imgSrcStr = JSON.parse( dataPhoto.replace(/([a-zA-Z0-9]+?):/g, '"$1":').replace(/'/g,'"') ); } else { imgSrcStr = dataPhoto; } //Judging whether multiple image sets if ( Object.prototype.toString.call( imgSrcStr ) =='[object Array]' ) { let largePhotos = '', thumbs = ''; imgSrcStrToW = imgSrcStr[0].large; //push the large photos largePhotos += '<div class="uix-lightbox__photo-container uix-lightbox__photo-sets-container"><a href="javascript:" class="uix-lightbox__photo-sets__prev"></a><a href="javascript:" class="uix-lightbox__photo-sets__next"></a><ul>'; for ( let i = 0; i < imgSrcStr.length; i++ ) { const tempID = 'lightbox-' + UixGUID.create(); largePhotos += '<li>'; largePhotos += ' <a class="uix-lightbox__original__link" data-target-id="'+tempID+'-sets-'+i+'" href="javascript:void(0);">'; largePhotos += ' <img src="'+ imgSrcStr[i].large +'" alt="">'; largePhotos += ' </a>'; largePhotos += ' <div class="uix-lightbox__original__target" id="'+tempID+'-sets-'+i+'">'; largePhotos += ' <img src="'+ imgSrcStr[i].large +'" alt="">'; largePhotos += ' </div>'; largePhotos += '</li>'; } largePhotos += '</ul></div>'; //push the thumbs thumbs += '<div class="uix-lightbox__thumb-container"><ul>'; for ( let k = 0; k < imgSrcStr.length; k++ ) { const active = ( k == 0 ) ? 'class="is-active"' : ''; thumbs += '<li '+active+'><img src="'+ imgSrcStr[k].thumb +'" alt=""></li>'; } thumbs += '</ul></div>'; htmlContent = largePhotos + thumbs; } else { const tempID = 'lightbox-' + UixGUID.create(); //Only one image imgSrcStrToW = imgSrcStr; htmlContent += '<div class="uix-lightbox__photo-container">'; htmlContent += ' <a class="uix-lightbox__original__link" data-target-id="'+tempID+'" href="javascript:void(0);">'; htmlContent += ' <img src="'+ imgSrcStr +'" alt="">'; htmlContent += ' </a>'; htmlContent += ' <div class="uix-lightbox__original__target" id="'+tempID+'">'; htmlContent += ' <img src="'+ imgSrcStr +'" alt="">'; htmlContent += ' </div>'; htmlContent += '</div>'; } $content.html( htmlContent ).promise().done( function(){ //Set current container type $( innerEl ).addClass( 'js-uix-pure-image' ); //Set container width const img = new Image(); img.src = imgSrcStrToW; img.onload = function() { //remove loading $( loaderEl ).addClass( 'is-loaded' ); // show the content container showLightboxContent(); let sw = window.innerWidth - 30, ow = this.width, oh = this.height, ratioH = oh/ow, ratioW = ow/oh, w = ( ow > customWidth ) ? customWidth : ow, h; if ( w > sw ) w = sw; h = w * ratioH; //Prevent height overflow if ( h > window.innerHeight ) h = window.innerHeight * 0.95; $( innerEl ).css( { 'width': w + 'px' } ); //Don't write variables outside const $lbSetsContainer = $( '.uix-lightbox__photo-container.uix-lightbox__photo-sets-container' ); $lbSetsContainer.css( { 'height': h + 'px' } ); //Set a new height & width of inside images $content.find( '.uix-lightbox__photo-sets-container ul > li img' ).css( { 'height': h + 'px' } ); if ( ! $( 'body' ).hasClass( 'rtl' ) ) { $content.find( '.uix-lightbox__photo-sets-container' ).css( { 'width': 'calc('+ h*ratioW +'px + 6rem)', 'margin-left': '-3rem' } ); } else { $content.find( '.uix-lightbox__photo-sets-container' ).css( { 'width': 'calc('+ h*ratioW +'px + 6rem)', 'margin-right': '-3rem' } ); } //If the image is larger than the current window, it will display at the top. //Don't write variables outside const $lbTarImg = $( '.uix-lightbox__photo-container > .uix-lightbox__original__target' ); if ( oh > window.innerHeight ) { $lbTarImg.addClass( 'uix-lightbox__original__target--imgfull' ); } else { $lbTarImg.removeClass( 'uix-lightbox__original__target--imgfull' ); } }; $( innerEl ).find( '> .uix-lightbox__html' ).removeClass( 'js-uix-no-img' ); }); } //////////////////////// //////// HTML ///////// //////////////////////// if ( typeof dataHtmlID != typeof undefined && dataHtmlID != '' ) { dataHtmlID = dataHtmlID.replace( '#', '' ); const $htmlAjaxContainer = $( '#' + dataHtmlID ).find( '.uix-lightbox__content > div' ); //show the lightbox showLightbox(); // Content pushing completed const htmlContentLoaded = function() { //remove loading $( loaderEl ).addClass( 'is-loaded' ); //Set current container type $( innerEl ).addClass( 'js-uix-custom' ); //Set container width if ( $( innerEl ).find( '> .uix-lightbox__html .uix-lightbox__content' ).length > 0 ) { if ( window.innerWidth <= 768 ) { $( innerEl ).css( 'width', window.innerWidth - 10 + 'px' ); } else { $( innerEl ).css( 'width', $( innerEl ).find( '> .uix-lightbox__html .uix-lightbox__content' ).width() + 'px' ); } $( innerEl ).find( '> .uix-lightbox__html' ).addClass( 'js-uix-no-img' ); } }; if ( $( wrapperEl ).hasClass( 'js-uix-ajax' ) ) { //Add content to the dynamic AJAX container const ajaxURL = $this.attr( 'href' ), ajaxConfig = dataAjax; // Modify the URL without reloading the page if( history.pushState ) { history.pushState( null, null, ajaxURL ); } else { location.hash = ajaxURL; } document.cookie = 'uix-lightbox-ajaxURL=' + ajaxURL; // Add a request or response interceptor const axiosInterceptor = axios.interceptors.request.use(function(config) { // Do something before request is sent // return config; }, function(error) { return Promise.reject(error); }); // To send data in the application/x-www-form-urlencoded format instead const formData = new FormData(); const defaultPostData = { action : 'load_singlepages_ajax_content' }; for(let k in defaultPostData) { formData.append(k, defaultPostData[k]); } // Create a request event axios({ timeout: 15000, method: ajaxConfig.method, url: ajaxURL, data: formData, responseType: 'text', }) .then(function (response) { const htmlCode = response.data; $htmlAjaxContainer.html( $( htmlCode ).find( dataAjax.target ).html() ).promise().done( function(){ $content.html( $( '#' + dataHtmlID ).html() ).promise().done( function(){ // Apply some asynchronism scripts $( document ).UixApplyAsyncScripts({ lightBox : false, ajaxPostList : false }); // show the content container showLightboxContent(); // Content pushing completed htmlContentLoaded(); }); }); }) .catch(function (error) { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx const status = error.response.status; console.log(status); if ( status == 404 || status == 405 ) window.location.href = ajaxURL; } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js console.log(error.request); // window.location.href = ajaxURL; } else { // If there was a problem, we need to // dispatch the error condition console.log(error.message); } }); // Remove an interceptor later axios.interceptors.request.eject(axiosInterceptor); } else { // show the content container showLightboxContent(); $content.html( $( '#' + dataHtmlID ).html() ).promise().done( function(){ // Content pushing completed htmlContentLoaded(); }); }//endif $( wrapperEl ).hasClass( 'js-uix-ajax' ) } return false; }); /* end click event for triggerEl */ //////////////////////// // Close the lightbox // //////////////////////// $( document ).off( 'click.LIGHTBOX_CLOSE' ).on( 'click.LIGHTBOX_CLOSE', closeEl + ',' + maskEl, function() { lightboxClose( docURL ); }); $( document ).off( 'click.LIGHTBOX_THUMB' ).on( 'click.LIGHTBOX_THUMB', '.uix-lightbox__thumb-container li', function() { lightboxThumbSwitch( $( this ).index(), $( this ) ); }); $( document ).off( 'click.LIGHTBOX_PHOTO_SETS' ).on( 'click.LIGHTBOX_PHOTO_SETS', '.uix-lightbox__photo-sets-container > a', function() { const $largePhoto = $( this ).closest( '.uix-lightbox__html' ).find( '.uix-lightbox__photo-container.uix-lightbox__photo-sets-container' ), $thumb = $( this ).closest( '.uix-lightbox__html' ).find( '.uix-lightbox__thumb-container li' ), total = $thumb.length, curIndex = $thumb.filter( '.is-active' ).index(); let prevIndex = curIndex - 1, nextIndex = curIndex + 1; if ( prevIndex < 0 ) prevIndex = total - 1; if ( nextIndex > total - 1 ) nextIndex = 0; if ( $( this ).hasClass( 'uix-lightbox__photo-sets__prev' ) ) { lightboxThumbSwitch( prevIndex, $thumb.eq( prevIndex ) ); } if ( $( this ).hasClass( 'uix-lightbox__photo-sets__next' ) ) { lightboxThumbSwitch( nextIndex, $thumb.eq( nextIndex ) ); } }); //////////////////////////////// // Close/Open enlarge image // /////////////////////////////// if ( window.innerWidth > 768 ) { $( document ).off( 'click.LIGHTBOX_ORGINAL_LINK' ).on( 'click.LIGHTBOX_ORGINAL_LINK', '.uix-lightbox__original__link', function( e ) { $( '.uix-lightbox__original__target#' + $( this ).data( 'target-id' ) ).addClass( 'is-active' ); if ( $( this ).closest( '.uix-lightbox__container.js-uix-no-fixed' ).length > 0 ) { $( '.uix-lightbox__container.js-uix-no-fixed, .uix-lightbox__original__target--imgfull' ).addClass( 'no-fixed-imgEnlarged' ); } //--- $( 'html' ).css( 'overflow-y', 'hidden' ); $( largeImgCloseEl ).addClass( 'is-active' ); }); $( document ).off( 'click.LIGHTBOX_LARGE_IMG_CLOSE' ).on( 'click.LIGHTBOX_LARGE_IMG_CLOSE', largeImgCloseEl, function( e ) { $( '.uix-lightbox__original__target' ).removeClass( 'is-active' ); $( '.uix-lightbox__container.js-uix-no-fixed, .uix-lightbox__original__target--imgfull' ).removeClass( 'no-fixed-imgEnlarged' ); //--- $( this ).removeClass( 'is-active' ); $( 'html' ).css( 'overflow-y', 'auto' ); }); } /* * Click thumbnail to show large photo * * @param {Number} index - The target index of large photo. * @param {Element} obj - Target large image <li>. * @return {Void} */ function lightboxThumbSwitch( index, obj ) { const $largePhoto = obj.closest( '.uix-lightbox__html' ).find( '.uix-lightbox__photo-container.uix-lightbox__photo-sets-container' ), $thumb = obj.closest( '.uix-lightbox__html' ).find( '.uix-lightbox__thumb-container li' ); // show the content container const showLightboxContent = function() { TweenMax.set( obj.closest( '.uix-lightbox__html' ), { css : { 'display' : 'block' }, onComplete : function() { TweenMax.to( this.target, 0.5, { alpha : 1 }); } }); }; $thumb.removeClass( 'is-active' ); obj.addClass( 'is-active' ); //all items TweenMax.set( $largePhoto.find( 'li' ), { css : { 'display' : 'none', 'opacity' : 0 }, onComplete : function() { $( this.target ).removeClass( 'is-active' ); } }); //current item TweenMax.set( $largePhoto.find( 'li' ).eq( index ), { css : { 'display' : 'block', 'opacity' : 0 }, onComplete : function() { const _cur = this.target; $( _cur ).addClass( 'is-active' ); // //Reset the container height const imgClick = new Image(); imgClick.src = $largePhoto.find( 'li' ).eq( index ).find( 'img' ).attr( 'src' ); imgClick.onload = function() { //remove loading $( loaderEl ).addClass( 'is-loaded' ); // show the content container showLightboxContent(); let sw = window.innerWidth - 30, ow = this.width, oh = this.height, ratioH = oh/ow, w = ( ow > customWidth ) ? customWidth : ow, h; if ( w > sw ) w = sw; h = w * ratioH; //Prevent height overflow if ( h > window.innerHeight ) h = window.innerHeight * 0.95; $largePhoto.css( { 'height': h + 'px' } ) .find( 'img' ).css( { 'height': h + 'px' } ); //If the image is larger than the current window, it will display at the top. //Don't write variables outside const $lbTarImg = $largePhoto.find( 'li' ).eq( index ).find( '.uix-lightbox__original__target' ); if ( oh > window.innerHeight ) { $lbTarImg.addClass( 'uix-lightbox__original__target--imgfull' ); } else { $lbTarImg.removeClass( 'uix-lightbox__original__target--imgfull' ); } TweenMax.to( _cur, 0.5, { alpha : 1 }); };//imgClick.onload } }); } /* * Close the lightbox * * @param {String} url - The current page URL for history. * @return {Void} */ function lightboxClose( url ) { //Detect URL change when AJAX calls are done if ( $( wrapperEl ).hasClass( 'js-uix-ajax' ) ) { history.pushState( null, null, url ); } //Remove all dynamic classes $( wrapperEl ).removeClass( 'js-uix-no-fixed js-uix-ajax' ); $( closeEl ).removeClass( 'is-active' ); //Add a scroll bar. $( 'html' ).css( 'overflow-y', 'auto' ); //Reset current container type $( innerEl ).removeClass( 'js-uix-custom js-uix-pure-image' ); //close windows $( wrapperEl ).hide(); $( maskEl ).hide(); // Unlocks the page $.scrollLock( false ); //Remove class for body //When scrollLock is used, scrollTop value will change $( 'body' ).removeClass( 'scrollLock' ); } }; module.components.pageLoaded.push( module.LIGHTBOX.pageLoaded ); return class LIGHTBOX { constructor() { this.module = module; } }; })( UixModuleInstance, jQuery, window, document );