| Server IP : 89.248.107.232 / Your IP : 216.73.217.70 Web Server : Apache System : Linux host2.kasilh.com 5.14.0-687.36.1.el9_8.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Aug 7 05:40:49 EDT 2026 x86_64 User : seg ( 10005) PHP Version : 7.4.33 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/vhosts/seg-sa.es/grupo-seg.com/wp-content/plugins/mapplic-geo/admin/js/ |
Upload File : |
(function() {
"use strict";
function MapplicGeoAdmin(element) {
let self = this;
let obj = null;
var __ = function(t, n) { return t; }
if (typeof wp !== 'undefined') __ = wp.i18n.__;
this.init = function() {
const s = this;
this.el = document.getElementById('mgeo-admin');
if (!this.el) return false;
this.el.classList.add('mgeo-admin');
element.addEventListener('mapready', function(e) {
obj = e.detail;
s.help = new Help().init();
// bar
const bar = s.blankSection('mgeo-bar');
const save = document.createElement('button');
save.classList.add('mgeo-admin-save', 'mgeo-admin-button', 'mgeo-admin-button-primary');
save.innerHTML = __('Save Changes', 'mgeo');
bar.appendChild(save);
// raw
const raw = document.createElement('button');
raw.classList.add('mgeo-admin-button');
raw.innerHTML = __('Raw', 'mgeo');
bar.appendChild(raw);
raw.addEventListener('click', function(e) {
e.preventDefault();
const popup = document.createElement('div');
popup.classList.add('mgeo-raw-popup');
const h = document.createElement('h1');
h.innerHTML = __('Raw data', 'mgeo');
popup.appendChild(h);
const textarea = document.createElement('textarea');
textarea.setAttribute('rows', '20');
textarea.classList.add('mgeo-raw-text');
textarea.spellcheck = false;
textarea.value = JSON.stringify(self.fetchData(), null, 2);
popup.appendChild(textarea);
const update = document.createElement('button');
update.classList.add('mgeo-admin-button', 'mgeo-admin-button-primary');
update.innerHTML = __('Update', 'mgeo');
popup.appendChild(update);
update.addEventListener('click', function(e) {
e.preventDefault();
let data = false;
try { data = JSON.parse(textarea.value); }
catch(e) { alert(__('Invalid JSON!', 'mgeo')); }
self.save(data);
});
Fancybox.show([{ src: popup, type: 'html' }], { mainClass: 'mgeo-admin mgeo-admin-popup mgeo-raw-popup' });
});
const title = document.createElement('h3');
title.innerHTML = obj.el.dataset.shortcode || obj.o.data;
bar.appendChild(title);
// layouts
const layouts = document.createElement('div');
layouts.classList.add('mgeo-admin-layouts');
const desktop = document.createElement('button');
desktop.classList.add('mgeo-admin-desktop');
layouts.appendChild(desktop);
const tablet = document.createElement('button');
tablet.classList.add('mgeo-admin-tablet');
layouts.appendChild(tablet);
const mobile = document.createElement('button');
mobile.classList.add('mgeo-admin-mobile');
layouts.appendChild(mobile);
// panels
const locations = s.blankSection('mgeo-admin-locations-panel');
s.locations = new Locations().init(obj.dir.l);
locations.appendChild(s.locations.el);
const others = s.blankSection('mgeo-admin-others');
s.settings = new Settings().init(obj.o);
s.settings.el.classList.add('two-thirds');
others.appendChild(s.settings.el);
const column = document.createElement('div');
column.classList.add('third', 'last');
others.appendChild(column);
s.styles = new Styles().init(obj.styles.s);
column.appendChild(s.styles.el);
s.layers = new Layers().init(obj.container.layers);
column.prepend(s.layers.el);
s.groups = new Groups().init(obj.dir.g);
column.appendChild(s.groups.el);
// colorpicker init
Coloris({
el: '.mgeo-colorpicker',
theme: 'large',
format: 'mixed'
});
save.addEventListener('click', function(e) {
e.preventDefault();
self.save();
});
const form = document.getElementById('post');
if (form) document.getElementById('post').addEventListener('submit', function(e) { self.save(); });
});
}
this.save = function(data = null) {
if (data === null) data = self.fetchData();
if (!data) return false;
data = JSON.stringify(data);
if (obj.wp) {
document.querySelector('#mgeo-mapdata').value = data;
document.getElementById('post').submit();
}
else {
fetch('save.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: data
}).then(res => {
window.history.forward(1);
window.location.reload(true);
});
}
}
this.blankSection = function(id) {
const section = document.createElement('section');
if (id) section.id = id;
this.el.appendChild(section);
const inner = document.createElement('div');
inner.classList.add('mgeo-inner');
section.appendChild(inner);
return inner;
}
this.fetchLocations = function() {
let locations = [];
this.el.querySelectorAll('#mgeo-location-table tbody.mgeo-editable > tr').forEach(function(el, i) {
const location = {};
el.querySelectorAll('td.mgeo-cell-field').forEach(function(td, i) {
if (td.innerHTML) location[td.getAttribute('data-field')] = td.innerHTML;
});
locations.push(location);
});
return locations;
}
this.fetchLayer = function(el) {
const layer = {};
layer.id = self.validateId(el.querySelector('.mgeo-layer-id'));
if (!layer.id) return false;
self.setField(layer, 'title', el.querySelector('.mgeo-layer-title').value);
self.setField(layer, 'type', el.querySelector('.mgeo-layer-type').value);
self.setField(layer, 'source', el.querySelector('.mgeo-layer-source')?.value);
self.setField(layer, 'style', el.querySelector('.mgeo-layer-style').value);
self.setField(layer, 'extent', el.querySelector('.mgeo-layer-extent').value);
self.setField(layer, 'minZoom', el.querySelector('.mgeo-layer-minzoom').value);
self.setField(layer, 'maxZoom', el.querySelector('.mgeo-layer-maxzoom').value);
self.setField(layer, 'opacity', el.querySelector('.mgeo-layer-opacity').value);
self.setField(layer, 'selectable', el.querySelector('.mgeo-layer-selectable').checked);
self.setField(layer, 'isolated', el.querySelector('.mgeo-layer-isolated').checked);
self.setField(layer, 'hide', el.querySelector('.mgeo-layer-hide').checked);
self.setField(layer, 'disabled', el.querySelector('.mgeo-layer-disabled').checked);
return layer;
}
this.fetchData = function() {
const data = {};
let halt = false;
this.el.querySelectorAll('.error').forEach(function(el) { el.classList.remove('error'); });
// settings
data.settings = {};
data.settings.data = obj.o.data;
this.el.querySelectorAll('#mgeo-admin-settings input, #mgeo-admin-settings select, #mgeo-admin-settings textarea').forEach(function(el, i) {
if (el.value) {
const setting = el.className.replace('mgeo-setting-', '');
if (el.type == 'checkbox') data.settings[setting] = el.checked;
else if (el.type == 'number') data.settings[setting] = parseFloat(el.value);
else data.settings[setting] = el.value;
}
});
// styles
data.styles = [];
this.el.querySelectorAll('#mgeo-admin-styles .mgeo-admin-list > .mgeo-admin-list-item').forEach(function(el, i) {
const style = {
class: self.validateId(el.querySelector('.mgeo-style-class')),
base: {}
};
if (!style.class) halt = true;
const base = el.querySelector('.mgeo-style-base').value;
if (base) style.base = { fill: base };
const hover = el.querySelector('.mgeo-style-hover').value;
if (hover) style.hover = { fill: hover };
const active = el.querySelector('.mgeo-style-active').value;
if (active) style.active = { fill: active };
const stroke = el.querySelector('.mgeo-style-stroke').value;
if (stroke) style.base.stroke = stroke;
const strokeWidth = el.querySelector('.mgeo-style-stroke-width').value;
if (strokeWidth) style.base.strokeWidth = strokeWidth;
const textColor = el.querySelector('.mgeo-style-text-color').value;
if (textColor) style.base.textColor = textColor;
data.styles.push(style);
});
// groups
data.groups = [];
this.el.querySelectorAll('#mgeo-admin-groups .mgeo-admin-list > .mgeo-admin-list-item').forEach(function(el) {
const group = {};
group.id = self.validateId(el.querySelector('.mgeo-group-id'));
if (!group.id) halt = true;
self.setField(group, 'title', el.querySelector('.mgeo-group-title').value);
self.setField(group, 'color', el.querySelector('.mgeo-group-color').value);
self.setField(group, 'thumbnail', el.querySelector('.mgeo-group-thumbnail').value);
self.setField(group, 'style', el.querySelector('.mgeo-group-style').value);
self.setField(group, 'hide', el.querySelector('.mgeo-group-hide').checked);
data.groups.push(group);
});
// layers
data.layers = [];
this.el.querySelectorAll('#mgeo-admin-layers .mgeo-admin-list > .mgeo-admin-list-item').forEach(function(el) {
if (el.classList.contains('mgeo-layer-group')) {
const lg = {};
lg.id = self.validateId(el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-id'));
if (!lg.id) halt = true;
self.setField(lg, 'title', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-title').value);
self.setField(lg, 'extent', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-extent')?.value);
self.setField(lg, 'minZoom', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-minzoom').value);
self.setField(lg, 'maxZoom', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-maxzoom').value);
self.setField(lg, 'opacity', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-opacity').value);
self.setField(lg, 'selectable', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-selectable').checked);
self.setField(lg, 'isolated', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-isolated').checked);
self.setField(lg, 'hide', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-hide').checked);
self.setField(lg, 'disabled', el.querySelector(':scope > .mgeo-admin-list-item-body .mgeo-layer-disabled').checked);
lg.layers = [];
el.querySelectorAll('.mgeo-gl-list > .mgeo-admin-list-item').forEach(function(sub) {
let layer = self.fetchLayer(sub);
if (!layer) halt = true;
lg.layers.push(layer);
});
data.layers.push(lg);
}
else {
let layer = self.fetchLayer(el);
if (!layer) halt = true;
data.layers.push(layer);
}
});
// unsaved rows
this.el.querySelectorAll('#mgeo-location-table tr.mgeo-edit').forEach(function(el) {
self.locations.saveRow(el);
});
// locations
data.locations = this.fetchLocations();
if (halt) return false;
else return data;
}
this.setField = function(object, attribute, value) {
if (value) object[attribute] = value;
}
this.newText = function(type, content) {
const el = document.createElement(type);
el.innerHTML = content;
return el;
}
this.validateId = function(field) {
const value = field.value.trim();
if (/^[A-Za-z]+[\w\-\:\.]*$/.test(value)) return value;
else {
field.focus();
field.closest('.mgeo-admin-list-item')?.classList.add('opened');
if (field.parentNode.tagName === 'LABEL') field.parentNode.classList.add('error');
else field.classList.add('error');
return false;
}
}
// fields
this.newTextInput = function(name, value, title = false, help = false) {
const input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('spellcheck', 'false');
if (name) input.setAttribute('class', name);
if (value) input.setAttribute('value', value);
if (title) {
const label = document.createElement('label');
label.innerHTML = __(title, 'mgeo');
if (help) self.help.addHelp(label, help);
label.appendChild(input);
return label;
}
else return input;
}
this.newNumberInput = function(name, value, title = false, help = false) {
const input = document.createElement('input');
input.setAttribute('type', 'number');
if (name) input.setAttribute('class', name);
if (value) input.setAttribute('value', value);
if (title) {
const label = document.createElement('label');
label.innerHTML = __(title, 'mgeo');
if (help) self.help.addHelp(label, help);
label.appendChild(input);
return label;
}
else return input;
}
this.newOpacityInput = function(name, value, title = false) {
const input = document.createElement('input');
input.setAttribute('type', 'number');
input.setAttribute('min', '0');
input.setAttribute('max', '1');
input.setAttribute('step', '.01');
if (name) input.setAttribute('class', name);
if (value) input.setAttribute('value', value);
if (title) {
const label = document.createElement('label');
label.innerHTML = __(title, 'mgeo');
label.appendChild(input);
return label;
}
else return input;
}
this.newActionInput = function(name, type, value, title = false, help = false) {
const input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('spellcheck', 'false');
if (name) input.setAttribute('class', name);
if (value) input.setAttribute('value', value);
const button = document.createElement('button');
button.classList.add('mgeo-input-action');
let el = document.createElement('label');
if (title) el.innerHTML = __(title, 'mgeo');
el.appendChild(input);
el.appendChild(button);
if (type == 'extent') {
button.appendChild(document.createElement('i')).classList.add('mgeo-icon-extent');
button.addEventListener('click', function(e) {
e.preventDefault();
obj.container.editExtent(input);
obj.el.scrollIntoView();
});
}
else if (type == 'file') {
button.appendChild(document.createElement('i')).classList.add('mgeo-icon-upload');
button.addEventListener('click', function(e) {
e.preventDefault();
const popup = wp.media({
title: 'Select or Upload File',
button: { text: 'Select' },
multiple: false
});
popup.open();
popup.on('select', function() {
let attachment = popup.state().get('selection').first().toJSON();
input.value = attachment.url;
});
});
}
return el;
}
this.newCheckbox = function(name, value, title = false, help = false) {
const input = document.createElement('input');
input.setAttribute('type', 'checkbox');
if (name) input.setAttribute('class', name);
if (value) input.checked = true;
if (title) {
const label = document.createElement('label');
label.classList.add('mgeo-admin-checkbox');
label.innerHTML = __(title, 'mgeo');
if (help) self.help.addHelp(label, help);
label.appendChild(input);
return label;
}
else return input;
}
this.newSelect = function(name = false, options, value, title = false, help = false, multi = false, translate = true) {
const select = document.createElement('select');
if (name) select.classList.add(name);
if (multi) select.setAttribute('multiple', '');
for (const o in options) {
const option = document.createElement('option');
option.setAttribute('value', o);
option.innerHTML = typeof options[o] === 'string' ? options[o] : options[o].title;
if (translate) option.innerHTML = __(option.innerHTML, 'mgeo');
if (o == value) option.setAttribute('selected', '');
select.appendChild(option);
}
if (title) {
const label = document.createElement('label');
label.innerHTML = __(title, 'mgeo');
if (help) self.help.addHelp(label, help);
label.appendChild(select);
return label;
}
else return select;
}
this.newTypeInput = function(value = '', title = false) {
const types = Object.keys(obj.container.markers);
types.unshift('', 'text', 'circle', 'square', 'thumb', 'dot-l', 'dot-r');
const container = document.createElement('ul');
container.classList.add('mgeo-admin-type');
types.forEach(function(type) {
const item = document.createElement('li');
if (type) item.style.backgroundImage = 'url(' + obj.localize.pdir + '/admin/img/markers/' + type + '.png)';
if (value == type) item.classList.add('mgeo-selected');
const name = document.createElement('small');
name.innerHTML = type;
item.appendChild(name);
item.addEventListener('click', function() {
container.querySelector('li.mgeo-selected')?.classList.remove('mgeo-selected');
this.classList.add('mgeo-selected');
});
container.appendChild(item);
});
if (title) {
const label = document.createElement('label');
label.innerHTML = title;
label.appendChild(container);
return label;
}
else return container;
}
// help
function Help() {
const s = this;
this.text = {
'id': 'Unique ID (required)<br> - starts with a letter<br> - no space or special characters allowed',
'class': 'Unique class name (required)<br> - starts with a letter<br> - no space or special characters allowed',
'title': 'Title of the location displayed in popups and directory.',
'desc': 'HTML enabled description text displayed in popups.',
'coord': 'Comma separeted <b>latitude</b> and <b>longitude</b> of location<br> - viewport center is the initial value for new locations<br> - if left blank, position will be estimated',
'zoom': 'Focus zoom level of location<br> - if left blank, the global <b>Max zoom</b> will be used<br> - if the value is negative, zoom will be disabled',
'type': 'Type of the marker. Use the first, blank option for no marker.',
'label': 'Text added to the marker if supported',
'fill': 'Hex color used for marker and popup styling. It will be overwritten if a <b>style</b> is defined.',
'style': 'Predefined style used for complex marker and popup styling. Overwrites standard <b>fill</b> attribute.',
'action': 'Action to perform when a location is focused.',
'image': 'Image displayed in popups. Always use web optimized images for the best performance.',
'thumbnail': 'Thumbnail displayed in directory or as marker if "thumb" <b>type</b> is used.',
'group': 'Group(s) the location belongs to.',
'link': 'URL used for redirects or popup buttons.',
'about': 'Short description of the location displayed in popups and directory.',
'layer': 'ID of the layer the location belongs to. If left blank and there is no matching vector feature available, the global markers layer will be used.',
'sample': 'ID of the location to use as <b>sample</b>.',
'hide': 'Hide location from directory only.',
'disabled': 'Temporarily disable item.',
'global-sample': 'Every location will inherit attributes from this global sample.',
'mousewheel': 'Enable zoom with mouse wheel.',
'mousewheel-shift': 'Require SHIFT key for mouse wheel zooming.',
'hover-tooltip': 'Enable hover tooltip.',
'hover-tooltip-follow': 'Hover tooltip will follow the cursor instead of being centered.',
'deeplinking': 'Deeplinking generates custom URL for each location.',
'bluronzoomout': 'Unfocus location when zoomed all the way out.',
'resetzoomonblur': 'Zoom all the way out when a location popup is closed',
'sidebar': 'Map control containing a location directory with optional search/filters and popup window, displayed on the left side of the map by default.',
'search': 'Enable sidebar search and filters.',
'right-sidebar': 'Right aligned sidebar.',
'sort-by-title': 'Sort sidebar directory by location title.',
'thumbnails': 'Enable location thumbnails in sidebar directory.',
'sidebar-above': 'The sidebar appears above the map on portrait view.',
'csv': 'External CSV file linked to the map. The first line is the header and each additional line defines a location.',
'import-csv': 'Import all locations from the linked CSV file. Link to external CSV will be removed.',
'export-csv': 'Export all internal locations in CSV format.',
'constrain-zoom': 'Constrain zoom levels to whole numbers.',
'custom-css': 'Customize your map with CSS styles.',
'map-rotation': 'Enable map rotation and define where the control should appear.',
'fullscreen': 'Enable fullscreen and define where the control should appear.',
'zoom-buttons': 'Enable zoom buttons and define where the control should appear.',
'reset-button': 'Enable reset button and define where the control should appear.',
'level-selector': 'Enable level selector and define where the control should appear.',
'attribution': 'Add attribution to the bottom right corner of the map. Note that <b>attributions are required</b> for most data sources!',
'collapsed-attribution': 'Make the attribution collapsed by default.'
}
this.init = function() {
this.el = document.createElement('small');
this.el.classList.add('mgeo-help-tooltip');
document.body.appendChild(this.el);
return this;
}
this.addHelp = function(parent, key) {
if (!s.text[key] || !parent) return false;
const el = document.createElement('span');
el.classList.add('mgeo-help');
el.innerHTML = '?';
el.addEventListener('mouseout', function() { s.el.style.visibility = 'hidden'; });
el.addEventListener('mouseover', function() {
const bcr = el.getBoundingClientRect();
s.el.style.top = (bcr.top + window.scrollY) + 'px';
s.el.style.left = (bcr.left + bcr.width) + 'px';
s.el.innerHTML = __(s.text[key], 'mgeo');
s.el.style.visibility = 'visible';
});
parent.appendChild(el);
}
}
// settings
function Settings() {
const s = this;
this.zoneOptions = {
'' : '(Disabled)',
'top-left': 'Top left',
'top-right': 'Top right',
'bottom-left': 'Bottom left',
'bottom-right': 'Bottom right'
};
this.init = function(o) {
this.el = document.createElement('div');
this.el.id = 'mgeo-admin-settings';
const title = document.createElement('h2');
title.innerHTML = __('Settings', 'mgeo');
this.el.appendChild(title);
const icon = document.createElement('i');
icon.classList.add('mgeo-admin-icon', 'mgeo-icon-settings');
title.prepend(icon);
// blocks
const block1 = document.createElement('div');
this.el.appendChild(block1);
const block2 = document.createElement('div');
this.el.appendChild(block2).classList.add('half');
const block3 = document.createElement('div');
this.el.appendChild(block3).classList.add('half', 'last');
// general
block1.appendChild(self.newActionInput('mgeo-setting-extent', 'extent', o.extent, 'Extent'));
block1.appendChild(self.newNumberInput('mgeo-setting-portrait', o.portrait, 'Portrait breakpoint (pixels)')).classList.add('third');
block1.appendChild(self.newNumberInput('mgeo-setting-minZoom', o.minZoom, 'Min zoom')).classList.add('third');
block1.appendChild(self.newNumberInput('mgeo-setting-maxZoom', o.maxZoom, 'Max zoom')).classList.add('third', 'last');
block1.appendChild(self.newTextInput('mgeo-setting-globalSample', o.globalSample, 'Global sample ID', 'global-sample')).classList.add('third');
block1.appendChild(self.newTextInput('mgeo-setting-moreText', o.moreText, 'Custom "More" text')).classList.add('third');
block1.appendChild(self.newText('h3', __('Container', 'mgeo')));
block1.appendChild(self.newNumberInput('mgeo-setting-minHeight', o.minHeight, 'Min height (pixel)')).classList.add('third');
block1.appendChild(self.newNumberInput('mgeo-setting-maxHeight', o.maxHeight, 'Max height (pixel)')).classList.add('third');
// features
block2.appendChild(self.newText('h3', __('Features', 'mgeo')));
block2.appendChild(self.newCheckbox('mgeo-setting-mouseWheel', o.mouseWheel, 'Mousewheel zoom', 'mousewheel'));
block2.appendChild(self.newCheckbox('mgeo-setting-mouseWheelShift', o.mouseWheelShift, 'Mousewheel requires shift key', 'mousewheel-shift'));
block2.appendChild(self.newCheckbox('mgeo-setting-hoverTooltip', o.hoverTooltip, 'Hover tooltip', 'hover-tooltip'));
block2.appendChild(self.newCheckbox('mgeo-setting-hoverTooltipFollow', o.hoverTooltipFollow, 'Hover tooltip follows cursor', 'hover-tooltip-follow'));
block2.appendChild(self.newCheckbox('mgeo-setting-deeplinking', o.deeplinking, 'Deeplinking', 'deeplinking'));
block2.appendChild(self.newCheckbox('mgeo-setting-blurOnZoomOut', o.blurOnZoomOut, 'Blur on zoom out', 'bluronzoomout'));
block2.appendChild(self.newCheckbox('mgeo-setting-resetZoomOnBlur', o.resetZoomOnBlur, 'Reset zoom on blur', 'resetzoomonblur'));
// sidebar
block2.appendChild(self.newText('h3', __('Sidebar', 'mgeo')));
block2.appendChild(self.newCheckbox('mgeo-setting-sidebar', o.sidebar, 'Sidebar', 'sidebar'));
block2.appendChild(self.newCheckbox('mgeo-setting-search', o.search, 'Search and filters', 'search'));
block2.appendChild(self.newCheckbox('mgeo-setting-rightSidebar', o.rightSidebar, 'Right aligned', 'right-sidebar'));
block2.appendChild(self.newCheckbox('mgeo-setting-sortbytitle', o.sortbytitle, 'Sort by title', 'sort-by-title'));
block2.appendChild(self.newCheckbox('mgeo-setting-thumbnail', o.thumbnail, 'Thumbnails', 'thumbnails'));
block2.appendChild(self.newCheckbox('mgeo-setting-portraitSidebarAbove', o.portraitSidebarAbove, 'Sidebar above map on portrait mode', 'sidebar-above'));
// csv
block2.appendChild(self.newText('h3', __('CSV data', 'mgeo')));
block2.appendChild(self.newActionInput('mgeo-setting-csv', 'file', o.csv, 'Link CSV source', 'csv'));
const importlabel = document.createElement('label');
importlabel.innerHTML = __('Import from CSV', 'mgeo');
self.help.addHelp(importlabel, 'import-csv');
block2.appendChild(importlabel);
const importcsv = document.createElement('button');
importcsv.innerHTML = __('Import', 'mgeo');
if (!o.csv) importcsv.disabled = true;
else {
importcsv.addEventListener('click', function(e) {
e.preventDefault();
if (!obj.o.csv) alert(__('There is no CSV file linked, nothing to import.', 'mgeo'));
else {
const externals = self.locations.tbodyext.querySelectorAll('tr');
if (confirm('Would you like to import ' + externals.length + ' locations?')) {
s.el.querySelector('.mgeo-setting-csv').value = '';
externals.forEach(function(el) { self.locations.tbody.append(el) } );
self.save();
}
}
});
}
importlabel.appendChild(importcsv);
const exportlabel = document.createElement('label');
exportlabel.innerHTML = __('Export to CSV file', 'mgeo');
self.help.addHelp(exportlabel, 'export-csv');
block2.appendChild(exportlabel);
const exportcsv = document.createElement('button');
exportcsv.innerHTML = __('Export', 'mgeo');
exportcsv.addEventListener('click', function(e) {
e.preventDefault();
const l = self.fetchLocations();
let columns = new Set();
columns.add('id');
for (const id in l) columns = new Set([...columns, ...Object.keys(l[id])]);
let csv = Papa.unparse(Object.values(l), { columns: Array.from(columns) });
window.open('data:text/csv;charset=utf-8,' + escape(csv));
});
exportlabel.appendChild(exportcsv);
// advanced
block2.appendChild(self.newText('h3', __('Advanced', 'mgeo')));
block2.appendChild(self.newCheckbox('mgeo-setting-constrainResolution', o.constrainResolution, 'Constrain zoom resolution', 'constrain-zoom'));
block2.appendChild(self.newCheckbox('mgeo-setting-improvedPerformance', o.improvedPerformance, 'Improve performance', 'improved-performance'));
// custom css
const textarea = document.createElement('textarea');
textarea.setAttribute('rows', '6');
textarea.setAttribute('class', 'mgeo-setting-customcss');
textarea.setAttribute('spellcheck', 'false');
if (o.customcss) textarea.innerHTML = o.customcss;
const label = document.createElement('label');
label.innerHTML = __('Custom CSS', 'mgeo');
self.help.addHelp(label, 'custom-css');
label.appendChild(textarea);
block2.appendChild(label);
// controls
block3.appendChild(self.newText('h3', __('Controls', 'mgeo')));
block3.appendChild(self.newSelect('mgeo-setting-rotation', this.zoneOptions, o.rotation, 'Map rotation', 'map-rotation'));
block3.appendChild(self.newSelect('mgeo-setting-fullscreen', this.zoneOptions, o.fullscreen, 'Fullscreen', 'fullscreen'));
block3.appendChild(self.newSelect('mgeo-setting-zoomButtons', this.zoneOptions, o.zoomButtons, 'Zoom buttons', 'zoom-buttons'));
block3.appendChild(self.newSelect('mgeo-setting-resetButton', this.zoneOptions, o.resetButton, 'Reset button', 'reset-button'));
block3.appendChild(self.newSelect('mgeo-setting-levelselector', this.zoneOptions, o.levelselector, 'Level selector', 'level-selector'));
block3.appendChild(self.newCheckbox('mgeo-setting-attribution', o.attribution, 'Show attribution', 'attribution')).classList.add('space');
block3.appendChild(self.newCheckbox('mgeo-setting-attributionCollapsible', o.attributionCollapsible, 'Collapsed attribution', 'collapsed-attribution'));
// API keys
block3.appendChild(self.newText('h3', __('API keys', 'mgeo')));
block3.appendChild(self.newTextInput('mgeo-setting-maptilerkey', o.maptilerkey, 'MapTiler key'));
block3.appendChild(self.newTextInput('mgeo-setting-mapboxtoken', o.mapboxtoken, 'Mapbox access token'));
block3.appendChild(self.newTextInput('mgeo-setting-bingmapskey', o.bingmapskey, 'Bing Maps key'));
return this;
}
}
// styles
function Styles() {
const s = this;
this.options = {'' : __('(None)', 'mgeo')};
this.init = function(styles) {
this.el = document.createElement('div');
this.el.id = 'mgeo-admin-styles';
const title = document.createElement('h2');
title.innerHTML = 'Styles';
this.el.appendChild(title);
const icon = document.createElement('i');
icon.classList.add('mgeo-admin-icon', 'mgeo-icon-styles');
title.prepend(icon);
const list = document.createElement('ul');
list.classList.add('mgeo-admin-list');
this.el.appendChild(list);
const add = document.createElement('button'); // add button
add.classList.add('mgeo-admin-new-style', 'mgeo-admin-button');
add.innerHTML = 'Style';
add.insertAdjacentHTML('afterbegin', '<i class="mgeo-icon-plus"></i>');
add.addEventListener('click', function(e) {
e.preventDefault();
const empty = s.createStyleElement(false);
list.prepend(empty);
setTimeout(function() { empty.classList.add('opened'); }, 10);
setTimeout(function() { list.querySelector('input').focus(); }, 200);
});
this.el.prepend(add);
for (const id in styles) {
this.options[styles[id].class] = styles[id].class;
list.appendChild(this.createStyleElement(styles[id]));
}
// sortable
Sortable.create(list, {
animation: 200,
handle: '#mgeo-admin-styles .mgeo-admin-list-item-handle',
delay: 50,
delayOnTouchOnly: true
});
return this;
}
this.createStyleElement = function(style) {
const item = document.createElement('li');
item.classList.add('mgeo-admin-list-item');
const handle = document.createElement('div');
handle.classList.add('mgeo-admin-list-item-handle');
item.appendChild(handle);
handle.addEventListener('click', function() { item.classList.toggle('opened'); });
const title = document.createElement('span');
if (style.class) title.innerHTML = style.class;
else title.innerHTML = __('[New Style]', 'mgeo');
handle.appendChild(title);
handle.appendChild(document.createElement('i')).classList.add('mgeo-icon-arrow-down');
const body = document.createElement('div');
body.classList.add('mgeo-admin-list-item-body');
item.appendChild(body);
// fields
body.appendChild(self.newTextInput('mgeo-style-class', style.class, 'Class', 'class')).classList.add('half');
body.appendChild(self.newTextInput('mgeo-style-text-color mgeo-colorpicker', style?.base?.textColor, 'Text color')).classList.add('half','last');
body.appendChild(self.newTextInput('mgeo-style-base mgeo-colorpicker', style?.base?.fill, 'Base color')).classList.add('third');
body.appendChild(self.newTextInput('mgeo-style-hover mgeo-colorpicker', style?.hover?.fill, 'Hover color')).classList.add('third');
body.appendChild(self.newTextInput('mgeo-style-active mgeo-colorpicker', style?.active?.fill, 'Active color')).classList.add('third', 'last');
body.appendChild(self.newTextInput('mgeo-style-stroke mgeo-colorpicker', style?.base?.stroke, 'Stroke color')).classList.add('space', 'half');
body.appendChild(self.newNumberInput('mgeo-style-stroke-width', style?.base?.strokeWidth, 'Stroke width')).classList.add('space', 'half', 'last');
// remove button
const remove = document.createElement('a');
remove.classList.add('mgeo-remove-button', 'space');
remove.innerHTML = 'Remove';
body.appendChild(remove);
remove.addEventListener('click', function() { if (!style.class || confirm('Are you sure you want to remove "' + style.class + '" style?')) item.parentNode.removeChild(item); });
return item;
}
}
// groups
function Groups() {
const s = this;
this.options = {'' : __('(None)', 'mgeo')};
this.init = function(groups) {
this.el = document.createElement('div');
this.el.id = 'mgeo-admin-groups';
const title = document.createElement('h2');
title.innerHTML = __('Groups', 'mgeo');
this.el.appendChild(title);
const icon = document.createElement('i');
icon.classList.add('mgeo-admin-icon', 'mgeo-icon-groups');
title.prepend(icon);
const list = document.createElement('ul');
list.classList.add('mgeo-admin-list');
this.el.appendChild(list);
const add = document.createElement('button'); // add button
add.classList.add('mgeo-admin-new-group', 'mgeo-admin-button');
add.innerHTML = __('Group', 'mgeo');
add.insertAdjacentHTML('afterbegin', '<i class="mgeo-icon-plus"></i>');
add.addEventListener('click', function(e) {
e.preventDefault();
const empty = s.createGroupElement(false);
list.prepend(empty);
setTimeout(function() { empty.classList.add('opened'); }, 10);
setTimeout(function() { list.querySelector('input').focus(); }, 200);
});
this.el.prepend(add);
for (const id in groups) {
this.options[groups[id].id] = groups[id].title;
list.appendChild(this.createGroupElement(groups[id]));
}
// sortable
Sortable.create(list, {
animation: 200,
handle: '#mgeo-admin-groups .mgeo-admin-list-item-handle',
delay: 50,
delayOnTouchOnly: true
});
return this;
}
this.createGroupElement = function(group) {
const item = document.createElement('li');
item.classList.add('mgeo-admin-list-item');
const handle = document.createElement('div');
handle.classList.add('mgeo-admin-list-item-handle');
item.appendChild(handle);
handle.addEventListener('click', function() { item.classList.toggle('opened'); });
const title = document.createElement('span');
if (group.title) title.innerHTML = group.title;
else title.innerHTML = __('[New Group]', 'mgeo');
handle.appendChild(title);
handle.appendChild(document.createElement('i')).classList.add('mgeo-icon-arrow-down');
const body = document.createElement('div');
body.classList.add('mgeo-admin-list-item-body');
item.appendChild(body);
// fields
const idInput = self.newTextInput('mgeo-group-id', group.id, 'ID', 'id');
idInput.classList.add('half');
if (group) idInput.querySelector('.mgeo-group-id').setAttribute('disabled', '');
body.appendChild(idInput);
const titleInput = self.newTextInput('mgeo-group-title', group.title, 'Title');
titleInput.classList.add('half', 'last');
body.appendChild(titleInput);
const colorInput = self.newTextInput('mgeo-group-color mgeo-colorpicker', group.color, 'Color');
colorInput.classList.add('half');
body.appendChild(colorInput);
const thumbnailInput = self.newActionInput('mgeo-group-thumbnail', 'file', group.thumbnail, 'Thumbnail');
thumbnailInput.classList.add('half', 'last');
body.appendChild(thumbnailInput);
body.appendChild(self.newSelect('mgeo-group-style', self.styles.options, group.style, 'Style', false, false, false)).classList.add('half');
const hideCheckbox = self.newCheckbox('mgeo-group-hide', group.hide, 'Hide from directory');
hideCheckbox.classList.add('single', 'space');
body.appendChild(hideCheckbox);
// remove button
const remove = document.createElement('a');
remove.classList.add('mgeo-remove-button');
remove.innerHTML = __('Remove', 'mgeo');
body.appendChild(remove);
remove.addEventListener('click', function() { if (!group.id || confirm('Are you sure you want to remove "' + group.title + '" group?')) item.parentNode.removeChild(item); });
return item;
}
}
// layers
function Layers() {
const s = this;
this.options = {'' : __('(Global)', 'mgeo')};
this.type = {
'osm': {
'title': 'OpenStreetMap',
'source': false
},
'markers': {
'title': 'Markers',
'source': false
},
'builtin': {
'title': 'Built-in vector',
'source': {
'world/world.json': 'World Countries',
'world/continents.json': 'Continents',
'world/africa.json': 'Africa',
'world/asia.json': 'Asia',
'world/europe.json': 'Europe',
'world/north-america.json': 'North America',
'world/south-america.json': 'South America',
'AL.json': 'Albania',
'AR.json': 'Argentina',
'AM.json': 'Armenia',
'AU.json': 'Australia',
'AT.json': 'Austria',
'AZ.json': 'Azerbaijan',
'BY.json': 'Belarus',
'BE.json': 'Belgium',
'BA.json': 'Bosnia and Herzegovina',
'BR.json': 'Brazil',
'BG.json': 'Bulgaria',
'CA.json': 'Canada',
'CL.json': 'Chile',
'CN.json': 'China',
'CO.json': 'Colombia',
'CR.json': 'Costa Rica',
'HR.json': 'Croatia',
'CU.json': 'Cuba',
'CY.json': 'Cyprus',
'CZ.json': 'Czech Republic',
'DK.json': 'Denmark',
'EG.json': 'Egypt',
'EE.json': 'Estonia',
'FI.json': 'Finland',
'FR.json': 'France',
'GE.json': 'Georgia',
'DE.json': 'Germany',
'GR.json': 'Greece',
'HU.json': 'Hungary',
'IS.json': 'Iceland',
'IN.json': 'India',
'ID.json': 'Indonesia',
'IR.json': 'Iran',
'IQ.json': 'Iraq',
'IE.json': 'Ireland',
'IL.json': 'Israel',
'IT.json': 'Italy',
'JP.json': 'Japan',
'KE.json': 'Kenya',
'KR.json': 'Korea',
'LV.json': 'Latvia',
'LT.json': 'Lithuania',
'LU.json': 'Luxembourg',
'MK.json': 'Macedonia',
'MY.json': 'Malaysia',
'MX.json': 'Mexico',
'MN.json': 'Mongolia',
'ME.json': 'Montenegro',
'MA.json': 'Morocco',
'NL.json': 'Netherlands',
'NZ.json': 'New Zealand',
'NO.json': 'Norway',
'PK.json': 'Pakistan',
'PA.json': 'Panama',
'PY.json': 'Paraguay',
'PE.json': 'Peru',
'PH.json': 'Philippines',
'PL.json': 'Poland',
'PT.json': 'Portugal',
'QA.json': 'Qatar',
'RO.json': 'Romania',
'RU.json': 'Russian Federation',
'SA.json': 'Saudi Arabia',
'RS.json': 'Serbia',
'SK.json': 'Slovakia',
'SI.json': 'Slovenia',
'ZA.json': 'South Africa',
'ES.json': 'Spain',
'SE.json': 'Sweden',
'CH.json': 'Switzerland',
'TW.json': 'Taiwan',
'TH.json': 'Thailand',
'TN.json': 'Tunisia',
'TR.json': 'Turkey',
'UA.json': 'Ukraine',
'AE.json': 'United Arab Emirates',
'GB.json': 'United Kingdom',
'US.json': 'United States',
'UY.json': 'Uruguay',
'VN.json': 'Vietnam'
}
},
'geojson': {
'title': 'GeoJSON'
},
'topojson': {
'title': 'TopoJSON'
},
'image': {
'title': 'Image'
},
'svg': {
'title': 'SVG'
},
'xyz': {
'title': 'XYZ'
},
'stamen': {
'title': 'Stamen',
'source': {
'watercolor': 'Watercolor',
'terrain': 'Terrain',
'terrain-labels': 'Terrain Labels',
'toner': 'Toner',
'toner-labels': 'Toner Labels',
'toner-lite': 'Toner Lite'
}
},
'maptiler': {
'title': 'MapTiler',
'source': {
'basic': 'Basic',
'bright': 'Bright',
'hybrid': 'Hybrid',
'pastel': 'Pastel',
'satellite-v2': 'Satellite',
'streets': 'Streets',
'topo': 'Topo',
'voyager': 'Voyager'
}
},
'bingmaps': {
'title': 'Bing Maps',
'source': {
'Aerial': 'Aerial',
'AerialWithLabelsOnDemand': 'Aerial with labels',
'RoadOnDemand': 'Road',
'CanvasDark': 'Canvas Dark',
'CanvasLight': 'Canvas Light',
'CanvasGray': 'Canvas Gray'
}
},
'mapbox': {
'title': 'Mapbox Vector',
'source': {
'bright': 'Bright',
'streets': 'Streets',
'outdoors': 'Outdoors',
'light': 'Light',
'dark': 'Dark'
}
}
}
this.init = function(layers) {
this.el = document.createElement('div');
this.el.id = 'mgeo-admin-layers';
const title = document.createElement('h2');
title.innerHTML = __('Layers', 'mgeo');
this.el.appendChild(title);
const icon = document.createElement('i');
icon.classList.add('mgeo-admin-icon', 'mgeo-icon-layers');
title.prepend(icon);
const list = document.createElement('ul');
list.classList.add('mgeo-admin-list');
this.el.appendChild(list);
const addlg = document.createElement('button');
addlg.classList.add('mgeo-admin-new-layer-group', 'mgeo-admin-button');
addlg.innerHTML = __('Group', 'mgeo');
addlg.insertAdjacentHTML('afterbegin', '<i class="mgeo-icon-plus"></i>');
addlg.addEventListener('click', function(e) {
e.preventDefault();
const newlg = s.createLayerGroup({ layers: []});
list.prepend(newlg);
setTimeout(function() { newlg.classList.add('opened'); }, 10);
setTimeout(function() { list.querySelector('input').focus(); }, 200);
});
this.el.prepend(addlg);
const add = document.createElement('button'); // add button
add.classList.add('mgeo-admin-new-layer', 'mgeo-admin-button');
add.innerHTML = __('Layer', 'mgeo');
add.insertAdjacentHTML('afterbegin', '<i class="mgeo-icon-plus"></i>');
add.addEventListener('click', function(e) {
e.preventDefault();
const newlayer = s.createLayerElement(false);
list.prepend(newlayer);
setTimeout(function() { newlayer.classList.add('opened'); }, 10);
setTimeout(function() { list.querySelector('input').focus(); }, 200);
});
this.el.prepend(add);
if (layers && layers.length > 0) {
for (const layer of layers) {
if (!layer.layers) list.appendChild(this.createLayerElement(layer));
else {
const lg = list.appendChild(this.createLayerGroup(layer));
for (const sub of layer.layers) lg.querySelector(':scope > .mgeo-gl-list').appendChild(this.createLayerElement(sub));
}
}
}
// sortable
Sortable.create(list, {
animation: 200,
group: 'shared',
handle: '#mgeo-admin-layers .mgeo-admin-list-item-handle',
delay: 50,
delayOnTouchOnly: true
});
return this;
}
this.createLayerElement = function(layer) {
if (layer.type == 'markers') this.options[layer.id] = layer.title;
const item = document.createElement('li');
item.classList.add('mgeo-admin-list-item');
const handle = document.createElement('div');
handle.classList.add('mgeo-admin-list-item-handle');
item.appendChild(handle);
handle.addEventListener('click', function() { item.classList.toggle('opened'); });
const title = document.createElement('span');
if (layer) title.innerHTML = layer.title;
else title.innerHTML = __('[New Layer]', 'mgeo');
handle.appendChild(title);
handle.appendChild(document.createElement('i')).classList.add('mgeo-icon-arrow-down');
const type = document.createElement('small');
if (this.type[layer.type]) type.innerHTML = ' - ' + this.type[layer.type].title;
handle.appendChild(type);
const body = document.createElement('div');
body.classList.add('mgeo-admin-list-item-body');
item.appendChild(body);
// fields
const idInput = self.newTextInput('mgeo-layer-id', layer.id, 'ID', 'id');
if (layer.id) idInput.querySelector('.mgeo-layer-id').setAttribute('disabled', '');
idInput.classList.add('half');
body.appendChild(idInput);
body.appendChild(self.newTextInput('mgeo-layer-title', layer.title, 'Title')).classList.add('half', 'last');
const typeSelect = self.newSelect('mgeo-layer-type', this.type, layer.type, 'Type');
typeSelect.classList.add('half');
body.appendChild(typeSelect);
const select = typeSelect.querySelector('select.mgeo-layer-type');
const sourceContainer = document.createElement('div');
body.appendChild(sourceContainer).classList.add('half', 'last');
select.addEventListener('input', function(e) {
if (sourceContainer.firstChild) sourceContainer.removeChild(sourceContainer.firstChild);
if (s.type[e.target.value].source == false) { /* no field */ }
else if (s.type[e.target.value].source) sourceContainer.appendChild(self.newSelect('mgeo-layer-source', s.type[e.target.value].source, layer.source, 'Source'));
else sourceContainer.appendChild(self.newActionInput('mgeo-layer-source', 'file', layer.source, 'Source/URL'));
});
select.dispatchEvent(new Event('input', { target: select }));
body.appendChild(self.newSelect('mgeo-layer-style', self.styles.options, layer.style, 'Style', false, false, false)).classList.add('half');
body.appendChild(self.newActionInput('mgeo-layer-extent', 'extent', layer.extent, 'Extent')).classList.add('space');
body.appendChild(self.newNumberInput('mgeo-layer-minzoom', layer.minZoom, 'Min zoom')).classList.add('third');
body.appendChild(self.newNumberInput('mgeo-layer-maxzoom', layer.maxZoom, 'Max zoom')).classList.add('third');
body.appendChild(self.newOpacityInput('mgeo-layer-opacity', layer.opacity, 'Opacity')).classList.add('third', 'last');
body.appendChild(self.newCheckbox('mgeo-layer-selectable', layer.selectable, 'Selectable')).classList.add('single', 'space');
body.appendChild(self.newCheckbox('mgeo-layer-isolated', layer.isolated, 'Isolated')).classList.add('single');
body.appendChild(self.newCheckbox('mgeo-layer-hide', layer.hide, 'Hide by default')).classList.add('single');
body.appendChild(self.newCheckbox('mgeo-layer-disabled', layer.disabled, 'Disable')).classList.add('third', 'left');
// remove button
const remove = document.createElement('a');
remove.classList.add('mgeo-remove-button');
remove.innerHTML = __('Remove', 'mgeo');
body.appendChild(remove);
remove.addEventListener('click', function() { if (confirm('Are you sure you want to remove "' + layer.title + '" layer?')) item.parentNode.removeChild(item); });
return item;
}
this.createLayerGroup = function(layer) {
const item = document.createElement('li');
item.classList.add('mgeo-admin-list-item', 'mgeo-layer-group');
const handle = document.createElement('div');
handle.classList.add('mgeo-admin-list-item-handle');
item.appendChild(handle);
handle.addEventListener('click', function() { item.classList.toggle('opened'); });
const title = document.createElement('span');
if (layer.title) title.innerHTML = layer.title;
else title.innerHTML = __('[New Group]', 'mgeo');
handle.appendChild(title);
const body = document.createElement('div');
body.classList.add('mgeo-admin-list-item-body');
item.appendChild(body);
const list = document.createElement('ul');
list.classList.add('mgeo-gl-list');
item.appendChild(list);
// sortable
Sortable.create(list, {
animation: 200,
group: {
name: 'shared',
put: function(to, from, el) { return !el.classList.contains('mgeo-layer-group'); }
},
handle: '#mgeo-admin-layers .mgeo-admin-list-item-handle',
delay: 50,
delayOnTouchOnly: true
});
// fields
const idInput = self.newTextInput('mgeo-layer-id', layer.id, 'ID', 'id');
idInput.classList.add('half');
body.appendChild(idInput);
body.appendChild(self.newTextInput('mgeo-layer-title', layer.title, 'Title')).classList.add('half', 'last');
body.appendChild(self.newNumberInput('mgeo-layer-minzoom', layer.minZoom, 'Min zoom')).classList.add('third');
body.appendChild(self.newNumberInput('mgeo-layer-maxzoom', layer.maxZoom, 'Max zoom')).classList.add('third');
body.appendChild(self.newOpacityInput('mgeo-layer-opacity', layer.opacity, 'Opacity')).classList.add('third', 'last');
body.appendChild(self.newCheckbox('mgeo-layer-selectable', layer.selectable, 'Selectable')).classList.add('single', 'space');
body.appendChild(self.newCheckbox('mgeo-layer-isolated', layer.isolated, 'Isolated')).classList.add('single');
body.appendChild(self.newCheckbox('mgeo-layer-hide', layer.hide, 'Hide by default')).classList.add('single');
body.appendChild(self.newCheckbox('mgeo-layer-disabled', layer.disabled, 'Disable')).classList.add('third');
// remove button
const remove = document.createElement('a');
remove.classList.add('mgeo-remove-button');
remove.innerHTML = __('Remove', 'mgeo');
body.appendChild(remove);
remove.addEventListener('click', function() { if (confirm('Are you sure you want to remove "' + layer.title + '" layer group and all sublayers?')) item.parentNode.removeChild(item); });
return item;
}
}
// locations
function Locations() {
const s = this;
this.keys = null;
this.edit = null;
this.tbody = null;
this.tbodyext = null;
this.tablemode = true;
let ma = null;
let maCount = null;
this.init = function(l) {
this.el = document.createElement('div');
this.el.id = 'mgeo-admin-locations';
const title = document.createElement('h2'); // title
title.innerHTML = __('Locations', 'mgeo');
this.el.appendChild(title);
const toggle = document.createElement('label');
toggle.classList.add('mgeo-edit-mode');
toggle.innerHTML = __('Edit table', 'mgeo');
const editmode = document.createElement('input');
editmode.setAttribute('type', 'checkbox');
editmode.checked = s.tablemode;
editmode.addEventListener('change', function() { s.tablemode = this.checked; });
toggle.appendChild(editmode);
title.appendChild(toggle);
const icon = document.createElement('i');
icon.classList.add('mgeo-admin-icon', 'mgeo-icon-locations');
title.prepend(icon);
// table
const tc = document.createElement('div');
tc.id = ('mgeo-location-table')
this.el.appendChild(tc);
const table = document.createElement('table');
tc.appendChild(table);
// keys
s.keys = new Set(['id', 'title', 'desc', 'coord', 'zoom', 'type', 'label', 'fill', 'style', 'action', 'image', 'thumbnail', 'group', 'link', 'about', 'layer', 'sample', 'scale', 'hide', 'disabled']);
for (const id in l) s.keys = new Set([...s.keys, ...Object.keys(l[id])]);
s.keys.delete('feature');
s.keys.delete('marker');
s.keys.delete('res');
s.keys.delete('external');
s.keys = [...s.keys];
// header
const thead = document.createElement('thead');
const row = document.createElement('tr');
let el = document.createElement('th');
let cb = document.createElement('input');
cb.setAttribute('type', 'checkbox');
cb.addEventListener('change', function() {
const state = this.checked;
const event = new Event('change');
table.querySelectorAll('tbody tr > td:first-child input[type="checkbox"]').forEach(function(el) {
el.checked = state;
el.dispatchEvent(event);
});
});
el.appendChild(cb);
row.appendChild(el);
for (const key of s.keys) {
el = document.createElement('th');
el.innerHTML = key;
self.help.addHelp(el, key);
if (key == 'desc') el.classList.add('mgeo-cell-l');
else if (['id', 'title', 'about', 'type', 'image', 'thumbnail'].includes(key)) el.classList.add('mgeo-cell-m');
row.appendChild(el);
}
thead.appendChild(row);
table.appendChild(thead);
// rows
s.tbody = document.createElement('tbody');
s.tbody.classList.add('mgeo-editable');
s.tbodyext = document.createElement('tbody');
s.tbodyext.classList.add('mgeo-external');
for (const id in l) {
if (l[id].external) s.tbodyext.appendChild(this.createRowElement(l[id]));
else s.tbody.appendChild(this.createRowElement(l[id]));
}
table.appendChild(s.tbody);
table.appendChild(s.tbodyext);
// multiactions
ma = document.createElement('div');
ma.classList.add('mgeo-multiactions');
this.el.appendChild(ma);
const maText = document.createElement('span')
maText.innerHTML = __(' locations selected', 'mgeo');
ma.append(maText);
maCount = document.createElement('b');
maCount.innerHTML = '0';
maText.prepend(maCount);
const maDelete = document.createElement('button'); // add button
maDelete.classList.add('mgeo-admin-button', 'mgeo-admin-button-delete');
maDelete.innerHTML = __('Delete', 'mgeo');
maDelete.addEventListener('click', function(e) {
e.preventDefault();
s.tbody.querySelectorAll('tr.mgeo-selected').forEach(function(el) {
s.tbody.removeChild(el);
});
cb.checked = false;
ma.classList.remove('opened');
});
ma.append(maDelete);
// auto populate
const autopop = document.createElement('button');
autopop.classList.add('mgeo-admin-autopop', 'mgeo-admin-button');
autopop.innerHTML = __('Auto-populate', 'mgeo');
autopop.addEventListener('click', function(e) {
e.preventDefault();
for (let id in obj.container.l) {
let source = obj.container.l[id].object.getSource();
if (source.getFeatures !== undefined) {
source.getFeatures().forEach(function(f, i) {
let id = f.getId();
if (!l[id]) {
let data = {id: id, title: f.get('name')};
s.tbody.appendChild(s.createRowElement(data));
obj.dir.modifyLocation(null, data);
}
});
}
}
autopop.style.display = 'none';
});
this.el.prepend(autopop);
const nrspan = document.createElement('span');
nrspan.innerHTML = '0';
autopop.appendChild(nrspan);
for (let id in obj.container.l) {
if (obj.container.l[id].object.getSource !== undefined && obj.container.l[id].object?.getSource()) {
obj.container.l[id].object.getSource().on('featuresloadend', function(e) {
if (obj.container.emptyfeatures > 0) {
nrspan.innerHTML = obj.container.emptyfeatures;
autopop.style.display = 'block';
}
});
}
}
// add
const add = document.createElement('button'); // add button
add.classList.add('mgeo-admin-new-location', 'mgeo-admin-button');
add.innerHTML = __('Location', 'mgeo');
add.insertAdjacentHTML('afterbegin', '<i class="mgeo-icon-plus"></i>');
this.el.prepend(add);
add.addEventListener('click', function(e) {
e.preventDefault();
s.openPopup();
});
// sortable
Sortable.create(s.tbody, {
animation: 200,
handle: '#mgeo-admin-locations tr > td:first-child',
delay: 50,
delayOnTouchOnly: true,
ghostClass: 'mgeo-drag',
onStart: function() { s.tbody.classList.add('mgeo-dragging'); },
onEnd: function() { s.tbody.classList.remove('mgeo-dragging'); }
});
// feature click
obj.el.addEventListener('featureclick', function(e) {
const feature = e.detail.feature,
location = obj.dir.getLocation(feature.getId());
if (!location && feature.getId() && confirm('Assign a new location to "' + feature.getId() + '"?')) s.openPopup(false, {id: feature.getId(), title: feature.get('name'), desc: '', coord: obj.container.getCoord(e.detail.coord) });
});
// location focus
obj.el.addEventListener('locationfocus', function(e) {
const location = e.detail.location;
if (location?.id) {
const row = s.getRow(location.id);
if (row) s.makeRowEditable(row);
}
});
// popup edit button
obj.el.addEventListener('popuprender', function(e) {
const id = e.detail.dataset.location;
if (obj.dir.l[id].res.external) return false;
const edit = document.createElement('a');
edit.innerHTML = 'Edit';
edit.addEventListener('click', function() {
const row = s.getRow(id);
if (row) s.openPopup(row);
});
e.detail.querySelector('.mgeo-buttons').appendChild(edit);
});
// map reset
obj.el.addEventListener('mapreset', function() {
s.saveRow(s.edit);
});
return this;
}
this.getRow = function(id) {
return s.tbody.querySelector('tr[data-id="' + id + '"]');
}
this.getDataFromRow = function(row) {
if (!row) return null;
const location = {};
row.querySelectorAll('.mgeo-cell-field').forEach(function(el) {
const field = el.getAttribute('data-field');
if (field) location[field] = el.innerHTML;
});
return location;
}
this.getDataFromPopup = function(popup) {
if (!popup) return null;
const id = self.validateId(popup.querySelector('.mgeo-location-id'));
if (!id) return false;
const location = {
id: id,
title: popup.querySelector('.mgeo-location-title').value,
coord: popup.querySelector('.mgeo-location-coord').value,
zoom: popup.querySelector('.mgeo-location-zoom').value,
action: popup.querySelector('.mgeo-location-action').value,
link: popup.querySelector('.mgeo-location-link').value,
label: popup.querySelector('.mgeo-location-label').value,
type: popup.querySelector('.mgeo-admin-type > .mgeo-selected > small').innerHTML,
fill: popup.querySelector('.mgeo-location-fill').value,
style: popup.querySelector('.mgeo-location-style').value,
image: popup.querySelector('.mgeo-location-image').value,
thumbnail: popup.querySelector('.mgeo-location-thumbnail').value,
group: popup.querySelector('.mgeo-location-group').value,
about: popup.querySelector('.mgeo-location-about').value,
layer: popup.querySelector('.mgeo-location-layer').value,
sample: popup.querySelector('.mgeo-location-sample').value,
hide: popup.querySelector('.mgeo-location-hide').checked,
disabled: popup.querySelector('.mgeo-location-disabled').checked
};
const textarea = popup.querySelector('.mgeo-location-desc');
if (textarea) location.desc = tinymce.get(textarea.id).getContent();
return location;
}
this.openPopup = function(row = null, data = {desc: '', coord: obj.container.getCoord()}) {
s.saveRow(s.edit);
if (row) data = this.getDataFromRow(row);
const popup = document.createElement('div');
this.el.prepend(popup);
popup.appendChild(self.newTextInput('mgeo-location-id', data.id, 'ID', 'id')).classList.add('half');
popup.appendChild(self.newTextInput('mgeo-location-title', data.title, 'Title', 'title')).classList.add('half', 'last');
const textarea = document.createElement('textarea');
textarea.classList.add('mgeo-location-desc');
textarea.value = data.desc;
popup.appendChild(textarea);
popup.appendChild(self.newTextInput('mgeo-location-about', data.about, 'About', 'about'));
popup.appendChild(self.newTextInput('mgeo-location-coord', data.coord, 'Coordinate', 'coord')).classList.add('three-fourths');
popup.appendChild(self.newNumberInput('mgeo-location-zoom', data.zoom, 'Zoom', 'zoom')).classList.add('fourth', 'last');
popup.appendChild(self.newSelect('mgeo-location-action', obj.actions.a, data.action, 'Action', 'action')).classList.add('half');
popup.appendChild(self.newTextInput('mgeo-location-link', data.link, 'Link', 'link')).classList.add('half', 'last');
popup.appendChild(self.newTypeInput(data.type, 'Type', 'type')).classList.add('half');
const col = document.createElement('div');
col.classList.add('half', 'last')
col.appendChild(self.newTextInput('mgeo-location-label', data.label, 'Label', 'label'));
col.appendChild(self.newTextInput('mgeo-location-fill mgeo-colorpicker', data.fill, 'Fill', 'fill'));
col.appendChild(self.newSelect('mgeo-location-style', self.styles.options, data.style, 'Style', 'style', false, false));
popup.appendChild(col);
popup.appendChild(self.newActionInput('mgeo-location-image', 'file', data.image, 'Image', 'image')).classList.add('half');
popup.appendChild(self.newActionInput('mgeo-location-thumbnail', 'file', data.thumbnail, 'Thumbnail', 'thumbnail')).classList.add('half', 'last');
popup.appendChild(self.newTextInput('mgeo-location-sample', data.sample, 'Sample', 'sample')).classList.add('half');
popup.appendChild(self.newSelect('mgeo-location-layer', self.layers.options, data.layer, 'Layer', 'layer', false, false)).classList.add('half', 'last');
popup.appendChild(self.newSelect('mgeo-location-group', self.groups.options, data.group, 'Group', 'group', true, false)).classList.add('half', 'last');
popup.appendChild(self.newCheckbox('mgeo-location-hide', data.hide, 'Hide from directory', 'hide'));
popup.appendChild(self.newCheckbox('mgeo-location-disabled', data.disabled, 'Disable', 'disabled'));
if (row) {
const del = document.createElement('button');
del.classList.add('mgeo-admin-button');
del.innerHTML = __('Delete', 'mgeo');
del.addEventListener('click', function(e) {
e.preventDefault();
if (confirm(__('Are you sure you want to delete the location?', 'mgeo'))) {
row.parentNode.removeChild(row);
Fancybox.close();
obj.actions.blur();
obj.dir.modifyLocation(data.id, null);
}
});
popup.appendChild(del);
const duplicate = document.createElement('button');
duplicate.classList.add('mgeo-admin-button');
duplicate.innerHTML = __('Duplicate', 'mgeo');
duplicate.addEventListener('click', function(e) {
e.preventDefault();
/* duplicate location */
});
popup.appendChild(duplicate);
const save = document.createElement('button');
save.classList.add('mgeo-admin-button', 'mgeo-admin-button-primary');
save.innerHTML = __('Save location', 'mgeo');
save.addEventListener('click', function(e) {
e.preventDefault();
const updated = s.getDataFromPopup(popup);
if (updated) {
s.updateRow(row, updated);
Fancybox.close();
obj.actions.blur();
obj.dir.modifyLocation(data.id, s.getDataFromRow(row));
}
});
popup.appendChild(save);
}
else {
const add = document.createElement('button');
add.classList.add('mgeo-admin-button', 'mgeo-admin-button-primary');
add.innerHTML = __('Add location', 'mgeo');
add.addEventListener('click', function(e) {
e.preventDefault();
const data = s.getDataFromPopup(popup);
if (data) {
s.tbody.prepend(s.createRowElement(data));
Fancybox.close();
obj.dir.modifyLocation(null, data);
}
});
popup.appendChild(add);
}
// popup
Fancybox.show([{ src: popup, type: 'html' }], {
mainClass: 'mgeo-admin mgeo-admin-popup',
on: {
reveal: function() {
tinymce.init({
target: textarea,
plugins: 'link image',
toolbar: 'undo redo | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | styleselect',
menubar: false
});
Coloris({
el: '.mgeo-admin-popup .mgeo-colorpicker',
theme: 'large',
format: 'mixed'
});
}
}
});
}
this.createRowElement = function(location) {
const row = document.createElement('tr');
if (location?.id) row.setAttribute('data-id', location.id);
// first col
let el = document.createElement('td');
if (!location || !location.external) {
const cb = document.createElement('input');
cb.setAttribute('type', 'checkbox');
cb.addEventListener('change', function() {
if (this.checked) row.classList.add('mgeo-selected');
else row.classList.remove('mgeo-selected');
const count = s.tbody.querySelectorAll('tr > td:first-child input[type="checkbox"]:checked').length;
maCount.innerHTML = count;
ma.classList.toggle('opened', count > 0);
});
el.appendChild(cb);
// save
const save = document.createElement('button');
save.classList.add('mgeo-location-save');
save.setAttribute('title', 'Save location');
save.appendChild(document.createElement('i')).classList.add('mgeo-icon-save');
save.addEventListener('click', function(e) {
e.preventDefault();
s.saveRow(row);
});
el.appendChild(save);
// duplicate
const duplicate = document.createElement('button');
duplicate.classList.add('mgeo-location-duplicate');
duplicate.setAttribute('title', 'Duplicate location');
duplicate.appendChild(document.createElement('i')).classList.add('mgeo-icon-duplicate');
duplicate.addEventListener('click', function(e) {
e.preventDefault();
s.saveRow(row);
const data = s.getDataFromRow(row);
data.id = data.id + '-d';
const clone = s.createRowElement(data);
s.tbody.prepend(clone);
s.makeRowEditable(clone);
});
el.appendChild(duplicate);
// delete
const del = document.createElement('button');
del.classList.add('mgeo-location-delete');
del.setAttribute('title', 'Delete location');
del.appendChild(document.createElement('i')).classList.add('mgeo-icon-delete');
del.addEventListener('click', function(e) {
e.preventDefault();
if (confirm(__('Are you sure you want to delete the location?', 'mgeo'))) {
row.parentNode.removeChild(row);
obj.dir.modifyLocation(location.id, null);
}
});
el.appendChild(del);
// edit
row.addEventListener('click', function(e) {
if (!row.classList.contains('mgeo-edit') && (e.target.classList.contains('mgeo-cell-field') || e.target.closest('.mgeo-cell-field'))) {
if (s.tablemode) s.makeRowEditable(row);
else s.openPopup(row);
if (location) obj.container.zoomTo(location);
}
});
}
row.appendChild(el);
for (const key of s.keys) {
el = document.createElement('td');
el.classList.add('mgeo-cell-field');
el.setAttribute('data-field', key);
if (location && location[key]) el.innerHTML = location[key];
if (key == 'id') el.classList.add('mgeo-cell-nobreak');
if (key == 'fill') el.classList.add('mgeo-cell-color');
row.appendChild(el);
}
return row;
}
this.makeRowEditable = function(row) {
if (s.edit) s.saveRow(s.edit);
let coord = null;
row.querySelectorAll('td.mgeo-cell-field').forEach(function(el, i) {
el.setAttribute('data-value', el.innerHTML);
el.innerHTML = '';
const value = el.getAttribute('data-value');
switch (el.getAttribute('data-field')) {
case 'desc':
const textarea = document.createElement('textarea');
textarea.value = value;
el.appendChild(textarea);
tinymce.init({
target: textarea,
plugins: 'link image code',
toolbar: 'undo redo | code | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | styleselect',
menubar: false
});
break;
case 'coord':
coord = el.appendChild(self.newTextInput(false, value));
break;
case 'action':
el.appendChild(self.newSelect(false, obj.actions.a, value));
break;
case 'zoom':
el.appendChild(self.newNumberInput(false, value));
break;
case 'type':
el.appendChild(self.newTypeInput(value));
break;
case 'image':
case 'thumbnail':
el.appendChild(self.newActionInput(false, 'file', value));
break;
case 'group':
el.appendChild(self.newSelect(false, self.groups.options, value, false, true, false, false));
break;
case 'layer':
el.appendChild(self.newSelect(false, self.layers.options, value, false, false, false, false));
break;
case 'style':
el.appendChild(self.newSelect(false, self.styles.options, value, false, false, false, false));
break;
case 'scale':
el.appendChild(self.newNumberInput(false, value));
break;
case 'hide':
case 'disabled':
el.appendChild(self.newCheckbox(false, value === 'true'));
break;
default:
const input = document.createElement('input');
input.setAttribute('type', 'text');
input.setAttribute('size', 12);
input.value = value;
if (el.classList.contains('mgeo-cell-color')) input.classList.add('mgeo-colorpicker');
el.appendChild(input);
}
});
row.classList.add('mgeo-edit');
s.edit = row;
obj.container.startMarkerDrag(row.getAttribute('data-id'), coord);
}
this.updateRow = function(row, location) {
row.setAttribute('data-id', location.id);
row.querySelectorAll('td.mgeo-cell-field').forEach(function(el) {
const field = el.getAttribute('data-field');
if (field) {
if (field === 'hide' || field == 'disabled') {
if (location[field]) el.innerHTML = 'true';
else el.innerHTML = '';
}
else if (location[field] != undefined) {
el.innerHTML = location[field];
el.dataset.value = location[field];
}
}
});
}
this.saveRow = function(row) {
if (!row) return false;
const id = self.validateId(row.querySelector('.mgeo-cell-field[data-field="id"] > input'));
if (!id) return false;
row.querySelectorAll('td.mgeo-cell-field').forEach(function(el) {
const field = el.querySelector(':scope > input, :scope > select, :scope > label > input');
if (field) {
if (field.getAttribute('type') === 'checkbox') {
if (field.checked) el.innerHTML = 'true';
else el.innerHTML = '';
}
else el.innerHTML = field.value;
return;
}
// desc
const textarea = el.querySelector(':scope > textarea');
if (textarea) {
el.innerHTML = tinymce.get(textarea.id).getContent();
tinymce.get(textarea.id).remove();
return;
}
// type
const type = el.querySelector(':scope > .mgeo-admin-type > .mgeo-selected > small');
if (type) el.innerHTML = type.innerHTML;
});
row.setAttribute('data-id', row.querySelector('.mgeo-cell-field[data-field="id"]').innerHTML);
row.classList.remove('mgeo-edit');
obj.container.stopMarkerDrag();
s.edit = null;
}
}
}
let admin = new MapplicGeoAdmin(document.querySelector('.mgeo-map'));
admin.init();
})();