IMPR: Plugin Refactoring

This commit is contained in:
Tony Air 2020-06-18 06:18:13 +07:00
parent 7b8595229f
commit 113c3507fc
4 changed files with 236 additions and 291 deletions

38
src/js/_events.js Executable file
View File

@ -0,0 +1,38 @@
/**
* Add your global events here
*/
module.exports = {
AJAX: 'ajax-load',
TABHIDDEN: 'tab-hidden',
TABFOCUSED: 'tab-focused',
OFFLINE: 'offline',
ONLINE: 'online',
LOADED: 'load',
SWIPELEFT: 'swipeleft panleft',
SWIPERIGHT: 'swiperight panright',
ALLERTAPPEARED: 'alert-appeared',
ALERTREMOVED: 'alert-removed',
LODEDANDREADY: 'load-ready',
LAZYIMAGEREADY: 'image-lazy-bg-loaded',
LAZYIMAGESREADY: 'images-lazy-loaded',
MAPLOADED: 'map-loaded',
MAPAPILOADED: 'map-api-loaded',
MAPMARKERCLICK: 'map-marker-click',
MAPPOPUPCLOSE: 'map-popup-close',
SCROLL: 'scroll',
RESIZE: 'resize',
CAROUSEL_READY: 'bs.carousel.ready',
SET_TARGET_UPDATE: 'set-target-update',
RESTORE_FIELD: 'restore-field',
FORM_INIT_BASICS: 'form-basics',
FORM_INIT_STEPPED: 'form-init-stepped',
FORM_INIT_VALIDATE: 'form-init-validate',
FORM_INIT_VALIDATE_FIELD: 'form-init-validate-field',
FORM_INIT_STORAGE: 'form-init-storage',
FORM_VALIDATION_FAILED: 'form-validation-failed',
FORM_STEPPED_NEW_STEP: 'form-new-step',
FORM_STEPPED_FIRST_STEP: 'form-first-step',
FORM_STEPPED_LAST_STEP: 'form-last-step',
FORM_FIELDS: 'input,textarea,select',
};

View File

