jQuery(function($){
var freshNonceRequest=null;
enhanceClearableTextFields();
enhanceSafariDateInputs();
enhanceCategoryPickers();
enhanceKeywordAutocomplete();
watchSearchUiMounts();
function categorySelects(){
return $('.em-event-search-form select.em-search-category-select, .em-event-search-form select[name="event-category"], .em-event-search-form select[data-role="search-category"]').filter(function(){
return !$(this).closest('.wp-admin, .em-submit-shell, .em-user-events-filters').length;
});
}
function enhanceClearableTextFields(){
$('.em-search-text-control').each(function(){
var $control=$(this);
var $input=$control.find('input').first();
if(!$input.length){
return;
}
syncClearableTextField($input);
});
}
function syncClearableTextField($input){
$input.closest('.em-search-text-control').toggleClass('is-empty', $.trim($input.val()||'')==='');
}
$(document).on('input change', '.em-search-text-control input', function(){
syncClearableTextField($(this));
});
$(document).on('click', '[data-role="clear-search-text"]', function(event){
event.preventDefault();
var $input=$(this).closest('.em-search-text-control').find('input').first();
$input.val('').trigger('input').trigger('change').trigger('focus');
});
registerSafariDateSubmitNormalizer();
registerSafariDatePickerHandlers();
function isSafariBrowser(){
var ua=window.navigator.userAgent||'';
return /Safari/i.test(ua)&&!/Chrome|Chromium|CriOS|FxiOS|Edg|OPR|Android/i.test(ua);
}
function enhanceSafariDateInputs(){
if(!isSafariBrowser()){
return;
}
$('.em-search-date-control input[type="date"]').each(function(){
var $input=$(this);
if($input.data('emSafariDateReady')){
return;
}
var value=$.trim($input.val()||'');
$input
.data('emSafariDateReady', true)
.attr('type', 'text')
.attr('inputmode', 'numeric')
.attr('autocomplete', 'off')
.attr('placeholder', 'gg/mm/aaaa')
.addClass('em-safari-date-input');
if(isIsoDate(value)){
$input.val(isoToDisplayDate(value));
}
if(!$input.siblings('[data-role="open-safari-date-picker"]').length){
$('<button>', {
type: 'button',
class: 'em-safari-date-picker-toggle',
'data-role': 'open-safari-date-picker',
'aria-label': 'Apri calendario',
title: 'Apri calendario'
}).insertAfter($input);
}});
}
function registerSafariDateSubmitNormalizer(){
if(window.emSafariDateSubmitNormalizerReady){
return;
}
window.emSafariDateSubmitNormalizerReady=true;
window.emNormalizeSearchDates=function(form){
normalizeSafariDateInputs($(form));
};
$(document).on('submit.emSafariDateNormalizer', '.em-event-search-form, .em-artist-search-form', function(){
normalizeSafariDateInputs($(this));
});
document.addEventListener('submit', function(event){
var form=event.target;
if(!form||!form.matches||!form.matches('.em-event-search-form, .em-artist-search-form')){
return;
}
normalizeSafariDateInputs($(form));
}, true);
}
function registerSafariDatePickerHandlers(){
if(window.emSafariDatePickerHandlersReady){
return;
}
window.emSafariDatePickerHandlersReady=true;
$(document).on('click', '[data-role="open-safari-date-picker"]', function(event){
event.preventDefault();
event.stopPropagation();
openSafariDatePicker($(this).closest('.em-search-date-control').find('.em-safari-date-input').first());
});
$(document).on('focus click', '.em-safari-date-input', function(event){
event.stopPropagation();
openSafariDatePicker($(this));
});
$(document).on('keydown', '.em-safari-date-input', function(event){
if(event.key==='ArrowDown'){
event.preventDefault();
openSafariDatePicker($(this));
}
if(event.key==='Escape'){
closeSafariDatePicker();
}});
$(document).on('click', '.em-safari-date-picker [data-date]', function(event){
event.preventDefault();
event.stopPropagation();
var $button=$(this);
var $picker=$button.closest('.em-safari-date-picker');
var $input=$picker.closest('.em-search-date-control').find('.em-safari-date-input').first();
$input.val(isoToDisplayDate($button.attr('data-date')||'')).trigger('input').trigger('change').trigger('focus');
closeSafariDatePicker();
});
$(document).on('click', '.em-safari-date-picker [data-month-shift]', function(event){
event.preventDefault();
event.stopPropagation();
var $picker=$(this).closest('.em-safari-date-picker');
var shift=parseInt($(this).attr('data-month-shift'), 10)||0;
var year=parseInt($picker.attr('data-year'), 10);
var month=parseInt($picker.attr('data-month'), 10);
var next=new Date(year, month + shift, 1);
renderSafariDatePicker($picker, next.getFullYear(), next.getMonth(), $picker.attr('data-selected')||'');
});
$(document).on('click', function(event){
if(!$(event.target).closest('.em-search-date-control').length){
closeSafariDatePicker();
}});
$(document).on('click', '[data-role="clear-search-date"]', function(){
closeSafariDatePicker();
});
}
function openSafariDatePicker($input){
if(!$input.length){
return;
}
var $control=$input.closest('.em-search-date-control');
var selectedIso=displayToIsoDate($.trim($input.val()||''));
var base=selectedIso ? parseIsoDate(selectedIso):new Date();
var $picker=$control.children('.em-safari-date-picker');
$('.em-safari-date-picker').not($picker).remove();
if(!$picker.length){
$picker=$('<div>', {
class: 'em-safari-date-picker',
role: 'dialog',
'aria-label': 'Seleziona data'
});
$control.append($picker);
}
renderSafariDatePicker($picker, base.getFullYear(), base.getMonth(), selectedIso);
}
function closeSafariDatePicker(){
$('.em-safari-date-picker').remove();
}
function renderSafariDatePicker($picker, year, month, selectedIso){
var monthNames=['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'];
var dayNames=['L', 'M', 'M', 'G', 'V', 'S', 'D'];
var first=new Date(year, month, 1);
var daysInMonth=new Date(year, month + 1, 0).getDate();
var startOffset=(first.getDay() + 6) % 7;
$picker.empty().attr({
'data-year': year,
'data-month': month,
'data-selected': selectedIso||''
});
var $header=$('<div>', { class: 'em-safari-date-picker__header' });
$header.append($('<button>', { type: 'button', class: 'em-safari-date-picker__nav', 'data-month-shift': '-1', 'aria-label': 'Mese precedente', text: '<' }),
$('<div>', { class: 'em-safari-date-picker__title', text: monthNames[month] + ' ' + year }),
$('<button>', { type: 'button', class: 'em-safari-date-picker__nav', 'data-month-shift': '1', 'aria-label': 'Mese successivo', text: '>' })
);
var $grid=$('<div>', { class: 'em-safari-date-picker__grid' });
dayNames.forEach(function(dayName){
$grid.append($('<span>', { class: 'em-safari-date-picker__weekday', text: dayName }));
});
for (var blank=0; blank < startOffset; blank++){
$grid.append($('<span>', { class: 'em-safari-date-picker__blank' }));
}
for (var day=1; day <=daysInMonth; day++){
var iso=year + '-' + padDatePart(month + 1) + '-' + padDatePart(day);
$grid.append($('<button>', {
type: 'button',
class: 'em-safari-date-picker__day' + (iso===selectedIso ? ' is-selected':''),
'data-date': iso,
'aria-pressed': iso===selectedIso ? 'true':'false',
text: String(day)
}));
}
$picker.append($header, $grid);
}
function normalizeSafariDateInputs($form){
$form.find('.em-safari-date-input').each(function(){
var $input=$(this);
var value=$.trim($input.val()||'');
if(value===''){
return;
}
var iso=displayToIsoDate(value);
if(iso){
$input.val(iso);
}});
}
function isIsoDate(value){
return /^\d{4}-\d{2}-\d{2}$/.test(value);
}
function isoToDisplayDate(value){
if(!isIsoDate(value)){
return value;
}
var parts=value.split('-');
return parts[2] + '/' + parts[1] + '/' + parts[0];
}
function displayToIsoDate(value){
if(isIsoDate(value)){
return isValidIsoDate(value) ? value:'';
}
var match=value.match(/^(\d{1,2})[\/\-.](\d{1,2})[\/\-.](\d{4})$/);
if(!match){
return '';
}
var day=('0' + match[1]).slice(-2);
var month=('0' + match[2]).slice(-2);
var year=match[3];
var iso=year + '-' + month + '-' + day;
return isValidIsoDate(iso) ? iso:'';
}
function isValidIsoDate(value){
if(!isIsoDate(value)){
return false;
}
var parts=value.split('-');
var date=parseIsoDate(value);
return date.getFullYear()===Number(parts[0])&&date.getMonth()===Number(parts[1]) - 1&&date.getDate()===Number(parts[2]);
}
function parseIsoDate(value){
var parts=value.split('-');
return new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2]));
}
function padDatePart(value){
return ('0' + value).slice(-2);
}
function enhanceCategoryPickers(){
categorySelects().each(function(){
var $select=$(this);
if($select.data('emCategoryPickerReady')){
return;
}
$select.data('emCategoryPickerReady', true);
var pickerId=($select.attr('id')||'em-category') + '-picker';
var groups=readGroups($select);
var expandedGroups={};
var $picker=$('<div>', { class: 'em-category-picker em-category-picker--selectlike', id: pickerId });
var $button=$('<button>', {
type: 'button',
class: 'em-category-picker__button',
'aria-haspopup': 'listbox',
'aria-expanded': 'false'
});
var $value=$('<span>', { class: 'em-category-picker__value' });
var $panel=$('<div>', { class: 'em-category-picker__panel', role: 'listbox' });
var $search=$('<input>', {
type: 'search',
class: 'em-category-picker__search',
placeholder: 'Cerca categoria',
'aria-label': 'Cerca categoria'
}).attr('autocomplete', 'off');
var $list=$('<div>', { class: 'em-category-picker__list' });
$button.append($value, $('<span>', { class: 'em-category-picker__chevron', 'aria-hidden': 'true', text: '⌄' }));
$panel.append($search, $list);
$picker.append($button, $panel);
$select.after($picker).addClass('em-search-native-select');
syncButton();
buildList();
$picker.on('click', function(event){
event.stopPropagation();
});
$button.on('click', function(event){
event.stopPropagation();
if($(event.target).closest('.em-category-picker__clear').length){
event.preventDefault();
expandedGroups={};
selectValue('');
return;
}
$picker.hasClass('is-open') ? closePicker():openPicker();
});
$button.on('keydown', function(event){
if(event.key==='Enter'||event.key===' '||event.key==='ArrowDown'){
event.preventDefault();
openPicker();
}});
$search.on('input', buildList);
$search.on('keydown', function(event){
if(event.key==='Escape'){
closePicker();
$button.trigger('focus');
}});
$list.on('click', '.em-category-picker__option', function(event){
event.preventDefault();
event.stopPropagation();
var toggleGroup=$(this).attr('data-toggle-group');
if(toggleGroup){
expandedGroups[toggleGroup] = !expandedGroups[toggleGroup];
buildList();
return;
}
selectValue($(this).attr('data-value')||'');
});
$list.on('keydown', '.em-category-picker__option', function(event){
if(event.key==='Enter'||event.key===' '){
event.preventDefault();
$(this).trigger('click');
}
if(event.key==='Escape'){
closePicker();
$button.trigger('focus');
}});
$select.on('change', function(){
syncButton();
buildList();
});
$(document).on('click.emCategoryPicker', function(event){
if(!$picker.is(event.target)&&!$picker.has(event.target).length){
closePicker();
}});
function readGroups($source){
var result=[];
var direct={ label: 'Categorie', value: '', parentLabel: 'Categorie', children: [] };
$source.children().each(function(){
var $node=$(this);
if($node.is('option')){
direct.children.push({
label: $.trim($node.text()),
value: $node.val(),
parent: false,
group: direct.label
});
}
if($node.is('optgroup')){
var group={
label: $.trim($node.attr('label')||''),
value: '',
parentLabel: $.trim($node.attr('label')||''),
children: []
};
$node.children('option').each(function(){
var $option=$(this);
var label=$.trim($option.text());
var isParent=/^Tutti:\s*/i.test(label);
if(isParent){
group.value=$option.val();
group.parentLabel=label.replace(/^Tutti:\s*/i, '');
}
group.children.push({
label: label.replace(/^Tutti:\s*/i, 'Tutti: '),
value: $option.val(),
parent: isParent,
group: group.label
});
});
result.push(group);
}});
if(direct.children.length){
result.unshift(direct);
}
return result;
}
function selectedLabel(){
return ($.trim($select.find('option:selected').text())||'Tutte le categorie').replace(/^Tutti:\s*/i, '');
}
function syncButton(){
var value=$select.val();
$button.toggleClass('has-selection', value!=='');
$value.empty();
if(value){
$value.append($('<span>', { class: 'em-category-picker__selected-badge' })
.text(selectedLabel())
.append($('<span>', { class: 'em-category-picker__clear', 'aria-hidden': 'true', text: 'x' }))
);
}else{
$value.text('Tutte le categorie');
}}
function optionMatches(option, filter){
return !filter||option.label.toLowerCase().indexOf(filter)!==-1||(option.group||'').toLowerCase().indexOf(filter)!==-1;
}
function appendOption(option, extraClass){
var selected=option.value===$select.val();
var $item=$('<button>', {
type: 'button',
class: 'em-category-picker__option' + (selected ? ' is-selected':'') + (option.parent ? ' is-parent':'') + (extraClass ? ' ' + extraClass:''),
'data-value': option.value,
role: 'option',
'aria-selected': selected ? 'true':'false'
});
$item.append($('<span>', { class: 'em-category-picker__option-label', text: option.label }));
if(option.group&&!option.parent){
$item.append($('<span>', { class: 'em-category-picker__option-group', text: option.group }));
}
$list.append($item);
}
function appendGroupToggle(group, expanded){
var $item=$('<button>', {
type: 'button',
class: 'em-category-picker__option em-category-picker__option--group-toggle' + (expanded ? ' is-expanded':''),
'data-toggle-group': group.label,
'aria-expanded': expanded ? 'true':'false'
});
$item.append($('<span>', { class: 'em-category-picker__option-label', text: group.parentLabel||group.label }));
$item.append($('<span>', { class: 'em-category-picker__expand-icon', 'aria-hidden': 'true', text: expanded ? '-':'+' }));
$list.append($item);
}
function buildList(){
var filter=$.trim($search.val()||'').toLowerCase();
var hasFilter=filter!=='';
var rendered=0;
$list.empty();
$.each(groups, function(index, group){
var matching=group.children.filter(function(option){
return optionMatches(option, filter);
});
if(!matching.length&&(!hasFilter||group.label.toLowerCase().indexOf(filter)===-1)){
return;
}
if(group.label==='Categorie'){
$.each(matching, function(optionIndex, option){
appendOption(option);
rendered++;
});
return;
}
var expanded=hasFilter||expandedGroups[group.label]===true;
appendGroupToggle(group, expanded);
rendered++;
if(!expanded){
return;
}
$.each(matching, function(optionIndex, option){
appendOption(option, 'em-category-picker__option--child');
rendered++;
});
});
if(!rendered){
$list.append($('<div>', { class: 'em-category-picker__empty', text: 'Nessuna categoria trovata' }));
}}
function openPicker(){
$('.em-category-picker.is-open').not($picker).removeClass('is-open').find('.em-category-picker__button').attr('aria-expanded', 'false');
$picker.addClass('is-open');
$button.attr('aria-expanded', 'true');
buildList();
window.setTimeout(function(){
$search.trigger('focus');
}, 0);
}
function closePicker(){
$picker.removeClass('is-open');
$button.attr('aria-expanded', 'false');
}
function selectValue(value){
$select.val(value).trigger('change');
syncButton();
buildList();
closePicker();
}});
}
function enhanceKeywordAutocomplete(){
$('.em-search-keyword').each(function(){
var $input=$(this);
if($input.data('emKeywordAutocompleteReady')||typeof $input.autocomplete!=='function'){
return;
}
$input.data('emKeywordAutocompleteReady', true);
$input.autocomplete({
source: function(request, response){
var ajaxConfig=typeof nc!=='undefined' ? nc:{};
ensureSearchNonce(ajaxConfig).then(function(){
requestSearchSuggestions(ajaxConfig, request.term, false).done(function(result){
response(result&&result.success&&result.data ? result.data.suggestions||[]:[]);
}).fail(function(){
response([]);
});
}, function(){
response([]);
});
},
minLength: 2,
delay: 160,
select: function(event, ui){
$input.val(ui.item.value||ui.item.label||'');
return false;
},
open: function(){
$('.ui-autocomplete').addClass('em-search-keyword-menu');
}}).autocomplete('instance')._renderItem=function(ul, item){
return $('<li>')
.append($('<div>', { class: 'em-search-suggestion' })
.append($('<span>', { class: 'em-search-suggestion__type' }).text(item.type||''))
.append($('<span>', { class: 'em-search-suggestion__label' }).text(item.label||item.value||''))
)
.appendTo(ul);
};});
}
function ensureSearchNonce(ajaxConfig){
if(ajaxConfig.searchNonceFresh&&ajaxConfig.nonce){
return $.Deferred().resolve(ajaxConfig.nonce).promise();
}
return refreshSearchNonce(ajaxConfig).then(function(nonce){
ajaxConfig.nonce=nonce;
ajaxConfig.searchNonceFresh=true;
if(typeof nc!=='undefined'){
nc.nonce=nonce;
nc.searchNonceFresh=true;
}
return nonce;
});
}
function requestSearchSuggestions(ajaxConfig, term, didRefreshNonce){
return $.ajax({
url: ajaxConfig.url||'',
method: 'GET',
dataType: 'json',
data: {
action: 'em_search_suggestions',
_nonce: ajaxConfig.nonce||'',
q: term
}}).then(function(result){
return result;
},
function(xhr){
if(didRefreshNonce||!xhr||xhr.status!==403){
return $.Deferred().reject(xhr).promise();
}
return refreshSearchNonce(ajaxConfig).then(function(nonce){
ajaxConfig.nonce=nonce;
ajaxConfig.searchNonceFresh=true;
if(typeof nc!=='undefined'){
nc.nonce=nonce;
nc.searchNonceFresh=true;
}
return requestSearchSuggestions(ajaxConfig, term, true);
});
}
);
}
function refreshSearchNonce(ajaxConfig){
if(freshNonceRequest){
return freshNonceRequest;
}
freshNonceRequest=$.ajax({
url: ajaxConfig.url||'',
method: 'GET',
dataType: 'json',
data: {
action: 'em_event_list_nonce'
}}).then(function(result){
freshNonceRequest=null;
if(result&&result.success&&result.data&&result.data.nonce){
return result.data.nonce;
}
return $.Deferred().reject().promise();
}, function(xhr){
freshNonceRequest=null;
return $.Deferred().reject(xhr).promise();
});
return freshNonceRequest;
}
function watchSearchUiMounts(){
if(!window.MutationObserver||!document.body){
return;
}
var scheduled=false;
var observer=new MutationObserver(function(mutations){
var shouldRun=mutations.some(function(mutation){
return Array.prototype.some.call(mutation.addedNodes||[], function(node){
return node.nodeType===1&&($(node).is('.em-event-search-form, select, input')||$(node).find('.em-event-search-form, select, input').length);
});
});
if(!shouldRun||scheduled){
return;
}
scheduled=true;
window.setTimeout(function(){
scheduled=false;
enhanceCategoryPickers();
enhanceKeywordAutocomplete();
enhanceClearableTextFields();
enhanceSafariDateInputs();
}, 80);
});
observer.observe(document.body, { childList: true, subtree: true });
}});