288 lines
8.9 KiB
JavaScript
288 lines
8.9 KiB
JavaScript
const toggleBackgroundElements = (hide) => {
|
|
$('main, header, footer, [data-aria-hide-on-modal]').attr('aria-hidden', hide ? 'true' : 'false');
|
|
};
|
|
|
|
const trapFocus = (modal) => {
|
|
const focusableElements = modal.find('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])').get();
|
|
const firstElement = focusableElements[0];
|
|
const lastElement = focusableElements[focusableElements.length - 1];
|
|
|
|
modal.on('keydown', function (e) {
|
|
if (e.key === 'Tab') {
|
|
if (e.shiftKey) {
|
|
// Shift+Tab
|
|
if (document.activeElement === firstElement) {
|
|
e.preventDefault();
|
|
lastElement.focus();
|
|
}
|
|
} else {
|
|
// Tab
|
|
if (document.activeElement === lastElement) {
|
|
e.preventDefault();
|
|
firstElement.focus();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
|
|
wpj.focus = {
|
|
focusName: ADMIN ? "focusAdmin" : "focus",
|
|
create: (options) => {
|
|
let focusName = ADMIN ? "focusAdmin" : "focus";
|
|
let $wpjFocuses = wpj.focus.getFocuses();
|
|
const template = $(wpj.focus.getFocusLoadingTemplate());
|
|
$wpjFocuses.append(template);
|
|
|
|
const $focus = template[focusName](options);
|
|
|
|
$focus[focusName]('load');
|
|
|
|
return $focus[focusName]('instance');
|
|
},
|
|
createDeduplicated: (endpoint, ajaxSubmit = false, removeOnClose = false, focusCustomClass = null, focusTriggerEventName = null) => {
|
|
// zaridim, ze existuje wrapper, ve kterem budu focusy vytvaret
|
|
let $wpjFocuses = wpj.focus.getFocuses();
|
|
let focusName = ADMIN ? "focusAdmin" : "focus";
|
|
|
|
// pokud jsem focus uz jednou vytvoril, tak otevru ten uz vytvoreny
|
|
const $existingFocus = $wpjFocuses.find('.focus[data-focus-endpoint="'+ endpoint +'"]');
|
|
if ($existingFocus.length) {
|
|
$existingFocus[focusName]('show');
|
|
return;
|
|
}
|
|
|
|
// pridam novy focus s vychozi loading sablonou
|
|
$wpjFocuses.append(
|
|
wpj.focus.getFocusLoadingTemplate(endpoint)
|
|
);
|
|
|
|
// inicializuju focus a zavolam na nem load, aby se naloadoval
|
|
const $focus = $wpjFocuses.find('.focus[data-focus-endpoint="'+ endpoint +'"]')[focusName]({
|
|
opened: true,
|
|
onDemandEndpoint: endpoint,
|
|
ajaxSubmit: ajaxSubmit,
|
|
removeOnClose: removeOnClose,
|
|
focusCustomClass: focusCustomClass,
|
|
focusTriggerEventName: focusTriggerEventName
|
|
});
|
|
|
|
$focus[focusName]('load');
|
|
},
|
|
getFocusLoadingTemplate: (endpoint) => {
|
|
if (endpoint){
|
|
return '<div data-focus-endpoint="' + endpoint + '" class="focus"><div class="focus-dialog"><div class="focus-content"><div class="focus-loading"></div></div></div></div>';
|
|
}
|
|
return '<div class="focus"><div class="focus-dialog"><div class="focus-content"><div class="focus-loading"></div></div></div></div>';
|
|
},
|
|
getFocuses: () => {
|
|
let $wpjFocuses = $('[data-wpj-focuses]');
|
|
if (!$wpjFocuses.length) {
|
|
// vytvorim si wrapper
|
|
$('body').append('<div data-wpj-focuses style="z-index: 999"></div>');
|
|
$wpjFocuses = $('[data-wpj-focuses]');
|
|
}
|
|
return $wpjFocuses;
|
|
}
|
|
};
|
|
|
|
$.widget("wpj." + wpj.focus.focusName, {
|
|
options: {
|
|
opened: false,
|
|
closeOnBgClick: true,
|
|
addBodyPadding: false,
|
|
onDemandEndpoint: null,
|
|
ajaxSubmit: false,
|
|
removeOnClose: false,
|
|
show: null,
|
|
hide: null,
|
|
},
|
|
_create: function() {
|
|
var me = this;
|
|
|
|
this.element.on('click', '[data-focus=close]', function() {
|
|
return me.hide();
|
|
});
|
|
|
|
this._super();
|
|
|
|
if (this.options.opened) {
|
|
this.show(true);
|
|
}
|
|
},
|
|
toggle: function(show) {
|
|
if (typeof show === 'undefined') {
|
|
show = !this.element.is('.active');
|
|
}
|
|
|
|
return show ? this.show() : this.hide();
|
|
},
|
|
show: function(immediate) {
|
|
this.element.addClass('active').attr('tabindex', '-1').focus();
|
|
const focusableElements = this.element.find('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
|
|
|
var me = this,
|
|
$body = $('body');
|
|
|
|
if (this.options.addBodyPadding && wpj.domUtils.getScrollbarWidth()) {
|
|
this.element.add('body').css('padding-right', wpj.domUtils.getScrollbarWidth());
|
|
}
|
|
|
|
$body
|
|
.on('mousedown.focus', function(e) {
|
|
// pac-item => results in googlemaps input autocomplete
|
|
if (me.element.has(e.target).length || !me.options.closeOnBgClick ||
|
|
$(e.target).hasClass('pac-item') || $(e.target).hasClass('pac-item-query') || $(e.target).parents('.pac-item').length) {
|
|
return;
|
|
}
|
|
|
|
me.hide();
|
|
})
|
|
.on('keydown.focus', function(e) {
|
|
if (e.key !== 'Escape') {
|
|
return true;
|
|
}
|
|
|
|
me.hide();
|
|
return false;
|
|
})
|
|
.removeClass('focus-closed')
|
|
.addClass('focus-opened');
|
|
|
|
toggleBackgroundElements(true);
|
|
trapFocus(this.element);
|
|
|
|
setTimeout(() => {
|
|
const firstFocusable = focusableElements.length > 0 ? focusableElements.get(0) : this.element.get(0);
|
|
|
|
if (firstFocusable && typeof firstFocusable.focus === 'function')
|
|
firstFocusable.focus();
|
|
}, 50);
|
|
|
|
if (!immediate) {
|
|
$body.addClass('focus-transition');
|
|
}
|
|
|
|
if (this.options.ajaxSubmit) {
|
|
this.registerAjaxSubmit();
|
|
}
|
|
|
|
this._trigger( "show" );
|
|
|
|
return false;
|
|
},
|
|
hide: function() {
|
|
this.element.removeClass('active');
|
|
$('body')
|
|
.off('mousedown.focus')
|
|
.off('keydown.focus')
|
|
.removeClass('focus-opened')
|
|
.addClass('focus-closed');
|
|
|
|
if (this.options.addBodyPadding && wpj.domUtils.getScrollbarWidth()) {
|
|
this.element.add('body').css('padding-right', 0);
|
|
}
|
|
|
|
this.element.trigger('focusClosed');
|
|
|
|
toggleBackgroundElements(false);
|
|
|
|
const lastFocused = this.element.data('last-focused');
|
|
|
|
if (lastFocused && typeof lastFocused.focus === 'function') {
|
|
lastFocused.focus();
|
|
} else {
|
|
document.body.focus();
|
|
}
|
|
|
|
|
|
if (this.options.ajaxSubmit) {
|
|
this.element.off('submit', 'form');
|
|
}
|
|
|
|
if (this.options.removeOnClose) {
|
|
this.element.remove();
|
|
}
|
|
|
|
this._trigger( "hide" );
|
|
|
|
return false;
|
|
},
|
|
load: function () {
|
|
if (!this.options.onDemandEndpoint) {
|
|
return;
|
|
}
|
|
|
|
const me = this;
|
|
if (this.options.focusCustomClass) {
|
|
me.element.addClass(this.options.focusCustomClass);//('focus-delivery-widgets');
|
|
}
|
|
|
|
// Handle callback
|
|
if (typeof this.options.onDemandEndpoint === "function") {
|
|
this.options.onDemandEndpoint(me.element.find('.focus-content')[0]);
|
|
return;
|
|
}
|
|
|
|
// Handle global function
|
|
if (typeof window[this.options.onDemandEndpoint] === "function") {
|
|
window[this.options.onDemandEndpoint](me.element.find('.focus-content')[0]);
|
|
return;
|
|
}
|
|
|
|
// nacteni ondemand focusu
|
|
fetch(this.options.onDemandEndpoint)
|
|
.then((response) => response.text())
|
|
.then((response) => {
|
|
const focusClasses = [...$(response).prop('classList'), ...['active']];
|
|
// replacnu obsah focusu naloadovanym obsahem
|
|
me.element.html($(response).html());
|
|
// nastavim focusu classy podle nacteneho focusu
|
|
me.element.attr('class', focusClasses.join(' '))
|
|
|
|
if (me.options.focusTriggerEventName) {
|
|
$('body').trigger(me.options.focusTriggerEventName, me);
|
|
}
|
|
});
|
|
},
|
|
registerAjaxSubmit: function () {
|
|
const me = this;
|
|
this.element.on('submit', 'form', function (e) {
|
|
e.preventDefault();
|
|
|
|
const $this = $(e.target);
|
|
const data = $this.serialize();
|
|
const url = $this.attr('action');
|
|
|
|
wpj.domUtils.reloadPartsFromUrl(url, me.element.find('[data-reload]'), data);
|
|
});
|
|
|
|
this.element.on('click', '[data-ondemand]', function(e) {
|
|
const $this = $(e.target);
|
|
const url = $this.attr('href');
|
|
|
|
wpj.domUtils.reloadPartsFromUrl(url, me.element.find('[data-reload]'), undefined, () => {});
|
|
return false;
|
|
});
|
|
}
|
|
});
|
|
|
|
$(document).on('click', '[data-wpj-focus]', function () {
|
|
const endpoint = $(this).data('wpj-focus');
|
|
const ajaxSubmit = $(this).data('wpj-focus-ajax');
|
|
const removeOnClose = $(this).data('wpj-focus-remove-on-close');
|
|
const focusCustomClass = $(this).data('wpj-focus-custom-class');
|
|
const focusTriggerEventName = $(this).data('wpj-focus-trigger-event-name');
|
|
if (endpoint) {
|
|
wpj.focus.createDeduplicated(endpoint, !!ajaxSubmit, removeOnClose, focusCustomClass, focusTriggerEventName);
|
|
}
|
|
|
|
return false;
|
|
});
|
|
|
|
// Pro nacteni fallback focusu pri nacteni stranky (nikotino - vyber prodejny)
|
|
if (MODULES.COMPONENTS) {
|
|
window.dispatchEvent(new Event("wpjFocusLoaded"));
|
|
}
|