@ -1,123 +1,74 @@
/* /*
* MetaLightbox v0.61 * MetaLightbox
* https://tony.twma.pro * https://tony.twma.pro
* *
*/ */
// optional:
//=require ../../bower_components/jquery-zoom/jquery.zoom.js //=require ../../bower_components/jquery-zoom/jquery.zoom.js
(function($, window, document) { "use strict";
var pluginName = 'metaLightbox',
defaults = {
effect: 'fade',
theme: 'default',
keyboardNav: true,
clickOverlayToClose: true,
onInit: function() {},
beforeShowLightbox: function() {},
afterShowLightbox: function(lightbox) {},
beforeHideLightbox: function() {},
afterHideLightbox: function() {},
onPrev: function(element) {},
onNext: function(element) {},
errorMessage:
'The requested content cannot be loaded. Please try again later.',
};
function MetaLightbox(element, options) { import $ from 'jquery';
/*this.el = element;
this.$el = $(this.el);*/
this.options = $.extend({}, defaults, options); import Events from './_events';
this._defaults = defaults; const MetaLightboxUI = (($) => {
this._name = pluginName; const W = window;
const D = document;
const $Body = $('body');
this.init(); const NAME = 'MetaLightboxUI';
}
MetaLightbox.prototype = { class MetaLightboxUI {
init: function() { static init() {
var $this = this, console.log(`Initializing: ${NAME}`);
$html = $('html');
this.ajaxLoaded = false; const ui = this;
ui.isMSIE = /*@cc_on!@*/ 0;
ui.isHidpi = ui.isHidpi();
// make object globally accessible
document.MetaLightbox = this;
// Need this so we don't use CSS transitions in mobile $(`.js${NAME},[data-toggle="lightbox"],[data-lightbox-gallery]`).on('click', (e) => {
if (!$html.hasClass('meta-lightbox-notouch')) e.preventDefault();
$html.addClass('meta-lightbox-notouch');
if ('ontouchstart' in document)
$html.removeClass('meta-lightbox-notouch');
// Setup the click
$(document).on(
'click',
'[data-toggle="lightbox"],[data-lightbox-gallery]',
function(e) {
e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const $link = $(e.currentTarget);
$this.showLightbox(this); ui.show($link);
return false; });
}, }
);
// keyboardNav static isHidpi() {
if (this.options.keyboardNav) { console.log(`${NAME}: isHidpi`);
$('body') const mediaQuery =
.off('keyup') '(-webkit-min-device-pixel-ratio: 1.5),\
.on('keyup', (e) => { (min--moz-device-pixel-ratio: 1.5),\
var code = e.keyCode ? e.keyCode : e.which; (-o-min-device-pixel-ratio: 3/2),\
// Escape (min-resolution: 1.5dppx)';
if (code === 27) { if (W.devicePixelRatio > 1) return true;
$this.destructLightbox(); return W.matchMedia && W.matchMedia(mediaQuery).matches;
} }
// Left
if (code === 37) {
$('.meta-lightbox-prev').trigger('click');
}
// Right
if (code === 39) {
$('.meta-lightbox-next').trigger('click');
}
});
}
this.options.onInit.call(this); static show($link) {
}, console.log(`${NAME}: show`);
const ui = this;
showLightbox: function(element) { const $lightbox = this.constructLightbox();
this.el = element; if (!$lightbox) return;
this.$el = $(this.el);
var $this = this, const $content = ui.$content;
lightbox, if (!$content) return;
content,
currentLink,
galleryItems;
this.options.beforeShowLightbox.call(this); $('body').addClass(`meta-lightbox-body-effect-fade`);
lightbox = this.constructLightbox();
if (!lightbox) return;
content = lightbox.find('.meta-lightbox-content');
if (!content) return;
currentLink = this.$el;
$('body').addClass(`meta-lightbox-body-effect-${this.options.effect}`);
// Add content // Add content
this.processContent(content, currentLink); ui.process($content, $link);
// Nav // Nav
if (this.$el.data('lightbox-gallery')) { if ($link.data('lightbox-gallery')) {
galleryItems = $( const $galleryItems = $(`[data-lightbox-gallery="${$link.data('lightbox-gallery')}"]`);
`[data-lightbox-gallery="${this.$el.data('lightbox-gallery')}"]`,
);
if (galleryItems.length === 1) { if ($galleryItems.length === 1) {
$('.meta-lightbox-nav').hide(); $('.meta-lightbox-nav').hide();
} else { } else {
$('.meta-lightbox-nav').show(); $('.meta-lightbox-nav').show();
@ -126,66 +77,110 @@
// Prev // Prev
$('.meta-lightbox-prev') $('.meta-lightbox-prev')
.off('click') .off('click')
.on('click', function(e) { .on('click', (e) => {
e.preventDefault(); e.preventDefault();
var index = galleryItems.index(currentLink); const index = $galleryItems.index(currentLink);
currentLink = galleryItems.eq(index - 1); let $currentLink = $galleryItems.eq(index - 1);
if (!$(currentLink).length) currentLink = galleryItems.last(); if (!$currentLink.length) $currentLink = $galleryItems.last();
$this.processContent(content, currentLink); $this.process($content, $currentLink);
$this.options.onPrev.call(this, [currentLink]);
}); });
// Next // Next
$('.meta-lightbox-next') $('.meta-lightbox-next')
.off('click') .off('click')
.on('click', function(e) { .on('click', (e) => {
e.preventDefault(); e.preventDefault();
var index = galleryItems.index(currentLink); const index = $galleryItems.index(currentLink);
currentLink = galleryItems.eq(index + 1); $currentLink = $galleryItems.eq(index + 1);
if (!$(currentLink).length) currentLink = galleryItems.first(); if (!$currentLink.length) $currentLink = $galleryItems.first();
$this.processContent(content, currentLink); $this.process($content, $currentLink);
$this.options.onNext.call(this, [currentLink]);
}); });
} }
setTimeout(function() { setTimeout(() => {
lightbox.addClass('meta-lightbox-open'); ui.$overlay.addClass('meta-lightbox-open');
$this.options.afterShowLightbox.call(this, [lightbox]);
}, 1); // For CSS transitions }, 1); // For CSS transitions
}, }
processContent: function(content, link) { static constructLightbox() {
var $this = this, console.log(`${NAME}: constructLightbox`);
img, const ui = this;
video,
src,
classTerm,
iframe,
wrap;
href = link.attr('href'); const overlay = $('<div>', {
if (!href) { class: 'meta-lightbox-overlay meta-lightbox-theme-default meta-lightbox-effect-fade',
href = link.data('href'); });
const wrap = $('<div>', {
class: 'meta-lightbox-wrap',
});
const content = $('<div>', {
class: 'meta-lightbox-content',
});
const nav = $(
'<a href="#" class="meta-lightbox-nav meta-lightbox-prev"><i class="fas fa fa-chevron-left"></i> <span class="sr-only">Previous</span></a><a href="#" class="meta-lightbox-nav meta-lightbox-next"><i class="fa fas fa-chevron-right"></i> <span class="sr-only">Next</span></a>',
);
const close = $(
'<a href="#" class="meta-lightbox-close fas fa fa-times" title="Close"><span class="sr-only">Close</span></a>',
);
const title = $('<div>', {
class: 'meta-lightbox-title-wrap',
});
if (ui.$overlay) return ui.$overlay;
if (ui.isMSIE) overlay.addClass('meta-lightbox-ie');
wrap.append(content);
wrap.append(title);
overlay.append(wrap);
overlay.append(nav);
overlay.append(close);
$('body').append(overlay);
overlay.on('click', (e) => {
e.preventDefault();
ui.hide();
});
close.on('click', (e) => {
e.preventDefault();
ui.hide();
});
ui.$overlay = overlay;
ui.$content = content;
ui.$title = title;
return ui.$overlay;
}
static setTitle(str) {
const ui = this;
ui.$title.html(str);
}
static process($content, $link) {
console.log(`${NAME}: process`);
const ui = this;
const href = $link.attr('href').length ? $link.attr('href') : $link.data('href');
if (!href.length) {
console.log($link);
console.error(NAME + ': href(attr/data) is missing');
} }
content.html('').addClass('meta-lightbox-loading'); const $pageSpinner = $('#PageLoading');
const loadingContent = $pageSpinner.length ? $pageSpinner.html() : '';
// Is HiDPI? ui.$content.html(loadingContent).addClass('meta-lightbox-loading');
if (this.isHidpi() && link.data('lightbox-hidpi')) {
href = link.data('lightbox-hidpi');
}
// Image // Image
if (href.match(/\.(jpeg|jpg|gif|png)$/i) != null) { if (href.match(/\.(jpeg|jpg|gif|png|svg)$/i)) {
/*if ($(window).width() < 768) { const img = $('<img>', {
window.open(href, '_blank');
}*/
img = $('<img>', {
src: href, src: href,
}); });
img.on('load', () => { img.on('load', () => {
var wrap = $('<div class="meta-lightbox-image"></div>'), const wrap = $('<div class="meta-lightbox-image"></div>'),
$content = $('.meta-lightbox-content'),
imgwrapper = $('<span class="meta-lightbox-zoom-wrapper"></span>'); imgwrapper = $('<span class="meta-lightbox-zoom-wrapper"></span>');
imgwrapper.append(img); imgwrapper.append(img);
@ -196,6 +191,7 @@
'line-height': `${$content.height()}px`, 'line-height': `${$content.height()}px`,
height: `${$content.height()}px`, // For Firefox height: `${$content.height()}px`, // For Firefox
}); });
$(window).resize(() => { $(window).resize(() => {
wrap.css({ wrap.css({
'line-height': `${$content.height()}px`, 'line-height': `${$content.height()}px`,
@ -207,29 +203,22 @@
imgwrapper.zoom(); imgwrapper.zoom();
} }
content.html(wrap).removeClass('meta-lightbox-loading'); ui.$content.html(wrap);
$this.contentLoaded(); ui.contentLoaded();
}); });
/*.each(function () {
if (this.complete) $(this).load();
});*/
img.on('error', () => { img.on('error', () => {
var wrap = $( const wrap = $(
`<div class="meta-lightbox-error"><p>${$this.options.errorMessage}</p></div>`, `<div class="meta-lightbox-error"><p class="alert alert-error alert-danger">${$this.options.errorMessage}</p></div>`,
); );
content.html(wrap).removeClass('meta-lightbox-loading');
$this.contentLoaded(); ui.$content.html(wrap);
ui.contentLoaded();
}); });
// Set the title // Set the title
if (link.data('title')) { const title = $link.data('title') ? $link.data('title') : $link.attr('title');
$this.setTitle(link.data('title')); ui.setTitle(title);
} else if (link.attr('title')) {
$this.setTitle(link.attr('title'));
} else {
$('.meta-lightbox-title-wrap').html('');
}
// google analytics // google analytics
if (typeof ga === 'function') { if (typeof ga === 'function') {
@ -237,33 +226,30 @@
} }
} }
// Video (Youtube/Vimeo) // Video (Youtube/Vimeo)
else if ( else if (href.match(/(youtube|youtube-nocookie|youtu|vimeo)\.(com|be)\/(watch\?v=([\w-]+)|([\w-]+))/)) {
(video = href.match( let video = href.match(/(youtube|youtube-nocookie|youtu|vimeo)\.(com|be)\/(watch\?v=([\w-]+)|([\w-]+))/);
/(youtube|youtube-nocookie|youtu|vimeo)\.(com|be)\/(watch\?v=([\w-]+)|([\w-]+))/, let classTerm = 'meta-lightbox-video';
)) let src;
) {
src = '';
classTerm = 'meta-lightbox-video';
if (video[1] == 'youtube') { if (video[1] == 'youtube') {
src = `https://www.youtube.com/embed/${video[4]}`; src = `https://www.youtube.com/embed/${video[4]}`;
classTerm = 'meta-lightbox-youtube'; classTerm = classTerm + ' meta-lightbox-youtube';
} }
if (video[1] == 'youtu') { if (video[1] == 'youtu') {
src = `https://www.youtube.com/embed/${video[3]}`; src = `https://www.youtube.com/embed/${video[3]}`;
classTerm = 'meta-lightbox-youtube'; classTerm = classTerm + ' meta-lightbox-youtube';
} }
if (video[1] == 'youtube-nocookie') { if (video[1] == 'youtube-nocookie') {
src = `https://www.youtube-nocookie.com/embed/${video[4]}`; src = `https://www.youtube-nocookie.com/embed/${video[4]}`;
classTerm = 'nivo-lightbox-youtube'; classTerm = classTerm+' meta-lightbox-youtube';
} }
if (video[1] == 'vimeo') { if (video[1] == 'vimeo') {
src = `https://player.vimeo.com/video/${video[3]}`; src = `https://player.vimeo.com/video/${video[3]}`;
classTerm = 'meta-lightbox-vimeo'; classTerm = classTerm + ' meta-lightbox-vimeo';
} }
if (src) { if (src) {
iframe = $('<iframe>', { const $iframe = $('<iframe>', {
src, src,
class: classTerm, class: classTerm,
frameborder: 0, frameborder: 0,
@ -271,21 +257,24 @@
hspace: 0, hspace: 0,
scrolling: 'auto', scrolling: 'auto',
}); });
content.html(iframe);
iframe.on('load', () => { $Body.append('<div id="IFramePreload" class="hidden d-none iframe-preload" style="display:none"></div>');
content.removeClass('meta-lightbox-loading'); const $preload = $('#IFramePreload');
$this.contentLoaded(); $preload.html($iframe);
$iframe.on('load', () => {
console.log(`${NAME}: the iframe was loaded`);
$preload.html('');
$preload.remove();
ui.$content.html($iframe);
ui.contentLoaded();
}); });
} }
// Set the title // Set the title
if (link.data('title')) { const title = $link.data('title') ? $link.data('title') : $link.attr('title');
$this.setTitle(link.data('title')); ui.setTitle(title);
} else if (link.attr('title')) {
$this.setTitle(link.attr('title'));
} else {
$('.meta-lightbox-title-wrap').html('');
}
// google analytics // google analytics
if (typeof ga === 'function') { if (typeof ga === 'function') {
@ -296,11 +285,7 @@
else if (href.substring(0, 1) == '#') { else if (href.substring(0, 1) == '#') {
if ($(href).length) { if ($(href).length) {
wrap = $('<div class="meta-lightbox-inline" />'); wrap = $('<div class="meta-lightbox-inline" />');
wrap.append( wrap.append($(href).clone().show());
$(href)
.clone()
.show(),
);
// Vertically center html // Vertically center html
if (wrap.outerHeight() < content.height()) { if (wrap.outerHeight() < content.height()) {
@ -320,14 +305,14 @@
} }
}); });
content.html(wrap).removeClass('meta-lightbox-loading'); ui.$content.html(wrap);
$this.contentLoaded(); ui.contentLoaded();
} else { } else {
wrap = $( wrap = $(
`<div class="meta-lightbox-error"><p>${$this.options.errorMessage}</p></div>`, `<div class="meta-lightbox-error"><p>${$this.options.errorMessage}</p></div>`,
); );
content.html(wrap).removeClass('meta-lightbox-loading'); ui.$content.html(wrap);
$this.contentLoaded(); ui.contentLoaded();
} }
$('.meta-lightbox-title-wrap').html(''); $('.meta-lightbox-title-wrap').html('');
@ -347,30 +332,30 @@
method: 'GET', method: 'GET',
cache: false, cache: false,
statusCode: { statusCode: {
404: function() { 404: function () {
console.log('page not found'); console.log('page not found');
window.location.href = url; window.location.href = url;
}, },
302: function() { 302: function () {
console.log('redirect 302'); console.log('redirect 302');
window.location.href = url; window.location.href = url;
}, },
}, },
error: function(jqXHR) { error: function (jqXHR) {
console.log(`AJAX request failure.${jqXHR.statusText}`); console.log(`AJAX request failure.${jqXHR.statusText}`);
var wrap = $( var wrap = $(
`<div class="meta-lightbox-error"><p>${$this.options.errorMessage}</p></div>`, `<div class="meta-lightbox-error"><p>${$this.options.errorMessage}</p></div>`,
); );
content.html(wrap).removeClass('meta-lightbox-loading'); ui.$content.html(wrap);
$this.contentLoaded(); ui.contentLoaded();
// google analytics // google analytics
if (typeof ga === 'function') { if (typeof ga === 'function') {
ga('send', 'event', 'error', 'AJAX ERROR', jqXHR.statusText); ga('send', 'event', 'error', 'AJAX ERROR', jqXHR.statusText);
} }
}, },
success: function(data, status, jqXHR) { success: function (data, status, jqXHR) {
try { try {
const dataJson = $.parseJSON(data); const dataJson = $.parseJSON(data);
if (typeof dataJson === 'object') { if (typeof dataJson === 'object') {
@ -485,93 +470,29 @@
} }
}, 500); }, 500);
$this.contentLoaded(); ui.contentLoaded();
}, },
}); });
} }
}, };
setTitle: function(text) { static contentLoaded() {
var titleWrap = $('<div>', { const ui = this;
class: 'meta-lightbox-title',
});
titleWrap.text(text);
$('.meta-lightbox-title-wrap').html(titleWrap);
},
contentLoaded: function() { ui.$content.removeClass('meta-lightbox-loading');
setTimeout(() => { setTimeout(() => {
$(window).trigger('meta-lightbox-loaded'); $(W).trigger('meta-lightbox-loaded');
}, 1); // For CSS transitions }, 1); // For CSS transitions
setTimeout(() => { setTimeout(() => {
$('body').addClass('meta-lightbox-body-effect-fade'); $Body.addClass('meta-lightbox-body-effect-fade');
}, 600); }, 600);
}, };
constructLightbox: function() { static hide(callback) {
var $this = this, const ui = this;
overlay = $('<div>', {
class: `meta-lightbox-overlay meta-lightbox-theme-${this.options.theme} meta-lightbox-effect-${this.options.effect}`,
}),
wrap = $('<div>', {
class: 'meta-lightbox-wrap',
}),
content = $('<div>', {
class: 'meta-lightbox-content',
}),
nav = $(
'<a href="#" class="meta-lightbox-nav meta-lightbox-prev"><i class="fas fa fa-chevron-left"></i> <span class="sr-only">Previous</span></a><a href="#" class="meta-lightbox-nav meta-lightbox-next"><i class="fa fas fa-chevron-right"></i> <span class="sr-only">Next</span></a>',
),
close = $(
'<a href="#" class="meta-lightbox-close fas fa fa-times" title="Close"><span class="sr-only">Close</span></a>',
),
title = $('<div>', {
class: 'meta-lightbox-title-wrap',
}),
isMSIE = /*@cc_on!@*/ 0,
$overlay = $('.meta-lightbox-overlay');
if ($overlay.length) return $overlay; const $overlay = ui.$overlay;
if (isMSIE) overlay.addClass('meta-lightbox-ie');
wrap.append(content);
wrap.append(title);
overlay.append(wrap);
overlay.append(nav);
overlay.append(close);
$('body').append(overlay);
if ($this.options.clickOverlayToClose) {
overlay.on('click', (e) => {
var $target = $(e.target);
if (
$target.hasClass('meta-lightbox-zoom-wrapper') ||
$target.hasClass('meta-lightbox-content') ||
$target.hasClass('meta-lightbox-wrap') ||
$target.hasClass('meta-lightbox-image') ||
$target.hasClass('meta-lightbox-overlay')
) {
$this.destructLightbox();
}
});
}
close.on('click', (e) => {
e.preventDefault();
$this.destructLightbox();
});
return overlay;
},
destructLightbox: function() {
var $this = this,
$overlay = $('.meta-lightbox-overlay'),
isMSIE = /*@cc_on!@*/ 0;
this.options.beforeHideLightbox.call(this);
var title = $('.meta-lightbox-ajax').data('curr-title'), var title = $('.meta-lightbox-ajax').data('curr-title'),
link = $('.meta-lightbox-ajax').data('curr-link'); link = $('.meta-lightbox-ajax').data('curr-link');
@ -606,15 +527,11 @@
$overlay.removeClass('meta-lightbox-open'); $overlay.removeClass('meta-lightbox-open');
$('.meta-lightbox-nav').hide(); $('.meta-lightbox-nav').hide();
$('body').removeClass( $Body.removeClass('meta-lightbox-body-effect-fade');
`meta-lightbox-body-effect-${$this.options.effect}`, $('.meta-lightbox-content .meta-lightbox-zoom-wrapper').trigger('zoom.destroy');
);
$('.meta-lightbox-content .meta-lightbox-zoom-wrapper').trigger(
'zoom.destroy',
);
// For IE // For IE
if (isMSIE) { if (ui.isMSIE) {
$overlay.find('iframe').attr('src', ' '); $overlay.find('iframe').attr('src', ' ');
$overlay.find('iframe').remove(); $overlay.find('iframe').remove();
} }
@ -626,29 +543,17 @@
// Empty content (for videos) // Empty content (for videos)
$('.meta-lightbox-content').empty(); $('.meta-lightbox-content').empty();
$('body').removeClass('meta-lightbox-body-effect-fade'); $Body.removeClass('meta-lightbox-body-effect-fade');
}
}
this.options.afterHideLightbox.call(this); $(W).on(`${Events.AJAX} ${Events.LOADED}`, () => {
}, MetaLightboxUI.init();
});
isHidpi: function() { W.MetaLightboxUI = MetaLightboxUI;
var mediaQuery =
'(-webkit-min-device-pixel-ratio: 1.5),\
(min--moz-device-pixel-ratio: 1.5),\
(-o-min-device-pixel-ratio: 3/2),\
(min-resolution: 1.5dppx)';
if (window.devicePixelRatio > 1) return true;
return window.matchMedia && window.matchMedia(mediaQuery).matches;
},
};
$.fn[pluginName] = function(options) { return MetaLightboxUI;
return this.each(function() { })($);
if (!$.data(this, pluginName)) {
$.data(this, pluginName, new MetaLightbox(this, options));
}
});
};
$(document).metaLightbox(); export default MetaLightboxUI;
})(jQuery, this, document);

View File

@ -43,6 +43,7 @@
text-align: center; text-align: center;
width: 1.2em; width: 1.2em;
height: 1.2em; height: 1.2em;
line-height: 1.2em;
&:focus { &:focus {
color: $lightbox-link-hover-color; color: $lightbox-link-hover-color;

View File

@ -77,6 +77,7 @@
position: absolute; position: absolute;
top: 2%; top: 2%;
right: 2%; right: 2%;
line-height: 1em;
} }
.meta-lightbox-image { .meta-lightbox-image {