163 lines
5.0 KiB
JavaScript
163 lines
5.0 KiB
JavaScript
/**
|
|
* Settings → Viator Structure editor. Regions and cities are plain DOM
|
|
* blocks; cities can only be added from the Viator destination search, and
|
|
* indexed field names are assigned on submit.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var cfg = window.vcStructure || {};
|
|
var i18n = cfg.i18n || {};
|
|
var form = document.getElementById('vc-structure-form');
|
|
var list = document.getElementById('vc-regions');
|
|
if (!form || !list) {
|
|
return;
|
|
}
|
|
|
|
function slugify(s) {
|
|
return String(s).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
}
|
|
|
|
function fromTemplate(id) {
|
|
var tpl = document.getElementById(id);
|
|
return tpl.content.firstElementChild.cloneNode(true);
|
|
}
|
|
|
|
function usedIds() {
|
|
var ids = {};
|
|
list.querySelectorAll('.vc-city [data-f="id"]').forEach(function (input) {
|
|
ids[input.value] = true;
|
|
});
|
|
return ids;
|
|
}
|
|
|
|
function move(el, dir) {
|
|
if (dir < 0 && el.previousElementSibling) {
|
|
el.parentNode.insertBefore(el, el.previousElementSibling);
|
|
} else if (dir > 0 && el.nextElementSibling) {
|
|
el.parentNode.insertBefore(el.nextElementSibling, el);
|
|
}
|
|
}
|
|
|
|
function addCity(region, item) {
|
|
var row = fromTemplate('vc-tpl-city');
|
|
row.querySelector('[data-f="id"]').value = item.id;
|
|
row.querySelector('[data-f="name"]').value = item.name;
|
|
row.querySelector('[data-f="slug"]').value = slugify(item.name);
|
|
row.querySelector('.vc-city__name').textContent = item.name;
|
|
row.querySelector('.vc-city__id').textContent = item.id;
|
|
region.querySelector('.vc-cities tbody').appendChild(row);
|
|
}
|
|
|
|
function search(region) {
|
|
var q = region.querySelector('.vc-city-search input[type="search"]');
|
|
var out = region.querySelector('.vc-results');
|
|
out.textContent = i18n.searching || '…';
|
|
|
|
var data = new FormData();
|
|
data.append('action', 'vc_search_destinations');
|
|
data.append('_ajax_nonce', cfg.nonce);
|
|
data.append('q', q.value);
|
|
|
|
fetch(cfg.ajaxUrl, { method: 'POST', credentials: 'same-origin', body: data })
|
|
.then(function (r) { return r.json(); })
|
|
.then(function (res) {
|
|
if (!res || !res.success) {
|
|
out.textContent = (res && res.data && res.data.message) || i18n.failed;
|
|
return;
|
|
}
|
|
if (!res.data.results.length) {
|
|
out.textContent = i18n.noMatches;
|
|
return;
|
|
}
|
|
var used = usedIds();
|
|
out.innerHTML = '';
|
|
res.data.results.forEach(function (item) {
|
|
var row = document.createElement('div');
|
|
var btn = document.createElement('button');
|
|
btn.type = 'button';
|
|
btn.className = 'button button-small';
|
|
if (used[item.id]) {
|
|
btn.disabled = true;
|
|
btn.textContent = i18n.used;
|
|
} else {
|
|
btn.textContent = i18n.add;
|
|
btn.addEventListener('click', function () {
|
|
addCity(region, item);
|
|
out.innerHTML = '';
|
|
q.value = '';
|
|
});
|
|
}
|
|
var label = document.createElement('span');
|
|
label.textContent = item.name + ' (ID ' + item.id + ')';
|
|
row.appendChild(btn);
|
|
row.appendChild(label);
|
|
out.appendChild(row);
|
|
});
|
|
})
|
|
.catch(function () { out.textContent = i18n.failed; });
|
|
}
|
|
|
|
list.addEventListener('click', function (e) {
|
|
var btn = e.target.closest('[data-act]');
|
|
if (!btn) {
|
|
return;
|
|
}
|
|
var region = btn.closest('.vc-region');
|
|
var city = btn.closest('.vc-city');
|
|
var target = city || region;
|
|
switch (btn.getAttribute('data-act')) {
|
|
case 'up': move(target, -1); break;
|
|
case 'down': move(target, 1); break;
|
|
case 'remove-city': city.remove(); break;
|
|
case 'remove-region':
|
|
if (window.confirm(i18n.confirm)) {
|
|
region.remove();
|
|
}
|
|
break;
|
|
case 'search': search(region); break;
|
|
}
|
|
});
|
|
|
|
list.addEventListener('keydown', function (e) {
|
|
if (e.key === 'Enter' && e.target.matches('.vc-city-search input[type="search"]')) {
|
|
e.preventDefault();
|
|
search(e.target.closest('.vc-region'));
|
|
}
|
|
});
|
|
|
|
// Suggest a region slug from its name until the slug is edited by hand.
|
|
list.addEventListener('input', function (e) {
|
|
var input = e.target;
|
|
if (input.matches('.vc-region__head [data-f="slug"]')) {
|
|
input.dataset.touched = '1';
|
|
}
|
|
if (input.matches('.vc-region__head [data-f="name"]')) {
|
|
var slug = input.closest('.vc-region__head').querySelector('[data-f="slug"]');
|
|
if (!slug.dataset.touched && (slug.value === '' || slug.dataset.auto === '1')) {
|
|
slug.value = slugify(input.value);
|
|
slug.dataset.auto = '1';
|
|
}
|
|
}
|
|
});
|
|
|
|
document.getElementById('vc-add-region').addEventListener('click', function () {
|
|
var region = fromTemplate('vc-tpl-region');
|
|
list.appendChild(region);
|
|
region.querySelector('[data-f="name"]').focus();
|
|
});
|
|
|
|
form.addEventListener('submit', function () {
|
|
list.querySelectorAll('.vc-region').forEach(function (region, i) {
|
|
region.querySelectorAll('.vc-region__head [data-f]').forEach(function (input) {
|
|
input.name = 'vc_structure[' + i + '][' + input.dataset.f + ']';
|
|
});
|
|
region.querySelectorAll('.vc-city').forEach(function (city, j) {
|
|
city.querySelectorAll('[data-f]').forEach(function (input) {
|
|
input.name = 'vc_structure[' + i + '][cities][' + j + '][' + input.dataset.f + ']';
|
|
});
|
|
});
|
|
});
|
|
});
|
|
})();
|