PageSourceSearch

https://www.differentetcompetent.org/wp-content/plugins/mapsvg/dist/mapsvg-front.umd.js?ver=6.2.25

js differentetcompetent.org collected 2026-10-09 21:29:18 UTC 654,579 bytes, 15,644 lines download raw bytes

1(function (global, factory) {
2    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('Handlebars'), require('Bloodhound'), require('CodeMirror')) :
3    typeof define === 'function' && define.amd ? define(['exports', 'Handlebars', 'Bloodhound', 'CodeMirror'], factory) :
4    (global = global || self, factory(global.mapsvg = {}, global.Handlebars, global.Bloodhound, global.CodeMirror));
5}(this, (function (exports, Handlebars, Bloodhound, CodeMirror) { 'use strict';
6
7    Handlebars = Handlebars && Handlebars.hasOwnProperty('default') ? Handlebars['default'] : Handlebars;
8    Bloodhound = Bloodhound && Bloodhound.hasOwnProperty('default') ? Bloodhound['default'] : Bloodhound;
9
10    /**
11     * Global MapSVG class. It contains all other MapSVG classes and some static methods.
12     * @constructor
13     * @example
14     * var mapsvg = MapSVG.get(0); // get first map instance
15     * var mapsvg2 = MapSVG.get(1); // get second map instance
16     * var mapsvg3 = MapSVG.getById(123); // get map by ID
17     *
18     * var mapsvg = new MapSVG.Map("my-container",{
19     *   source: "/path/to/map.svg"
20     * });
21     *
22     * var marker = new MapSVG.Marker({
23     *   location: location,
24     *   mapsvg: mapsvg
25     * });
26     *
27     * if(MapSVG.isPhone){
28     *  // do something special for mobile devices
29     * }
30     *
31     *
32     */
33    var MapSVG = function () {};
34    const $ = jQuery;
35
36    MapSVG.formBuilder = {};
37    MapSVG.mediaUploader = {};
38
39    if (typeof wp !== "undefined" && typeof wp.media !== "undefined") {
40        MapSVG.mediaUploader = wp.media({
41            title: "Choose images",
42            button: {
43                text: "Choose images",
44            },
45            multiple: true,
46        });
47    }
48
49    /**
50     * Keeps loaded HBS templates
51     * @type {Array}
52     * @private
53     * @static
54     * @property
55     */
56    MapSVG.templatesLoaded = {};
57
58    /**
59     * Keeps URLs
60     * @type {Array}
61     * @private
62     * @static
63     * @property
64     */
65    if (typeof mapsvg_paths !== "undefined") {
66        MapSVG.urls = mapsvg_paths;
67    } else {
68        MapSVG.urls = {};
69    }
70    if (typeof ajaxurl !== "undefined") {
71        MapSVG.urls.ajaxurl = ajaxurl;
72    }
73
74    /**
75     * Keeps map instances
76     * @type {Array}
77     * @private
78     * @static
79     * @property
80     */
81    MapSVG.instances = [];
82
83    MapSVG.userAgent = navigator.userAgent.toLowerCase();
84
85    /**
86     * Determines if current device is touch-device
87     * @type {boolean}
88     * @static
89     * @property
90     */
91    MapSVG.touchDevice =
92        "ontouchstart" in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
93    // (MapSVG.userAgent.indexOf("ipad") > -1) ||
94    // (MapSVG.userAgent.indexOf("iphone") > -1) ||
95    // (MapSVG.userAgent.indexOf("ipod") > -1) ||
96    // (MapSVG.userAgent.indexOf("android") > -1);
97
98    /**
99     * Determines if current device is iOS-device
100     * @type {boolean}
101     * @static
102     * @property
103     */
104    MapSVG.ios =
105        MapSVG.userAgent.indexOf("ipad") > -1 ||
106        MapSVG.userAgent.indexOf("iphone") > -1 ||
107        MapSVG.userAgent.indexOf("ipod") > -1;
108
109    /**
110     * Determines if current device is Android-device
111     * @type {boolean}
112     * @static
113     * @property
114     */
115    MapSVG.android = MapSVG.userAgent.indexOf("android");
116
117    /**
118     * Determines if current device is mobile-device
119     * @type {boolean}
120     * @static
121     * @property
122     */
123    MapSVG.isPhone = window.matchMedia("only screen and (max-width: 812px)").matches;
124
125    /**
126     * Keeps browser information
127     * @type {object}
128     * @static
129     * @property
130     */
131    MapSVG.browser = {};
132    MapSVG.browser.ie =
133        MapSVG.userAgent.indexOf("msie") > -1 ||
134        MapSVG.userAgent.indexOf("trident") > -1 ||
135        MapSVG.userAgent.indexOf("edge") > -1
136            ? {}
137            : false;
138    MapSVG.browser.firefox = MapSVG.userAgent.indexOf("firefox") > -1;
139    MapSVG.browser.safari =
140        MapSVG.userAgent.indexOf("safari") > -1 && MapSVG.userAgent.indexOf("chrome") === -1;
141
142    /**
143     * Contains device information
144     * @type {object}
145     * @static
146     * @property
147     */
148    var ua = window.navigator.userAgent;
149    MapSVG.device = {};
150    MapSVG.device.ios = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
151    MapSVG.device.android = !!ua.match(/Android/i);
152
153    if (!String.prototype.trim) {
154        String.prototype.trim = function () {
155            return this.replace(/^\s+|\s+$/g, "");
156        };
157    }
158
159    /**
160     * Converts mouse event object to x/y coordinates
161     * @param e
162     * @returns {{x: *, y: *}}
163     */
164    MapSVG.mouseCoords = function (e) {
165        if (e.clientX) {
166            return { x: e.clientX + $(document).scrollLeft(), y: e.clientY + $(document).scrollTop() };
167        }
168        if (e.pageX) {
169            return { x: e.pageX, y: e.pageY };
170        } else if (MapSVG.touchDevice) {
171            e = e.originalEvent || e;
172            return e.touches && e.touches[0]
173                ? { x: e.touches[0].pageX, y: e.touches[0].pageY }
174                : { x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY };
175        }
176    };
177
178    /**
179     * Adds new instance of the map
180     * @param {MapSVG.Map} mapsvg
181     */
182    MapSVG.addInstance = function (mapsvg) {
183        MapSVG.instances.push(mapsvg);
184    };
185
186    MapSVG.get = function (index) {
187        return MapSVG.instances[index];
188    };
189
190    MapSVG.getById = function (id) {
191        var instance = MapSVG.instances.filter(function (i) {
192            return i.id == id;
193        });
194        if (instance.length > 0) {
195            return instance[0];
196        }
197    };
198
199    MapSVG.getByContainerId = function (id) {
200        var instance = MapSVG.instances.filter(function (i) {
201            return i.$map.attr("id") == id;
202        });
203        if (instance.length > 0) {
204            return instance[0];
205        }
206    };
207
208    MapSVG.extend = function (sub, base) {
209        sub.prototype = Object.create(base.prototype);
210        sub.prototype.constructor = sub;
211    };
212
213    MapSVG.ucfirst = function (string) {
214        return string.charAt(0).toUpperCase() + string.slice(1);
215    };
216    MapSVG.parseBoolean = function (string) {
217        switch (String(string).toLowerCase()) {
218            case "on":
219            case "true":
220            case "1":
221            case "yes":
222            case "y":
223                return true;
224            case "off":
225            case "false":
226            case "0":
227            case "no":
228            case "n":
229                return false;
230            default:
231                return undefined;
232        }
233    };
234    MapSVG.isNumber = function (n) {
235        return !isNaN(parseFloat(n)) && isFinite(n);
236    };
237
238    MapSVG.safeURL = function (url) {
239        if (url.indexOf("http://") == 0 || url.indexOf("https://") == 0)
240            url = "//" + url.split("://").pop();
241        return url.replace(/^.*\/\/[^\/]+/, "");
242    };
243
244    MapSVG.convertToText = function (obj) {
245        //create an array that will later be joined into a string.
246        var string = [];
247
248        //is object
249        //    Both arrays and objects seem to return "object"
250        //    when typeof(obj) is applied to them. So instead
251        //    I am checking to see if they have the property
252        //    join, which normal objects don't have but
253        //    arrays do.
254        if (obj === null) {
255            return null;
256        }
257        if (obj === undefined) {
258            return '""';
259        } else if (typeof obj == "object" && obj.join == undefined) {
260            var prop;
261            for (prop in obj) {
262                if (obj.hasOwnProperty(prop)) {
263                    var key = '"' + prop.replace(/\"/g, '\\"') + '"'; //prop.search(/[^a-zA-Z]+/) === -1 ?  prop : ...
264                    string.push(key + ": " + MapSVG.convertToText(obj[prop]));
265                }
266            }
267            return "{" + string.join(",") + "}";
268
269            //is array
270        } else if (typeof obj == "object" && !(obj.join == undefined)) {
271            var prop;
272            for (prop in obj) {
273                string.push(MapSVG.convertToText(obj[prop]));
274            }
275            return "[" + string.join(",") + "]";
276
277            //is function
278        } else if (typeof obj == "function") {
279            return obj.toString().replace("function anonymous", "function");
280            // string.push(obj.toString().replace('function anonymous','function'));
281
282            //all other values can be done with JSON.stringify
283        } else {
284            return JSON.stringify(obj);
285            // var s = JSON.stringify(obj);
286            // string.push(s);
287        }
288    };
289
290    // Create Element.remove() function if not exists
291    if (!("remove" in Element.prototype)) {
292        Element.prototype.remove = function () {
293            if (this.parentNode) {
294                this.parentNode.removeChild(this);
295            }
296        };
297    }
298
299    Math.hypot =
300        Math.hypot ||
301        function () {
302            var y = 0;
303            var length = arguments.length;
304
305            for (var i = 0; i < length; i++) {
306                if (arguments[i] === Infinity || arguments[i] === -Infinity) {
307                    return Infinity;
308                }
309                y += arguments[i] * arguments[i];
310            }
311            return Math.sqrt(y);
312        };
313    SVGElement.prototype.getTransformToElement =
314        SVGElement.prototype.getTransformToElement ||
315        function (toElement) {
316            let value;
317            try {
318                value = toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
319            } catch (e) {
320                return;
321            }
322            return value;
323        };
324
325    Map.prototype.toArray = function () {
326        return Array.from(this, ([name, value]) => value);
327    };
328
329    MapSVG.ResizeSensor = class ResizeSensor {
330        constructor(element, callback) {
331            var _this = this;
332            _this.element = element;
333            _this.callback = callback;
334            var style = getComputedStyle(element);
335            var zIndex = parseInt(style.zIndex);
336            if (isNaN(zIndex)) {
337                zIndex = 0;
338            }
339            zIndex--;
340            _this.expand = document.createElement("div");
341            _this.expand.style.position = "absolute";
342            _this.expand.style.left = "0px";
343            _this.expand.style.top = "0px";
344            _this.expand.style.right = "0px";
345            _this.expand.style.bottom = "0px";
346            _this.expand.style.overflow = "hidden";
347            _this.expand.style.zIndex = zIndex.toString();
348            _this.expand.style.visibility = "hidden";
349            var expandChild = document.createElement("div");
350            expandChild.style.position = "absolute";
351            expandChild.style.left = "0px";
352            expandChild.style.top = "0px";
353            expandChild.style.width = "10000000px";
354            expandChild.style.height = "10000000px";
355            _this.expand.appendChild(expandChild);
356            _this.shrink = document.createElement("div");
357            _this.shrink.style.position = "absolute";
358            _this.shrink.style.left = "0px";
359            _this.shrink.style.top = "0px";
360            _this.shrink.style.right = "0px";
361            _this.shrink.style.bottom = "0px";
362            _this.shrink.style.overflow = "hidden";
363            _this.shrink.style.zIndex = zIndex.toString();
364            _this.shrink.style.visibility = "hidden";
365            var shrinkChild = document.createElement("div");
366            shrinkChild.style.position = "absolute";
367            shrinkChild.style.left = "0px";
368            shrinkChild.style.top = "0px";
369            shrinkChild.style.width = "200%";
370            shrinkChild.style.height = "200%";
371            _this.shrink.appendChild(shrinkChild);
372            _this.element.appendChild(_this.expand);
373            _this.element.appendChild(_this.shrink);
374            var size = element.getBoundingClientRect();
375            _this.currentWidth = size.width;
376            _this.currentHeight = size.height;
377            _this.setScroll();
378            _this.expand.addEventListener("scroll", function () {
379                _this.onScroll();
380            });
381            _this.shrink.addEventListener("scroll", function () {
382                _this.onScroll();
383            });
384        }
385        onScroll() {
386            var _this = this;
387            var size = _this.element.getBoundingClientRect();
388            var newWidth = size.width;
389            var newHeight = size.height;
390            if (newWidth != _this.currentWidth || newHeight != _this.currentHeight) {
391                _this.currentWidth = newWidth;
392                _this.currentHeight = newHeight;
393                _this.callback();
394            }
395            this.setScroll();
396        }
397        setScroll() {
398            this.expand.scrollLeft = 10000000;
399            this.expand.scrollTop = 10000000;
400            this.shrink.scrollLeft = 10000000;
401            this.shrink.scrollTop = 10000000;
402        }
403        destroy() {
404            this.expand.remove();
405            this.shrink.remove();
406        }
407    };
408
409    MapSVG.nonce = function () {
410        return mapsvg_runtime_vars.nonce;
411    };
412
413    /**
414     * Adds # hash at the beginning of HEX color value
415     * @param {String} color
416     * @returns {String}
417     * @private
418     */
419    MapSVG.fixColorHash = (color) => {
420        const hexColorNoHash = new RegExp(/^([0-9a-f]{3}|[0-9a-f]{6})$/i);
421        if (color && color.match(hexColorNoHash) !== null) {
422            color = "#" + color;
423        }
424        return color;
425    };
426
427    /**
428     * Delays method execution.
429     * For example, it can be used in search input fields to prevent sending
430     * an ajax request on each key press.
431     * @param {Function} method
432     * @param {number} delay
433     * @param {object} scope
434     * @param {array} params
435     * @private
436     */
437    MapSVG.throttle = (method, delay, scope, params) => {
438        clearTimeout(method._tId);
439        method._tId = setTimeout(function () {
440            method.apply(scope, params);
441        }, delay);
442    };
443    MapSVG.geocode = (query, callback) => {
444        if (!window.google) {
445            console.error("MapSVG: can't do Geocoding - Google Maps API is not loaded.");
446            jQuery.growl.error({
447                title: "Error",
448                message: "Google Maps API files are not loaded",
449            });
450            return false;
451        }
452        // if (!MapSVG.options.google_api_key) {
453        //     jQuery.growl.error({
454        //         title: "Error",
455        //         message: "Google Maps API key is not provided",
456        //     });
457        //     return false;
458        // }
459        if (!MapSVG.geocoder) {
460            MapSVG.geocoder = new google.maps.Geocoder();
461        }
462
463        MapSVG.throttle(MapSVG.geocoder.geocode, 500, MapSVG.geocoder, [
464            query,
465            function (results, status) {
466                if (status === "OK") {
467                    callback(results);
468                } else {
469                    jQuery.growl.error({
470                        title: "Error: " + status,
471                        message:
472                            "There is some problem with Google API keys. See browser's console for more details",
473                    });
474                }
475            },
476        ]);
477    };
478
479    MapSVG.handleFailedRequest = (response) => {
480        var message = "";
481
482        if (response.status === 403) {
483            if (response.responseText.indexOf("Wordfence") !== -1) {
484                message +=
485                    "The request has been blocked by Wordfence. " +
486                    'Switch Wordfence to "Learning mode", and save the map settings again. ' +
487                    "If the settings are saved successfully, you can switch Wordfence back to normal mode.";
488            } else {
489                message +=
490                    "The request has been blocked by your server. " +
491                    "Do you have mod_sec Apache's module enabled? If that's the case you need to change its settings.";
492            }
493        } else {
494            if (response && response.responseText) {
495                try {
496                    var _response = JSON.parse(response.responseText);
497                    if (_response && _response.data && _response.data.error) {
498                        message = _response.data.error;
499                    }
500                } catch (e) {
501                }
502            }
503        }
504
505        $.growl.error({
506            title: "Error: " + response.status + " " + response.statusText,
507            message: message,
508            duration: 30000,
509        });
510    };
511
512    if (!Object.values) {
513        Object.values = function (object) {
514            return Object.keys(object).map(function (k) {
515                return object[k];
516            });
517        };
518    }
519
520    window.MapSVG = MapSVG;
521
522    const defRegionTemplate = "<div>\n" +
523        "  <p>This is the demo content of the <strong>Region %templateType%</strong>.</p>\n" +
524        '  <p>How to edit it: if you are in mapsvg control panel now, click on the following link to open the template editor for this view: <a href="#" class="mapsvg-template-link" data-template="%templateTypeSnake%Region">Menu > Templates > Region %templateType%</a>.</p>\n' +
525        '  <p>More information about templates: <a href="https://mapsvg.com/docs/map-editor/templates" target="_blank">mapsvg.com/docs/map-editor/templates</a></p>\n' +
526        "</div>\n" +
527        "<hr />\n\n" +
528        "<!-- Region fields are available in this template -->\n" +
529        "<h5>{{#if title}} {{title}} {{else}} {{id}} {{/if}}</h5>\n" +
530        "<p>Status: {{status_text}}</p>\n\n" +
531        "<!-- Show all linked Database Objects: -->\n" +
532        "{{#each objects}}\n\n" +
533        "  <!-- DB Object are available inside of this block -->\n\n" +
534        "  <h5>{{title}}</h5>\n" +
535        "  <!-- When you need to render a field as HTML, use 3 curly braces instead of 2:-->\n" +
536        "  <p>{{{description}}}</p>\n" +
537        "  <p><em>{{location.address.formatted}}</em></p>\n\n" +
538        "  <!-- Show all images: -->\n" +
539        "  {{#each images}}\n" +
540        '    <!-- Image fields "thumbnail", "medium", "full" -->\n' +
541        "    <!-- are available in this block                -->\n" +
542        '    <img src="{{thumbnail}}" />\n' +
543        "  {{/each}}\n\n" +
544        "{{/each}}";
545    const defDBTemplate = "<div>\n" +
546        "  <p>This is the demo content of the <strong>DB Object %templateType%</strong>.</p>\n" +
547        '  <p>How to edit it: if you are in mapsvg control panel now, click on the following link to open the template editor for this view: <a href="#" class="mapsvg-template-link" data-template="%templateTypeSnake%">Menu > Templates > DB Object %templateType%</a>.</p>\n' +
548        '  <p>More information about templates: <a href="https://mapsvg.com/docs/map-editor/templates" target="_blank">mapsvg.com/docs/map-editor/templates</a></p>\n' +
549        "</div>\n" +
550        "<hr />\n\n" +
551        "<!-- DB Object fields are available in this template. -->\n" +
552        "<h5>{{title}}</h5>\n" +
553        "<!-- When you need to render a fields as HTML, use 3 curly braces instead of 2:-->\n" +
554        "<p>{{{description}}}</p>\n" +
555        "<p><em>{{location.address.formatted}}</em></p>\n\n" +
556        "<!-- Show all images: -->\n" +
557        "{{#each images}}\n" +
558        '  <!-- Image fields "thumbnail", "medium", "full" -->\n' +
559        "  <!-- are available in this block                -->\n" +
560        '  <img src="{{thumbnail}}" />\n' +
561        "{{/each}}\n\n" +
562        "<!-- Show all linked Regions, comma-separated: -->\n" +
563        "<p> Regions: \n" +
564        "  {{#each regions}}\n" +
565        "    <!-- Region fields are available in this block -->\n" +
566        "    {{#if title}}\n" +
567        "      {{title}}\n" +
568        "    {{else}}\n" +
569        "      {{id}}\n" +
570        "    {{/if}}{{#unless @last}}, {{/unless}}\n" +
571        "  {{/each}}\n" +
572        "</p>";
573    const dirItemItemTemplate = "<!-- If Directory Source = Database: DB Object fields are available in this template -->\n" +
574        "<!-- If Directory Source = Regions: Region fields are available in this template -->\n" +
575        "{{title}}";
576    const DefaultOptions = {
577        source: "",
578        markerLastID: 0,
579        regionLastID: 0,
580        dataLastID: 1,
581        disableAll: false,
582        width: null,
583        height: null,
584        lockAspectRatio: false,
585        padding: { top: 0, left: 0, right: 0, bottom: 0 },
586        maxWidth: null,
587        maxHeight: null,
588        minWidth: null,
589        minHeight: null,
590        loadingText: "Loading map...",
591        colorsIgnore: false,
592        colors: {
593            baseDefault: "#000000",
594            background: "#eeeeee",
595            selected: 40,
596            hover: 20,
597            directory: "#fafafa",
598            detailsView: "",
599            status: {},
600            clusters: "",
601            clustersBorders: "",
602            clustersText: "",
603            clustersHover: "",
604            clustersHoverBorders: "",
605            clustersHoverText: "",
606            markers: {
607                base: { opacity: 100, saturation: 100 },
608                hovered: { opacity: 100, saturation: 100 },
609                unhovered: { opacity: 40, saturation: 100 },
610                active: { opacity: 100, saturation: 100 },
611                inactive: { opacity: 40, saturation: 100 },
612            },
613        },
614        regions: {},
615        clustering: { on: false },
616        viewBox: [],
617        cursor: "default",
618        manualRegions: false,
619        onClick: null,
620        mouseOver: null,
621        mouseOut: null,
622        menuOnClick: null,
623        beforeLoad: null,
624        afterLoad: null,
625        zoom: {
626            on: true,
627            limit: [0, 22],
628            delta: 2,
629            buttons: { on: true, location: "right" },
630            mousewheel: true,
631            fingers: true,
632            hideSvg: false,
633            hideSvgZoomLevel: 7,
634        },
635        scroll: { on: true, limit: false, background: false, spacebar: false },
636        responsive: true,
637        tooltips: { on: false, position: "bottom-right", template: "", maxWidth: "", minWidth: 100 },
638        popovers: {
639            on: false,
640            position: "top",
641            template: "",
642            centerOn: true,
643            width: 300,
644            maxWidth: 50,
645            maxHeight: 50,
646        },
647        multiSelect: false,
648        regionStatuses: {
649            "1": { label: "Enabled", value: "1", color: "", disabled: false },
650            "0": { label: "Disabled", value: "0", color: "", disabled: true },
651        },
652        events: {
653            afterLoad: "function(){\n" +
654                "  // var mapsvg = this;\n" +
655                "  // var regions = mapsvg.regions;\n" +
656                "  // var dbObjects = mapsvg.database.getLoaded();\n" +
657                "}",
658            beforeLoad: "function(){\n" +
659                "  // var mapsvg = this;\n" +
660                "  // var settings = mapsvg.options;\n" +
661                "  // console.log(settings);\n" +
662                "}",
663            databaseLoaded: "function (){\n" +
664                "  // var mapsvg = this;\n" +
665                "  // var dbObjects = mapsvg.database.getLoaded();\n" +
666                "}",
667            "click.region": "function (e, mapsvg){\n" +
668                "  // var region = this;\n" +
669                "  // console.log(region);\n" +
670                "}",
671            "mouseover.region": "function (e, mapsvg){\n" +
672                "  // var region = this;\n" +
673                "  // console.log(region);\n" +
674                "}",
675            "mouseout.region": "function (e, mapsvg){\n" +
676                "  // var region = this;\n" +
677                "  // console.log(region);\n" +
678                "}",
679            "click.marker": "function (e, mapsvg){\n" +
680                "  // var marker = this;\n" +
681                "  // console.log(marker);\n" +
682                "}",
683            "mouseover.marker": "function (e, mapsvg){\n" +
684                "  // var marker = this;\n" +
685                "  // console.log(marker);\n" +
686                "}",
687            "mouseout.marker": "function (e, mapsvg){\n" +
688                "  // var marker = this;\n" +
689                "  // console.log(marker);\n" +
690                "}",
691            "click.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
692            "mouseover.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
693            "mouseout.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
694            "shown.popover": "function (mapsvg){\n" + "  // var popoverjQueryObject = this;\n" + "}",
695            "closed.popover": "function (mapsvg){\n" + "  // var popoverjQueryObject = this;\n" + "}",
696            "closed.detailsView": "function (mapsvg){\n" + "  // var detailsjQueryObject = this;\n" + "}",
697            "shown.detailsView": "function (mapsvg){\n" + "  // var detailsjQueryObject = this;\n" + "}",
698        },
699        css: "#mapsvg-map-%id% .mapsvg-tooltip {\n\n}\n" +
700            "#mapsvg-map-%id% .mapsvg-popover {\n\n}\n" +
701            "#mapsvg-map-%id% .mapsvg-details-container {\n\n}\n" +
702            "#mapsvg-map-%id% .mapsvg-directory-item {\n\n}\n" +
703            "#mapsvg-map-%id% .mapsvg-region-label {\n" +
704            "  /* background-color: rgba(255,255,255,.6); */\n" +
705            "  font-size: 11px;\n" +
706            "  padding: 3px 5px;\n" +
707            "  border-radius: 4px;\n" +
708            "}\n" +
709            "#mapsvg-map-%id% .mapsvg-marker-label {\n" +
710            "  padding: 3px 5px;\n" +
711            "  /*\n" +
712            "  border-radius: 4px;\n" +
713            "  background-color: white;\n" +
714            "  margin-top: -4px;\n" +
715            "  */\n}\n" +
716            "#mapsvg-map-%id% .mapsvg-filters-wrap {\n\n}\n" +
717            "\n\n\n\n\n\n",
718        templates: {
719            popoverRegion: defRegionTemplate
720                .replace(/%templateType%/g, "Popover")
721                .replace(/%templateTypeSnake%/g, "popover"),
722            popoverMarker: defDBTemplate
723                .replace(/%templateType%/g, "Popover")
724                .replace(/%templateTypeSnake%/g, "popover"),
725            tooltipRegion: "<!-- Region fields are available in this template -->\n{{id}} - {{title}}",
726            tooltipMarker: "<!-- DB Object fields are available in this template -->\n{{title}}",
727            directoryItem: dirItemItemTemplate,
728            directoryCategoryItem: '<!-- Available fields: "label", "value", "counter" -->\n<span class="mapsvg-category-label">{{label}}</span>\n<span class="mapsvg-category-counter">{{counter}}</span>\n<span class="mapsvg-chevron"></span>',
729            detailsView: defDBTemplate
730                .replace(/%templateType%/g, "Details View")
731                .replace(/%templateTypeSnake%/g, "detailsView"),
732            detailsViewRegion: defRegionTemplate
733                .replace(/%templateType%/g, "Details View")
734                .replace(/%templateTypeSnake%/g, "detailsView"),
735            labelMarker: "<!-- DB Object fields are available in this template -->\n{{title}}",
736            labelRegion: "<!-- Region fields are available in this template -->\n{{title}}",
737            labelLocation: "You are here!",
738        },
739        choropleth: {
740            on: false,
741            source: "regions",
742            sourceFieldSelect: {
743                on: false,
744                variants: [],
745            },
746            bubbleMode: false,
747            bubbleSize: {
748                min: 20,
749                max: 40,
750            },
751            labels: { low: "low", high: "high" },
752            colors: { lowRGB: null, highRGB: null, low: "#550000", high: "#ee0000", noData: "#333333" },
753            min: 0,
754            max: 0,
755            coloring: {
756                mode: "gradient",
757                noData: {
758                    color: "#999999",
759                    description: "No data",
760                },
761                gradient: {
762                    colors: {
763                        lowRGB: null,
764                        highRGB: null,
765                        diffRGB: null,
766                        low: "#550000",
767                        high: "#ee0000",
768                    },
769                    labels: {
770                        low: "low",
771                        high: "high",
772                    },
773                    values: {
774                        min: null,
775                        max: null,
776                        maxAdjusted: null,
777                    },
778                },
779                palette: {
780                    outOfRange: {
781                        color: "#ececec",
782                        description: "Out of range",
783                    },
784                    colors: [
785                        {
786                            color: "#550000",
787                            valueFrom: 0,
788                            valueTo: 50,
789                            description: "",
790                        },
791                    ],
792                },
793                legend: {
794                    on: true,
795                    layout: "vertical",
796                    container: "bottom-left",
797                    title: "Choropleth map",
798                    text: "",
799                    description: "",
800                    width: "20%",
801                    height: "20%",
802                },
803            },
804        },
805        filters: {
806            on: true,
807            source: "database",
808            location: "header",
809            modalLocation: "map",
810            width: "100%",
811            hide: false,
812            showButtonText: "Filters",
813            clearButtonText: "Clear all",
814            clearButton: false,
815            searchButton: false,
816            searchButtonText: "Search",
817            padding: "",
818        },
819        menu: {
820            on: false,
821            hideOnMobile: true,
822            location: "leftSidebar",
823            locationMobile: "leftSidebar",
824            search: false,
825            containerId: "",
826            searchPlaceholder: "Search...",
827            searchFallback: false,
828            source: "database",
829            showFirst: "map",
830            showMapOnClick: true,
831            minHeight: "400",
832            sortBy: "id",
833            sortDirection: "desc",
834            categories: {
835                on: false,
836                groupBy: "",
837                hideEmpty: true,
838                collapse: true,
839                collapseOther: true,
840            },
841            clickActions: {
842                region: "default",
843                marker: "default",
844                directoryItem: {
845                    triggerClick: true,
846                    showPopover: false,
847                    showDetails: true,
848                },
849            },
850            detailsViewLocation: "overDirectory",
851            noResultsText: "No results found",
852            filterout: { field: "", cond: "=", val: "" },
853        },
854        database: {
855            pagination: {
856                on: true,
857                perpage: 30,
858                next: "Next",
859                prev: "Prev.",
860                showIn: "both",
861            },
862            loadOnStart: true,
863            table: "",
864        },
865        actions: {
866            map: {
867                afterLoad: {
868                    selectRegion: false,
869                },
870            },
871            region: {
872                mouseover: {
873                    showTooltip: false,
874                },
875                click: {
876                    addIdToUrl: false,
877                    showDetails: true,
878                    showDetailsFor: "region",
879                    filterDirectory: false,
880                    loadObjects: false,
881                    showPopover: false,
882                    showPopoverFor: "region",
883                    goToLink: false,
884                    linkField: "Region.link",
885                },
886                touch: {
887                    showPopover: false,
888                },
889            },
890            marker: {
891                mouseover: {
892                    showTooltip: false,
893                },
894                click: {
895                    showDetails: true,
896                    showPopover: false,
897                    goToLink: false,
898                    linkField: "Object.link",
899                },
900                touch: {
901                    showPopover: false,
902                },
903            },
904            directoryItem: {
905                click: {
906                    showDetails: true,
907                    showPopover: false,
908                    goToLink: false,
909                    selectRegion: true,
910                    fireRegionOnClick: true,
911                    linkField: "Object.link",
912                },
913                hover: {
914                    centerOnMarker: false,
915                },
916            },
917        },
918        detailsView: {
919            location: "map",
920            containerId: "",
921            width: "100%",
922            mobileFullscreen: true,
923        },
924        mobileView: {
925            labelMap: "Map",
926            labelList: "List",
927            labelClose: "Close",
928        },
929        googleMaps: {
930            on: false,
931            apiKey: "",
932            loaded: false,
933            center: "auto",
934            type: "roadmap",
935            minZoom: 1,
936            style: "default",
937            styleJSON: [],
938            language: "en",
939        },
940        groups: [],
941        floors: [],
942        layersControl: {
943            on: false,
944            position: "top-left",
945            label: "Show on map",
946            expanded: true,
947            maxHeight: "100%",
948        },
949        floorsControl: {
950            on: false,
951            position: "top-left",
952            label: "Floors",
953            expanded: false,
954            maxHeight: "100%",
955        },
956        containers: {
957            leftSidebar: { on: false, width: "250px" },
958            rightSidebar: { on: false, width: "250px" },
959            header: { on: true, height: "auto" },
960            footer: { on: false, height: "auto" },
961        },
962        labelsMarkers: { on: false },
963        labelsRegions: { on: false },
964        svgFileVersion: 1,
965        fitMarkers: false,
966        fitMarkersOnStart: false,
967        fitSingleMarkerZoom: 20,
968        controls: {
969            location: "right",
970            zoom: true,
971            zoomReset: false,
972            userLocation: false,
973            previousMap: false,
974        },
975        previousMapsIds: [],
976    };
977
978    // TinyColor v1.4.1
979    // https://github.com/bgrins/TinyColor
980    // Brian Grinstead, MIT License
981
982    //(function(Math) {
983
984    var trimLeft = /^\s+/,
985        trimRight = /\s+$/,
986        tinyCounter = 0,
987        mathRound = Math.round,
988        mathMin = Math.min,
989        mathMax = Math.max,
990        mathRandom = Math.random;
991
992    function tinycolor(color, opts) {
993        color = color ? color : "";
994        opts = opts || {};
995
996        // If input is already a tinycolor, return itself
997        if (color instanceof tinycolor) {
998            return color;
999        }
1000        // If we are called as a function, call using new instead
1001        if (!(this instanceof tinycolor)) {
1002            return new tinycolor(color, opts);
1003        }
1004
1005        var rgb = inputToRGB(color);
1006        (this._originalInput = color),
1007            (this._r = rgb.r),
1008            (this._g = rgb.g),
1009            (this._b = rgb.b),
1010            (this._a = rgb.a),
1011            (this._roundA = mathRound(100 * this._a) / 100),
1012            (this._format = opts.format || rgb.format);
1013        this._gradientType = opts.gradientType;
1014
1015        // Don't let the range of [0,255] come back in [0,1].
1016        // Potentially lose a little bit of precision here, but will fix issues where
1017        // .5 gets interpreted as half of the total, instead of half of 1
1018        // If it was supposed to be 128, this was already taken care of b
vendor: 11,167 bytes, lines 1018-1336
1018y `inputToRgb`
1019        if (this._r < 1) {
1020            this._r = mathRound(this._r);
1021        }
1022        if (this._g < 1) {
1023            this._g = mathRound(this._g);
1024        }
1025        if (this._b < 1) {
1026            this._b = mathRound(this._b);
1027        }
1028
1029        this._ok = rgb.ok;
1030        this._tc_id = tinyCounter++;
1031    }
1032
1033    tinycolor.prototype = {
1034        isDark: function () {
1035            return this.getBrightness() < 128;
1036        },
1037        isLight: function () {
1038            return !this.isDark();
1039        },
1040        isValid: function () {
1041            return this._ok;
1042        },
1043        getOriginalInput: function () {
1044            return this._originalInput;
1045        },
1046        getFormat: function () {
1047            return this._format;
1048        },
1049        getAlpha: function () {
1050            return this._a;
1051        },
1052        getBrightness: function () {
1053            //http://www.w3.org/TR/AERT#color-contrast
1054            var rgb = this.toRgb();
1055            return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
1056        },
1057        getLuminance: function () {
1058            //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
1059            var rgb = this.toRgb();
1060            var RsRGB, GsRGB, BsRGB, R, G, B;
1061            RsRGB = rgb.r / 255;
1062            GsRGB = rgb.g / 255;
1063            BsRGB = rgb.b / 255;
1064
1065            if (RsRGB <= 0.03928) {
1066                R = RsRGB / 12.92;
1067            } else {
1068                R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);
1069            }
1070            if (GsRGB <= 0.03928) {
1071                G = GsRGB / 12.92;
1072            } else {
1073                G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);
1074            }
1075            if (BsRGB <= 0.03928) {
1076                B = BsRGB / 12.92;
1077            } else {
1078                B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);
1079            }
1080            return 0.2126 * R + 0.7152 * G + 0.0722 * B;
1081        },
1082        setAlpha: function (value) {
1083            this._a = boundAlpha(value);
1084            this._roundA = mathRound(100 * this._a) / 100;
1085            return this;
1086        },
1087        toHsv: function () {
1088            var hsv = rgbToHsv(this._r, this._g, this._b);
1089            return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
1090        },
1091        toHsvString: function () {
1092            var hsv = rgbToHsv(this._r, this._g, this._b);
1093            var h = mathRound(hsv.h * 360),
1094                s = mathRound(hsv.s * 100),
1095                v = mathRound(hsv.v * 100);
1096            return this._a == 1
1097                ? "hsv(" + h + ", " + s + "%, " + v + "%)"
1098                : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")";
1099        },
1100        toHsl: function () {
1101            var hsl = rgbToHsl(this._r, this._g, this._b);
1102            return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
1103        },
1104        toHslString: function () {
1105            var hsl = rgbToHsl(this._r, this._g, this._b);
1106            var h = mathRound(hsl.h * 360),
1107                s = mathRound(hsl.s * 100),
1108                l = mathRound(hsl.l * 100);
1109            return this._a == 1
1110                ? "hsl(" + h + ", " + s + "%, " + l + "%)"
1111                : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")";
1112        },
1113        toHex: function (allow3Char) {
1114            return rgbToHex(this._r, this._g, this._b, allow3Char);
1115        },
1116        toHexString: function (allow3Char) {
1117            return "#" + this.toHex(allow3Char);
1118        },
1119        toHex8: function (allow4Char) {
1120            return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
1121        },
1122        toHex8String: function (allow4Char) {
1123            return "#" + this.toHex8(allow4Char);
1124        },
1125        toRgb: function () {
1126            return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
1127        },
1128        toRgbString: function () {
1129            return this._a == 1
1130                ? "rgb(" +
1131                      mathRound(this._r) +
1132                      ", " +
1133                      mathRound(this._g) +
1134                      ", " +
1135                      mathRound(this._b) +
1136                      ")"
1137                : "rgba(" +
1138                      mathRound(this._r) +
1139                      ", " +
1140                      mathRound(this._g) +
1141                      ", " +
1142                      mathRound(this._b) +
1143                      ", " +
1144                      this._roundA +
1145                      ")";
1146        },
1147        toPercentageRgb: function () {
1148            return {
1149                r: mathRound(bound01(this._r, 255) * 100) + "%",
1150                g: mathRound(bound01(this._g, 255) * 100) + "%",
1151                b: mathRound(bound01(this._b, 255) * 100) + "%",
1152                a: this._a,
1153            };
1154        },
1155        toPercentageRgbString: function () {
1156            return this._a == 1
1157                ? "rgb(" +
1158                      mathRound(bound01(this._r, 255) * 100) +
1159                      "%, " +
1160                      mathRound(bound01(this._g, 255) * 100) +
1161                      "%, " +
1162                      mathRound(bound01(this._b, 255) * 100) +
1163                      "%)"
1164                : "rgba(" +
1165                      mathRound(bound01(this._r, 255) * 100) +
1166                      "%, " +
1167                      mathRound(bound01(this._g, 255) * 100) +
1168                      "%, " +
1169                      mathRound(bound01(this._b, 255) * 100) +
1170                      "%, " +
1171                      this._roundA +
1172                      ")";
1173        },
1174        toName: function () {
1175            if (this._a === 0) {
1176                return "transparent";
1177            }
1178
1179            if (this._a < 1) {
1180                return false;
1181            }
1182
1183            return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
1184        },
1185        toFilter: function (secondColor) {
1186            var hex8String = "#" + rgbaToArgbHex(this._r, this._g, this._b, this._a);
1187            var secondHex8String = hex8String;
1188            var gradientType = this._gradientType ? "GradientType = 1, " : "";
1189
1190            if (secondColor) {
1191                var s = tinycolor(secondColor);
1192                secondHex8String = "#" + rgbaToArgbHex(s._r, s._g, s._b, s._a);
1193            }
1194
1195            return (
1196                "progid:DXImageTransform.Microsoft.gradient(" +
1197                gradientType +
1198                "startColorstr=" +
1199                hex8String +
1200                ",endColorstr=" +
1201                secondHex8String +
1202                ")"
1203            );
1204        },
1205        toString: function (format) {
1206            var formatSet = !!format;
1207            format = format || this._format;
1208
1209            var formattedString = false;
1210            var hasAlpha = this._a < 1 && this._a >= 0;
1211            var needsAlphaFormat =
1212                !formatSet &&
1213                hasAlpha &&
1214                (format === "hex" ||
1215                    format === "hex6" ||
1216                    format === "hex3" ||
1217                    format === "hex4" ||
1218                    format === "hex8" ||
1219                    format === "name");
1220
1221            if (needsAlphaFormat) {
1222                // Special case for "transparent", all other non-alpha formats
1223                // will return rgba when there is transparency.
1224                if (format === "name" && this._a === 0) {
1225                    return this.toName();
1226                }
1227                return this.toRgbString();
1228            }
1229            if (format === "rgb") {
1230                formattedString = this.toRgbString();
1231            }
1232            if (format === "prgb") {
1233                formattedString = this.toPercentageRgbString();
1234            }
1235            if (format === "hex" || format === "hex6") {
1236                formattedString = this.toHexString();
1237            }
1238            if (format === "hex3") {
1239                formattedString = this.toHexString(true);
1240            }
1241            if (format === "hex4") {
1242                formattedString = this.toHex8String(true);
1243            }
1244            if (format === "hex8") {
1245                formattedString = this.toHex8String();
1246            }
1247            if (format === "name") {
1248                formattedString = this.toName();
1249            }
1250            if (format === "hsl") {
1251                formattedString = this.toHslString();
1252            }
1253            if (format === "hsv") {
1254                formattedString = this.toHsvString();
1255            }
1256
1257            return formattedString || this.toHexString();
1258        },
1259        clone: function () {
1260            return tinycolor(this.toString());
1261        },
1262
1263        _applyModification: function (fn, args) {
1264            var color = fn.apply(null, [this].concat([].slice.call(args)));
1265            this._r = color._r;
1266            this._g = color._g;
1267            this._b = color._b;
1268            this.setAlpha(color._a);
1269            return this;
1270        },
1271        lighten: function () {
1272            return this._applyModification(lighten, arguments);
1273        },
1274        brighten: function () {
1275            return this._applyModification(brighten, arguments);
1276        },
1277        darken: function () {
1278            return this._applyModification(darken, arguments);
1279        },
1280        desaturate: function () {
1281            return this._applyModification(desaturate, arguments);
1282        },
1283        saturate: function () {
1284            return this._applyModification(saturate, arguments);
1285        },
1286        greyscale: function () {
1287            return this._applyModification(greyscale, arguments);
1288        },
1289        spin: function () {
1290            return this._applyModification(spin, arguments);
1291        },
1292
1293        _applyCombination: function (fn, args) {
1294            return fn.apply(null, [this].concat([].slice.call(args)));
1295        },
1296        analogous: function () {
1297            return this._applyCombination(analogous, arguments);
1298        },
1299        complement: function () {
1300            return this._applyCombination(complement, arguments);
1301        },
1302        monochromatic: function () {
1303            return this._applyCombination(monochromatic, arguments);
1304        },
1305        splitcomplement: function () {
1306            return this._applyCombination(splitcomplement, arguments);
1307        },
1308        triad: function () {
1309            return this._applyCombination(triad, arguments);
1310        },
1311        tetrad: function () {
1312            return this._applyCombination(tetrad, arguments);
1313        },
1314    };
1315
1316    // If input is an object, force 1 into "1.0" to handle ratios properly
1317    // String input requires "1.0" as input, so 1 will be treated as 1
1318    tinycolor.fromRatio = function (color, opts) {
1319        if (typeof color == "object") {
1320            var newColor = {};
1321            for (var i in color) {
1322                if (color.hasOwnProperty(i)) {
1323                    if (i === "a") {
1324                        newColor[i] = color[i];
1325                    } else {
1326                        newColor[i] = convertToPercentage(color[i]);
1327                    }
1328                }
1329            }
1330            color = newColor;
1331        }
1332
1333        return tinycolor(color, opts);
1334    };
1335
1336    // Given a string or object, convert that input to RGB
vendor: 8,705 bytes, lines 1337-1617
1337    // Possible string inputs:
1338    //
1339    //     "red"
1340    //     "#f00" or "f00"
1341    //     "#ff0000" or "ff0000"
1342    //     "#ff000000" or "ff000000"
1343    //     "rgb 255 0 0" or "rgb (255, 0, 0)"
1344    //     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1345    //     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1346    //     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1347    //     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1348    //     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1349    //     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1350    //
1351    function inputToRGB(color) {
1352        var rgb = { r: 0, g: 0, b: 0 };
1353        var a = 1;
1354        var s = null;
1355        var v = null;
1356        var l = null;
1357        var ok = false;
1358        var format = false;
1359
1360        if (typeof color == "string") {
1361            color = stringInputToObject(color);
1362        }
1363
1364        if (typeof color == "object") {
1365            if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
1366                rgb = rgbToRgb(color.r, color.g, color.b);
1367                ok = true;
1368                format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1369            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
1370                s = convertToPercentage(color.s);
1371                v = convertToPercentage(color.v);
1372                rgb = hsvToRgb(color.h, s, v);
1373                ok = true;
1374                format = "hsv";
1375            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
1376                s = convertToPercentage(color.s);
1377                l = convertToPercentage(color.l);
1378                rgb = hslToRgb(color.h, s, l);
1379                ok = true;
1380                format = "hsl";
1381            }
1382
1383            if (color.hasOwnProperty("a")) {
1384                a = color.a;
1385            }
1386        }
1387
1388        a = boundAlpha(a);
1389
1390        return {
1391            ok: ok,
1392            format: color.format || format,
1393            r: mathMin(255, mathMax(rgb.r, 0)),
1394            g: mathMin(255, mathMax(rgb.g, 0)),
1395            b: mathMin(255, mathMax(rgb.b, 0)),
1396            a: a,
1397        };
1398    }
1399
1400    // Conversion Functions
1401    // --------------------
1402
1403    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1404    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1405
1406    // `rgbToRgb`
1407    // Handle bounds / percentage checking to conform to CSS color spec
1408    // <http://www.w3.org/TR/css3-color/>
1409    // *Assumes:* r, g, b in [0, 255] or [0, 1]
1410    // *Returns:* { r, g, b } in [0, 255]
1411    function rgbToRgb(r, g, b) {
1412        return {
1413            r: bound01(r, 255) * 255,
1414            g: bound01(g, 255) * 255,
1415            b: bound01(b, 255) * 255,
1416        };
1417    }
1418
1419    // `rgbToHsl`
1420    // Converts an RGB color value to HSL.
1421    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1422    // *Returns:* { h, s, l } in [0,1]
1423    function rgbToHsl(r, g, b) {
1424        r = bound01(r, 255);
1425        g = bound01(g, 255);
1426        b = bound01(b, 255);
1427
1428        var max = mathMax(r, g, b),
1429            min = mathMin(r, g, b);
1430        var h,
1431            s,
1432            l = (max + min) / 2;
1433
1434        if (max == min) {
1435            h = s = 0; // achromatic
1436        } else {
1437            var d = max - min;
1438            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1439            switch (max) {
1440                case r:
1441                    h = (g - b) / d + (g < b ? 6 : 0);
1442                    break;
1443                case g:
1444                    h = (b - r) / d + 2;
1445                    break;
1446                case b:
1447                    h = (r - g) / d + 4;
1448                    break;
1449            }
1450
1451            h /= 6;
1452        }
1453
1454        return { h: h, s: s, l: l };
1455    }
1456
1457    // `hslToRgb`
1458    // Converts an HSL color value to RGB.
1459    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1460    // *Returns:* { r, g, b } in the set [0, 255]
1461    function hslToRgb(h, s, l) {
1462        var r, g, b;
1463
1464        h = bound01(h, 360);
1465        s = bound01(s, 100);
1466        l = bound01(l, 100);
1467
1468        function hue2rgb(p, q, t) {
1469            if (t < 0) t += 1;
1470            if (t > 1) t -= 1;
1471            if (t < 1 / 6) return p + (q - p) * 6 * t;
1472            if (t < 1 / 2) return q;
1473            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
1474            return p;
1475        }
1476
1477        if (s === 0) {
1478            r = g = b = l; // achromatic
1479        } else {
1480            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1481            var p = 2 * l - q;
1482            r = hue2rgb(p, q, h + 1 / 3);
1483            g = hue2rgb(p, q, h);
1484            b = hue2rgb(p, q, h - 1 / 3);
1485        }
1486
1487        return { r: r * 255, g: g * 255, b: b * 255 };
1488    }
1489
1490    // `rgbToHsv`
1491    // Converts an RGB color value to HSV
1492    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1493    // *Returns:* { h, s, v } in [0,1]
1494    function rgbToHsv(r, g, b) {
1495        r = bound01(r, 255);
1496        g = bound01(g, 255);
1497        b = bound01(b, 255);
1498
1499        var max = mathMax(r, g, b),
1500            min = mathMin(r, g, b);
1501        var h,
1502            s,
1503            v = max;
1504
1505        var d = max - min;
1506        s = max === 0 ? 0 : d / max;
1507
1508        if (max == min) {
1509            h = 0; // achromatic
1510        } else {
1511            switch (max) {
1512                case r:
1513                    h = (g - b) / d + (g < b ? 6 : 0);
1514                    break;
1515                case g:
1516                    h = (b - r) / d + 2;
1517                    break;
1518                case b:
1519                    h = (r - g) / d + 4;
1520                    break;
1521            }
1522            h /= 6;
1523        }
1524        return { h: h, s: s, v: v };
1525    }
1526
1527    // `hsvToRgb`
1528    // Converts an HSV color value to RGB.
1529    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1530    // *Returns:* { r, g, b } in the set [0, 255]
1531    function hsvToRgb(h, s, v) {
1532        h = bound01(h, 360) * 6;
1533        s = bound01(s, 100);
1534        v = bound01(v, 100);
1535
1536        var i = Math.floor(h),
1537            f = h - i,
1538            p = v * (1 - s),
1539            q = v * (1 - f * s),
1540            t = v * (1 - (1 - f) * s),
1541            mod = i % 6,
1542            r = [v, q, p, p, t, v][mod],
1543            g = [t, v, v, q, p, p][mod],
1544            b = [p, p, t, v, v, q][mod];
1545
1546        return { r: r * 255, g: g * 255, b: b * 255 };
1547    }
1548
1549    // `rgbToHex`
1550    // Converts an RGB color to hex
1551    // Assumes r, g, and b are contained in the set [0, 255]
1552    // Returns a 3 or 6 character hex
1553    function rgbToHex(r, g, b, allow3Char) {
1554        var hex = [
1555            pad2(mathRound(r).toString(16)),
1556            pad2(mathRound(g).toString(16)),
1557            pad2(mathRound(b).toString(16)),
1558        ];
1559
1560        // Return a 3 character hex if possible
1561        if (
1562            allow3Char &&
1563            hex[0].charAt(0) == hex[0].charAt(1) &&
1564            hex[1].charAt(0) == hex[1].charAt(1) &&
1565            hex[2].charAt(0) == hex[2].charAt(1)
1566        ) {
1567            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1568        }
1569
1570        return hex.join("");
1571    }
1572
1573    // `rgbaToHex`
1574    // Converts an RGBA color plus alpha transparency to hex
1575    // Assumes r, g, b are contained in the set [0, 255] and
1576    // a in [0, 1]. Returns a 4 or 8 character rgba hex
1577    function rgbaToHex(r, g, b, a, allow4Char) {
1578        var hex = [
1579            pad2(mathRound(r).toString(16)),
1580            pad2(mathRound(g).toString(16)),
1581            pad2(mathRound(b).toString(16)),
1582            pad2(convertDecimalToHex(a)),
1583        ];
1584
1585        // Return a 4 character hex if possible
1586        if (
1587            allow4Char &&
1588            hex[0].charAt(0) == hex[0].charAt(1) &&
1589            hex[1].charAt(0) == hex[1].charAt(1) &&
1590            hex[2].charAt(0) == hex[2].charAt(1) &&
1591            hex[3].charAt(0) == hex[3].charAt(1)
1592        ) {
1593            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
1594        }
1595
1596        return hex.join("");
1597    }
1598
1599    // `rgbaToArgbHex`
1600    // Converts an RGBA color to an ARGB Hex8 string
1601    // Rarely used, but required for "toFilter()"
1602    function rgbaToArgbHex(r, g, b, a) {
1603        var hex = [
1604            pad2(convertDecimalToHex(a)),
1605            pad2(mathRound(r).toString(16)),
1606            pad2(mathRound(g).toString(16)),
1607            pad2(mathRound(b).toString(16)),
1608        ];
1609
1610        return hex.join("");
1611    }
1612
1613    // `equals`
1614    // Can be called with any tinycolor input
1615    tinycolor.equals = function (color1, color2) {
1616        if (!color1 || !color2) {
1617            return false;
vendor: 4,315 bytes, lines 1618-1755
1618        }
1619        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1620    };
1621
1622    tinycolor.random = function () {
1623        return tinycolor.fromRatio({
1624            r: mathRandom(),
1625            g: mathRandom(),
1626            b: mathRandom(),
1627        });
1628    };
1629
1630    // Modification Functions
1631    // ----------------------
1632    // Thanks to less.js for some of the basics here
1633    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1634
1635    function desaturate(color, amount) {
1636        amount = amount === 0 ? 0 : amount || 10;
1637        var hsl = tinycolor(color).toHsl();
1638        hsl.s -= amount / 100;
1639        hsl.s = clamp01(hsl.s);
1640        return tinycolor(hsl);
1641    }
1642
1643    function saturate(color, amount) {
1644        amount = amount === 0 ? 0 : amount || 10;
1645        var hsl = tinycolor(color).toHsl();
1646        hsl.s += amount / 100;
1647        hsl.s = clamp01(hsl.s);
1648        return tinycolor(hsl);
1649    }
1650
1651    function greyscale(color) {
1652        return tinycolor(color).desaturate(100);
1653    }
1654
1655    function lighten(color, amount) {
1656        amount = amount === 0 ? 0 : amount || 10;
1657        var hsl = tinycolor(color).toHsl();
1658        hsl.l += amount / 100;
1659        hsl.l = clamp01(hsl.l);
1660        return tinycolor(hsl);
1661    }
1662
1663    function brighten(color, amount) {
1664        amount = amount === 0 ? 0 : amount || 10;
1665        var rgb = tinycolor(color).toRgb();
1666        rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * -(amount / 100))));
1667        rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * -(amount / 100))));
1668        rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * -(amount / 100))));
1669        return tinycolor(rgb);
1670    }
1671
1672    function darken(color, amount) {
1673        amount = amount === 0 ? 0 : amount || 10;
1674        var hsl = tinycolor(color).toHsl();
1675        hsl.l -= amount / 100;
1676        hsl.l = clamp01(hsl.l);
1677        return tinycolor(hsl);
1678    }
1679
1680    // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
1681    // Values outside of this range will be wrapped into this range.
1682    function spin(color, amount) {
1683        var hsl = tinycolor(color).toHsl();
1684        var hue = (hsl.h + amount) % 360;
1685        hsl.h = hue < 0 ? 360 + hue : hue;
1686        return tinycolor(hsl);
1687    }
1688
1689    // Combination Functions
1690    // ---------------------
1691    // Thanks to jQuery xColor for some of the ideas behind these
1692    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1693
1694    function complement(color) {
1695        var hsl = tinycolor(color).toHsl();
1696        hsl.h = (hsl.h + 180) % 360;
1697        return tinycolor(hsl);
1698    }
1699
1700    function triad(color) {
1701        var hsl = tinycolor(color).toHsl();
1702        var h = hsl.h;
1703        return [
1704            tinycolor(color),
1705            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1706            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }),
1707        ];
1708    }
1709
1710    function tetrad(color) {
1711        var hsl = tinycolor(color).toHsl();
1712        var h = hsl.h;
1713        return [
1714            tinycolor(color),
1715            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1716            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1717            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }),
1718        ];
1719    }
1720
1721    function splitcomplement(color) {
1722        var hsl = tinycolor(color).toHsl();
1723        var h = hsl.h;
1724        return [
1725            tinycolor(color),
1726            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }),
1727            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l }),
1728        ];
1729    }
1730
1731    function analogous(color, results, slices) {
1732        results = results || 6;
1733        slices = slices || 30;
1734
1735        var hsl = tinycolor(color).toHsl();
1736        var part = 360 / slices;
1737        var ret = [tinycolor(color)];
1738
1739        for (hsl.h = (hsl.h - ((part * results) >> 1) + 720) % 360; --results; ) {
1740            hsl.h = (hsl.h + part) % 360;
1741            ret.push(tinycolor(hsl));
1742        }
1743        return ret;
1744    }
1745
1746    function monochromatic(color, results) {
1747        results = results || 6;
1748        var hsv = tinycolor(color).toHsv();
1749        var h = hsv.h,
1750            s = hsv.s,
1751            v = hsv.v;
1752        var ret = [];
1753        var modification = 1 / results;
1754
1755        while (results--) {
vendor: 4,157 bytes, lines 1756-1864
1756            ret.push(tinycolor({ h: h, s: s, v: v }));
1757            v = (v + modification) % 1;
1758        }
1759
1760        return ret;
1761    }
1762
1763    // Utility Functions
1764    // ---------------------
1765
1766    tinycolor.mix = function (color1, color2, amount) {
1767        amount = amount === 0 ? 0 : amount || 50;
1768
1769        var rgb1 = tinycolor(color1).toRgb();
1770        var rgb2 = tinycolor(color2).toRgb();
1771
1772        var p = amount / 100;
1773
1774        var rgba = {
1775            r: (rgb2.r - rgb1.r) * p + rgb1.r,
1776            g: (rgb2.g - rgb1.g) * p + rgb1.g,
1777            b: (rgb2.b - rgb1.b) * p + rgb1.b,
1778            a: (rgb2.a - rgb1.a) * p + rgb1.a,
1779        };
1780
1781        return tinycolor(rgba);
1782    };
1783
1784    // Readability Functions
1785    // ---------------------
1786    // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
1787
1788    // `contrast`
1789    // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
1790    tinycolor.readability = function (color1, color2) {
1791        var c1 = tinycolor(color1);
1792        var c2 = tinycolor(color2);
1793        return (
1794            (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) /
1795            (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05)
1796        );
1797    };
1798
1799    // `isReadable`
1800    // Ensure that foreground and background color combinations meet WCAG2 guidelines.
1801    // The third argument is an optional Object.
1802    //      the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
1803    //      the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
1804    // If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
1805
1806    // *Example*
1807    //    tinycolor.isReadable("#000", "#111") => false
1808    //    tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
1809    tinycolor.isReadable = function (color1, color2, wcag2) {
1810        var readability = tinycolor.readability(color1, color2);
1811        var wcag2Parms, out;
1812
1813        out = false;
1814
1815        wcag2Parms = validateWCAG2Parms(wcag2);
1816        switch (wcag2Parms.level + wcag2Parms.size) {
1817            case "AAsmall":
1818            case "AAAlarge":
1819                out = readability >= 4.5;
1820                break;
1821            case "AAlarge":
1822                out = readability >= 3;
1823                break;
1824            case "AAAsmall":
1825                out = readability >= 7;
1826                break;
1827        }
1828        return out;
1829    };
1830
1831    // `mostReadable`
1832    // Given a base color and a list of possible foreground or background
1833    // colors for that base, returns the most readable color.
1834    // Optionally returns Black or White if the most readable color is unreadable.
1835    // *Example*
1836    //    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
1837    //    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString();  // "#ffffff"
1838    //    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
1839    //    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
1840    tinycolor.mostReadable = function (baseColor, colorList, args) {
1841        var bestColor = null;
1842        var bestScore = 0;
1843        var readability;
1844        var includeFallbackColors, level, size;
1845        args = args || {};
1846        includeFallbackColors = args.includeFallbackColors;
1847        level = args.level;
1848        size = args.size;
1849
1850        for (var i = 0; i < colorList.length; i++) {
1851            readability = tinycolor.readability(baseColor, colorList[i]);
1852            if (readability > bestScore) {
1853                bestScore = readability;
1854                bestColor = tinycolor(colorList[i]);
1855            }
1856        }
1857
1858        if (
1859            tinycolor.isReadable(baseColor, bestColor, { level: level, size: size }) ||
1860            !includeFallbackColors
1861        ) {
1862            return bestColor;
1863        } else {
1864            args.includeFallbackColors = false;
vendor: 12,185 bytes, lines 1865-2238
1865            return tinycolor.mostReadable(baseColor, ["#fff", "#000"], args);
1866        }
1867    };
1868
1869    // Big List of Colors
1870    // ------------------
1871    // <http://www.w3.org/TR/css3-color/#svg-color>
1872    var names = (tinycolor.names = {
1873        aliceblue: "f0f8ff",
1874        antiquewhite: "faebd7",
1875        aqua: "0ff",
1876        aquamarine: "7fffd4",
1877        azure: "f0ffff",
1878        beige: "f5f5dc",
1879        bisque: "ffe4c4",
1880        black: "000",
1881        blanchedalmond: "ffebcd",
1882        blue: "00f",
1883        blueviolet: "8a2be2",
1884        brown: "a52a2a",
1885        burlywood: "deb887",
1886        burntsienna: "ea7e5d",
1887        cadetblue: "5f9ea0",
1888        chartreuse: "7fff00",
1889        chocolate: "d2691e",
1890        coral: "ff7f50",
1891        cornflowerblue: "6495ed",
1892        cornsilk: "fff8dc",
1893        crimson: "dc143c",
1894        cyan: "0ff",
1895        darkblue: "00008b",
1896        darkcyan: "008b8b",
1897        darkgoldenrod: "b8860b",
1898        darkgray: "a9a9a9",
1899        darkgreen: "006400",
1900        darkgrey: "a9a9a9",
1901        darkkhaki: "bdb76b",
1902        darkmagenta: "8b008b",
1903        darkolivegreen: "556b2f",
1904        darkorange: "ff8c00",
1905        darkorchid: "9932cc",
1906        darkred: "8b0000",
1907        darksalmon: "e9967a",
1908        darkseagreen: "8fbc8f",
1909        darkslateblue: "483d8b",
1910        darkslategray: "2f4f4f",
1911        darkslategrey: "2f4f4f",
1912        darkturquoise: "00ced1",
1913        darkviolet: "9400d3",
1914        deeppink: "ff1493",
1915        deepskyblue: "00bfff",
1916        dimgray: "696969",
1917        dimgrey: "696969",
1918        dodgerblue: "1e90ff",
1919        firebrick: "b22222",
1920        floralwhite: "fffaf0",
1921        forestgreen: "228b22",
1922        fuchsia: "f0f",
1923        gainsboro: "dcdcdc",
1924        ghostwhite: "f8f8ff",
1925        gold: "ffd700",
1926        goldenrod: "daa520",
1927        gray: "808080",
1928        green: "008000",
1929        greenyellow: "adff2f",
1930        grey: "808080",
1931        honeydew: "f0fff0",
1932        hotpink: "ff69b4",
1933        indianred: "cd5c5c",
1934        indigo: "4b0082",
1935        ivory: "fffff0",
1936        khaki: "f0e68c",
1937        lavender: "e6e6fa",
1938        lavenderblush: "fff0f5",
1939        lawngreen: "7cfc00",
1940        lemonchiffon: "fffacd",
1941        lightblue: "add8e6",
1942        lightcoral: "f08080",
1943        lightcyan: "e0ffff",
1944        lightgoldenrodyellow: "fafad2",
1945        lightgray: "d3d3d3",
1946        lightgreen: "90ee90",
1947        lightgrey: "d3d3d3",
1948        lightpink: "ffb6c1",
1949        lightsalmon: "ffa07a",
1950        lightseagreen: "20b2aa",
1951        lightskyblue: "87cefa",
1952        lightslategray: "789",
1953        lightslategrey: "789",
1954        lightsteelblue: "b0c4de",
1955        lightyellow: "ffffe0",
1956        lime: "0f0",
1957        limegreen: "32cd32",
1958        linen: "faf0e6",
1959        magenta: "f0f",
1960        maroon: "800000",
1961        mediumaquamarine: "66cdaa",
1962        mediumblue: "0000cd",
1963        mediumorchid: "ba55d3",
1964        mediumpurple: "9370db",
1965        mediumseagreen: "3cb371",
1966        mediumslateblue: "7b68ee",
1967        mediumspringgreen: "00fa9a",
1968        mediumturquoise: "48d1cc",
1969        mediumvioletred: "c71585",
1970        midnightblue: "191970",
1971        mintcream: "f5fffa",
1972        mistyrose: "ffe4e1",
1973        moccasin: "ffe4b5",
1974        navajowhite: "ffdead",
1975        navy: "000080",
1976        oldlace: "fdf5e6",
1977        olive: "808000",
1978        olivedrab: "6b8e23",
1979        orange: "ffa500",
1980        orangered: "ff4500",
1981        orchid: "da70d6",
1982        palegoldenrod: "eee8aa",
1983        palegreen: "98fb98",
1984        paleturquoise: "afeeee",
1985        palevioletred: "db7093",
1986        papayawhip: "ffefd5",
1987        peachpuff: "ffdab9",
1988        peru: "cd853f",
1989        pink: "ffc0cb",
1990        plum: "dda0dd",
1991        powderblue: "b0e0e6",
1992        purple: "800080",
1993        rebeccapurple: "663399",
1994        red: "f00",
1995        rosybrown: "bc8f8f",
1996        royalblue: "4169e1",
1997        saddlebrown: "8b4513",
1998        salmon: "fa8072",
1999        sandybrown: "f4a460",
2000        seagreen: "2e8b57",
2001        seashell: "fff5ee",
2002        sienna: "a0522d",
2003        silver: "c0c0c0",
2004        skyblue: "87ceeb",
2005        slateblue: "6a5acd",
2006        slategray: "708090",
2007        slategrey: "708090",
2008        snow: "fffafa",
2009        springgreen: "00ff7f",
2010        steelblue: "4682b4",
2011        tan: "d2b48c",
2012        teal: "008080",
2013        thistle: "d8bfd8",
2014        tomato: "ff6347",
2015        turquoise: "40e0d0",
2016        violet: "ee82ee",
2017        wheat: "f5deb3",
2018        white: "fff",
2019        whitesmoke: "f5f5f5",
2020        yellow: "ff0",
2021        yellowgreen: "9acd32",
2022    });
2023
2024    // Make it easy to access colors via `hexNames[hex]`
2025    var hexNames = (tinycolor.hexNames = flip(names));
2026
2027    // Utilities
2028    // ---------
2029
2030    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
2031    function flip(o) {
2032        var flipped = {};
2033        for (var i in o) {
2034            if (o.hasOwnProperty(i)) {
2035                flipped[o[i]] = i;
2036            }
2037        }
2038        return flipped;
2039    }
2040
2041    // Return a valid alpha value [0,1] with all invalid values being set to 1
2042    function boundAlpha(a) {
2043        a = parseFloat(a);
2044
2045        if (isNaN(a) || a < 0 || a > 1) {
2046            a = 1;
2047        }
2048
2049        return a;
2050    }
2051
2052    // Take input from [0, n] and return it as [0, 1]
2053    function bound01(n, max) {
2054        if (isOnePointZero(n)) {
2055            n = "100%";
2056        }
2057
2058        var processPercent = isPercentage(n);
2059        n = mathMin(max, mathMax(0, parseFloat(n)));
2060
2061        // Automatically convert percentage into number
2062        if (processPercent) {
2063            n = parseInt(n * max, 10) / 100;
2064        }
2065
2066        // Handle floating point rounding errors
2067        if (Math.abs(n - max) < 0.000001) {
2068            return 1;
2069        }
2070
2071        // Convert into [0, 1] range if it isn't already
2072        return (n % max) / parseFloat(max);
2073    }
2074
2075    // Force a number between 0 and 1
2076    function clamp01(val) {
2077        return mathMin(1, mathMax(0, val));
2078    }
2079
2080    // Parse a base-16 hex value into a base-10 integer
2081    function parseIntFromHex(val) {
2082        return parseInt(val, 16);
2083    }
2084
2085    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
2086    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
2087    function isOnePointZero(n) {
2088        return typeof n == "string" && n.indexOf(".") != -1 && parseFloat(n) === 1;
2089    }
2090
2091    // Check to see if string passed in is a percentage
2092    function isPercentage(n) {
2093        return typeof n === "string" && n.indexOf("%") != -1;
2094    }
2095
2096    // Force a hex value to have 2 characters
2097    function pad2(c) {
2098        return c.length == 1 ? "0" + c : "" + c;
2099    }
2100
2101    // Replace a decimal with it's percentage value
2102    function convertToPercentage(n) {
2103        if (n <= 1) {
2104            n = n * 100 + "%";
2105        }
2106
2107        return n;
2108    }
2109
2110    // Converts a decimal to a hex value
2111    function convertDecimalToHex(d) {
2112        return Math.round(parseFloat(d) * 255).toString(16);
2113    }
2114    // Converts a hex value to a decimal
2115    function convertHexToDecimal(h) {
2116        return parseIntFromHex(h) / 255;
2117    }
2118
2119    var matchers = (function () {
2120        // <http://www.w3.org/TR/css3-values/#integers>
2121        var CSS_INTEGER = "[-\\+]?\\d+%?";
2122
2123        // <http://www.w3.org/TR/css3-values/#number-value>
2124        var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2125
2126        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
2127        var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2128
2129        // Actual matching.
2130        // Parentheses and commas are optional, but not required.
2131        // Whitespace can take the place of commas or opening paren
2132        var PERMISSIVE_MATCH3 =
2133            "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2134        var PERMISSIVE_MATCH4 =
2135            "[\\s|\\(]+(" +
2136            CSS_UNIT +
2137            ")[,|\\s]+(" +
2138            CSS_UNIT +
2139            ")[,|\\s]+(" +
2140            CSS_UNIT +
2141            ")[,|\\s]+(" +
2142            CSS_UNIT +
2143            ")\\s*\\)?";
2144
2145        return {
2146            CSS_UNIT: new RegExp(CSS_UNIT),
2147            rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
2148            rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
2149            hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
2150            hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
2151            hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
2152            hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
2153            hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2154            hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2155            hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2156            hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2157        };
2158    })();
2159
2160    // `isValidCSSUnit`
2161    // Take in a single string / number and check to see if it looks like a CSS unit
2162    // (see `matchers` above for definition).
2163    function isValidCSSUnit(color) {
2164        return !!matchers.CSS_UNIT.exec(color);
2165    }
2166
2167    // `stringInputToObject`
2168    // Permissive string parsing.  Take in a number of formats, and output an object
2169    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2170    function stringInputToObject(color) {
2171        color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase();
2172        var named = false;
2173        if (names[color]) {
2174            color = names[color];
2175            named = true;
2176        } else if (color == "transparent") {
2177            return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2178        }
2179
2180        // Try to match string input using regular expressions.
2181        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2182        // Just return an object and let the conversion functions handle that.
2183        // This way the result will be the same whether the tinycolor is initialized with string or object.
2184        var match;
2185        if ((match = matchers.rgb.exec(color))) {
2186            return { r: match[1], g: match[2], b: match[3] };
2187        }
2188        if ((match = matchers.rgba.exec(color))) {
2189            return { r: match[1], g: match[2], b: match[3], a: match[4] };
2190        }
2191        if ((match = matchers.hsl.exec(color))) {
2192            return { h: match[1], s: match[2], l: match[3] };
2193        }
2194        if ((match = matchers.hsla.exec(color))) {
2195            return { h: match[1], s: match[2], l: match[3], a: match[4] };
2196        }
2197        if ((match = matchers.hsv.exec(color))) {
2198            return { h: match[1], s: match[2], v: match[3] };
2199        }
2200        if ((match = matchers.hsva.exec(color))) {
2201            return { h: match[1], s: match[2], v: match[3], a: match[4] };
2202        }
2203        if ((match = matchers.hex8.exec(color))) {
2204            return {
2205                r: parseIntFromHex(match[1]),
2206                g: parseIntFromHex(match[2]),
2207                b: parseIntFromHex(match[3]),
2208                a: convertHexToDecimal(match[4]),
2209                format: named ? "name" : "hex8",
2210            };
2211        }
2212        if ((match = matchers.hex6.exec(color))) {
2213            return {
2214                r: parseIntFromHex(match[1]),
2215                g: parseIntFromHex(match[2]),
2216                b: parseIntFromHex(match[3]),
2217                format: named ? "name" : "hex",
2218            };
2219        }
2220        if ((match = matchers.hex4.exec(color))) {
2221            return {
2222                r: parseIntFromHex(match[1] + "" + match[1]),
2223                g: parseIntFromHex(match[2] + "" + match[2]),
2224                b: parseIntFromHex(match[3] + "" + match[3]),
2225                a: convertHexToDecimal(match[4] + "" + match[4]),
2226                format: named ? "name" : "hex8",
2227            };
2228        }
2229        if ((match = matchers.hex3.exec(color))) {
2230            return {
2231                r: parseIntFromHex(match[1] + "" + match[1]),
2232                g: parseIntFromHex(match[2] + "" + match[2]),
2233                b: parseIntFromHex(match[3] + "" + match[3]),
2234                format: named ? "name" : "hex",
2235            };
2236        }
2237
2238        return false;
2239    }
2240
2241    function validateWCAG2Parms(parms) {
2242        // return valid WCAG2 parms for isReadable.
2243        // If input parms are invalid, return {"level":"AA", "size":"small"}
2244        var level, size;
2245        parms = parms || { level: "AA", size: "small" };
2246        level = (parms.level || "AA").toUpperCase();
2247        size = (parms.size || "small").toLowerCase();
2248        if (level !== "AA" && level !== "AAA") {
2249            level = "AA";
2250        }
2251        if (size !== "small" && size !== "large") {
2252            size = "small";
2253        }
2254        return { level: level, size: size };
2255    }
2256
2257    const $$1 = jQuery;
2258    class Server {
2259        constructor() {
2260            this.apiUrl = MapSVG.urls.api;
2261        }
2262        getUrl(path) {
2263            return this.apiUrl + path;
2264        }
2265        get(path, data) {
2266            return $$1.ajax({
2267                url: this.apiUrl + path,
2268                type: "GET",
2269                data: data,
2270                beforeSend: function (xhr) {
2271                    if (MapSVG.nonce()) {
2272                        xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2273                    }
2274                },
2275            });
2276        }
2277        post(path, data) {
2278            const ajaxParams = {
2279                url: this.apiUrl + path,
2280                type: "POST",
2281                data: data,
2282                beforeSend: function (xhr) {
2283                    if (MapSVG.nonce()) {
2284                        xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2285                    }
2286                },
2287            };
2288            if (data instanceof FormData) {
2289                ajaxParams["processData"] = false;
2290                ajaxParams["contentType"] = false;
2291            }
2292            return $$1.ajax(ajaxParams);
2293        }
2294        put(path, data) {
2295            const ajaxParams = {
2296                url: this.apiUrl + path,
2297                type: "POST",
2298                data: data,
2299                beforeSend: function (xhr) {
2300                    if (MapSVG.nonce()) {
2301                        xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2302                    }
2303                    xhr.setRequestHeader("X-HTTP-Method-Override", "PUT");
2304                },
2305            };
2306            if (data instanceof FormData) {
2307                ajaxParams["processData"] = false;
2308                ajaxParams["contentType"] = false;
2309            }
2310            return $$1.ajax(ajaxParams);
2311        }
2312        delete(path, data) {
2313            return $$1.ajax({
2314                url: this.apiUrl + path,
2315                type: "POST",
2316                data: data,
2317                beforeSend: function (xhr) {
2318                    if (MapSVG.nonce()) {
2319                        xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2320                    }
2321                    xhr.setRequestHeader("X-HTTP-Method-Override", "DELETE");
2322                },
2323            });
2324        }
2325        ajax(path, data) {
2326            data.url = this.getUrl(path);
2327            data.beforeSend = function (xhr) {
2328                if (MapSVG.nonce()) {
2329                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2330                }
2331            };
2332            return $$1.ajax(data);
2333        }
2334    }
2335
2336    class Events {
2337        constructor(context) {
2338            this.events = {};
2339            this.context = context;
2340        }
2341        on(event, callbackOrObjectType, callback) {
2342            if (!this.events[event])
2343                this.events[event] = [];
2344            let callbackFunction;
2345            if (typeof callbackOrObjectType === "string") {
2346                callbackFunction = callback;
2347            }
2348            else {
2349                callbackFunction = callbackOrObjectType;
2350            }
2351            this.events[event].push(callbackFunction);
2352            return this;
2353        }
2354        off(event, callback) {
2355            const _this = this;
2356            if (this.events[event] && this.events[event].length) {
2357                this.events[event].forEach(function (_callback, index) {
2358                    if (typeof callback === "undefined") {
2359                        _this.events[event].splice(index, 1);
2360                    }
2361                    else if (_callback === callback) {
2362                        _this.events[event].splice(index, 1);
2363                    }
2364                });
2365            }
2366            return this;
2367        }
2368        trigger(event, thisArg, args) {
2369            if (this.events[event] && this.events[event].length)
2370                this.events[event].forEach((callback) => {
2371                    try {
2372                        callback && callback.apply(thisArg || this.context, args || [this.context]);
2373                    }
2374                    catch (err) {
2375                        console.error(err);
2376                    }
2377                });
2378            return this;
2379        }
2380    }
2381
2382    class ArrayIndexed extends Array {
2383        constructor(indexKey, items, options) {
2384            if (items) {
2385                super(...items);
2386            }
2387            else {
2388                super();
2389            }
2390            this.key = indexKey;
2391            this.dict = {};
2392            this.nextId = 1;
2393            if (options) {
2394                this.options = options;
2395            }
2396            else {
2397                this.options = { autoId: false, unique: false };
2398            }
2399            if (this.length > 0) {
2400                let i = 0;
2401                const _this = this;
2402                if (this.options.autoId) {
2403                    let maxId = 0;
2404                    let missingIds = false;
2405                    this.forEach(function (item) {
2406                        if (item[_this.key] != null) {
2407                            if (item[_this.key] > maxId) {
2408                                maxId = item[_this.key];
2409                            }
2410                        }
2411                        else {
2412                            missingIds = true;
2413                        }
2414                    });
2415                    this.nextId = ++maxId;
2416                    if (missingIds) {
2417                        this.forEach(function (item) {
2418                            if (item[_this.key] == null) {
2419                                item[_this.key] = _this.nextId;
2420                                _this.nextId++;
2421                            }
2422                        });
2423                    }
2424                }
2425                this.forEach(function (item) {
2426                    _this.dict[item[_this.key]] = i;
2427                    i++;
2428                });
2429            }
2430        }
2431        push(item) {
2432            const length = super.push(item);
2433            if (this.options.autoId === true) {
2434                item[this.key] = this.nextId;
2435                this.nextId++;
2436            }
2437            this.dict[item[this.key]] = length - 1;
2438            return length;
2439        }
2440        pop() {
2441            const item = this[this.length - 1];
2442            const id = item[this.key];
2443            const length = super.pop();
2444            delete this.dict[id];
2445            this.reindex();
2446            return super.pop();
2447        }
2448        update(data) {
2449            if (data[this.key] != null) {
2450                const obj = this.get(data[this.key]);
2451                for (const i in data) {
2452                    obj[i] = data[i];
2453                }
2454                return obj;
2455            }
2456            return false;
2457        }
2458        get(id) {
2459            return this.findById(id);
2460        }
2461        findById(id) {
2462            return this[this.dict[id]];
2463        }
2464        deleteById(id) {
2465            const index = this.dict[id];
2466            if (typeof index !== "undefined") {
2467                delete this.dict[id];
2468                this.splice(index, 1);
2469            }
2470        }
2471        delete(id) {
2472            this.deleteById(id);
2473        }
2474        clear() {
2475            this.length = 0;
2476            this.reindex();
2477        }
2478        reindex() {
2479            const _this = this;
2480            this.dict = {};
2481            this.forEach(function (item, index) {
2482                _this.dict[item[_this.key]] = index;
2483            });
2484        }
2485        sort(compareFn) {
2486            super.sort(compareFn);
2487            this.reindex();
2488            return this;
2489        }
2490        splice(start, deleteCount) {
2491            const res = super.splice(start, deleteCount);
2492            this.reindex();
2493            return res;
2494        }
2495    }
2496
2497    class SchemaField {
2498        constructor(field) {
2499            const booleans = ["visible", "searchable", "readonly", "protected"];
2500            for (const key in field) {
2501                this[key] = field[key];
2502            }
2503            booleans.forEach((paramName) => {
2504                if (typeof this[paramName] !== "undefined") {
2505                    this[paramName] = MapSVG.parseBoolean(this[paramName]);
2506                }
2507                else {
2508                    this[paramName] = false;
2509                }
2510            });
2511            if (typeof this.options !== "undefined") {
2512                if (!(this.options instanceof ArrayIndexed)) {
2513                    this.options = new ArrayIndexed("value", this.options);
2514                }
2515            }
2516        }
2517    }
2518
2519    class Schema {
2520        constructor(options) {
2521            this.fields = new ArrayIndexed("name");
2522            this.build(options);
2523            this.lastChangeTime = Date.now();
2524            this.events = new Events(this);
2525        }
2526        build(options) {
2527            const allowedParams = ["id", "title", "type", "name", "fields"];
2528            allowedParams.forEach((paramName) => {
2529                const setter = "set" + MapSVG.ucfirst(paramName);
2530                if (typeof options[paramName] !== "undefined" && typeof this[setter] == "function") {
2531                    this[setter](options[paramName]);
2532                }
2533            });
2534        }
2535        update(options) {
2536            this.build(options);
2537        }
2538        setId(id) {
2539            this.id = id;
2540        }
2541        setTitle(title) {
2542            this.title = title;
2543        }
2544        setName(name) {
2545            this.name = name;
2546        }
2547        loaded() {
2548            return this.fields.length !== 0;
2549        }
2550        setFields(fields) {
2551            if (fields) {
2552                this.fields.clear();
2553                fields.forEach((fieldParams) => {
2554                    this.fields.push(new SchemaField(fieldParams));
2555                });
2556            }
2557        }
2558        getFields() {
2559            return this.fields;
2560        }
2561        getFieldsAsArray() {
2562            return this.fields;
2563        }
2564        getFieldNames() {
2565            return this.fields.map((f) => f.name);
2566        }
2567        getField(field) {
2568            return this.fields.findById(field);
2569        }
2570        getFieldByType(type) {
2571            let f = null;
2572            this.fields.forEach(function (field) {
2573                if (field.type === type)
2574                    f = field;
2575            });
2576            return f;
2577        }
2578        getColumns(filters) {
2579            filters = filters || {};
2580            const columns = this.fields;
2581            const needfilters = Object.keys(filters).length !== 0;
2582            let results = [];
2583            if (needfilters) {
2584                let filterpass;
2585                columns.forEach(function (obj) {
2586                    filterpass = true;
2587                    for (const param in filters) {
2588                        filterpass = obj[param] == filters[param];
2589                    }
2590                    filterpass && results.push(obj);
2591                });
2592            }
2593            else {
2594                results = columns;
2595            }
2596            return results;
2597        }
2598        getData() {
2599            const data = {
2600                id: this.id,
2601                title: this.title,
2602                name: this.name,
2603                fields: this.fields,
2604                type: this.type,
2605            };
2606            return data;
2607        }
2608    }
2609
2610    class Query {
2611        constructor(options) {
2612            this.filters = {};
2613            this.filterout = {};
2614            this.page = 1;
2615            if (options) {
2616                for (const i in options) {
2617                    if (typeof options[i] !== "undefined") {
2618                        this[i] = options[i];
2619                    }
2620                }
2621            }
2622        }
2623        setFields(fields) {
2624            const _this = this;
2625            for (const key in fields) {
2626                if (key == "filters") {
2627                    _this.setFilters(fields[key]);
2628                }
2629                else {
2630                    _this[key] = fields[key];
2631                }
2632            }
2633        }
2634        update(query) {
2635            for (const i in query) {
2636                if (typeof query[i] !== "undefined") {
2637                    if (i === "filters") {
2638                        this.setFilters(query[i]);
2639                    }
2640                    else {
2641                        this[i] = query[i];
2642                    }
2643                }
2644            }
2645        }
2646        get() {
2647            return {
2648                search: this.search,
2649                searchField: this.searchField,
2650                searchFallback: this.searchFallback,
2651                filters: this.filters,
2652                filterout: this.filterout,
2653                page: this.page,
2654                sort: this.sort,
2655                perpage: this.perpage,
2656                lastpage: this.lastpage,
2657            };
2658        }
2659        clearFilters() {
2660            this.resetFilters();
2661        }
2662        setFilters(fields) {
2663            const _this = this;
2664            for (const key in fields) {
2665                if (fields[key] === null || fields[key] === "" || fields[key] === undefined) {
2666                    if (_this.filters[key]) {
2667                        delete _this.filters[key];
2668                    }
2669                }
2670                else {
2671                    _this.filters[key] = fields[key];
2672                }
2673            }
2674        }
2675        setSearch(search) {
2676            this.search = search;
2677        }
2678        setFilterOut(fields) {
2679            if (fields === null) {
2680                delete this.filterout;
2681            }
2682            else {
2683                this.filterout = fields;
2684            }
2685        }
2686        resetFilters(fields) {
2687            this.filters = {};
2688            this.setSearch("");
2689        }
2690        setFilterField(field, value) {
2691            this.filters[field] = value;
2692        }
2693        hasFilters() {
2694            return Object.keys(this.filters).length > 0 || this.search.length > 0;
2695        }
2696        removeFilter(fieldName) {
2697            this.filters[fieldName] = null;
2698            delete this.filters[fieldName];
2699        }
2700        requestSchema(requestSchema) {
2701            this.withSchema = requestSchema ? requestSchema : true;
2702        }
2703    }
2704
2705    class LocationAddress {
2706        constructor(fields) {
2707            for (const i in fields) {
2708                this[i] = fields[i];
2709            }
2710        }
2711        getData() {
2712            const copy = {};
2713            [
2714                "route",
2715                "address_formatted",
2716                "administrative_area_level_1",
2717                "administrative_area_level_1_short",
2718                "administrative_area_level_2",
2719                "administrative_area_level_2_short",
2720                "country",
2721                "country_short",
2722                "postal_code",
2723            ].forEach((field) => {
2724                if (this[field]) {
2725                    copy[field] = this[field];
2726                }
2727            });
2728            return copy;
2729        }
2730        get state() {
2731            return this.country_short === "US" ? this.administrative_area_level_1 : null;
2732        }
2733        get state_short() {
2734            return this.country_short === "US" ? this.administrative_area_level_1_short : null;
2735        }
2736        get county() {
2737            return this.country_short === "US" ? this.administrative_area_level_2 : null;
2738        }
2739        get zip() {
2740            return this.postal_code;
2741        }
2742    }
2743
2744    class ScreenPoint {
2745        constructor(x, y) {
2746            this.x = x;
2747            this.y = y;
2748        }
2749    }
2750    class SVGPoint {
2751        constructor(x, y) {
2752            let _x, _y;
2753            if (typeof x === "object") {
2754                if (x.x && x.y) {
2755                    _x = parseFloat(x.x + "");
2756                    _y = parseFloat(x.y + "");
2757                }
2758                else {
2759                    console.error("MapSVG: incorrect format of {x, y} object for SVGPoint.");
2760                    _x = 0;
2761                    _y = 0;
2762                }
2763            }
2764            else {
2765                _x = parseFloat(x + "");
2766                _y = parseFloat(y + "");
2767            }
2768            this.x = _x;
2769            this.y = _y;
2770        }
2771        toString() {
2772            return this.x + "," + this.y;
2773        }
2774    }
2775    class GeoPoint {
2776        constructor(lat, lng) {
2777            let _lat, _lng;
2778            if (typeof lat === "object") {
2779                if (lat.lat && lat.lng) {
2780                    _lat = parseFloat(lat.lat + "");
2781                    _lng = parseFloat(lat.lng + "");
2782                }
2783                else {
2784                    console.error("MapSVG: incorrect format of {lat, lng} object for GeoPoint.");
2785                    _lat = 0;
2786                    _lng = 0;
2787                }
2788            }
2789            else {
2790                _lat = parseFloat(lat + "");
2791                _lng = parseFloat(lng + "");
2792            }
2793            this.lat = _lat;
2794            this.lng = _lng;
2795        }
2796        toString() {
2797            return this.lat + "," + this.lng;
2798        }
2799    }
2800    class Location {
2801        constructor(options) {
2802            this.update(options);
2803        }
2804        update(options) {
2805            if (options.object) {
2806                this.setObject(options.object);
2807            }
2808            if (options.img) {
2809                this.setImage(options.img);
2810            }
2811            if (options.address) {
2812                this.setAddress(options.address);
2813            }
2814            if (options.svgPoint) {
2815                this.setSvgPoint(options.svgPoint);
2816            }
2817            if (options.geoPoint) {
2818                this.setGeoPoint(options.geoPoint);
2819            }
2820        }
2821        setObject(object) {
2822            this.object = object;
2823        }
2824        setImage(imgUrl) {
2825            if (typeof imgUrl !== "string") {
2826                return;
2827            }
2828            let src = imgUrl.split("/").pop();
2829            if (imgUrl.indexOf("uploads") !== -1) {
2830                src = "uploads/" + src;
2831            }
2832            this.img = src;
2833            this.imagePath = this.getImageUrl();
2834            this.marker && this.marker && this.marker.setImage(this.imagePath);
2835        }
2836        getImageUrl() {
2837            if (this.img && this.img.indexOf("uploads/") === 0) {
2838                return MapSVG.urls.uploads + "markers/" + this.img.replace("uploads/", "");
2839            }
2840            else {
2841                return MapSVG.urls.root + "markers/" + (this.img || "_pin_default.png");
2842            }
2843        }
2844        setAddress(address) {
2845            this.address = new LocationAddress(address);
2846        }
2847        setSvgPoint(svgPoint) {
2848            this.svgPoint = svgPoint instanceof SVGPoint ? svgPoint : new SVGPoint(svgPoint);
2849            if (this.marker) {
2850                this.marker.setSvgPointFromLocation();
2851            }
2852        }
2853        setGeoPoint(geoPoint) {
2854            this.geoPoint = geoPoint instanceof GeoPoint ? geoPoint : new GeoPoint(geoPoint);
2855            if (this.marker) {
2856                this.marker.setSvgPointFromLocation();
2857            }
2858        }
2859        getMarkerImage() {
2860            if (this.img && this.img.indexOf("uploads/") === 0) {
2861                return MapSVG.urls.uploads + "markers/" + this.img.replace("uploads/", "");
2862            }
2863            else {
2864                return MapSVG.urls.root + "markers/" + (this.img || "_pin_default.png");
2865            }
2866        }
2867        getData() {
2868            const data = {
2869                img: this.img,
2870                imagePath: this.imagePath,
2871                markerImagePath: this.marker && this.marker.object
2872                    ? this.marker.object.getMarkerImage()
2873                    : this.imagePath,
2874                address: this.address,
2875            };
2876            if (this.geoPoint) {
2877                data.geoPoint = { lat: this.geoPoint.lat, lng: this.geoPoint.lng };
2878            }
2879            if (this.svgPoint) {
2880                data.svgPoint = { x: this.svgPoint.x, y: this.svgPoint.y };
2881            }
2882            return data;
2883        }
2884    }
2885
2886    class CustomObject {
2887        constructor(params, schema) {
2888            this.initialLoad = true;
2889            this.setSchema(schema);
2890            this.dirtyFields = [];
2891            this.regions = [];
2892            this._regions = {};
2893            if (params.id !== undefined) {
2894                this.id = params.id;
2895            }
2896            this.initialLoad = true;
2897            this.build(params);
2898            this.initialLoad = false;
2899            if (this.id) {
2900                this.clearDirtyFields();
2901            }
2902        }
2903        setSchema(schema) {
2904            this.schema = schema;
2905            this.schema.events.on("changed", () => this.setLocationField());
2906            this.fields = schema.getFieldNames();
2907            this.setLocationField();
2908        }
2909        build(params) {
2910            for (const fieldName in params) {
2911                const field = this.schema.getField(fieldName);
2912                if (field) {
2913                    if (!this.initialLoad) {
2914                        this.dirtyFields.push(fieldName);
2915                    }
2916                    switch (field.type) {
2917                        case "region":
2918                            this.regions = params[fieldName];
2919                            break;
2920                        case "location":
2921                            if (params[fieldName] != null &&
2922                                params[fieldName] != "" &&
2923                                Object.keys(params[fieldName]).length !== 0) {
2924                                const data = {
2925                                    img: this.isMarkersByFieldEnabled()
2926                                        ? this.getMarkerImage()
2927                                        : params[fieldName].img,
2928                                    address: new LocationAddress(params[fieldName].address),
2929                                };
2930                                if (params[fieldName].geoPoint &&
2931                                    params[fieldName].geoPoint.lat &&
2932                                    params[fieldName].geoPoint.lng) {
2933                                    data.geoPoint = new GeoPoint(params[fieldName].geoPoint);
2934                                }
2935                                else if (params[fieldName].svgPoint &&
2936                                    params[fieldName].svgPoint.x &&
2937                                    params[fieldName].svgPoint.y) {
2938                                    data.svgPoint = new SVGPoint(params[fieldName].svgPoint);
2939                                }
2940                                if (this.location != null) {
2941                                    this.location.update(data);
2942                                }
2943                                else {
2944                                    this.location = new Location(data);
2945                                }
2946                            }
2947                            else {
2948                                this.location = null;
2949                            }
2950                            break;
2951                        case "post":
2952                            if (params.post) {
2953                                this.post = params.post;
2954                            }
2955                            break;
2956                        case "select":
2957                            this[fieldName] = params[fieldName];
2958                            if (!field.multiselect) {
2959                                this[fieldName + "_text"] = this.getEnumLabel(field, params, fieldName);
2960                            }
2961                            break;
2962                        case "radio":
2963                            this[fieldName] = params[fieldName];
2964                            this[fieldName + "_text"] = this.getEnumLabel(field, params, fieldName);
2965                            break;
2966                        default:
2967                            this[fieldName] = params[fieldName];
2968                            break;
2969                    }
2970                }
2971            }
2972            const locationField = this.getLocationField();
2973            if (locationField && this.isMarkersByFieldEnabled() && this.isMarkerFieldChanged(params)) {
2974                this.reloadMarkerImage();
2975            }
2976        }
2977        isMarkerFieldChanged(params) {
2978            return Object.keys(params).indexOf(this.getLocationField().markerField) !== -1;
2979        }
2980        setLocationField() {
2981        }
2982        getLocationField() {
2983            return this.schema.getFieldByType("location");
2984        }
2985        reloadMarkerImage() {
2986            this.location && this.location.setImage(this.getMarkerImage());
2987        }
2988        getMarkerImage() {
2989            let fieldValue;
2990            if (this.isMarkersByFieldEnabled()) {
2991                const locationField = this.getLocationField();
2992                fieldValue = this[locationField.markerField];
2993                if (!fieldValue) {
2994                    return locationField.defaultMarkerPath || MapSVG.defaultMarkerImage;
2995                }
2996                else {
2997                    if (locationField.markerField === "regions") {
2998                        fieldValue = fieldValue[0] && fieldValue[0].id;
2999                    }
3000                    else if (typeof fieldValue === "object" && fieldValue.length) {
3001                        fieldValue = fieldValue[0].value;
3002                    }
3003                    return (locationField.markersByField[fieldValue] ||
3004                        locationField.defaultMarkerPath ||
3005                        MapSVG.defaultMarkerImage);
3006                }
3007            }
3008            else {
3009                return this.location.imagePath;
3010            }
3011        }
3012        isMarkersByFieldEnabled() {
3013            const locationField = this.getLocationField();
3014            if (!locationField) {
3015                return false;
3016            }
3017            if (locationField.markersByFieldEnabled &&
3018                locationField.markerField &&
3019                Object.values(locationField.markersByField).length > 0) {
3020                return true;
3021            }
3022            else {
3023                return false;
3024            }
3025        }
3026        clone() {
3027            const data = this.getData();
3028            return new CustomObject(data, this.schema);
3029        }
3030        getEnumLabel(field, params, fieldName) {
3031            const value = field.options.get(params[fieldName]);
3032            if (typeof value !== "undefined") {
3033                return value.label;
3034            }
3035            else {
3036                return "";
3037            }
3038        }
3039        update(params) {
3040            this.build(params);
3041        }
3042        getDirtyFields() {
3043            const data = {};
3044            this.dirtyFields.forEach((field) => {
3045                data[field] = this[field];
3046            });
3047            data.id = this.id;
3048            if (data.location != null && data.location instanceof Location) {
3049                data.location = data.location.getData();
3050            }
3051            if (this.schema.getFieldByType("region")) {
3052                data.regions = this.regions;
3053            }
3054            return data;
3055        }
3056        clearDirtyFields() {
3057            this.dirtyFields = [];
3058        }
3059        getData() {
3060            const data = {};
3061            const fields = this.schema.getFields();
3062            fields.forEach((field) => {
3063                switch (field.type) {
3064                    case "region":
3065                        data[field.name] = this[field.name];
3066                        break;
3067                    case "select":
3068                        data[field.name] = this[field.name];
3069                        if (!field.multiselect) {
3070                            data[field.name + "_text"] = this[field.name + "_text"];
3071                        }
3072                        break;
3073                    case "post":
3074                        data[field.name] = this[field.name];
3075                        data["post"] = this.post;
3076                        break;
3077                    case "status":
3078                    case "radio":
3079                        data[field.name] = this[field.name];
3080                        data[field.name + "_text"] = this[field.name + "_text"];
3081                        break;
3082                    case "location":
3083                        data[field.name] = this[field.name] ? this[field.name].getData() : null;
3084                        break;
3085                    default:
3086                        data[field.name] = this[field.name];
3087                        break;
3088                }
3089            });
3090            return data;
3091        }
3092        getRegions(regionsTableName) {
3093            return this.regions;
3094        }
3095        getRegionsForTable(regionsTableName) {
3096            return this.regions
3097                ? this.regions.filter((region) => !region.tableName || region.tableName === regionsTableName)
3098                : [];
3099        }
3100    }
3101
3102    const $$2 = jQuery;
3103    class Repository {
3104        constructor(objectName, path) {
3105            this.server = new Server();
3106            this.query = new Query();
3107            this.events = new Events(this);
3108            this.className = "";
3109            this.objectNameSingle = objectName;
3110            this.objectNameMany = objectName + "s";
3111            this.setPath(path);
3112            this.objects = new ArrayIndexed("id");
3113            this.completeChunks = 0;
3114        }
3115        setNoFiltersNoLoad(value) {
3116            this.noFiltersNoLoad = value;
3117        }
3118        setDataSource(path) {
3119            this.setPath(path);
3120            this.query = new Query({ withSchema: true });
3121            return this.find().done(() => {
3122                this.query.update({ withSchema: false });
3123            });
3124        }
3125        setPath(path) {
3126            this.path = path.replace(/\/+$/, "") + "/";
3127        }
3128        setSchema(schema) {
3129            this.schema = schema;
3130        }
3131        getSchema() {
3132            return this.schema;
3133        }
3134        loadDataFromResponse(response) {
3135            let data;
3136            data = this.decodeData(response);
3137            this.objects.clear();
3138            if (data[this.objectNameMany] && data[this.objectNameMany].length) {
3139                this.hasMoreRecords =
3140                    this.query.perpage && data[this.objectNameMany].length > this.query.perpage;
3141                if (this.hasMoreRecords) {
3142                    data[this.objectNameMany].pop();
3143                }
3144                data[this.objectNameMany].forEach((obj) => {
3145                    this.objects.push(obj);
3146                });
3147            }
3148            else {
3149                this.hasMoreRecords = false;
3150            }
3151            this.loaded = true;
3152            this.events.trigger("loaded");
3153        }
3154        reload() {
3155            return this.find();
3156        }
3157        create(object) {
3158            const defer = jQuery.Deferred();
3159            defer.promise();
3160            const data = {};
3161            data[this.objectNameSingle] = this.encodeData(object);
3162            this.server
3163                .post(this.path, data)
3164                .done((response) => {
3165                const data = this.decodeData(response);
3166                const object = data[this.objectNameSingle];
3167                this.objects.push(object);
3168                defer.resolve(object);
3169                this.events.trigger("created", this, [object]);
3170            })
3171                .fail((response) => {
3172                defer.reject(response);
3173            });
3174            return defer;
3175        }
3176        findById(id, nocache = false) {
3177            const defer = jQuery.Deferred();
3178            defer.promise();
3179            let object;
3180            if (!nocache) {
3181                object = this.objects.findById(id.toString());
3182            }
3183            if (!nocache && object) {
3184                defer.resolve(object);
3185            }
3186            else {
3187                this.server
3188                    .get(this.path + id)
3189                    .done((response) => {
3190                    const data = this.decodeData(response);
3191                    defer.resolve(data[this.objectNameSingle]);
3192                })
3193                    .fail((response) => {
3194                    defer.reject(response);
3195                });
3196            }
3197            return defer;
3198        }
3199        find(query) {
3200            this.events.trigger("load");
3201            const defer = jQuery.Deferred();
3202            defer.promise();
3203            if (typeof query !== "undefined") {
3204                this.query.update(query);
3205            }
3206            if (this.noFiltersNoLoad && !this.query.hasFilters()) {
3207                this.objects.clear();
3208                this.events.trigger("loaded");
3209                defer.resolve(this.getLoaded());
3210                return defer;
3211            }
3212            if (!this.schema) {
3213                this.query.update({ withSchema: true });
3214            }
3215            this.server
3216                .get(this.path, this.query)
3217                .done((response) => {
3218                if (!this.schema) {
3219                    this.query.update({ withSchema: false });
3220                }
3221                this.loadDataFromResponse(response);
3222                defer.resolve(this.getLoaded());
3223            })
3224                .fail((response) => {
3225                defer.reject(response);
3226            });
3227            return defer;
3228        }
3229        getLoaded() {
3230            return this.objects;
3231        }
3232        getLoadedObject(id) {
3233            return this.objects.findById(id.toString());
3234        }
3235        getLoadedAsArray() {
3236            return this.objects;
3237        }
3238        update(object) {
3239            const defer = jQuery.Deferred();
3240            defer.promise();
3241            const data = {};
3242            const objectUpdatedFields = "getDirtyFields" in object ? object.getDirtyFields() : object;
3243            data[this.objectNameSingle] = this.encodeData(objectUpdatedFields);
3244            this.server
3245                .put(this.path + objectUpdatedFields.id, data)
3246                .done((response) => {
3247                if ("clearDirtyFields" in object) {
3248                    object.clearDirtyFields();
3249                }
3250                defer.resolve(object);
3251                this.events.trigger("updated", this, object);
3252            })
3253                .fail((response, stat) => {
3254                defer.reject(response, stat);
3255            });
3256            return defer;
3257        }
3258        delete(id) {
3259            const defer = jQuery.Deferred();
3260            defer.promise();
3261            this.server
3262                .delete(this.path + id)
3263                .done((response) => {
3264                this.objects.delete(id.toString());
3265                this.events.trigger("deleted");
3266                defer.resolve();
3267            })
3268                .fail((response) => {
3269                defer.reject(response);
3270            });
3271            return defer;
3272        }
3273        clear() {
3274            const defer = jQuery.Deferred();
3275            defer.promise();
3276            this.server
3277                .delete(this.path)
3278                .done((response) => {
3279                this.objects.clear();
3280                this.events.trigger("loaded");
3281                this.events.trigger("cleared");
3282                defer.resolve();
3283            })
3284                .fail((response) => {
3285                defer.reject(response);
3286            });
3287            return defer;
3288        }
3289        onFirstPage() {
3290            return this.query.page === 1;
3291        }
3292        onLastPage() {
3293            return this.hasMoreRecords === false;
3294        }
3295        encodeData(params) {
3296            return params;
3297        }
3298        decodeData(dataJSON) {
3299            let data;
3300            if (typeof dataJSON === "string") {
3301                data = JSON.parse(dataJSON);
3302            }
3303            else {
3304                data = dataJSON;
3305            }
3306            if ((data.object || data.region || data.regions || data.objects) && data.schema) {
3307                this.setSchema(new Schema(data.schema));
3308            }
3309            const dataFormatted = {};
3310            for (const key in data) {
3311                if (data[key]) {
3312                    switch (key) {
3313                        case "object":
3314                        case "region":
3315                            dataFormatted[key] = new CustomObject(data[key], this.schema);
3316                            break;
3317                        case "objects":
3318                        case "regions":
3319                            dataFormatted[key] = data[key].map((obj) => new CustomObject(obj, this.schema));
3320                            break;
3321                        case "schema":
3322                            dataFormatted[key] = this.schema || new Schema(data[key]);
3323                            break;
3324                        case "schemas":
3325                            dataFormatted[key] = data[key].map((obj) => new Schema(obj));
3326                            break;
3327                    }
3328                }
3329            }
3330            return dataFormatted;
3331        }
3332        import(data, convertLatlngToAddress, mapsvg) {
3333            const _this = this;
3334            const locationField = _this.schema.getFieldByType("location");
3335            let language = "en";
3336            if (locationField && locationField.language) {
3337                language = locationField.language;
3338            }
3339            data = this.formatCSV(data, mapsvg);
3340            return this.importByChunks(data, language, convertLatlngToAddress).done(function () {
3341                _this.find();
3342            });
3343        }
3344        importByChunks(data, language, convertLatlngToAddress) {
3345            const _this = this;
3346            let i, j, temparray, chunk = 50;
3347            const chunks = [];
3348            for (i = 0, j = data.length; i < j; i += chunk) {
3349                temparray = data.slice(i, i + chunk);
3350                chunks.push(temparray);
3351            }
3352            if (chunks.length > 0) {
3353                let delay = 0;
3354                const delayPlus = chunks[0][0] && chunks[0][0].location ? 1000 : 0;
3355                var defer = $$2.Deferred();
3356                defer.promise();
3357                _this.completeChunks = 0;
3358                chunks.forEach(function (chunk) {
3359                    delay += delayPlus;
3360                    setTimeout(function () {
3361                        const data = {
3362                            language: language,
3363                            convertLatlngToAddress: convertLatlngToAddress,
3364                        };
3365                        data[_this.objectNameMany] = JSON.stringify(chunk);
3366                        _this.server
3367                            .post(_this.path + "import", data)
3368                            .done(function (_data) {
3369                            _this.completeChunk(chunks, defer);
3370                        })
3371                            .fail((response) => {
3372                            console.error(response);
3373                        });
3374                    }, delay);
3375                });
3376            }
3377            return defer;
3378        }
3379        completeChunk(chunks, defer) {
3380            const _this = this;
3381            _this.completeChunks++;
3382            if (_this.completeChunks === chunks.length) {
3383                defer.resolve();
3384            }
3385        }
3386        formatCSV(data, mapsvg) {
3387            const _this = this;
3388            const latLngRegex = /^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/g;
3389            const regionsTable = mapsvg.regionsRepository.getSchema().name;
3390            data.forEach(function (object, index) {
3391                const newObject = {};
3392                for (const key in object) {
3393                    let field = _this.schema.getField(key);
3394                    if (key === "post") {
3395                        field = { type: "post" };
3396                    }
3397                    if (field !== undefined) {
3398                        switch (field.type) {
3399                            case "region":
3400                                newObject[key] = {};
3401                                newObject[key] = object[key]
3402                                    .split(",")
3403                                    .map(function (regionId) {
3404                                    return regionId.trim();
3405                                })
3406                                    .filter(function (rId) {
3407                                    return (mapsvg.getRegion(rId) !== undefined ||
3408                                        mapsvg.regions.find(function (item) {
3409                                            return item.title === rId;
3410                                        }) !== undefined);
3411                                })
3412                                    .map(function (rId) {
3413                                    let r = mapsvg.getRegion(rId);
3414                                    if (typeof r === "undefined") {
3415                                        r = mapsvg.regions.find(function (item) {
3416                                            return item.title === rId;
3417                                        });
3418                                    }
3419                                    return { id: r.id, title: r.title, tableName: regionsTable };
3420                                });
3421                                break;
3422                            case "location":
3423                                if (object[key].match(latLngRegex)) {
3424                                    const coords = object[key].split(",").map(function (n) {
3425                                        return parseFloat(n);
3426                                    });
3427                                    if (coords.length == 2 &&
3428                                        coords[0] > -90 &&
3429                                        coords[0] < 90 &&
3430                                        coords[1] > -180 &&
3431                                        coords[1] < 180) {
3432                                        newObject[key] = {
3433                                            geoPoint: { lat: coords[0], lng: coords[1] },
3434                                        };
3435                                    }
3436                                    else {
3437                                        newObject[key] = "";
3438                                    }
3439                                }
3440                                else if (object[key]) {
3441                                    newObject[key] = { address: object[key] };
3442                                }
3443                                if (typeof newObject[key] == "object") {
3444                                    newObject[key].img = mapsvg.options.defaultMarkerImage;
3445                                }
3446                                break;
3447                            case "select":
3448                                const field = _this.schema.getField(key);
3449                                if (field.multiselect) {
3450                                    const labels = _this.schema.getField(key).options.map(function (f) {
3451                                        return f.label;
3452                                    });
3453                                    newObject[key] = object[key]
3454                                        .split(",")
3455                                        .map(function (label) {
3456                                        return label.trim();
3457                                    })
3458                                        .filter(function (label) {
3459                                        return labels.indexOf(label) !== -1;
3460                                    })
3461                                        .map(function (label) {
3462                                        return _this.schema
3463                                            .getField(key)
3464                                            .options.filter(function (option) {
3465                                            return option.label == label;
3466                                        })[0];
3467                                    });
3468                                    if (newObject[key].length === 0) {
3469                                        const values = _this.schema
3470                                            .getField(key)
3471                                            .options.map(function (f) {
3472                                            return f.value + "";
3473                                        });
3474                                        newObject[key] = object[key]
3475                                            .split(",")
3476                                            .map(function (value) {
3477                                            return value.trim();
3478                                        })
3479                                            .filter(function (value) {
3480                                            return values.indexOf(value) !== -1;
3481                                        })
3482                                            .map(function (value) {
3483                                            return _this.schema
3484                                                .getField(key)
3485                                                .options.filter(function (option) {
3486                                                return option.value == value;
3487                                            })[0];
3488                                        });
3489                                    }
3490                                }
3491                                else {
3492                                    newObject[key] = object[key];
3493                                }
3494                                break;
3495                            case "radio":
3496                            case "text":
3497                            case "textarea":
3498                            case "status":
3499                            default:
3500                                newObject[key] = object[key];
3501                                break;
3502                        }
3503                    }
3504                }
3505                data[index] = newObject;
3506            });
3507            return data;
3508        }
3509    }
3510
3511    class MapsRepository extends Repository {
3512        constructor() {
3513            super("map", "maps");
3514            this.path = "maps/";
3515        }
3516        encodeData(params) {
3517            const data = {};
3518            if (typeof params.options !== "undefined") {
3519                data.options = JSON.stringify(params.options);
3520                data.options = data.options.replace(/select/g, "!mapsvg-encoded-slct");
3521                data.options = data.options.replace(/table/g, "!mapsvg-encoded-tbl");
3522                data.options = data.options.replace(/database/g, "!mapsvg-encoded-db");
3523                data.options = data.options.replace(/varchar/g, "!mapsvg-encoded-vc");
3524                data.options = data.options.replace(/int\(11\)/g, "!mapsvg-encoded-int");
3525            }
3526            if (typeof params.title !== "undefined") {
3527                data.title = params.title;
3528            }
3529            if (typeof params.id !== "undefined") {
3530                data.id = params.id;
3531            }
3532            if (typeof params.status !== "undefined") {
3533                data.status = params.status;
3534            }
3535            return data;
3536        }
3537        decodeData(dataJSON) {
3538            let data;
3539            if (typeof dataJSON === "string") {
3540                data = JSON.parse(dataJSON);
3541            }
3542            else {
3543                data = dataJSON;
3544            }
3545            return data;
3546        }
3547        copy(id, title) {
3548            const defer = jQuery.Deferred();
3549            defer.promise();
3550            const data = { options: { title: title } };
3551            this.server
3552                .post(this.path + id + "/copy", this.encodeData(data))
3553                .done((response) => {
3554                const data = this.decodeData(response);
3555                this.objects.clear();
3556                this.events.trigger("loaded");
3557                this.events.trigger("cleared");
3558                defer.resolve(data.map);
3559            })
3560                .fail(() => {
3561                defer.reject();
3562            });
3563            return defer;
3564        }
3565        createFromV2(object) {
3566            const defer = jQuery.Deferred();
3567            defer.promise();
3568            const data = {};
3569            data[this.objectNameSingle] = this.encodeData(object);
3570            this.server
3571                .post(this.path + "/createFromV2", data)
3572                .done((response) => {
3573                const data = this.decodeData(response);
3574                const object = data[this.objectNameSingle];
3575                this.objects.push(object);
3576                defer.resolve(object);
3577                this.events.trigger("created", this, [object]);
3578            })
3579                .fail(() => {
3580                defer.reject();
3581            });
3582            return defer;
3583        }
3584        delete(id) {
3585            const defer = jQuery.Deferred();
3586            defer.promise();
3587            this.server
3588                .delete(this.path + id)
3589                .done((response) => {
3590                this.objects.delete(id.toString());
3591                this.events.trigger("deleted");
3592                defer.resolve();
3593            })
3594                .fail(() => {
3595                defer.reject();
3596            });
3597            return defer;
3598        }
3599    }
3600
3601    class MapsV2Repository extends Repository {
3602        constructor() {
3603            super("map", "maps");
3604            this.path = "maps-v2/";
3605        }
3606        encodeData(params) {
3607            const data = {};
3608            data.options = JSON.stringify(params.options);
3609            data.options = data.options.replace(/select/g, "!mapsvg-encoded-slct");
3610            data.options = data.options.replace(/table/g, "!mapsvg-encoded-tbl");
3611            data.options = data.options.replace(/database/g, "!mapsvg-encoded-db");
3612            data.options = data.options.replace(/varchar/g, "!mapsvg-encoded-vc");
3613            data.id = params.id;
3614            data.title = params.title;
3615            return data;
3616        }
3617        decodeData(dataJSON) {
3618            let data;
3619            if (typeof dataJSON === "string") {
3620                data = JSON.parse(dataJSON);
3621            }
3622            else {
3623                data = dataJSON;
3624            }
3625            return data;
3626        }
3627    }
3628
3629    class Converter {
3630        constructor(mapElement, defViewBox, viewBox, geoViewBox) {
3631            this.mapElement = mapElement;
3632            this.defViewBox = defViewBox;
3633            this.viewBox = viewBox;
3634            this.yShift = 0;
3635            if (geoViewBox) {
3636                this.setGeoViewBox(geoViewBox);
3637            }
3638        }
3639        setYShift() {
3640            if (this.defViewBox.width === 20426) {
3641                this.yShift = 0;
3642                return;
3643            }
3644            if (this.geoViewBox) {
3645                const topLeftPoint = this.convertGeoToSVG(this.geoViewBox.ne);
3646                this.yShift = topLeftPoint.y - this.defViewBox.y;
3647            }
3648        }
3649        setGeoViewBox(geoViewBox) {
3650            this.geoViewBox = geoViewBox;
3651            this.mapLonDelta = this.geoViewBox.ne.lng - this.geoViewBox.sw.lng;
3652            this.mapLatBottomDegree = (this.geoViewBox.sw.lat * Math.PI) / 180;
3653            this.worldMapWidth = (this.defViewBox.width / this.mapLonDelta) * 360;
3654            this.worldMapRadius = ((this.defViewBox.width / this.mapLonDelta) * 360) / (2 * Math.PI);
3655            this.setYShift();
3656        }
3657        setWorldShift(on) {
3658            this.worldShift = on;
3659        }
3660        getScale() {
3661            return this.mapElement.clientWidth / this.viewBox.width;
3662        }
3663        convertSVGToPixel(svgPoint) {
3664            const scale = this.getScale();
3665            let shiftXByGM = 0;
3666            const shiftYByGM = 0;
3667            if (this.worldShift) {
3668                if (this.viewBox.x - this.defViewBox.x > this.defViewBox.width) {
3669                    shiftXByGM =
3670                        this.worldMapWidth *
3671                            Math.floor((this.viewBox.x - this.defViewBox.x) / this.defViewBox.width);
3672                }
3673            }
3674            return new ScreenPoint((svgPoint.x - this.viewBox.x + shiftXByGM) * scale, (svgPoint.y - this.viewBox.y + shiftYByGM) * scale);
3675        }
3676        convertPixelToSVG(screenPoint) {
3677            const scale = this.getScale();
3678            return new SVGPoint(screenPoint.x / scale + this.viewBox.x, screenPoint.y / scale + this.viewBox.y);
3679        }
3680        convertGeoToSVG(geoPoint) {
3681            if (!this.geoViewBox) {
3682                throw new Error("Can't do convertGeoToSVG() - geoViewBox is not provided.");
3683            }
3684            let x = (geoPoint.lng - this.geoViewBox.sw.lng) * (this.defViewBox.width / this.mapLonDelta);
3685            const lat = (geoPoint.lat * Math.PI) / 180;
3686            const mapOffsetY = (this.worldMapRadius / 2) *
3687                Math.log((1 + Math.sin(this.mapLatBottomDegree)) / (1 - Math.sin(this.mapLatBottomDegree)));
3688            let y = this.defViewBox.height -
3689                ((this.worldMapRadius / 2) * Math.log((1 + Math.sin(lat)) / (1 - Math.sin(lat))) -
3690                    mapOffsetY);
3691            x += this.defViewBox.x;
3692            y += this.defViewBox.y;
3693            y -= this.yShift;
3694            return new SVGPoint(x, y);
3695        }
3696        convertSVGToGeo(svgPoint) {
3697            if (!this.geoViewBox) {
3698                throw new Error("Can't do convertSVGToGeo() - geoViewBox is not provided.");
3699            }
3700            const tx = svgPoint.x - this.defViewBox.x;
3701            const ty = svgPoint.y - this.defViewBox.y;
3702            const mapOffsetY = (this.worldMapRadius / 2) *
3703                Math.log((1 + Math.sin(this.mapLatBottomDegree)) / (1 - Math.sin(this.mapLatBottomDegree)));
3704            const equatorY = this.defViewBox.height + mapOffsetY;
3705            const a = (equatorY - ty) / this.worldMapRadius;
3706            let lat = (180 / Math.PI) * (2 * Math.atan(Math.exp(a)) - Math.PI / 2);
3707            let lng = this.geoViewBox.sw.lng + (tx / this.defViewBox.width) * this.mapLonDelta;
3708            lat = parseFloat(lat.toFixed(6));
3709            lng = parseFloat(lng.toFixed(6));
3710            return new GeoPoint(lat, lng);
3711        }
3712    }
3713
3714    const $$3 = jQuery;
3715    class ResizeSensor {
3716        constructor(element, callback) {
3717            const _this = this;
3718            _this.element = element;
3719            _this.callback = callback;
3720            const style = getComputedStyle(element);
3721            let zIndex = parseInt(style.zIndex);
3722            if (isNaN(zIndex)) {
3723                zIndex = 0;
3724            }
3725            zIndex--;
3726            _this.expand = document.createElement("div");
3727            _this.expand.style.position = "absolute";
3728            _this.expand.style.left = "0px";
3729            _this.expand.style.top = "0px";
3730            _this.expand.style.right = "0px";
3731            _this.expand.style.bottom = "0px";
3732            _this.expand.style.overflow = "hidden";
3733            _this.expand.style.zIndex = zIndex.toString();
3734            _this.expand.style.visibility = "hidden";
3735            const expandChild = document.createElement("div");
3736            expandChild.style.position = "absolute";
3737            expandChild.style.left = "0px";
3738            expandChild.style.top = "0px";
3739            expandChild.style.width = "10000000px";
3740            expandChild.style.height = "10000000px";
3741            _this.expand.appendChild(expandChild);
3742            _this.shrink = document.createElement("div");
3743            _this.shrink.style.position = "absolute";
3744            _this.shrink.style.left = "0px";
3745            _this.shrink.style.top = "0px";
3746            _this.shrink.style.right = "0px";
3747            _this.shrink.style.bottom = "0px";
3748            _this.shrink.style.overflow = "hidden";
3749            _this.shrink.style.zIndex = zIndex.toString();
3750            _this.shrink.style.visibility = "hidden";
3751            const shrinkChild = document.createElement("div");
3752            shrinkChild.style.position = "absolute";
3753            shrinkChild.style.left = "0px";
3754            shrinkChild.style.top = "0px";
3755            shrinkChild.style.width = "200%";
3756            shrinkChild.style.height = "200%";
3757            _this.shrink.appendChild(shrinkChild);
3758            _this.element.appendChild(_this.expand);
3759            _this.element.appendChild(_this.shrink);
3760            const size = element.getBoundingClientRect();
3761            _this.currentWidth = size.width;
3762            _this.currentHeight = size.height;
3763            _this.setScroll();
3764            _this.expand.addEventListener("scroll", function () {
3765                _this.onScroll();
3766            });
3767            _this.shrink.addEventListener("scroll", function () {
3768                _this.onScroll();
3769            });
3770        }
3771        onScroll() {
3772            const _this = this;
3773            const size = _this.element.getBoundingClientRect();
3774            const newWidth = size.width;
3775            const newHeight = size.height;
3776            if (newWidth != _this.currentWidth || newHeight != _this.currentHeight) {
3777                _this.currentWidth = newWidth;
3778                _this.currentHeight = newHeight;
3779                _this.callback();
3780            }
3781            this.setScroll();
3782        }
3783        setScroll() {
3784            this.expand.scrollLeft = 10000000;
3785            this.expand.scrollTop = 10000000;
3786            this.shrink.scrollLeft = 10000000;
3787            this.shrink.scrollTop = 10000000;
3788        }
3789        destroy() {
3790            this.expand.remove();
3791            this.shrink.remove();
3792        }
3793    }
3794
3795    class ViewBox {
3796        constructor(x, y, width, height) {
3797            if (typeof x === "object") {
3798                if (x.hasOwnProperty("x") &&
3799                    x.hasOwnProperty("y") &&
3800                    x.hasOwnProperty("width") &&
3801                    x.hasOwnProperty("height")) {
3802                    this.x = typeof x.x === "string" ? parseFloat(x.x) : x.x;
3803                    this.y = typeof x.y === "string" ? parseFloat(x.y) : x.y;
3804                    this.width = typeof x.width === "string" ? parseFloat(x.width) : x.width;
3805                    this.height = typeof x.height === "string" ? parseFloat(x.height) : x.height;
3806                }
3807                else if (typeof x === "object" && x.length && x.length === 4) {
3808                    this.x = typeof x[0] === "string" ? parseFloat(x[0]) : x[0];
3809                    this.y = typeof x[1] === "string" ? parseFloat(x[1]) : x[1];
3810                    this.width = typeof x[2] === "string" ? parseFloat(x[2]) : x[2];
3811                    this.height = typeof x[3] === "string" ? parseFloat(x[3]) : x[3];
3812                }
3813            }
3814            else {
3815                this.x = typeof x === "string" ? parseFloat(x) : x;
3816                this.y = typeof y === "string" ? parseFloat(y) : y;
3817                this.width = typeof width === "string" ? parseFloat(width) : width;
3818                this.height = typeof height === "string" ? parseFloat(height) : height;
3819            }
3820        }
3821        update(newViewBox) {
3822            this.x = newViewBox.x;
3823            this.y = newViewBox.y;
3824            this.width = newViewBox.width;
3825            this.height = newViewBox.height;
3826        }
3827        toString() {
3828            return this.x + " " + this.y + " " + this.width + " " + this.height;
3829        }
3830        toArray() {
3831            return [this.x, this.y, this.width, this.height];
3832        }
3833        clone() {
3834            return new ViewBox({ x: this.x, y: this.y, width: this.width, height: this.height });
3835        }
3836        fitsInViewBox(viewBox, atLeastByOneDimension) {
3837            if (atLeastByOneDimension === true) {
3838                return viewBox.width >
3838 this.width || viewBox.height > this.height;
3839            }
3840            else {
3841                return viewBox.width > this.width && viewBox.height > this.height;
3842            }
3843        }
3844        addPadding(padding) {
3845            if (padding.top) {
3846                this.y -= padding.top;
3847                this.height += padding.top;
3848            }
3849            if (padding.right) {
3850                this.width += padding.right;
3851            }
3852            if (padding.bottom) {
3853                this.height += padding.bottom;
3854            }
3855            if (padding.left) {
3856                this.x -= padding.left;
3857                this.width += padding.left;
3858            }
3859        }
3860    }
3861    class GeoViewBox {
3862        constructor(sw, ne) {
3863            this.sw = sw;
3864            this.ne = ne;
3865        }
3866    }
3867
3868    const $$4 = jQuery;
3869    class MapObject {
3870        constructor(element, mapsvg) {
3871            this.id = "";
3872            this.objects = [];
3873            this.events = new Events(this);
3874            this.element = element;
3875            this.mapsvg = mapsvg;
3876        }
3877        getBBox() {
3878            return new ViewBox(1, 2, 3, 4);
3879        }
3880        getGeoBounds() {
3881            const bbox = this.getBBox();
3882            const pointSW = new SVGPoint(bbox.x, bbox.y + bbox.height);
3883            const pointNE = new SVGPoint(bbox.x + bbox.width, bbox.y);
3884            const sw = this.mapsvg.converter.convertSVGToGeo(pointSW);
3885            const ne = this.mapsvg.converter.convertSVGToGeo(pointNE);
3886            return { sw: sw, ne: ne };
3887        }
3888        getComputedStyle(prop, elem) {
3889            elem = elem || this.element;
3890            return MapObject.getComputedStyle(prop, elem);
3891        }
3892        static getComputedStyle(prop, elem) {
3893            const _p1 = elem.getAttribute(prop);
3894            if (_p1) {
3895                return _p1;
3896            }
3897            const _p2 = elem.getAttribute("style");
3898            if (_p2) {
3899                const s = _p2.split(";");
3900                const z = s.filter(function (e) {
3901                    e = e.trim();
3902                    const attr = e.split(":");
3903                    if (attr[0] == prop)
3904                        return true;
3905                });
3906                if (z.length) {
3907                    return z[0].split(":").pop().trim();
3908                }
3909            }
3910            const parent = elem.parentElement;
3911            const elemType = parent ? parent.tagName : null;
3912            if (elemType && elemType != "svg")
3913                return MapObject.getComputedStyle(prop, parent);
3914            else
3915                return undefined;
3916        }
3917        getStyle(prop) {
3918            const _p1 = this.attr(prop);
3919            if (_p1) {
3920                return _p1;
3921            }
3922            const _p2 = this.attr("style");
3923            if (_p2) {
3924                const s = _p2.split(";");
3925                const z = s.filter(function (e) {
3926                    var e = e.trim();
3927                    if (e.indexOf(prop) === 0)
3928                        return e;
3929                });
3930                return z.length ? z[0].split(":").pop().trim() : undefined;
3931            }
3932            return "";
3933        }
3934        getCenter() {
3935            const x = this.element.getBoundingClientRect().left;
3936            const y = this.element.getBoundingClientRect().top;
3937            const w = this.element.getBoundingClientRect().width;
3938            const h = this.element.getBoundingClientRect().height;
3939            const point = new ScreenPoint(x + w / 2, y + h / 2);
3940            return point;
3941        }
3942        getCenterSVG() {
3943            const bbox = this.getBBox();
3944            const point = new SVGPoint(bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
3945            return point;
3946        }
3947        getCenterLatLng(yShift) {
3948            yShift = yShift ? yShift : 0;
3949            const bbox = this.getBBox();
3950            const x = bbox.x + bbox.width / 2;
3951            const y = bbox.y + bbox.height / 2 - yShift;
3952            const point = new SVGPoint(x, y);
3953            return this.mapsvg.converter.convertSVGToGeo(point);
3954        }
3955        attr(v1, v2 = null) {
3956            const svgDom = this.element;
3957            if (typeof v1 == "object") {
3958                for (const key in v1) {
3959                    const item = v1[key];
3960                    if (typeof item === "string" || typeof item === "number") {
3961                        svgDom.setAttribute(key, "" + item);
3962                    }
3963                }
3964            }
3965            else if (typeof v1 == "string" && (typeof v2 == "string" || typeof v2 == "number")) {
3966                svgDom.setAttribute(v1, "" + v2);
3967            }
3968            else if (v2 == undefined) {
3969                return svgDom.getAttribute(v1);
3970            }
3971        }
3972        setId(id) {
3973            if (id !== undefined) {
3974                this.id = id;
3975                this.element.setAttribute("id", id);
3976            }
3977        }
3978    }
3979
3980    const $$5 = jQuery;
3981    class Marker extends MapObject {
3982        constructor(params) {
3983            super(null, params.mapsvg);
3984            this.element = $$5("<div />").addClass("mapsvg-marker")[0];
3985            this.image = $$5('<img src="" />').addClass("mapsvg-marker-image")[0];
3986            if (params.object) {
3987                this.setObject(params.object);
3988            }
3989            if (!(params.location instanceof Location)) {
3990                throw new Error("MapSVG.Marker: no Location provided for Marker initializaton");
3991            }
3992            else {
3993                this.location = params.location;
3994                this.location.marker = this;
3995            }
3996            this.setImage(this.location.imagePath);
3997            $$5(this.element).append(this.image);
3998            if (params.width && params.height) {
3999                this.setSize(params.width, params.height);
4000            }
4001            else {
4002                this.setSize(15, 24);
4003            }
4004            this.setId(this.mapsvg.markerId());
4005            this.setSvgPointFromLocation();
4006            this.setAltAttr();
4007        }
4008        reload() {
4009            this.setImage();
4010            this.setSvgPointFromLocation();
4011        }
4012        getImagePath() {
4013            return (this.object && this.object.getMarkerImage()) || this.location.getMarkerImage();
4014        }
4015        setSize(width, height) {
4016            this.width = width;
4017            this.height = height;
4018            this.setCentered(this.width === this.height);
4019        }
4020        setSvgPointFromLocation() {
4021            const svgPoint = this.location.geoPoint &&
4022                this.location.geoPoint.lat !== 0 &&
4023                this.location.geoPoint.lng !== 0
4024                ? this.mapsvg.converter.convertGeoToSVG(this.location.geoPoint)
4025                : this.location.svgPoint;
4026            if (svgPoint) {
4027                this.setSvgPoint(svgPoint);
4028            }
4029        }
4030        setId(id) {
4031            MapObject.prototype.setId.call(this, id);
4032            this.mapsvg.markers.reindex();
4033        }
4034        getBBox() {
4035            if (this.centered) {
4036                return new ViewBox(this.svgPoint.x - this.width / 2 / this.mapsvg.scale, this.svgPoint.y - this.height / 2 / this.mapsvg.scale, this.width / this.mapsvg.scale, this.height / this.mapsvg.scale);
4037            }
4038            else {
4039                return new ViewBox(this.svgPoint.x - this.width / 2 / this.mapsvg.scale, this.svgPoint.y - this.height / this.mapsvg.scale, this.width / this.mapsvg.scale, this.height / this.mapsvg.scale);
4040            }
4041        }
4042        getOptions() {
4043            const o = {
4044                id: this.id,
4045                src: this.src,
4046                svgPoint: this.svgPoint,
4047                geoPoint: this.geoPoint,
4048            };
4049            $$5.each(o, function (key, val) {
4050                if (val == undefined) {
4051                    delete o[key];
4052                }
4053            });
4054            return o;
4055        }
4056        update(data) {
4057            for (const key in data) {
4058                const setter = "set" + MapSVG.ucfirst(key);
4059                if (setter in this)
4060                    this[setter](data[key]);
4061            }
4062        }
4063        setImage(src, skipChangingLocationImage = false) {
4064            if (!src) {
4065                src = this.getImagePath();
4066            }
4067            this.src = MapSVG.safeURL(src);
4068            const img = new Image();
4069            const marker = this;
4070            img.onload = function () {
4071                if (marker.image.getAttribute("src") !== "src") {
4072                    marker.image.setAttribute("src", marker.src);
4073                }
4074                marker.setSize(this.width, this.height);
4075                marker.adjustScreenPosition();
4076            };
4077            img.src = this.src;
4078            this.events.trigger("change");
4079        }
4080        setAltAttr() {
4081            const marker = this;
4082            marker.altAttr =
4083                typeof marker.object != "undefined" &&
4084                    typeof marker.object.title != "undefined" &&
4085                    marker.object.title !== ""
4086                    ? marker.object.title
4087                    : marker.id;
4088            marker.image.setAttribute("alt", marker.altAttr);
4089        }
4090        setSvgPoint(svgPoint) {
4091            this.svgPoint = svgPoint;
4092            this.adjustScreenPosition();
4093            this.events.trigger("change");
4094        }
4095        adjustScreenPosition() {
4096            const pos = this.mapsvg.converter.convertSVGToPixel(this.svgPoint);
4097            pos.x -= this.width / 2;
4098            pos.y -= !this.centered ? this.height : this.height / 2;
4099            this.setScreenPosition(pos.x, pos.y);
4100        }
4101        moveSrceenPositionBy(deltaX, deltaY) {
4102            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
4103            this.setScreenPosition(x, y);
4104        }
4105        setScreenPosition(x, y) {
4106            if (this.screenPoint instanceof ScreenPoint) {
4107                this.screenPoint.x = x;
4108                this.screenPoint.y = y;
4109            }
4110            else {
4111                this.screenPoint = new ScreenPoint(x, y);
4112            }
4113            this.updateVisibility();
4114            if (this.visible === true) {
4115                this.element.style.transform = "translate(" + x + "px," + y + "px)";
4116                this.adjustLabelScreenPosition();
4117            }
4118        }
4119        adjustLabelScreenPosition() {
4120            if (this.label) {
4121                const markerPos = this.screenPoint, x = Math.round(markerPos.x + this.width / 2 - $$5(this.label).outerWidth() / 2), y = Math.round(markerPos.y - $$5(this.label).outerHeight());
4122            }
4123        }
4124        inViewBox() {
4125            const x = this.screenPoint.x, y = this.screenPoint.y, mapFullWidth = this.mapsvg.containers.map.offsetWidth, mapFullHeight = this.mapsvg.containers.map.offsetHeight;
4126            return (x - this.width / 2 < 2 * mapFullWidth &&
4127                x + this.width / 2 > -mapFullWidth &&
4128                y - this.height / 2 < 2 * mapFullHeight &&
4129                y + this.height / 2 > -mapFullHeight);
4130        }
4131        updateVisibility() {
4132            if (this.inViewBox() === true) {
4133                this.visible = true;
4134                this.element.classList.remove("mapsvg-out-of-sight");
4135                if (this.label) {
4136                    this.label.classList.remove("mapsvg-out-of-sight");
4137                }
4138            }
4139            else {
4140                this.visible = false;
4141                this.element.classList.add("mapsvg-out-of-sight");
4142                if (this.label) {
4143                    this.label.classList.add("mapsvg-out-of-sight");
4144                }
4145            }
4146            return this.visible;
4147        }
4148        isMoving() {
4149            return this.moving;
4150        }
4151        setMoving(value) {
4152            this.moving = value;
4153        }
4154        drag(startCoords, scale, endCallback, clickCallback) {
4155            const _this = this;
4156            this.svgPointBeforeDrag = new SVGPoint(this.svgPoint.x, this.svgPoint.y);
4157            this.setMoving(true);
4158            $$5("body").on("mousemove.drag.mapsvg", function (e) {
4159                e.preventDefault();
4160                $$5(_this.mapsvg.containers.map).addClass("no-transitions");
4161                const mouseNew = MapSVG.mouseCoords(e);
4162                const dx = mouseNew.x - startCoords.x;
4163                const dy = mouseNew.y - startCoords.y;
4164                const newSvgPoint = new SVGPoint(_this.svgPointBeforeDrag.x + dx / scale, _this.svgPointBeforeDrag.y + dy / scale);
4165                _this.setSvgPoint(newSvgPoint);
4166            });
4167            $$5("body").on("mouseup.drag.mapsvg", function (e) {
4168                e.preventDefault();
4169                _this.undrag();
4170                const mouseNew = MapSVG.mouseCoords(e);
4171                const dx = mouseNew.x - startCoords.x;
4172                const dy = mouseNew.y - startCoords.y;
4173                const newSvgPoint = new SVGPoint(_this.svgPointBeforeDrag.x + dx / scale, _this.svgPointBeforeDrag.y + dy / scale);
4174                _this.setSvgPoint(newSvgPoint);
4175                if (_this.mapsvg.isGeo()) {
4176                    _this.geoPoint = _this.mapsvg.converter.convertSVGToGeo(newSvgPoint);
4177                }
4178                endCallback && endCallback.call(_this);
4179                if (_this.svgPointBeforeDrag.x == _this.svgPoint.x &&
4180                    _this.svgPointBeforeDrag.y == _this.svgPoint.y)
4181                    clickCallback && clickCallback.call(_this);
4182            });
4183        }
4184        undrag() {
4185            this.setMoving(false);
4186            $$5("body").off(".drag.mapsvg");
4187            $$5(this.mapsvg.containers.map).removeClass("no-transitions");
4188        }
4189        delete() {
4190            if (this.label) {
4191                this.label.remove();
4192                this.label = null;
4193            }
4194            $$5(this.element).empty().remove();
4195        }
4196        setObject(obj) {
4197            this.object = obj;
4198            $$5(this.element).attr("data-object-id", this.object.id);
4199        }
4200        hide() {
4201            $$5(this.element).addClass("mapsvg-marker-hidden");
4202            if (this.label) {
4203                $$5(this.label).hide();
4204            }
4205        }
4206        show() {
4207            $$5(this.element).removeClass("mapsvg-marker-hidden");
4208            if (this.label) {
4209                $$5(this.label).show();
4210            }
4211        }
4212        highlight() {
4213            $$5(this.element).addClass("mapsvg-marker-hover");
4214        }
4215        unhighlight() {
4216            $$5(this.element).removeClass("mapsvg-marker-hover");
4217        }
4218        select() {
4219            this.selected = true;
4220            $$5(this.element).addClass("mapsvg-marker-active");
4221        }
4222        deselect() {
4223            this.selected = false;
4224            $$5(this.element).removeClass("mapsvg-marker-active");
4225        }
4226        getData() {
4227            return this.object;
4228        }
4229        getChoroplethColor() {
4230            const markerValue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
4231            let color;
4232            if (!markerValue) {
4233                color = this.mapsvg.options.choropleth.coloring.noData.color;
4234            }
4235            else if (this.mapsvg.options.choropleth.coloring.mode === "gradient") {
4236                const gradient = this.mapsvg.options.choropleth.coloring.gradient, w = gradient.values.maxAdjusted === 0
4237                    ? 0
4238                    : (markerValue - gradient.values.min) / gradient.values.maxAdjusted, r = Math.round(gradient.colors.diffRGB.r * w + gradient.colors.lowRGB.r), g = Math.round(gradient.colors.diffRGB.g * w + gradient.colors.lowRGB.g), b = Math.round(gradient.colors.diffRGB.b * w + gradient.colors.lowRGB.b), a = (gradient.colors.diffRGB.a * w + gradient.colors.lowRGB.a).toFixed(2);
4239                color = "rgba(" + r + "," + g + "," + b + "," + a + ")";
4240            }
4241            else {
4242                const paletteColors = this.mapsvg.options.choropleth.coloring.palette.colors;
4243                if (!paletteColors[0].valueFrom && markerValue < paletteColors[0].valueTo) {
4244                    color = paletteColors[0].color;
4245                }
4246                else if (!paletteColors[paletteColors.length - 1].valueTo &&
4247                    markerValue > paletteColors[paletteColors.length - 1].valueFrom) {
4248                    color = paletteColors[paletteColors.length - 1].color;
4249                }
4250                else {
4251                    paletteColors.forEach(function (paletteColor) {
4252                        if (markerValue >= paletteColor.valueFrom &&
4253                            markerValue < paletteColor.valueTo) {
4254                            color = paletteColor.color;
4255                        }
4256                    });
4257                    color = color
4258                        ? color
4259                        : this.mapsvg.options.choropleth.coloring.palette.outOfRange.color;
4260                }
4261            }
4262            return color;
4263        }
4264        getBubbleSize() {
4265            let bubbleSize;
4266            if (this.object[this.mapsvg.options.choropleth.sourceField]) {
4267                const maxBubbleSize = Number(this.mapsvg.options.choropleth.bubbleSize.max), minBubbleSize = Number(this.mapsvg.options.choropleth.bubbleSize.min), maxSourceFieldvalue = this.mapsvg.options.choropleth.coloring.gradient.values.max, minSourceFieldvalue = this.mapsvg.options.choropleth.coloring.gradient.values.min, sourceFieldvalue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
4268                bubbleSize =
4269                    ((sourceFieldvalue - minSourceFieldvalue) /
4270                        (maxSourceFieldvalue - minSourceFieldvalue)) *
4271                        (maxBubbleSize - minBubbleSize) +
4272                        Number(minBubbleSize);
4273            }
4274            else {
4275                bubbleSize = false;
4276            }
4277            return bubbleSize;
4278        }
4279        getBubbleScreenPosition() {
4280            const bubbleSize = Number(this.getBubbleSize());
4281            return {
4282                x: this.width / 2 - bubbleSize / 2,
4283                y: this.height - bubbleSize / 2,
4284            };
4285        }
4286        drawBubble() {
4287            const bubbleId = "mapsvg-bubble-" + this.object.id;
4288            const bubbleValue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
4289            if (bubbleValue) {
4290                if (!this.bubble) {
4291                    this.bubble = $$5('<div id="' +
4292                        bubbleId +
4293                        '" data-marker-id="' +
4294                        this.element.id +
4295                        '" class="mapsvg-bubble mapsvg-marker-bubble"></div>')[0];
4296                    $$5(this.element).append(this.bubble);
4297                }
4298                const color = this.getChoroplethColor(), bubbleSize = Number(this.getBubbleSize());
4299                $$5(this.bubble)
4300                    .css("background-color", color)
4301                    .css("width", bubbleSize + "px")
4302                    .css("height", bubbleSize + "px")
4303                    .css("lineHeight", bubbleSize - 2 + "px");
4304            }
4305            else {
4306                $$5("#" + bubbleId).remove();
4307                delete this.bubble;
4308            }
4309        }
4310        setBubbleMode(bubbleMode) {
4311            this.bubbleMode = bubbleMode;
4312            if (bubbleMode) {
4313                this.setCentered(true);
4314                this.drawBubble();
4315                if (this.bubble) {
4316                    this.width = this.bubble.offsetWidth;
4317                    this.height = this.bubble.offsetHeight;
4318                    this.adjustScreenPosition();
4319                }
4320            }
4321            else {
4322                this.setImage(this.src);
4323            }
4324        }
4325        setLabel(html) {
4326            if (html) {
4327                if (!this.label) {
4328                    this.label = $$5("<div />").addClass("mapsvg-marker-label")[0];
4329                    $$5(this.element).append(this.label);
4330                }
4331                $$5(this.label).html(html);
4332            }
4333            else {
4334                if (this.label) {
4335                    $$5(this.label).remove();
4336                    delete this.label;
4337                }
4338            }
4339        }
4340        setCentered(on) {
4341            this.centered = on;
4342        }
4343    }
4344
4345    const $$6 = jQuery;
4346    class MarkerCluster extends MapObject {
4347        constructor(options, mapsvg) {
4348            super(null, mapsvg);
4349            this.svgPoint = options.svgPoint;
4350            this.cellX = options.cellX;
4351            this.cellY = options.cellY;
4352            this.markers = options.markers || [];
4353            this.cellSize = 50;
4354            this.width = 30;
4355            this.elem = $$6('<div class="mapsvg-marker-cluster">' + this.markers.length + "</div>")[0];
4356            $$6(this.elem).data("cluster", this);
4357            if (this.markers.length < 2) {
4358                $$6(this.elem).hide();
4359            }
4360            this.adjustScreenPosition();
4361        }
4362        addMarker(marker) {
4363            this.markers.push(marker);
4364            if (this.markers.length > 1) {
4365                if (this.markers.length === 2) {
4366                    $$6(this.elem).show();
4367                }
4368                if (this.markers.length === 2) {
4369                    const x = this.markers.map(function (m) {
4370                        return m.svgPoint.x;
4371                    });
4372                    this.min_x = Math.min.apply(null, x);
4373                    this.max_x = Math.max.apply(null, x);
4374                    const y = this.markers.map(function (m) {
4375                        return m.svgPoint.y;
4376                    });
4377                    this.min_y = Math.min.apply(null, y);
4378                    this.max_y = Math.max.apply(null, y);
4379                    this.svgPoint.x = this.min_x + (this.max_x - this.min_x) / 2;
4380                    this.svgPoint.y = this.min_y + (this.max_y - this.min_y) / 2;
4381                }
4382                if (this.markers.length > 2) {
4383                    if (marker.svgPoint.x < this.min_x) {
4384                        this.min_x = marker.svgPoint.x;
4385                    }
4386                    else if (marker.svgPoint.x > this.max_x) {
4387                        this.max_x = marker.svgPoint.x;
4388                    }
4389                    if (marker.svgPoint.y < this.min_y) {
4390                        this.min_y = marker.svgPoint.y;
4391                    }
4392                    else if (marker.svgPoint.x > this.max_x) {
4393                        this.max_y = marker.svgPoint.y;
4394                    }
4395                    this.svgPoint.x = this.min_x + (this.max_x - this.min_x) / 2;
4396                    this.svgPoint.y = this.min_y + (this.max_y - this.min_y) / 2;
4397                }
4398            }
4399            else {
4400                this.svgPoint.x = marker.svgPoint.x;
4401                this.svgPoint.y = marker.svgPoint.y;
4402            }
4403            $$6(this.elem).text(this.markers.length);
4404            this.adjustScreenPosition();
4405        }
4406        canTakeMarker(marker) {
4407            const _this = this;
4408            const screenPoint = _this.mapsvg.converter.convertSVGToPixel(marker.svgPoint);
4409            return (this.cellX === Math.ceil(screenPoint.x / this.cellSize) &&
4410                this.cellY === Math.ceil(screenPoint.y / this.cellSize));
4411        }
4412        destroy() {
4413            this.markers = null;
4414            $$6(this.elem).remove();
4415        }
4416        adjustScreenPosition() {
4417            const pos = this.mapsvg.converter.convertSVGToPixel(this.svgPoint);
4418            pos.x -= this.width / 2;
4419            pos.y -= this.width / 2;
4420            this.setScreenPosition(pos.x, pos.y);
4421        }
4422        moveSrceenPositionBy(deltaX, deltaY) {
4423            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
4424            this.setScreenPosition(x, y);
4425        }
4426        setScreenPosition(x, y) {
4427            if (this.screenPoint instanceof ScreenPoint) {
4428                this.screenPoint.x = x;
4429                this.screenPoint.y = y;
4430            }
4431            else {
4432                this.screenPoint = new ScreenPoint(x, y);
4433            }
4434            this.updateVisibility();
4435            if (this.visible === true) {
4436                this.elem.style.transform = "translate(" + x + "px," + y + "px)";
4437            }
4438        }
4439        inViewBox() {
4440            const x = this.screenPoint.x, y = this.screenPoint.y, mapFullWidth = this.mapsvg.containers.map.offsetWidth, mapFullHeight = this.mapsvg.containers.map.offsetHeight;
4441            return (x - this.width / 2 < mapFullWidth &&
4442                x + this.width / 2 > 0 &&
4443                y - this.width / 2 < mapFullHeight &&
4444                y + this.width / 2 > 0);
4445        }
4446        updateVisibility() {
4447            if (this.inViewBox() === true) {
4448                this.visible = true;
4449                this.elem.classList.remove("mapsvg-out-of-sight");
4450            }
4451            else {
4452                this.visible = false;
4453                this.elem.classList.add("mapsvg-out-of-sight");
4454            }
4455            return this.visible;
4456        }
4457        getBBox() {
4458            let bbox = {
4459                x: this.svgPoint.x,
4460                y: this.svgPoint.y,
4461                width: this.cellSize / this.mapsvg.getScale(),
4462                height: this.cellSize / this.mapsvg.getScale(),
4463            };
4464            bbox = $$6.extend(true, {}, bbox);
4465            return new ViewBox(bbox.x, bbox.y, bbox.width, bbox.height);
4466        }
4467        getData() {
4468            return this.markers.map((m) => m.object);
4469        }
4470    }
4471
4472    const $$7 = jQuery;
4473    class Region extends MapObject {
4474        constructor(element, mapsvg) {
4475            super(element, mapsvg);
4476            this.id = this.element.getAttribute("id");
4477            if (this.id && this.mapsvg.options.regionPrefix) {
4478                this.setId(this.id.replace(this.mapsvg.options.regionPrefix, ""));
4479            }
4480            this.id_no_spaces = this.id.replace(/\s/g, "_");
4481            this.element.setAttribute("class", (this.element.className || "") + " mapsvg-region");
4482            this.setStyleInitial();
4483            const regionOptions = this.mapsvg.options.regions && this.mapsvg.options.regions[this.id]
4484                ? this.mapsvg.options.regions[this.id]
4485                : null;
4486            this.disabled = this.getDisabledState();
4487            this.disabled && this.attr("class", this.attr("class") + " mapsvg-disabled");
4488            this.default_attr = {};
4489            this.selected_attr = {};
4490            this.hover_attr = {};
4491            let selected = false;
4492            if (regionOptions && regionOptions.selected) {
4493                selected = true;
4494                delete regionOptions.selected;
4495            }
4496            regionOptions && this.update(regionOptions);
4497            this.setFill();
4498            if (selected) {
4499                this.setSelected();
4500            }
4501            this.saveState();
4502        }
4503        adjustStroke(scale) {
4504            $$7(this.element).css({ "stroke-width": this.style["stroke-width"] / scale });
4505        }
4506        setStyleInitial() {
4507            this.style = { fill: this.getComputedStyle("fill") };
4508            this.style.stroke = this.getComputedStyle("stroke") || "";
4509            let w;
4510            w = this.getComputedStyle("stroke-width");
4511            w = w ? w.replace("px", "") : "1";
4512            w = parseFloat(w);
4513            this.style["stroke-width"] = w;
4514            $$7(this.element).attr("data-stroke-width", w);
4515        }
4516        saveState() {
4517            this.initialState = JSON.stringify(this.getOptions());
4518        }
4519        getBBox() {
4520            const _bbox = this.element.getBBox();
4521            const bbox = new ViewBox(_bbox.x, _bbox.y, _bbox.width, _bbox.height);
4522            const matrix = this.element.getTransformToElement(this.mapsvg.containers.svg);
4523            if (!matrix) {
4524                return _bbox;
4525            }
4526            const x2 = bbox.x + bbox.width;
4527            const y2 = bbox.y + bbox.height;
4528            let position = this.mapsvg.containers.svg.createSVGPoint();
4529            position.x = bbox.x;
4530            position.y = bbox.y;
4531            position = position.matrixTransform(matrix);
4532            bbox.x = position.x;
4533            bbox.y = position.y;
4534            position.x = x2;
4535            position.y = y2;
4536            position = position.matrixTransform(matrix);
4537            bbox.width = position.x - bbox.x;
4538            bbox.height = position.y - bbox.y;
4539            return bbox;
4540        }
4541        changed() {
4542            return JSON.stringify(this.getOptions()) != this.initialState;
4543        }
4544        edit() {
4545            this.elemOriginal = $$7(this.element).clone()[0];
4546        }
4547        editCommit() {
4548            this.elemOriginal = null;
4549        }
4550        editCancel() {
4551            this.mapsvg.containers.svg.appendChild(this.elemOriginal);
4552            this.element = this.elemOriginal;
4553            this.elemOriginal = null;
4554        }
4555        getOptions(forTemplate) {
4556            let o;
4557            o = {
4558                id: this.id,
4559                id_no_spaces: this.id_no_spaces,
4560                title: this.title,
4561                fill: this.mapsvg.options.regions[this.id] && this.mapsvg.options.regions[this.id].fill,
4562                data: this.data,
4563                choroplethValue: this.choroplethValue,
4564            };
4565            if (forTemplate) {
4566                o.disabled = this.disabled;
4567            }
4568            for (const key in o) {
4569                if (typeof o[key] === "undefined") {
4570                    delete o[key];
4571                }
4572            }
4573            if (this.customAttrs) {
4574                const that = this;
4575                this.customAttrs.forEach(function (attr) {
4576                    o[attr] = that[attr];
4577                });
4578            }
4579            return o;
4580        }
4581        forTemplate() {
4582            const data = {
4583                id: this.id,
4584                title: this.title,
4585                objects: this.objects,
4586                data: this.data,
4587            };
4588            if (this.data) {
4589                for (const key in this.data) {
4590                    if (key != "title" && key != "id")
4591                        data[key] = this.data[key];
4592                }
4593            }
4594            return data;
4595        }
4596        getData() {
4597            return this.forTemplate();
4598        }
4599        update(options) {
4600            for (const key in options) {
4601                const setter = "set" + MapSVG.ucfirst(key);
4602                if (setter in this)
4603                    this[setter](options[key]);
4604                else {
4605                    this[key] = options[key];
4606                    this.customAttrs = this.customAttrs || [];
4607                    this.customAttrs.push(key);
4608                }
4609            }
4610        }
4611        setTitle(title) {
4612            if (title) {
4613                this.title = title;
4614            }
4615            this.element.setAttribute("title", this.title);
4616        }
4617        setStyle(style) {
4618            $$7.extend(true, this.style, style);
4619            this.setFill();
4620        }
4621        getChoroplethColor() {
4622            const o = this.mapsvg.options.choropleth;
4623            let color = "";
4624            if (this.data &&
4625                (this.data[this.mapsvg.options.regionChoroplethField] ||
4626                    this.data[this.mapsvg.options.regionChoroplethField] === 0)) {
4627                const w = o.maxAdjusted === 0
4628                    ? 0
4629                    : (parseFloat(this.data[this.mapsvg.options.regionChoroplethField]) - o.min) /
4630                        o.maxAdjusted;
4631                const c = {
4632                    r: Math.round(o.colors.diffRGB.r * w + o.colors.lowRGB.r),
4633                    g: Math.round(o.colors.diffRGB.g * w + o.colors.lowRGB.g),
4634                    b: Math.round(o.colors.diffRGB.b * w + o.colors.lowRGB.b),
4635                    a: (o.colors.diffRGB.a * w + o.colors.lowRGB.a).toFixed(2),
4636                };
4637                color = "rgba(" + c.r + "," + c.g + "," + c.b + "," + c.a + ")";
4638            }
4639            else {
4640                color = o.colors.noData;
4641            }
4642            return color;
4643        }
4644        _new_getChoroplethColor() {
4645            let regionValue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]), color;
4646            if (!regionValue) {
4647                color = this.mapsvg.options.choropleth.coloring.noData.color;
4648            }
4649            else if (this.mapsvg.options.choropleth.coloring.mode === "gradient") {
4650                const gradient = this.mapsvg.options.choropleth.coloring.gradient, w = gradient.values.maxAdjusted === 0
4651                    ? 0
4652                    : (regionValue - gradient.values.min) / gradient.values.maxAdjusted, r = Math.round(gradient.colors.diffRGB.r * w + gradient.colors.lowRGB.r), g = Math.round(gradient.colors.diffRGB.g * w + gradient.colors.lowRGB.g), b = Math.round(gradient.colors.diffRGB.b * w + gradient.colors.lowRGB.b), a = (gradient.colors.diffRGB.a * w + gradient.colors.lowRGB.a).toFixed(2);
4653                color = "rgba(" + r + "," + g + "," + b + "," + a + ")";
4654            }
4655            else {
4656                const paletteColors = this.mapsvg.options.choropleth.coloring.palette.colors;
4657                if (!paletteColors[0].valueFrom && regionValue < paletteColors[0].valueTo) {
4658                    color = paletteColors[0].color;
4659                }
4660                else if (!paletteColors[paletteColors.length - 1].valueTo &&
4661                    regionValue > paletteColors[paletteColors.length - 1].valueFrom) {
4662                    color = paletteColors[paletteColors.length - 1].color;
4663                }
4664                else {
4665                    paletteColors.forEach(function (paletteColor) {
4666                        if (regionValue >= paletteColor.valueFrom &&
4667                            regionValue < paletteColor.valueTo) {
4668                            color = paletteColor.color;
4669                        }
4670                    });
4671                    color = color
4672                        ? color
4673                        : this.mapsvg.options.choropleth.coloring.palette.outOfRange.color;
4674                }
4675            }
4676            return color;
4677        }
4678        getBubbleSize() {
4679            let bubbleSize;
4680            if (this.data[this.mapsvg.options.choropleth.sourceField]) {
4681                const maxBubbleSize = Number(this.mapsvg.options.choropleth.bubbleSize.max), minBubbleSize = Number(this.mapsvg.options.choropleth.bubbleSize.min), maxSourceFieldvalue = this.mapsvg.options.choropleth.coloring.gradient.values.max, minSourceFieldvalue = this.mapsvg.options.choropleth.coloring.gradient.values.min, sourceFieldvalue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]);
4682                bubbleSize =
4683                    ((sourceFieldvalue - minSourceFieldvalue) /
4684                        (maxSourceFieldvalue - minSourceFieldvalue)) *
4685                        (maxBubbleSize - minBubbleSize) +
4686                        minBubbleSize;
4687            }
4688            else {
4689                bubbleSize = false;
4690            }
4691            return bubbleSize;
4692        }
4693        setFill(fill) {
4694            if (this.mapsvg.options.colorsIgnore) {
4695                $$7(this.element).css(this.style);
4696                return;
4697            }
4698            if (fill) {
4699                const regions = {};
4700                regions[this.id] = { fill: fill };
4701                $$7.extend(true, this.mapsvg.options, { regions: regions });
4702            }
4703            else if (!fill &&
4704                fill !== undefined &&
4705                this.mapsvg.options.regions &&
4706                this.mapsvg.options.regions[this.id] &&
4707                this.mapsvg.options.regions[this.id].fill) {
4708                delete this.mapsvg.options.regions[this.id].fill;
4709            }
4710            if (this.mapsvg.options.choropleth.on) {
4711                this.default_attr["fill"] = this.getChoroplethColor();
4712            }
4713            else if (this.status !== undefined &&
4714                this.mapsvg.regions &&
4715                this.mapsvg.regionsRepository.getSchema().getFieldByType("status") &&
4716                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict &&
4717                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict[this.status] &&
4718                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict[this.status].color) {
4719                this.default_attr["fill"] = this.mapsvg.regionsRepository
4720                    .getSchema()
4721                    .getFieldByType("status").optionsDict[this.status].color;
4722            }
4723            else if (this.mapsvg.options.regions[this.id] &&
4724                this.mapsvg.options.regions[this.id].fill) {
4725                this.default_attr["fill"] = this.mapsvg.options.regions[this.id].fill;
4726            }
4727            else if (this.mapsvg.options.colors.base) {
4728                this.default_attr["fill"] = this.mapsvg.options.colors.base;
4729            }
4730            else if (this.style.fill != "none") {
4731                this.default_attr["fill"] = this.style.fill
4732                    ? this.style.fill
4733                    : this.mapsvg.options.colors.baseDefault;
4734            }
4735            else {
4736                this.default_attr["fill"] = "none";
4737            }
4738            if (MapSVG.isNumber(this.mapsvg.options.colors.selected))
4739                this.selected_attr["fill"] = tinycolor(this.default_attr.fill)
4740                    .lighten(parseFloat("" + this.mapsvg.options.colors.selected))
4741                    .toRgbString();
4742            else
4743                this.selected_attr["fill"] = this.mapsvg.options.colors.selected;
4744            if (MapSVG.isNumber(this.mapsvg.options.colors.hover))
4745                this.hover_attr["fill"] = tinycolor(this.default_attr.fill)
4746                    .lighten(parseFloat("" + this.mapsvg.options.colors.hover))
4747                    .toRgbString();
4748            else
4749                this.hover_attr["fill"] = this.mapsvg.options.colors.hover;
4750            $$7(this.element).css("fill", this.default_attr["fill"]);
4751            this.fill = this.default_attr["fill"];
4752            if (this.style.stroke != "none" && this.mapsvg.options.colors.stroke != undefined) {
4753                $$7(this.element).css("stroke", this.mapsvg.options.colors.stroke);
4754            }
4755            else {
4756                const s = this.style.stroke == undefined ? "" : this.style.stroke;
4757                $$7(this.element).css("stroke", s);
4758            }
4759            if (this.selected)
4760                this.setSelected();
4761        }
4762        setDisabled(on, skipSetFill) {
4763            on = on !== undefined ? MapSVG.parseBoolean(on) : this.getDisabledState();
4764            const prevDisabled = this.disabled;
4765            this.disabled = on;
4766            this.attr("class", this.attr("class").replace("mapsvg-disabled", ""));
4767            if (on) {
4768                this.attr("class", this.attr("class") + " mapsvg-disabled");
4769            }
4770            if (this.disabled != prevDisabled)
4771                this.mapsvg.deselectRegion(this);
4772            !skipSetFill && this.setFill();
4773        }
4774        setStatus(status) {
4775            const statusOptions = this.mapsvg.options.regionStatuses && this.mapsvg.options.regionStatuses[status];
4776            if (statusOptions) {
4777                this.status = status;
4778                if (this.data) {
4779                    this.data.status = status;
4780                    this.data.status_text = statusOptions.label;
4781                }
4782                this.setDisabled(statusOptions.disabled, true);
4783            }
4784            else {
4785                this.status = undefined;
4786                if (this.data) {
4787                    this.data.status = undefined;
4788                    this.data.status_text = undefined;
4789                }
4790                this.setDisabled(false, true);
4791            }
4792            this.setFill();
4793        }
4794        setSelected() {
4795            this.mapsvg.selectRegion(this);
4796        }
4797        setchoroplethValue(val) {
4798            if ($$7.isNumeric(val)) {
4799                if (typeof val === "string") {
4800                    val = parseFloat(val);
4801                }
4802                this.choroplethValue = val;
4803            }
4804            else {
4805                this.choroplethValue = undefined;
4806            }
4807        }
4808        getDisabledState(asDefault) {
4809            const opts = this.mapsvg.options.regions[this.id];
4810            if (!asDefault && opts && opts.disabled !== undefined) {
4811                return opts.disabled;
4812            }
4813            else {
4814                return (this.mapsvg.options.disableAll ||
4815                    this.style.fill === "none" ||
4816                    this.id == "labels" ||
4817                    this.id == "Labels");
4818            }
4819        }
4820        highlight() {
4821            $$7(this.element).css({ fill: this.hover_attr.fill });
4822            $$7(this.element).addClass("mapsvg-region-hover");
4823        }
4824        unhighlight() {
4825            $$7(this.element).css({ fill: this.default_attr.fill });
4826            $$7(this.element).removeClass("mapsvg-region-hover");
4827        }
4828        select() {
4829            $$7(this.element).css({ fill: this.selected_attr.fill });
4830            this.selected = true;
4831            $$7(this.element).addClass("mapsvg-region-active");
4832        }
4833        deselect() {
4834            $$7(this.element).css({ fill: this.default_attr.fill });
4835            this.selected = false;
4836            $$7(this.element).removeClass("mapsvg-region-active");
4837        }
4838        setData(data) {
4839            this.data = data;
4840            if (typeof data.title !== "undefined") {
4841                this.setTitle(data.title);
4842            }
4843        }
4844        drawBubble() {
4845            if (this.data) {
4846                const bubbleId = "mapsvg-bubble-" + this.id;
4847                const bubbleValue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]);
4848                if (bubbleValue) {
4849                    if (!this.center) {
4850                        this.center = this.getCenterSVG();
4851                    }
4852                    const pos = this.mapsvg.converter.convertSVGToPixel(this.center);
4853                    if (!this.bubble) {
4854                        this.bubble = $$7('<div id="' +
4855                            bubbleId +
4856                            '" class="mapsvg-bubble mapsvg-region-bubble"></div>')[0];
4857                        $$7(this.mapsvg.layers.bubbles).append(this.bubble);
4858                    }
4859                    const color = this.getChoroplethColor();
4860                    const bubbleSize = Number(this.getBubbleSize());
4861                    $$7(this.bubble)
4862                        .css("transform", "translate(-50%,-50%) translate(" + pos.x + "px," + pos.y + "px)")
4863                        .css("background-color", color)
4864                        .css("width", bubbleSize + "px")
4865                        .css("height", bubbleSize + "px")
4866                        .css("lineHeight", bubbleSize - 2 + "px");
4867                }
4868                else {
4869                    delete this.bubble;
4870                }
4871            }
4872        }
4873        adjustLabelScreenPosition() {
4874            if (this.label) {
4875                if (!this.center) {
4876                    this.center = this.getCenterSVG();
4877                }
4878                const pos = this.mapsvg.converter.convertSVGToPixel(this.center), x = pos.x - this.label.offsetWidth / 2, y = pos.y - this.label.offsetHeight / 2;
4879                this.setLabelScreenPosition(x, y);
4880            }
4881        }
4882        adjustBubbleScreenPosition() {
4883            if (this.bubble) {
4884                if (!this.center) {
4885                    this.center = this.getCenterSVG();
4886                }
4887                const pos = this.mapsvg.converter.convertSVGToPixel(this.center), x = pos.x - this.bubble.offsetWidth / 2, y = pos.y - this.bubble.offsetHeight / 2;
4888                this.setBubbleScreenPosition(x, y);
4889            }
4890        }
4891        moveLabelScreenPositionBy(deltaX, deltaY) {
4892            if (this.label) {
4893                const labelStyle = window.getComputedStyle(this.label), matrix = labelStyle.transform || labelStyle.webkitTransform, matrixValues = matrix.match(/matrix.*\((.+)\)/)[1].split(", "), x = parseFloat(matrixValues[4]) - deltaX, y = parseFloat(matrixValues[5]) - deltaY;
4894                this.setLabelScreenPosition(x, y);
4895            }
4896        }
4897        moveBubbleScreenPositionBy(deltaX, deltaY) {
4898            if (this.bubble) {
4899                const labelStyle = window.getComputedStyle(this.bubble), matrix = labelStyle.transform || labelStyle.webkitTransform, matrixValues = matrix.match(/matrix.*\((.+)\)/)[1].split(", "), x = parseFloat(matrixValues[4]) - deltaX, y = parseFloat(matrixValues[5]) - deltaY;
4900                this.setBubbleScreenPosition(x, y);
4901            }
4902        }
4903        setLabelScreenPosition(x, y) {
4904            if (this.label) {
4905                this.label.style.transform = "translate(" + x + "px," + y + "px)";
4906            }
4907        }
4908        setBubbleScreenPosition(x, y) {
4909            if (this.bubble) {
4910                this.bubble.style.transform = "translate(" + x + "px," + y + "px)";
4911            }
4912        }
4913    }
4914
4915    class SchemaRepository extends Repository {
4916        constructor() {
4917            const objectName = "schema";
4918            super(objectName, +objectName + "s");
4919            this.className = "Schema";
4920            this.objectNameSingle = objectName;
4921            this.objectNameMany = objectName + "s";
4922            this.path = objectName + "s/";
4923            this.events = new Events(this);
4924        }
4925        create(schema) {
4926            const defer = jQuery.Deferred();
4927            defer.promise();
4928            const data = {};
4929            data[this.objectNameSingle] = this.encodeData(schema);
4930            this.server
4931                .post(this.path, data)
4932                .done((response) => {
4933                const data = this.decodeData(response);
4934                schema.id = data[this.objectNameSingle].id;
4935                this.objects.push(schema);
4936                this.events.trigger("created");
4937                schema.events.trigger("created");
4938                defer.resolve(schema);
4939            })
4940                .fail(() => {
4941                defer.reject();
4942            });
4943            return defer;
4944        }
4945        update(schema) {
4946            const defer = jQuery.Deferred();
4947            defer.promise();
4948            const data = {};
4949            data[this.objectNameSingle] = this.encodeData(schema);
4950            this.server
4951                .put(this.path + schema.id, data)
4952                .done((response) => {
4953                const data = this.decodeData(response);
4954                this.objects.push(schema);
4955                defer.resolve(schema);
4956                this.events.trigger("changed");
4957                schema.events.trigger("changed");
4958            })
4959                .fail(() => {
4960                defer.reject();
4961            });
4962            return defer;
4963        }
4964        encodeData(schema) {
4965            const _schema = schema.getData();
4966            let fieldsJsonString = JSON.stringify(_schema);
4967            fieldsJsonString = fieldsJsonString.replace(/select/g, "!mapsvg-encoded-slct");
4968            fieldsJsonString = fieldsJsonString.replace(/table/g, "!mapsvg-encoded-tbl");
4969            fieldsJsonString = fieldsJsonString.replace(/database/g, "!mapsvg-encoded-db");
4970            fieldsJsonString = fieldsJsonString.replace(/varchar/g, "!mapsvg-encoded-vc");
4971            fieldsJsonString = fieldsJsonString.replace(/int\(11\)/g, "!mapsvg-encoded-int");
4972            const back = JSON.parse(fieldsJsonString);
4973            back.fields = JSON.stringify(_schema.fields);
4974            return back;
4975        }
4976    }
4977
4978    const $$8 = jQuery;
4979    class Controller {
4980        constructor(options) {
4981            this.containers = {
4982                main: options.container,
4983            };
4984            this.mapsvg = options.mapsvg;
4985            this.template = options.template || "";
4986            this.scrollable = options.scrollable === undefined ? true : options.scrollable;
4987            this.withToolbar = options.withToolbar === undefined ? true : options.withToolbar;
4988            this.autoresize = MapSVG.parseBoolean(options.autoresize);
4989            this.templates = {
4990                toolbar: Handlebars.compile(this.getToolbarTemplate()),
4991                main: Handlebars.compile(this.getMainTemplate()),
4992            };
4993            this.data = options.data;
4994            this.width = options.width;
4995            this.color = options.color;
4996            this.events = new Events(this);
4997            if (options.events) {
4998                for (const eventName in options.events) {
4999                    if (typeof options.events[eventName] === "function") {
5000                        this.events.on(eventName, options.events[eventName]);
5001                    }
5002                }
5003            }
5004        }
5005        viewDidLoad() {
5006            const _this = this;
5007            _this.updateScroll();
5008            if (this.autoresize) {
5009                _this.adjustHeight();
5010                this.resizeSensor.setScroll();
5011            }
5012        }
5013        _viewDidLoad() {
5014            this.updateScroll();
5015        }
5016        viewDidAppear() { }
5017        viewDidDisappear() { }
5018        updateScroll() {
5019            if (!this.scrollable)
5020                return;
5021            const _this = this;
5022            $$8(this.containers.contentWrap).nanoScroller({
5023                preventPageScrolling: true,
5024            });
5025            setTimeout(function () {
5026                $$8(_this.containers.contentWrap).nanoScroller({
5027                    preventPageScrolling: true,
5028                });
5029            }, 300);
5030        }
5031        adjustHeight() {
5032            const _this = this;
5033            $$8(_this.containers.main).height($$8(_this.containers.main).find(".mapsvg-auto-height").outerHeight() +
5034                (_this.containers.toolbar ? $$8(_this.containers.toolbar).outerHeight() : 0));
5035        }
5036        _init() {
5037            const _this = this;
5038            _this.render();
5039            _this.init();
5040        }
5041        init() { }
5042        getToolbarTemplate() {
5043            return "";
5044        }
5045        setMainTemplate(template) {
5046            return (this.templates.main = Handlebars.compile(template));
5047        }
5048        getMainTemplate() {
5049            return this.template;
5050        }
5051        render() {
5052            const _this = this;
5053            this.containers.view = $$8("<div />")
5054                .attr("id", "mapsvg-controller-" + this.name)
5055                .addClass("mapsvg-controller-view")[0];
5056            this.containers.contentWrap = $$8("<div />").addClass("mapsvg-controller-view-wrap")[0];
5057            this.containers.contentWrap2 = $$8("<div />")[0];
5058            this.containers.sizer = $$8("<div />").addClass("mapsvg-auto-height")[0];
5059            this.containers.contentView = $$8("<div />").addClass("mapsvg-controller-view-content")[0];
5060            this.containers.sizer.appendChild(this.containers.contentView);
5061            if (this.scrollable) {
5062                $$8(this.containers.contentWrap).addClass("nano");
5063                $$8(this.containers.contentWrap2).addClass("nano-content");
5064            }
5065            this.containers.contentWrap.appendChild(this.containers.contentWrap2);
5066            this.containers.contentWrap2.appendChild(this.containers.sizer);
5067            if (this.withToolbar && this.templates.toolbar) {
5068                this.containers.toolbar = $$8("<div />").addClass("mapsvg-controller-view-toolbar")[0];
5069                this.containers.view.appendChild(this.containers.toolbar);
5070            }
5071            this.containers.view.append(this.containers.contentWrap);
5072            this.containers.main.appendChild(this.containers.view);
5073            $$8(this.containers.main).data("controller", this);
5074            if (this.width)
5075                this.containers.view.style.width = this.width;
5076            if (this.color)
5077                this.containers.view.style["background-color"] = this.color;
5078            _this.viewReadyToFill();
5079            this.redraw();
5080            setTimeout(function () {
5081                _this._viewDidLoad();
5082                _this.viewDidLoad();
5083                _this.setEventHandlersCommon();
5084                _this.setEventHandlers();
5085            }, 1);
5086        }
5087        viewReadyToFill() {
5088            const _this = this;
5089            if (_this.autoresize) {
5090                _this.resizeSensor = new ResizeSensor(this.containers.sizer, () => {
5091                    _this.adjustHeight();
5092                    _this.updateScroll();
5093                    _this.events.trigger("resize", this, [this]);
5094                });
5095            }
5096        }
5097        redraw(data) {
5098            if (data !== undefined) {
5099                this.data = data;
5100            }
5101            try {
5102                $$8(this.containers.contentView).html(this.templates.main(this.data));
5103            }
5104            catch (err) {
5105                console.error(err);
5106                $$8(this.containers.contentView).html("");
5107            }
5108            if (this.withToolbar && this.templates.toolbar)
5109                $$8(this.containers.toolbar).html(this.templates.toolbar(this.data));
5110            this.updateTopShift();
5111            if (this.noPadding)
5112                this.containers.contentView.style.padding = "0";
5113            this.updateScroll();
5114        }
5115        updateTopShift() {
5116            const _this = this;
5117            if (!this.withToolbar)
5118                return;
5119            $$8(_this.containers.contentWrap).css({
5120                top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5121            });
5122            setTimeout(function () {
5123                $$8(_this.containers.contentWrap).css({
5124                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5125                });
5126            }, 100);
5127            setTimeout(function () {
5128                $$8(_this.containers.contentWrap).css({
5129                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5130                });
5131            }, 200);
5132            setTimeout(function () {
5133                $$8(_this.containers.contentWrap).css({
5134                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5135                });
5136                _this.updateScroll();
5137            }, 500);
5138        }
5139        setEventHandlersCommon() { }
5140        setEventHandlers() { }
5141        destroy() {
5142            delete this.resizeSensor;
5143            $$8(this.containers.view).empty().remove();
5144        }
5145    }
5146
5147    const $$9 = jQuery;
5148    class DirectoryController extends Controller {
5149        constructor(options) {
5150            super(options);
5151            this.repository = options.repository;
5152            this.noPadding = true;
5153            this.position = options.position;
5154            this.search = options.search;
5155        }
5156        getToolbarTemplate() {
5157            let t = '<div class="mapsvg-directory-search-wrap">';
5158            t += '<div class="mapsvg-directory-filter-wrap filter-wrap"></div>';
5159            t += "</div>";
5160            t += "</div>";
5161            return t;
5162        }
5163        viewDidLoad() {
5164            const _this = this;
5165            this.menuBtn = $$9('<div class="mapsvg-button-menu"><i class="mapsvg-icon-menu"></i> ' +
5166                this.mapsvg.options.mobileView.labelList +
5167                "</div>")[0];
5168            this.mapBtn = $$9('<div class="mapsvg-button-map"><i class="mapsvg-icon-map"></i> ' +
5169                this.mapsvg.options.mobileView.labelMap +
5170                "</div>")[0];
5171            if (MapSVG.isPhone && _this.mapsvg.options.menu.hideOnMobile) {
5172                if (this.mapsvg.options.menu.showFirst == "map") {
5173                    this.toggle(false);
5174                }
5175                else {
5176                    this.toggle(true);
5177                }
5178            }
5179            this.mobileButtons = $$9('<div class="mapsvg-mobile-buttons"></div>')[0];
5180            this.mobileButtons.append(this.menuBtn, this.mapBtn);
5181            if (this.mapsvg.options.menu.on !== false) {
5182                this.mapsvg.containers.wrapAll.appendChild(this.mobileButtons);
5183            }
5184            this.events.trigger("shown", this.containers.view);
5185        }
5186        setEventHandlers() {
5187            const _this = this;
5188            $$9(window).on("resize", function () {
5189                _this.updateTopShift();
5190            });
5191            $$9(this.menuBtn).on("click", function () {
5192                _this.toggle(true);
5193            });
5194            $$9(this.mapBtn).on("click", function () {
5195                _this.toggle(false);
5196                _this.mapsvg.redraw();
5197            });
5198            $$9(this.containers.view)
5199                .on("click.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5200                if (e.target.nodeName == "A") {
5201                    return;
5202                }
5203                const objID = $$9(this).data("object-id");
5204                let regions;
5205                let marker;
5206                let detailsViewObject;
5207                let eventObject;
5208                _this.deselectItems();
5209                _this.selectItems(objID, false);
5210                if (MapSVG.isPhone && _this.mapsvg.options.menu.showMapOnClick) {
5211                    _this.toggle(false);
5212                }
5213                if (_this.mapsvg.options.menu.source == "regions") {
5214                    regions = [_this.mapsvg.getRegion(objID)];
5215                    eventObject = regions[0];
5216                    detailsViewObject = regions[0];
5217                }
5218                else {
5219                    detailsViewObject = _this.repository.getLoadedObject(objID);
5220                    eventObject = detailsViewObject;
5221                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5222                    if (_regions) {
5223                        regions = _regions
5224                            .map(function (region) {
5225                            return _this.mapsvg.getRegion(region.id);
5226                        })
5227                            .filter(function (r) {
5228                            return r !== undefined;
5229                        });
5230                    }
5231                }
5232                if (detailsViewObject.location && detailsViewObject.location.marker)
5233                    marker = detailsViewObject.location.marker;
5234                if (_this.mapsvg.options.actions.directoryItem.click.showDetail
5234s) {
5235                    _this.mapsvg.loadDetailsView(detailsViewObject);
5236                }
5237                if (regions && regions.length > 0) {
5238                    if (_this.mapsvg.options.actions.directoryItem.click.zoom) {
5239                        _this.mapsvg.zoomTo(regions, _this.mapsvg.options.actions.directoryItem.click.zoomToLevel);
5240                    }
5241                    if (regions.length > 1) {
5242                        _this.mapsvg.setMultiSelect(true);
5243                    }
5244                    regions.forEach(function (region) {
5245                        const center = region.getCenter();
5246                        e.clientX = center[0];
5247                        e.clientY = center[1];
5248                        if (_this.mapsvg.options.actions.directoryItem.click.selectRegion) {
5249                            _this.mapsvg.selectRegion(region, true);
5250                        }
5251                        if (_this.mapsvg.options.actions.directoryItem.click.showRegionPopover) {
5252                            if (_this.mapsvg.options.actions.directoryItem.click.zoom) {
5253                                setTimeout(function () {
5254                                    _this.mapsvg.showPopover(region);
5255                                }, 500);
5256                            }
5257                            else {
5258                                _this.mapsvg.showPopover(region);
5259                            }
5260                        }
5261                        if (_this.mapsvg.options.actions.directoryItem.click.fireRegionOnClick) {
5262                            _this.mapsvg.events.trigger("click.region", region, [region]);
5263                        }
5264                    });
5265                    if (regions.length > 1) {
5266                        _this.mapsvg.setMultiSelect(false, false);
5267                    }
5268                }
5269                if (marker) {
5270                    if (_this.mapsvg.options.actions.directoryItem.click.zoomToMarker) {
5271                        _this.mapsvg.zoomTo(marker, _this.mapsvg.options.actions.directoryItem.click.zoomToMarkerLevel);
5272                    }
5273                    if (_this.mapsvg.options.actions.directoryItem.click.showMarkerPopover) {
5274                        if (_this.mapsvg.options.actions.directoryItem.click.zoomToMarker) {
5275                            setTimeout(function () {
5276                                _this.mapsvg.showPopover(detailsViewObject);
5277                            }, 500);
5278                        }
5279                        else {
5280                            _this.mapsvg.showPopover(detailsViewObject);
5281                        }
5282                    }
5283                    if (_this.mapsvg.options.actions.directoryItem.click.fireMarkerOnClick) {
5284                        _this.mapsvg.events.trigger("click.marker", marker, [e, _this.mapsvg]);
5285                    }
5286                    _this.mapsvg.selectMarker(marker);
5287                }
5288                _this.events.trigger("click", this, [e, eventObject, _this.mapsvg]);
5289                const actions = _this.mapsvg.options.actions;
5290                if (actions.directoryItem.click.goToLink) {
5291                    const linkParts = actions.directoryItem.click.linkField.split(".");
5292                    let url;
5293                    if (linkParts.length > 1) {
5294                        const obj = linkParts.shift();
5295                        const attr = "." + linkParts.join(".");
5296                        if (obj == "Region") {
5297                            if (regions[0] && regions[0].data)
5298                                url = eval("regions[0].data" + attr);
5299                        }
5300                        else {
5301                            if (detailsViewObject)
5302                                url = eval("detailsViewObject" + attr);
5303                        }
5304                        if (url) {
5305                            if (actions.directoryItem.click.newTab) {
5306                                const win = window.open(url, "_blank");
5307                                win.focus();
5308                            }
5309                            else {
5310                                window.location.href = url;
5311                            }
5312                        }
5313                    }
5314                }
5315                if (actions.directoryItem.click.showAnotherMap) {
5316                    if (_this.mapsvg.editMode) {
5317                        alert('"Show another map" action is disabled in the preview');
5318                        return true;
5319                    }
5320                    const linkParts2 = actions.directoryItem.click.showAnotherMapField.split(".");
5321                    if (linkParts2.length > 1) {
5322                        const obj2 = linkParts2.shift();
5323                        const attr2 = "." + linkParts2.join(".");
5324                        let map_id;
5325                        if (obj2 == "Region") {
5326                            if (regions[0] && regions[0].data)
5327                                map_id = eval("regions[0].data" + attr2);
5328                        }
5329                        else {
5330                            if (detailsViewObject)
5331                                map_id = eval("detailsViewObject" + attr2);
5332                        }
5333                        if (map_id) {
5334                            const container = actions.directoryItem.click.showAnotherMapContainerId
5335                                ? $$9("#" + actions.directoryItem.click.showAnotherMapContainerId)[0]
5336                                : $$9(_this.mapsvg.containers.map)[0];
5337                            _this.mapsvg.loadMap(map_id, container);
5338                        }
5339                    }
5340                }
5341            })
5342                .on("mouseover.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5343                const objID = $$9(this).data("object-id");
5344                let regions;
5345                let detailsViewObject;
5346                let eventObject;
5347                let marker;
5348                if (_this.mapsvg.options.menu.source == "regions") {
5349                    regions = [_this.mapsvg.getRegion(objID)];
5350                    eventObject = regions[0];
5351                    detailsViewObject = regions[0];
5352                }
5353                else {
5354                    detailsViewObject = _this.repository.getLoadedObject(objID);
5355                    eventObject = detailsViewObject;
5356                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5357                    if (_regions) {
5358                        regions = _regions.map(function (region) {
5359                            return _this.mapsvg.getRegion(region.id);
5360                        });
5361                    }
5362                    if (detailsViewObject.location) {
5363                        marker = detailsViewObject.location.marker;
5364                    }
5365                }
5366                if (regions && regions.length) {
5367                    _this.mapsvg.highlightRegions(regions);
5368                }
5369                if (marker) {
5370                    _this.mapsvg.highlightMarker(marker);
5371                    if (_this.mapsvg.options.actions.directoryItem.hover.centerOnMarker) {
5372                        _this.mapsvg.centerOn(marker);
5373                    }
5374                }
5375                _this.events.trigger("mouseover", $$9(this), [e, eventObject, _this.mapsvg]);
5376            })
5377                .on("mouseout.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5378                const objID = $$9(this).data("object-id");
5379                let regions;
5380                let detailsViewObject;
5381                let eventObject;
5382                let marker;
5383                if (_this.mapsvg.options.menu.source == "regions") {
5384                    regions = [_this.mapsvg.getRegion(objID)];
5385                    eventObject = regions[0];
5386                    detailsViewObject = regions[0];
5387                }
5388                else {
5389                    detailsViewObject = _this.repository.getLoadedObject(objID);
5390                    eventObject = detailsViewObject;
5391                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5392                    if (_regions) {
5393                        regions = _regions.map(function (region) {
5394                            return _this.mapsvg.getRegion(region.id);
5395                        });
5396                    }
5397                    if (detailsViewObject.location) {
5398                        marker = detailsViewObject.location.marker;
5399                    }
5400                }
5401                if (regions && regions.length) {
5402                    _this.mapsvg.unhighlightRegions();
5403                }
5404                if (marker) {
5405                    _this.mapsvg.unhighlightMarker();
5406                }
5407                _this.events.trigger("mouseout", $$9(this), [e, eventObject, _this.mapsvg]);
5408            });
5409            $$9(this.containers.contentView).on("click", ".mapsvg-category-item", function () {
5410                const panel = $$9(this).next(".mapsvg-category-block");
5411                if (panel[0].style.maxHeight || panel.hasClass("active")) {
5412                    panel[0].style.maxHeight = null;
5413                }
5414                else {
5415                    panel[0].style.maxHeight = panel[0].scrollHeight + "px";
5416                }
5417                if ($$9(this).hasClass("active")) {
5418                    $$9(this).toggleClass("active", false);
5419                    $$9(this).next(".mapsvg-category-block").addClass("collapsed").removeClass("active");
5420                }
5421                else {
5422                    if (_this.mapsvg.options.menu.categories.collapseOther) {
5423                        $$9(this).parent().find(".mapsvg-category-item.active").removeClass("active");
5424                        $$9(this)
5425                            .parent()
5426                            .find(".mapsvg-category-block.active")
5427                            .removeClass("active")
5428                            .addClass("collapsed");
5429                    }
5430                    $$9(this).toggleClass("active", true);
5431                    $$9(this).next(".mapsvg-category-block").removeClass("collapsed").addClass("active");
5432                }
5433                const panels = $$9(".mapsvg-category-block.collapsed");
5434                panels.each(function (i, panel) {
5435                    panel.style.maxHeight = null;
5436                });
5437            });
5438        }
5439        highlightItems(ids) {
5440            const _this = this;
5441            if (typeof ids != "object")
5442                ids = [ids];
5443            ids.forEach(function (id) {
5444                $$9(_this.containers.view)
5445                    .find("#mapsvg-directory-item-" + _this.convertId(id)
5445)
5446                    .addClass("hover");
5447            });
5448        }
5449        unhighlightItems() {
5450            $$9(this.containers.view).find(".mapsvg-directory-item").removeClass("hover");
5451        }
5452        selectItems(ids, scrollTo = true) {
5453            if (typeof ids != "object")
5454                ids = [ids];
5455            ids.forEach((id) => {
5456                $$9(this.containers.view)
5457                    .find("#mapsvg-directory-item-" + this.convertId(id))
5458                    .addClass("selected");
5459            });
5460            if (scrollTo && $$9("#mapsvg-directory-item-" + ids[0]).length > 0) {
5461                this.scrollable &&
5462                    $$9(this.containers.contentWrap).nanoScroller({
5463                        scrollTo: $$9(this.containers.view).find("#mapsvg-directory-item-" + this.convertId(ids[0])),
5464                    });
5465            }
5466        }
5467        deselectItems() {
5468            $$9(this.containers.view).find(".mapsvg-directory-item").removeClass("selected");
5469        }
5470        removeItems(ids) {
5471            $$9(this.containers.view)
5472                .find("#mapsvg-directory-item-" + this.convertId(ids))
5473                .remove();
5474        }
5475        filterOut(items) {
5476            const _this = this;
5477            if (this.repository.path.indexOf("regions") !== -1) {
5478                let f;
5479                f = {
5480                    field: "",
5481                    val: "",
5482                };
5483                if (_this.mapsvg.options.menu.filterout.field) {
5484                    f.field = _this.mapsvg.options.menu.filterout.field;
5485                    f.val = _this.mapsvg.options.menu.filterout.val;
5486                }
5487                items = items.filter(function (item) {
5488                    let ok = true;
5489                    const status = _this.mapsvg.options.regionStatuses;
5490                    if (status[item.status]) {
5491                        ok = !status[item.status].disabled;
5492                    }
5493                    if (ok && f.field) {
5494                        ok = item[f.field] != f.val;
5495                    }
5496                    return ok;
5497                });
5498            }
5499            return items;
5500        }
5501        loadItemsToDirectory() {
5502            let items = [];
5503            const _this = this;
5504            if (!_this.repository.loaded)
5505                return false;
5506            if (_this.mapsvg.options.menu.categories &&
5507                _this.mapsvg.options.menu.categories.on &&
5508                _this.mapsvg.options.menu.categories.groupBy) {
5509                const categoryField = _this.mapsvg.options.menu.categories.groupBy;
5510                if (_this.repository.getSchema().getField(categoryField) === undefined ||
5511                    _this.repository.getSchema().getField(categoryField).options === undefined) {
5512                    return false;
5513                }
5514                const categories = _this.repository.getSchema().getField(categoryField).options;
5515                categories.forEach(function (category) {
5516                    let dbItems = _this.repository.getLoaded();
5517                    dbItems = _this.filterOut(dbItems);
5518                    const itemArr = [];
5519                    dbItems.forEach((item) => {
5520                        itemArr.push(item);
5521                    });
5522                    const catItems = itemArr.filter(function (object) {
5523                        if (categoryField === "regions") {
5524                            const objectRegions = typeof object[categoryField] !== "undefined" &&
5525                                object[categoryField].length
5526                                ? object[categoryField]
5527                                : [];
5528                            const objectRegionIDs = objectRegions.map(function (region) {
5529                                return region.id;
5530                            });
5531                            return objectRegionIDs.indexOf(category.id) !== -1;
5532                        }
5533                        else {
5534                            return object[categoryField] == category.value;
5535                        }
5536                    });
5537                    category.counter = catItems.length;
5538                    if (categoryField === "regions") {
5539                        category.label = category.title;
5540                        category.value = category.id;
5541                    }
5542                    catItems.sort(function (a, b) {
5543                        const field = _this.mapsvg.options.menu.sortBy;
5544                        return a[field] == b[field]
5545                            ? 0
5546                            : (_this.mapsvg.options.menu.sortDirection === "asc"
5547                                ? +(a[field] > [field])
5548                                : +(a[field] < [field])) || -1;
5549                    });
5550                    items.push({ category: category, items: catItems });
5551                });
5552                if (_this.mapsvg.options.menu.categories.hideEmpty) {
5553                    items = items.filter(function (item) {
5554                        return item.category.counter > 0;
5555                    });
5556                }
5557            }
5558            else {
5559                if (_this.mapsvg.options.menu.source === "regions") {
5560                    items = _this.repository.getLoaded().map((r) => {
5561                        const data = r.getData();
5562                        data.objects = _this.mapsvg.getRegion(data.id).objects;
5563                        data.id_no_spaces = data.id.split(" ").join("_");
5564                        return data;
5565                    });
5566                    items = _this.filterOut(items);
5567                }
5568                else {
5569                    items = _this.repository
5570                        .getLoaded()
5571                        .map((r) => r.getData(_this.mapsvg.regionsRepository.schema.name));
5572                }
5573            }
5574            try {
5575                $$9(this.containers.contentView).html(this.templates.main({ items: items }));
5576            }
5577            catch (err) {
5578                console.error('MapSVG: Error in the "Directory item" template');
5579                console.error(err);
5580            }
5581            if (items.length === 0) {
5582                $$9(this.containers.contentView).html('<div class="mapsvg-no-results">' +
5583                    this.mapsvg.options.menu.noResultsText +
5584                    "</div>");
5585            }
5586            if (_this.mapsvg.options.menu.categories.on) {
5587                if (_this.mapsvg.options.menu.categories.collapse && items.length > 1) {
5588                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("collapsed");
5589                }
5590                else if (_this.mapsvg.options.menu.categories.collapse && items.length === 1) {
5591                    $$9(this.containers.contentView).find(".mapsvg-category-item").addClass("active");
5592                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("active");
5593                    const panel = $$9(this.containers.contentView).find(".mapsvg-category-block")[0];
5594                    if (panel)
5595                        panel.style.maxHeight = panel.scrollHeight + "px";
5596                }
5597                else if (!_this.mapsvg.options.menu.categories.collapse) {
5598                    $$9(this.containers.contentView).find(".mapsvg-category-item").addClass("active");
5599                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("active");
5600                    const panels = $$9(this.containers.contentView).find(".mapsvg-category-block");
5601                    if (panels.length)
5602                        panels.each(function (i, panel) {
5603                            panel.style.maxHeight = panel.scrollHeight + "px";
5604                        });
5605                }
5606            }
5607            this.updateTopShift();
5608            this.updateScroll();
5609        }
5610        toggle(on) {
5611            const _this = this;
5612            if (on) {
5613                $$9(this.containers.main).parent().show();
5614                $$9(_this.mapsvg.containers.mapContainer).hide();
5615                $$9(this.menuBtn).addClass("active");
5616                $$9(this.mapBtn).removeClass("active");
5617            }
5618            else {
5619                $$9(this.containers.main).parent().hide();
5620                $$9(_this.mapsvg.containers.mapContainer).show();
5621                $$9(this.menuBtn).removeClass("active");
5622                $$9(this.mapBtn).addClass("active");
5623            }
5624            if (!$$9(this.containers.main).parent().is(":visible")) {
5625                if (MapSVG.isPhone) {
5626                    $$9(_this.mapsvg.containers.wrap).css("height", "auto");
5627                    _this.updateScroll();
5628                }
5629            }
5630            else {
5631                if (MapSVG.isPhone &&
5632                    $$9(this.containers.main).height() < parseInt(this.mapsvg.options.menu.minHeight)) {
5633                    $$9(_this.mapsvg.containers.wrap).css("height", parseInt(this.mapsvg.options.menu.minHeight) + "px");
5634                    _this.updateScroll();
5635                }
5636            }
5637            this.updateTopShift();
5638        }
5639        addPagination(pager) {
5640            $$9(this.containers.contentView).append('<div class="mapsvg-pagination-container"></div>');
5641            $$9(this.containers.contentView).find(".mapsvg-pagination-container").html(pager);
5642        }
5643        convertId(id) {
5644            return (id + "")
5645                .split(" ")
5646                .join("_")
5647                .replace(/(:|\(|\)|\.|\[|\]|,|=|@)/g, "\\$1");
5648        }
5649    }
5650
5651    const $$a = jQuery;
5652    class DetailsController extends Controller {
5653        constructor(options) {
5654            super(options);
5655            this.modal = options.modal;
5656        }
5657        getToolbarTemplate() {
5658            if (this.withToolbar)
5659                return '<div class="mapsvg-popover-close mapsvg-details-close"></div>';
5660            else
5661                return "";
5662        }
5663        viewDidLoad() {
5664            const _this = this;
5665            this.events.trigger("shown", _this, [_this]);
5666            if (this.modal &&
5667                MapSVG.isPhone &&
5668                this.mapsvg.options.detailsView.mobileFullscreen &&
5669                !this.mobileCloseBtn) {
5670                this.mobileCloseBtn = $$a('<button class="mapsvg-mobile-modal-close">' +
5671                    _this.mapsvg.options.mobileView.labelClose +
5672                    "</button>")[0];
5673                this.containers.view.appendChild(this.mobileCloseBtn);
5674            }
5675        }
5676        setEventHandlers() {
5677            const _this = this;
5678            $$a(this.containers.toolbar).on("click touchend", ".mapsvg-popover-close", function (e) {
5679                e.stopPropagation();
5680                _this.destroy();
5681                _this.events.trigger("closed", _this, [_this]);
5682            });
5683            $$a(this.containers.view).on("click touchend", ".mapsvg-mobile-modal-close", function (e) {
5684                e.stopPropagation();
5685                _this.destroy();
5686                _this.events.trigger("closed", _this, [_this]);
5687            });
5688        }
5689    }
5690
5691    const $$b = jQuery;
5692    class FormElement {
5693        constructor(options, formBuilder, external) {
5694            this.readonly = typeof options.readonly !== "undefined" ? options.readonly : false;
5695            this.protected = typeof options.protected !== "undefined" ? options.protected : false;
5696            this.auto_increment =
5697                typeof options.auto_increment !== "undefined" ? options.auto_increment : false;
5698            this.not_null = typeof options.not_null !== "undefined" ? options.not_null : false;
5699            this.searchable = typeof options.searchable !== "undefined" ? options.searchable : false;
5700            this.visible = typeof options.visible !== "undefined" ? options.visible : true;
5701            this.formBuilder = formBuilder;
5702            this.events = new Events(this);
5703            this.type = options.type;
5704            this.value = options.value;
5705            this.db_type = options.db_type || "varchar(255)";
5706            this.label = this.label || (options.label === undefined ? "Label" : options.label);
5707            this.name = this.name || options.name || "label";
5708            this.help = options.help || "";
5709            this.placeholder = options.placeholder;
5710            this.setExternal(external);
5711            let t = this.type;
5712            if (t === "marker" && this.mapIsGeo) {
5713                t = "marker-geo";
5714            }
5715            if (t === "location" && this.mapIsGeo) {
5716                t = "location-geo";
5717            }
5718            if (this.filtersMode) {
5719                this.parameterName = options.parameterName || "";
5720                this.parameterNameShort = this.parameterName.split(".")[1];
5721                this.name = this.parameterNameShort;
5722                this.placeholder = options.placeholder || "";
5723                this.templates = {
5724                    main: Handlebars.compile($$b("#mapsvg-filters-tmpl-" + t + "-view").html()),
5725                };
5726            }
5727            else {
5728                this.templates = {
5729                    main: Handlebars.compile($$b("#mapsvg-data-tmpl-" + t + "-view").html()),
5730                };
5731            }
5732            this.inputs = {};
5733        }
5734        init() {
5735            this.setDomElements();
5736            this.setEventHandlers();
5737        }
5738        setDomElements() {
5739            this.domElements = {
5740                main: $$b(this.templates.main(this.getDataForTemplate()))[0],
5741            };
5742            $$b(this.domElements.main).data("formElement", this);
5743            this.addSelect2();
5744        }
5745        setEventHandlers() {
5746            const _this = this;
5747            if (this.formBuilder.editMode) {
5748                $$b(this.domElements.main).on("click", function () {
5749                    _this.events.trigger("click", _this, [_this]);
5750                });
5751            }
5752        }
5753        addSelect2() {
5754            if ($$b().mselect2) {
5755                $$b(this.domElements.main)
5756                    .find("select")
5757                    .css({ width: "100%", display: "block" })
5758                    .mselect2()
5759                    .on("select2:focus", function () {
5760                    $$b(this).mselect2("open");
5761                });
5762                $$b(this.domElements.main)
5763                    .find(".select2-selection--multiple .select2-search__field")
5764                    .css("width", "100%");
5765            }
5766        }
5767        setEditorEventHandlers() {
5768            const _this = this;
5769            $$b(this.domElements.edit).on("click", "button.mapsvg-remove", function () {
5770                $$b(_this.domElements.main).empty().remove();
5771                $$b(_this.domElements.edit).empty().remove();
5772                _this.events.trigger("delete", _this, [_this]);
5773            });
5774            $$b(this.domElements.edit).on("click", ".mapsvg-filter-insert-options", function () {
5775                const objType = _this.parameterName.split(".")[0];
5776                const fieldName = _this.parameterName.split(".")[1];
5777                let field;
5778                if (objType == "Object") {
5779                    field = _this.formBuilder.mapsvg.objectsRepository.getSchema().getField(fieldName);
5780                }
5781                else {
5782                    if (fieldName == "id") {
5783                        const options = [];
5784                        _this.formBuilder.mapsvg.regions.forEach(function (r) {
5785                            options.push({ label: r.id, value: r.id });
5786                        });
5787                        field = {
5788                            options: options,
5789                        };
5790                    }
5791                    else if (fieldName === "title") {
5792                        const options = [];
5793                        _this.formBuilder.mapsvg.regions.forEach(function (r) {
5794                            options.push({ label: r.title, value: r.title });
5795                        });
5796                        field = { options: options };
5797                    }
5798                    else {
5799                        field = _this.formBuilder.mapsvg.regionsRepository
5800                            .getSchema()
5801                            .getField(fieldName);
5802                    }
5803                }
5804                if ((field && field.options) || fieldName === "regions") {
5805                    let options;
5806                    if (fieldName == "regions") {
5807                        const _options = _this.formBuilder.mapsvg.regions.map((r) => {
5808                            return { id: r.id, title: r.title };
5809                        });
5810                        _options.sort(function (a, b) {
5811                            if (a.title < b.title)
5812                                return -1;
5813                            if (a.title > b.title)
5814                                return 1;
5815                            return 0;
5816                        });
5817                        options = _options.map(function (o) {
5818                            return (o.title || o.id) + ":" + o.id;
5819                        });
5820                    }
5821                    else {
5822                        options = field.options.map(function (o) {
5823                            return o.label + ":" + o.value;
5824                        });
5825                    }
5826                    $$b(this)
5827                        .closest(".form-group")
5828                        .find("textarea")
5829                        .val(options.join("\n"))
5830                        .trigger("change");
5831                }
5832            });
5833            $$b(this.domElements.edit).on("keyup change paste", "input, textarea, select", function () {
5834                const prop = $$b(this).attr("name");
5835                const array = $$b(this).data("array");
5836                if (_this.type === "status" && array) {
5837                    const param = $$b(this).data("param");
5838                    const index = $$b(this).closest("tr").index();
5839                    _this.options[index] = _this.options[index] || {
5840                        label: "",
5841                        value: "",
5842                        color: "",
5843                        disabled: false,
5844                    };
5845                    _this.options[index][param] = $$b(this).is(":checkbox")
5846                        ? $$b(this).prop("checked")
5847                        : $$b(this).val();
5848                    _this.redraw();
5849                }
5850                else if (_this.type === "distance" && array) {
5851                    const param = $$b(this).data("param");
5852                    const index = $$b(this).closest("tr").index();
5853                    if (!_this.options[index]) {
5854                        _this.options[index] = { value: "", default: false };
5855                    }
5856                    if (param === "default") {
5857                        _this.options.forEach(function (option) {
5858                            option.default = false;
5859                        });
5860                        _this.options[index].default = $$b(this).prop("checked");
5861                    }
5862                    else {
5863                        _this.options[index].value = $$b(this).val();
5864                    }
5865                    _this.redraw();
5866                }
5867                else if (prop == "label" || prop == "name") {
5868                    return false;
5869                }
5870                else {
5871                    let value;
5872                    value =
5873                        $$b(this).attr("type") == "checkbox" ? $$b(this).prop("checked") : $$b(this).val();
5874                    if ($$b(this).attr("type") == "radio") {
5875                        const name = $$b(this).attr("name");
5876                        value = $$b('input[name="' + name + '"]:checked').val();
5877                    }
5878                    _this.update(prop, value);
5879                }
5880            });
5881            $$b(this.domElements.edit).on("keyup change paste", 'input[name="label"]', function () {
5882                if (!_this.nameChanged) {
5883                    _this.label = $$b(this).val() + "";
5884                    if (_this.type != "region" && _this.type != "location" && _this.type != "title") {
5885                        let str = $$b(this).val() + "";
5886                        str = str.toLowerCase().replace(/ /g, "_").replace(/\W/g, "");
5887                        if (str.length < 64) {
5888                            $$b(_this.domElements.edit).find('input[name="name"]').val(str);
5889                        }
5890                        _this.name = str + "";
5891                    }
5892                    $$b(_this.domElements.main).find("label").first().html(_this.label);
5893                    if (!_this.filtersMode) {
5894                        $$b(_this.domElements.main)
5895                            .find("label")
5896                            .first()
5897                            .append('<div class="field-name">' + _this.name + "</div>");
5898                    }
5899                }
5900            });
5901            $$b(this.domElements.edit).on("keyup change paste", 'input[name="name"]', function (e) {
5902                if (e.target.value) {
5903                    if (e.target.value.match(/[^a-zA-Z0-9_]/g)) {
5904                        e.target.value = e.target.value.replace(/[^a-zA-Z0-9_]/g, "");
5905                        $$b(e.target).trigger("change");
5906                    }
5907                    if (e.target.value[0].match(/[^a-zA-Z_]/g)) {
5908                        e.target.value =
5909                            e.target.value[0].replace(/[^a-zA-Z_]/g, "") + e.target.value.slice(1);
5910                        $$b(e.target).trigger("change");
5911                    }
5912                }
5913                if (_this.type != "region")
5914                    _this.name = e.target.value;
5915                $$b(_this.domElements.main)
5916                    .find("label")
5917                    .html(_this.label + '<div class="field-name">' + _this.name + "</div>");
5918                _this.nameChanged = true;
5919            });
5920            $$b(this.domElements.edit).on("keyup change paste", 'textarea[name="help"]', function (e) {
5921                $$b(_this.domElements.main).find(".form-text").text(e.target.value);
5922            });
5923        }
5924        getEditor() {
5925            if (!this.filtersMode) {
5926                this.templates.edit =
5927                    this.templates.edit ||
5928                        Handlebars.compile($$b("#mapsvg-data-tmpl-" + this.type + "-control").html());
5929            }
5930            else {
5931                this.templates.edit =
5932                    this.templates.edit ||
5933                        Handlebars.compile($$b("#mapsvg-filters-tmpl-" + this.type + "-control").html());
5934            }
5935            this.domElements.edit = $$b("<div>" + this.templates.edit(this.getDataForTemplate()) + "</div>")[0];
5936            return this.domElements.edit;
5937        }
5938        destroyEditor() {
5939            $$b(this.domElements.edit).empty().remove();
5940        }
5941        initEditor() {
5942            $$b(this.domElements.edit).find("input").first().select();
5943            if ($$b().colorpicker) {
5944                $$b(this.domElements.edit)
5945                    .find(".cpicker")
5946                    .colorpicker()
5947                    .on("changeColor.colorpicker", function (event) {
5948                    const input = $$b(this).find("input");
5949                    if (input.val() == "")
5950                        $$b(this).find("i").css({ "background-color": "" });
5951                });
5952            }
5953            if ($$b().mselect2) {
5954                if (this.type !== "distance") {
5955                    $$b(this.domElements.edit)
5956                        .find("select")
5957                        .css({ width: "100%", display: "block" })
5958                        .mselect2();
5959                }
5960            }
5961            this.setEditorEventHandlers();
5962        }
5963        getSchema() {
5964            let data;
5965            data = {
5966                type: this.type,
5967                db_type: this.db_type,
5968                label: this.label,
5969                name: this.name,
5970                value: this.value,
5971                searchable: this.searchable,
5972                help: this.help,
5973                visible: this.visible === undefined ? true : this.visible,
5974                readonly: this.readonly,
5975                placeholder: this.placeholder,
5976                protected: this.protected,
5977                auto_increment: this.auto_increment,
5978                not_null: this.not_null,
5979            };
5980            if (this.options) {
5981                data.options = this.getSchemaFieldOptionsList();
5982            }
5983            if (this.filtersMode) {
5984                data.parameterName = this.parameterName;
5985                data.parameterNameShort = this.parameterName.split(".")[1];
5986            }
5987            return data;
5988        }
5989        getSchemaFieldOptionsList() {
5990            const options = [];
5991            this.options.forEach((option, index) => {
5992                if (this.options[index].value !== "") {
5993                    options.push(this.options[index]);
5994                }
5995            });
5996            return options;
5997        }
5998        getDataForTemplate() {
5999            const data = this.getSchema();
6000            data._name = data.name;
6001            if (this.namespace) {
6002                data.name = this.name.split("[")[0];
6003                let suffix = this.name.split("[")[1] || "";
6004                if (suffix)
6005                    suffix = "[" + suffix;
6006                data.name = this.namespace + "[" + data.name + "]" + suffix;
6007            }
6008            data.external = this.external;
6009            return data;
6010        }
6011        update(prop, value) {
6012            const _this = this;
6013            if (prop == "options") {
6014                const options = [];
6015                value = value.split("\n").forEach(function (row) {
6016                    row = row.trim().split(":");
6017                    if (_this.type == "checkbox" && row.length == 3) {
6018                        options.push({
6019                            label: row[0],
6020                            name: row[1],
6021                            value: row[2],
6022                        });
6023                    }
6024                    else if ((_this.type == "radio" ||
6025                        _this.type == "select" ||
6026                        _this.type == "checkboxes") &&
6027                        row.length == 2) {
6028                        options.push({
6029                            label: row[0],
6030                            value: row[1],
6031                        });
6032                    }
6033                });
6034                this.options = options;
6035            }
6036            else {
6037                this[prop] = value;
6038            }
6039            if (prop == "parameterName") {
6040                $$b(this.domElements.edit).find(".mapsvg-filter-param-name").text(value);
6041            }
6042        }
6043        redraw() {
6044            const newView = $$b(this.templates.main(this.getDataForTemplate()));
6045            $$b(this.domElements.main).html(newView.html());
6046            if ($$b().mselect2) {
6047                if (this.type !== "distance") {
6048                    $$b(this.domElements.main)
6049                        .find("select")
6050                        .css({ width: "100%", display: "block" })
6051                        .mselect2()
6052                        .on("select2:focus", function () {
6053                        $$b(this).mselect2("open");
6054                    });
6055                }
6056                else {
6057                    $$b(this.domElements.main)
6058                        .find("select")
6059                        .mselect2()
6060                        .on("select2:focus", function () {
6061                        $$b(this).mselect2("open");
6062                    });
6063                }
6064            }
6065        }
6066        redrawEditor() {
6067            if (this.domElements.edit) {
6068                $$b(this.domElements.edit).empty();
6069                $$b(this.domElements.edit).html("<div>" + this.templates.edit(this.getDataForTemplate()) + "</div>");
6070                this.initEditor();
6071            }
6072        }
6073        setOptions(options) {
6074            if (options) {
6075                this.options = [];
6076                this.optionsDict = {};
6077                options.forEach((value, key) => {
6078                    this.options.push(value);
6079                    this.optionsDict[key] = value;
6080                });
6081                return this.options;
6082            }
6083            else {
6084                return this.setOptions([
6085                    { label: "Option one", name: "option_one", value: 1 },
6086                    { label: "Option two", name: "option_two", value: 2 },
6087                ]);
6088            }
6089        }
6090        getData() {
6091            return { name: this.name, value: this.getValue() };
6092        }
6093        destroy() {
6094            if ($$b().mselect2) {
6095                const sel = $$b(this.domElements.main).find(".mapsvg-select2");
6096                if (sel.length) {
6097                    sel.mselect2("destroy");
6098                }
6099            }
6100        }
6101        show() {
6102            $$b(this.domElements.main).show();
6103        }
6104        hide() {
6105            $$b(this.domElements.main).hide();
6106        }
6107        setExternal(params) {
6108            this.external = params;
6109            if (typeof this.external.mapIsGeo !== "undefined") {
6110                this.mapIsGeo = this.external.mapIsGeo;
6111            }
6112            if (typeof this.external.editMode !== "undefined") {
6113                this.editMode = this.external.editMode;
6114            }
6115            if (typeof this.external.filtersMode !== "undefined") {
6116                this.filtersMode = this.external.filtersMode;
6117            }
6118            if (typeof this.external.namespace !== "undefined") {
6119                this.namespace = this.external.namespace;
6120            }
6121        }
6122        getValue() {
6123            return this.value;
6124        }
6125        setValue(value, updateInput = true) {
6126            this.value = value;
6127            if (updateInput) {
6128                this.setInputValue(value);
6129            }
6130        }
6131        setInputValue(value) {
6132            return;
6133        }
6134        triggerChanged() {
6135            this.events.trigger("changed", this, [this]);
6136        }
6137    }
6138
6139    const $$c = jQuery;
6140    class CheckboxFormElement extends FormElement {
6141        constructor(options, formBuilder, external) {
6142            super(options, formBuilder, external);
6143            if (typeof options.showAsSwitch === "undefined") {
6144                this.showAsSwitch = true;
6145            }
6146            else {
6147                this.showAsSwitch = options.showAsSwitch;
6148            }
6149            this.db_type = "tinyint(1)";
6150            this.checkboxLabel = options.checkboxLabel;
6151            this.checkboxValue = options.checkboxValue;
6152        }
6153        setDomElements() {
6154            super.setDomElements();
6155            this.inputs.checkbox = $$c(this.domElements.main).find("input")[0];
6156            this.inputs.switch = $$c(this.domElements.main).find("input")[0];
6157        }
6158        setEventHandlers() {
6159            super.setEventHandlers();
6160            $$c(this.inputs.checkbox).on("change", (e) => {
6161                this.setValue(e.target.checked, false);
6162                this.triggerChanged();
6163            });
6164        }
6165        setEditorEventHandlers() {
6166            super.setEditorEventHandlers();
6167            $$c(this.domElements.edit).on("change", "[name='showAsSwitch']", (e) => {
6168                if (this.showAsSwitch) {
6169                    $$c(this.domElements.main)
6170                        .find("[name='checkboxToSwitch']")
6171                        .addClass("form-switch form-switch-md");
6172                }
6173                if (!this.showAsSwitch) {
6174                    $$c(this.domElements.main)
6175                        .find("[name='checkboxToSwitch']")
6176                        .removeClass("form-switch form-switch-md");
6177                }
6178            });
6179            $$c(this.domElements.edit).on("keyup change paste", '[name="checkboxLabel"]', 
6179(e) => {
6180                $$c(this.domElements.main).find(".form-check-label").text(e.target.value);
6181            });
6182        }
6183        getSchema() {
6184            const schema = super.getSchema();
6185            if (this.checkboxLabel) {
6186                schema.checkboxLabel = this.checkboxLabel;
6187            }
6188            if (this.checkboxValue) {
6189                schema.checkboxValue = this.checkboxValue;
6190            }
6191            schema.showAsSwitch = this.showAsSwitch;
6192            return schema;
6193        }
6194        setInputValue(value) {
6195            this.inputs.checkbox.checked = value === true;
6196        }
6197    }
6198
6199    const $$d = jQuery;
6200    class CheckboxesFormElement extends FormElement {
6201        constructor(options, formBuilder, external) {
6202            super(options, formBuilder, external);
6203            this.db_type = "text";
6204            this.checkboxLabel = options.checkboxLabel;
6205            this.setOptions(options.options);
6206        }
6207        setDomElements() {
6208            super.setDomElements();
6209            this.$checkboxes = $$d(this.domElements.main).find('input[type="checkbox"]');
6210            this.setInputValue(this.value || []);
6211        }
6212        setEventHandlers() {
6213            super.setEventHandlers();
6214            this.$checkboxes.on("change", (e) => {
6215                const values = [];
6216                $$d(this.domElements.main)
6217                    .find("input:checked")
6218                    .each((i, el) => {
6219                    values.push(jQuery(el).attr("value"));
6220                });
6221                this.setValue(values, false);
6222                this.triggerChanged();
6223            });
6224        }
6225        setInputValue(values) {
6226            if (values === null) {
6227                $$d(this.domElements.main).find(`input`).prop("checked", false);
6228            }
6229            else {
6230                values.forEach((value) => {
6231                    $$d(this.domElements.main).find(`input[value="${value}"]`).prop("checked", true);
6232                });
6233            }
6234        }
6235    }
6236
6237    const $$e = jQuery;
6238    class DateFormElement extends FormElement {
6239        constructor(options, formBuilder, external) {
6240            super(options, formBuilder, external);
6241            if (this.formBuilder.admin) {
6242                this.languages = [
6243                    "en-GB",
6244                    "ar",
6245                    "az",
6246                    "bg",
6247                    "bs",
6248                    "ca",
6249                    "cs",
6250                    "cy",
6251                    "da",
6252                    "de",
6253                    "el",
6254                    "es",
6255                    "et",
6256                    "eu",
6257                    "fa",
6258                    "fi",
6259                    "fo",
6260                    "fr",
6261                    "gl",
6262                    "he",
6263                    "hr",
6264                    "hu",
6265                    "hy",
6266                    "id",
6267                    "is",
6268                    "it",
6269                    "ja",
6270                    "ka",
6271                    "kh",
6272                    "kk",
6273                    "kr",
6274                    "lt",
6275                    "lv",
6276                    "mk",
6277                    "ms",
6278                    "nb",
6279                    "nl",
6280                    "nl-BE",
6281                    "no",
6282                    "pl",
6283                    "pt-BR",
6284                    "pt",
6285                    "ro",
6286                    "rs",
6287                    "rs-latin",
6288                    "ru",
6289                    "sk",
6290                    "sl",
6291                    "sq",
6292                    "sr",
6293                    "sr-latin",
6294                    "sv",
6295                    "sw",
6296                    "th",
6297                    "tr",
6298                    "uk",
6299                    "vi",
6300                    "zh-CN",
6301                    "zh-TW",
6302                ];
6303            }
6304            this.db_type = "varchar(50)";
6305            this.language = options.language;
6306        }
6307        setDomElements() {
6308            super.setDomElements();
6309            this.inputs.date = $$e(this.domElements.main).find("input")[0];
6310        }
6311        setEventHandlers() {
6312            super.setEventHandlers();
6313            $$e(this.inputs.date).on("change", (e) => {
6314                this.setValue(e.target.value, false);
6315                this.triggerChanged();
6316            });
6317        }
6318        getSchema() {
6319            const schema = super.getSchema();
6320            schema.language = this.language;
6321            return schema;
6322        }
6323        getDataForTemplate() {
6324            const data = super.getDataForTemplate();
6325            if (this.formBuilder.admin)
6326                data.languages = this.languages;
6327            data.language = this.language;
6328            return data;
6329        }
6330    }
6331
6332    const $$f = jQuery;
6333    class DistanceFormElement extends FormElement {
6334        constructor(options, formBuilder, external) {
6335            super(options, formBuilder, external);
6336            this.name = "distance";
6337            this.label = this.label || (options.label === undefined ? "Search radius" : options.label);
6338            this.distanceControl = options.distanceControl || "select";
6339            this.distanceUnits = options.distanceUnits || "km";
6340            this.distanceUnitsLabel = options.distanceUnitsLabel || "km";
6341            this.fromLabel = options.fromLabel || "from";
6342            this.placeholder = options.placeholder;
6343            this.userLocationButton = options.userLocationButton || false;
6344            this.type = options.type;
6345            this.addressField = options.addressField || true;
6346            this.addressFieldPlaceholder = options.addressFieldPlaceholder || "Address";
6347            this.languages = [
6348                { value: "sq", label: "Albanian" },
6349                { value: "ar", label: "Arabic" },
6350                {
6351                    value: "eu",
6352                    label: "Basque",
6353                },
6354                { value: "be", label: "Belarusian" },
6355                { value: "bg", label: "Bulgarian" },
6356                {
6357                    value: "my",
6358                    label: "Burmese",
6359                },
6360                { value: "bn", label: "Bengali" },
6361                { value: "ca", label: "Catalan" },
6362                {
6363                    value: "zh-cn",
6364                    label: "Chinese (simplified)",
6365                },
6366                { value: "zh-tw", label: "Chinese (traditional)" },
6367                {
6368                    value: "hr",
6369                    label: "Croatian",
6370                },
6371                { value: "cs", label: "Czech" },
6372                { value: "da", label: "Danish" },
6373                {
6374                    value: "nl",
6375                    label: "Dutch",
6376                },
6377                { value: "en", label: "English" },
6378                {
6379                    value: "en-au",
6380                    label: "English (australian)",
6381                },
6382                { value: "en-gb", label: "English (great Britain)" },
6383                {
6384                    value: "fa",
6385                    label: "Farsi",
6386                },
6387                { value: "fi", label: "Finnish" },
6388                { value: "fil", label: "Filipino" },
6389                {
6390                    value: "fr",
6391                    label: "French",
6392                },
6393                { value: "gl", label: "Galician" },
6394                { value: "de", label: "German" },
6395                {
6396                    value: "el",
6397                    label: "Greek",
6398                },
6399                { value: "gu", label: "Gujarati" },
6400                { value: "iw", label: "Hebrew" },
6401                {
6402                    value: "hi",
6403                    label: "Hindi",
6404                },
6405                { value: "hu", label: "Hungarian" },
6406                { value: "id", label: "Indonesian" },
6407                {
6408                    value: "it",
6409                    label: "Italian",
6410                },
6411                { value: "ja", label: "Japanese" },
6412                { value: "kn", label: "Kannada" },
6413                {
6414                    value: "kk",
6415                    label: "Kazakh",
6416                },
6417                { value: "ko", label: "Korean" },
6418                { value: "ky", label: "Kyrgyz" },
6419                {
6420                    value: "lt",
6421                    label: "Lithuanian",
6422                },
6423                { value: "lv", label: "Latvian" },
6424                { value: "mk", label: "Macedonian" },
6425                {
6426                    value: "ml",
6427                    label: "Malayalam",
6428                },
6429                { value: "mr", label: "Marathi" },
6430                { value: "no", label: "Norwegian" },
6431                {
6432                    value: "pl",
6433                    label: "Polish",
6434                },
6435                { value: "pt", label: "Portuguese" },
6436                {
6437                    value: "pt-br",
6438                    label: "Portuguese (brazil)",
6439                },
6440                { value: "pt-pt", label: "Portuguese (portugal)" },
6441                {
6442                    value: "pa",
6443                    label: "Punjabi",
6444                },
6445                { value: "ro", label: "Romanian" },
6446                { value: "ru", label: "Russian" },
6447                {
6448                    value: "sr",
6449                    label: "Serbian",
6450                },
6451                { value: "sk", label: "Slovak" },
6452                { value: "sl", label: "Slovenian" },
6453                {
6454                    value: "es",
6455                    label: "Spanish",
6456                },
6457                { value: "sv", label: "Swedish" },
6458                { value: "tl", label: "Tagalog" },
6459                {
6460                    value: "ta",
6461                    label: "Tamil",
6462                },
6463                { value: "te", label: "Telugu" },
6464                { value: "th", label: "Thai" },
6465                {
6466                    value: "tr",
6467                    label: "Turkish",
6468                },
6469                { value: "uk", label: "Ukrainian" },
6470                { value: "uz", label: "Uzbek" },
6471                {
6472                    value: "vi",
6473                    label: "Vietnamese",
6474                },
6475            ];
6476            this.countries = MapSVG.countries;
6477            this.country = options.country;
6478            this.language = options.language;
6479            this.searchByZip = options.searchByZip;
6480            this.zipLength = parseInt(options.zipLength) || 5;
6481            this.userLocationButton = MapSVG.parseBoolean(options.userLocationButton);
6482            this.options = options.options || [
6483                { value: "10", default: true },
6484                { value: "30", default: false },
6485                { value: "50", default: false },
6486                { value: "100", default: false },
6487            ];
6488            let defOption;
6489            if (this.value) {
6490                this.options.forEach((option) => {
6491                    if (option.value === this.value.length) {
6492                        defOption = option;
6493                    }
6494                });
6495            }
6496            if (!defOption) {
6497                defOption = this.options.find(function (option) {
6498                    return option.default === true;
6499                });
6500            }
6501            if (!defOption) {
6502                defOption = this.options[0];
6503            }
6504            const defLengthOption = this.options.find((opt) => opt.selected === true);
6505            this.defaultLength = defOption.value;
6506            this.setDefaultValue();
6507        }
6508        setDefaultValue() {
6509            this.value = {
6510                units: this.distanceUnits,
6511                geoPoint: { lat: null, lng: null },
6512                length: this.defaultLength,
6513                address: "",
6514                country: this.country,
6515            };
6516        }
6517        setDomElements() {
6518            super.setDomElements();
6519            this.inputs.units = ($$f(this.domElements.main).find('[name="distanceUnits"]')[0]);
6520            this.inputs.geoPoint = ($$f(this.domElements.main).find('[name="distanceGeoPoint"]')[0]);
6521            this.inputs.length = ($$f(this.domElements.main).find('[name="distanceLength"]')[0]);
6522            this.inputs.address = ($$f(this.domElements.main).find('[name="distance"]')[0]);
6523        }
6524        getSchema() {
6525            const schema = super.getSchema();
6526            schema.distanceControl = this.distanceControl;
6527            schema.distanceUnits = this.distanceUnits;
6528            schema.distanceUnitsLabel = this.distanceUnitsLabel;
6529            schema.fromLabel = this.fromLabel;
6530            schema.addressField = this.addressField;
6531            schema.addressFieldPlaceholder = this.addressFieldPlaceholder;
6532            schema.userLocationButton = this.userLocationButton;
6533            schema.placeholder = this.placeholder;
6534            schema.language = this.language;
6535            schema.country = this.country;
6536            schema.searchByZip = this.searchByZip;
6537            schema.zipLength = parseInt(this.zipLength + "");
6538            schema.userLocationButton = MapSVG.parseBoolean(this.userLocationButton);
6539            if (schema.distanceControl === "none") {
6540                schema.distanceDefault = schema.options.filter(function (o) {
6541                    return o.default;
6542                })[0].value;
6543            }
6544            schema.options.forEach(function (option, index) {
6545                if (schema.options[index].value === "") {
6546                    schema.options.splice(index, 1);
6547                }
6548                else {
6549                    schema.options[index].default = MapSVG.parseBoolean(schema.options[index].default);
6550                }
6551            });
6552            return schema;
6553        }
6554        getDataForTemplate() {
6555            const data = super.getDataForTemplate();
6556            if (this.formBuilder.admin) {
6557                data.languages = this.languages;
6558                data.countries = this.countries;
6559            }
6560            data.language = this.language;
6561            data.country = this.country;
6562            data.searchByZip = this.searchByZip;
6563            data.zipLength = this.zipLength;
6564            data.userLocationButton = MapSVG.parseBoolean(this.userLocationButton);
6565            return data;
6566        }
6567        destroy() {
6568            if ($$f().mselect2) {
6569                const sel = $$f(this.domElements.main).find(".mapsvg-select2");
6570                if (sel.length) {
6571                    sel.mselect2("destroy");
6572                }
6573            }
6574        }
6575        initEditor() {
6576            super.initEditor();
6577            this.mayBeAddDistanceRow();
6578            if ($$f().mselect2) {
6579                $$f(this.domElements.edit).find("select").mselect2();
6580            }
6581        }
6582        setEventHandlers() {
6583            super.setEventHandlers();
6584            const _this = this;
6585            $$f(this.domElements.edit).on("keyup change paste", ".mapsvg-edit-distance-row input", function () {
6586                _this.mayBeAddDistanceRow();
6587            });
6588            const server = new Server();
6589            const locations = new Bloodhound({
6590                datumTokenizer: Bloodhound.tokenizers.obj.whitespace("formatted_address"),
6591                queryTokenizer: Bloodhound.tokenizers.whitespace,
6592                remote: {
6593                    url: server.getUrl("geocoding") +
6594                        "?address=" +
6595                        (this.searchByZip === true ? "zip%20" : "") +
6596                        "%QUERY%&language=" +
6597                        this.language +
6598                        (this.country ? "&country=" + this.country : ""),
6599                    wildcard: "%QUERY%",
6600                    transform: function (response) {
6601                        if (response.error_message) {
6602                            alert(response.error_message);
6603                        }
6604                        return response.results;
6605                    },
6606                    rateLimitWait: 600,
6607                },
6608            });
6609            const thContainer = $$f(this.domElements.main).find(".typeahead");
6610            this.spinner = $$f("<span class='spinner-border spinner-border-sm'></span>")[0];
6611            if (this.searchByZip) {
6612                $$f(this.domElements.main).find(".mapsvg-distance-fields").addClass("search-by-zip");
6613                thContainer.on("change keyup", (e) => {
6614                    const zip = $$f(e.target).val().toString();
6615                    if (zip.length === _this.zipLength) {
6616                        $$f(this.spinner).appendTo($$f(e.target).closest(".distance-search-wrap"));
6617                        this.formBuilder.setIsLoading(true);
6618                        locations.search($$f(e.target).val(), (data) => this.handleAddressFieldChange(zip, data), (data) => this.handleAddressFieldChange(zip, data, true));
6619                    }
6620                });
6621            }
6622            else {
6623                const tH = thContainer
6624                    .typeahead({ minLength: 3 }, {
6625                    name: "mapsvg-addresses",
6626                    display: "formatted_address",
6627                    limit: 5,
6628                    async: true,
6629                    source: (query, sync, async) => {
6630                        const request = { address: query };
6631                        if (this.country) {
6632                            request.componentRestrictions = { country: this.country };
6633                        }
6634                        MapSVG.geocode(request, async);
6635                    },
6636                })
6637                    .on("typeahead:asyncrequest", (e) => {
6638                    $$f(this.spinner).appendTo($$f(e.target).closest(".twitter-typeahead"));
6639                    this.formBuilder.setIsLoading(true);
6640                })
6641                    .on("typeahead:asynccancel typeahead:asyncreceive", (e) => {
6642                    $$f(this.spinner).remove();
6643                    this.formBuilder.setIsLoading(false);
6644                });
6645                $$f(this.domElements.main).find(".mapsvg-distance-fields").removeClass("search-by-zip");
6646            }
6647            if (_this.userLocationButton) {
6648                const userLocationButton = $$f(this.domElements.main).find(".user-location-button");
6649                userLocationButton.on("click", () => {
6650                    _this.formBuilder.mapsvg.showUserLocation((location) => {
6651                        locations.search(location.geoPoint.lat + "," + location.geoPoint.lng, (data) => this.setAddressByUserLocation(data, location), (data) => this.setAddressByUserLocation(data, location));
6652                        this.setValue({ geoPoint: location.geoPoint });
6653                        this.triggerChanged();
6654                    });
6655                });
6656            }
6657            thContainer.on("change keyup", (e) => {
6658                const input = e.target;
6659                if (input.value === "" && this.getValue() !== null) {
6660                    this.setValue(null);
6661                    this.triggerChanged();
6662                }
6663            });
6664            thContainer.on("typeahead:select", (ev, item) => {
6665                this.setValue({
6666                    address: item.formatted_address,
6667                    geoPoint: item.geometry.location.toJSON(),
6668                });
6669                this.triggerChanged();
6670                thContainer.blur();
6671            });
6672            $$f(this.inputs.geoPoint).on("change", (e) => {
6673                const geoPoint = e.target.value.split(",").map((value) => parseFloat(value));
6674                this.setValue({ geoPoint: { lat: geoPoint[0], lng: geoPoint[1] } }, false);
6675                this.triggerChanged();
6676            });
6677            $$f(this.inputs.length).on("change", (e) => {
6678                this.setLength(parseInt(e.target.value), false);
6679                this.triggerChanged();
6680            });
6681        }
6682        setAddressByUserLocation(data, location) {
6683            if (data && data[0]) {
6684                this.setAddress(data[0].formatted_address);
6685            }
6686            else {
6687                this.setAddress(location.geoPoint.lat + "," + location.geoPoint.lng);
6688            }
6689        }
6690        handleAddressFieldChange(zip, data, removeSpinner = false) {
6691            if (removeSpinner) {
6692                $$f(this.spinner).remove();
6693                this.formBuilder.setIsLoading(false);
6694            }
6695            if (data && data[0]) {
6696                this.setValue({ address: zip, geoPoint: data[0].geometry.location }, false);
6697                this.triggerChanged();
6698            }
6699        }
6700        addSelect2() {
6701            if ($$f().mselect2) {
6702                $$f(this.domElements.main)
6703                    .find("select")
6704                    .mselect2()
6705                    .on("select2:focus", function () {
6706                    $$f(this).mselect2("open");
6707                });
6708            }
6709        }
6710        mayBeAddDistanceRow() {
6711            const _this = this;
6712            const editDistanceRow = $$f($$f("#mapsvg-edit-distance-row").html());
6713            const z = $$f(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child input");
6714            if (z && z.last() && z.last().val() && z.last().val().toString().trim().length) {
6715                const newRow = editDistanceRow.clone();
6716                newRow.insertAfter($$f(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child"));
6717            }
6718            const rows = $$f(_this.domElements.edit).find(".mapsvg-edit-distance-row");
6719            const row1 = rows.eq(rows.length - 2);
6720            const row2 = rows.eq(rows.length - 1);
6721            if (row1.length &&
6722                row2.length &&
6723                !row1.find("input:eq(0)").val().toString().trim() &&
6724                !row2.find("input:eq(0)").val().toString().trim()) {
6725                row2.remove();
6726            }
6727        }
6728        setValue(value, updateInput = true) {
6729            if (value === null) {
6730                this.setGeoPoint(null);
6731                this.setAddress("");
6732            }
6733            else {
6734                for (const key in value) {
6735                    if (typeof this.value[key] !== undefined) {
6736                        const method = "set" + MapSVG.ucfirst(key);
6737                        if (typeof this[method] === "function") {
6738                            this[method](value[key], updateInput);
6739                        }
6740                    }
6741                }
6742            }
6743        }
6744        setGeoPoint(geoPoint, updateInput = true) {
6745            this.value.geoPoint = geoPoint === null ? { lat: null, lng: null } : geoPoint;
6746            if (updateInput) {
6747                this.setInputGeoPointValue(geoPoint);
6748            }
6749        }
6750        setInputGeoPointValue(geoPoint) {
6751            this.inputs.geoPoint.value = geoPoint ? geoPoint.lat + "," + geoPoint.lng : "";
6752        }
6753        setLength(length, updateInput = true) {
6754            this.value.length = parseInt(length.toString());
6755            this.defaultLength = this.value.length;
6756            if (updateInput) {
6757                this.setInputLengthValue(this.value.length);
6758            }
6759        }
6760        setInputLengthValue(length) {
6761            this.inputs.length.value = length.toString();
6762        }
6763        setAddress(address, updateInput = true) {
6764            this.value.address = address !== null ? address : "";
6765            if (updateInput) {
6766                this.setInputAddressValue(this.value.address);
6767            }
6768        }
6769        setInputAddressValue(address) {
6770            this.inputs.address.value = address;
6771        }
6772        getValue() {
6773            return this.value.geoPoint.lat === null ? null : this.value;
6774        }
6775    }
6776
6777    const $$g = jQuery;
6778    class EmptyFormElement extends FormElement {
6779        constructor(options, formBuilder, external) {
6780            super(options, formBuilder, external);
6781            this.readonly = true;
6782        }
6783    }
6784
6785    class IdFormElement extends FormElement {
6786        constructor(options, formBuilder, external) {
6787            super(options, formBuilder, external);
6788        }
6789        getData() {
6790            return { name: "id", value: this.value };
6791        }
6792    }
6793
6794    function createCommonjsModule(fn, module) {
6795    	return module = { exports: {} }, fn(module, module.exports), module.exports;
6796    }
6797
6798    var sortable_min = createCommonjsModule(function (module) {
6799    /**!
6800     * Sortable
6801     * @author	RubaXa   <[email protected]>
6802     * @license MIT
6803     */
6804
6805    (function sortableModule(factory) {
6806
6807        {
6808            module.exports = factory();
6809        }
6810    })(function sortableFactory() {
6811
6812        if (typeof window == "undefined" || !window.document) {
6813            return function sortableError() {
6814                throw new Error("Sortable.js requires a window with a document");
6815            };
6816        }
6817
6818        var dragEl,
6819            parentEl,
6820            ghostEl,
6821            cloneEl,
6822            rootEl,
6823            nextEl,
6824            scrollEl,
6825            scrollParentEl,
6826            scrollCustomFn,
6827            lastEl,
6828            lastCSS,
6829            lastParentCSS,
6830            oldIndex,
6831            n
6831ewIndex,
6832            activeGroup,
6833            putSortable,
6834            autoScroll = {},
6835            tapEvt,
6836            touchEvt,
6837            moved,
6838            /** @const */
6839            RSPACE = /\s+/g,
6840            expando = "Sortable" + new Date().getTime(),
6841            win = window,
6842            document = win.document,
6843            parseInt = win.parseInt,
6844            $ = win.jQuery || win.Zepto,
6845            Polymer = win.Polymer,
6846            supportDraggable = !!("draggable" in document.createElement("div")),
6847            supportCssPointerEvents = (function (el) {
6848                // false when IE11
6849                if (navigator.userAgent.match(/Trident.*rv[ :]?11\./)) {
6850                    return false;
6851                }
6852                el = document.createElement("x");
6853                el.style.cssText = "pointer-events:auto";
6854                return el.style.pointerEvents === "auto";
6855            })(),
6856            _silent = false,
6857            abs = Math.abs,
6858            min = Math.min,
6859            touchDragOverListeners = [],
6860            _autoScroll = _throttle(function (
6861                /**Event*/ evt,
6862                /**Object*/ options,
6863                /**HTMLElement*/ rootEl
6864            ) {
6865                // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
6866                if (rootEl && options.scroll) {
6867                    var el,
6868                        rect,
6869                        sens = options.scrollSensitivity,
6870                        speed = options.scrollSpeed,
6871                        x = evt.clientX,
6872                        y = evt.clientY,
6873                        winWidth = window.innerWidth,
6874                        winHeight = window.innerHeight,
6875                        vx,
6876                        vy,
6877                        scrollOffsetX,
6878                        scrollOffsetY;
6879
6880                    // Delect scrollEl
6881                    if (scrollParentEl !== rootEl) {
6882                        scrollEl = options.scroll;
6883                        scrollParentEl = rootEl;
6884                        scrollCustomFn = options.scrollFn;
6885
6886                        if (scrollEl === true) {
6887                            scrollEl = rootEl;
6888
6889                            do {
6890                                if (
6891                                    scrollEl.offsetWidth < scrollEl.scrollWidth ||
6892                                    scrollEl.offsetHeight < scrollEl.scrollHeight
6893                                ) {
6894                                    break;
6895                                }
6896                                /* jshint boss:true */
6897                            } while ((scrollEl = scrollEl.parentNode));
6898                        }
6899                    }
6900
6901                    if (scrollEl) {
6902                        el = scrollEl;
6903                        rect = scrollEl.getBoundingClientRect();
6904                        vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
6905                        vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
6906                    }
6907
6908                    if (!(vx || vy)) {
6909                        vx = (winWidth - x <= sens) - (x <= sens);
6910                        vy = (winHeight - y <= sens) - (y <= sens);
6911
6912                        /* jshint expr:true */
6913                        (vx || vy) && (el = win);
6914                    }
6915
6916                    if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
6917                        autoScroll.el = el;
6918                        autoScroll.vx = vx;
6919                        autoScroll.vy = vy;
6920
6921                        clearInterval(autoScroll.pid);
6922
6923                        if (el) {
6924                            autoScroll.pid = setInterval(function () {
6925                                scrollOffsetY = vy ? vy * speed : 0;
6926                                scrollOffsetX = vx ? vx * speed : 0;
6927
6928                                if ("function" === typeof scrollCustomFn) {
6929                                    return scrollCustomFn.call(
6930                                        _this,
6931                                        scrollOffsetX,
6932                                        scrollOffsetY,
6933                                        evt
6934                                    );
6935                                }
6936
6937                                if (el === win) {
6938                                    win.scrollTo(
6939                                        win.pageXOffset + scrollOffsetX,
6940                                        win.pageYOffset + scrollOffsetY
6941                                    );
6942                                } else {
6943                                    el.scrollTop += scrollOffsetY;
6944                                    el.scrollLeft += scrollOffsetX;
6945                                }
6946                            }, 24);
6947                        }
6948                    }
6949                }
6950            },
6951            30),
6952            _prepareGroup = function (options) {
6953                function toFn(value, pull) {
6954                    if (value === void 0 || value === true) {
6955                        value = group.name;
6956                    }
6957
6958                    if (typeof value === "function") {
6959                        return value;
6960                    } else {
6961                        return function (to, from) {
6962                            var fromGroup = from.options.group.name;
6963
6964                            return pull
6965                                ? value
6966                                : value &&
6967                                      (value.join ? value.indexOf(fromGroup) > -1 : fromGroup == value);
6968                        };
6969                    }
6970                }
6971
6972                var group = {};
6973                var originalGroup = options.group;
6974
6975                if (!originalGroup || typeof originalGroup != "object") {
6976                    originalGroup = { name: originalGroup };
6977                }
6978
6979                group.name = originalGroup.name;
6980                group.checkPull = toFn(originalGroup.pull, true);
6981                group.checkPut = toFn(originalGroup.put);
6982
6983                options.group = group;
6984            };
6985        /**
6986         * @class  Sortable
6987         * @param  {HTMLElement}  el
6988         * @param  {Object}       [options]
6989         */
6990        function Sortable(el, options) {
6991            if (!(el && el.nodeType && el.nodeType === 1)) {
6992                throw "Sortable: `el` must be HTMLElement, and not " + {}.toString.call(el);
6993            }
6994
6995            this.el = el; // root element
6996            this.options = options = _extend({}, options);
6997
6998            // Export instance
6999            el[expando] = this;
7000
7001            // Default options
7002            var defaults = {
7003                group: Math.random(),
7004                sort: true,
7005                disabled: false,
7006                store: null,
7007                handle: null,
7008                scroll: true,
7009                scrollSensitivity: 30,
7010                scrollSpeed: 10,
7011                draggable: /[uo]l/i.test(el.nodeName) ? "li" : ">*",
7012                ghostClass: "sortable-ghost",
7013                chosenClass: "sortable-chosen",
7014                dragClass: "sortable-drag",
7015                ignore: "a, img",
7016                filter: null,
7017                animation: 0,
7018                setData: function (dataTransfer, dragEl) {
7019                    dataTransfer.setData("Text", dragEl.textContent);
7020                },
7021                dropBubble: false,
7022                dragoverBubble: false,
7023                dataIdAttr: "data-id",
7024                delay: 0,
7025                forceFallback: false,
7026                fallbackClass: "sortable-fallback",
7027                fallbackOnBody: false,
7028                fallbackTolerance: 0,
7029                fallbackOffset: { x: 0, y: 0 },
7030            };
7031
7032            // Set default options
7033            for (var name in defaults) {
7034                !(name in options) && (options[name] = defaults[name]);
7035            }
7036
7037            _prepareGroup(options);
7038
7039            // Bind all private methods
7040            for (var fn in this) {
7041                if (fn.charAt(0) === "_" && typeof this[fn] === "function") {
7042                    this[fn] = this[fn].bind(this);
7043                }
7044            }
7045
7046            // Setup drag mode
7047            this.nativeDraggable = options.forceFallback ? false : supportDraggable;
7048
7049            // Bind events
7050            _on(el, "mousedown", this._onTapStart);
7051            _on(el, "touchstart", this._onTapStart);
7052
7053            if (this.nativeDraggable) {
7054                _on(el, "dragover", this);
7055                _on(el, "dragenter", this);
7056            }
7057
7058            touchDragOverListeners.push(this._onDragOver);
7059
7060            // Restore sorting
7061            options.store && this.sort(options.store.get(this));
7062        }
7063
7064        Sortable.prototype = /** @lends Sortable.prototype */ {
7065            constructor: Sortable,
7066
7067            _onTapStart: function (/** Event|TouchEvent */ evt) {
7068                if (evt.target.tagName == "i" || evt.target.tagName == "I") {
7069                    evt.target.click();
7070                    return;
7071                }
7072                var _this = this,
7073                    el = this.el,
7074                    options = this.options,
7075                    type = evt.type,
7076                    touch = evt.touches && evt.touches[0],
7077                    target = (touch || evt).target,
7078                    originalTarget = (evt.target.shadowRoot && evt.path[0]) || target,
7079                    filter = options.filter,
7080                    startIndex;
7081
7082                // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
7083                if (dragEl) {
7084                    return;
7085                }
7086
7087                if ((type === "mousedown" && evt.button !== 0) || options.disabled) {
7088                    return; // only left button or enabled
7089                }
7090
7091                if (options.handle && !_closest(originalTarget, options.handle, el)) {
7092                    return;
7093                }
7094
7095                target = _closest(target, options.draggable, el);
7096
7097                if (!target) {
7098                    return;
7099                }
7100
7101                // Get the index of the dragged element within its parent
7102                startIndex = _index(target, options.draggable);
7103
7104                // Check filter
7105                if (typeof filter === "function") {
7106                    if (filter.call(this, evt, target, this)) {
7107                        _dispatchEvent(_this, originalTarget, "filter", target, el, startIndex);
7108                        evt.preventDefault();
7109                        return; // cancel dnd
7110                    }
7111                } else if (filter) {
7112                    filter = filter.split(",").some(function (criteria) {
7113                        criteria = _closest(originalTarget, criteria.trim(), el);
7114
7115                        if (criteria) {
7116                            _dispatchEvent(_this, criteria, "filter", target, el, startIndex);
7117                            return true;
7118                        }
7119                    });
7120
7121                    if (filter) {
7122                        evt.preventDefault();
7123                        return; // cancel dnd
7124                    }
7125                }
7126
7127                // Prepare `dragstart`
7128                this._prepareDragStart(evt, touch, target, startIndex);
7129            },
7130
7131            _prepareDragStart: function (
7132                /** Event */ evt,
7133                /** Touch */ touch,
7134                /** HTMLElement */ target,
7135                /** Number */ startIndex
7136            ) {
7137                var _this = this,
7138                    el = _this.el,
7139                    options = _this.options,
7140                    ownerDocument = el.ownerDocument,
7141                    dragStartFn;
7142
7143                if (target && !dragEl && target.parentNode === el) {
7144                    tapEvt = evt;
7145
7146                    rootEl = el;
7147                    dragEl = target;
7148                    parentEl = dragEl.parentNode;
7149                    nextEl = dragEl.nextSibling;
7150                    activeGroup = options.group;
7151                    oldIndex = startIndex;
7152
7153                    this._lastX = (touch || evt).clientX;
7154                    this._lastY = (touch || evt).clientY;
7155
7156                    dragEl.style["will-change"] = "transform";
7157
7158                    dragStartFn = function () {
7159                        // Delayed drag has been triggered
7160                        // we can re-enable the events: touchmove/mousemove
7161                        _this._disableDelayedDrag();
7162
7163                        // Make the element draggable
7164                        dragEl.draggable = _this.nativeDraggable;
7165
7166                        // Chosen item
7167                        _toggleClass(dragEl, options.chosenClass, true);
7168
7169                        // Bind the events: dragstart/dragend
7170                        _this._triggerDragStart(touch);
7171
7172                        // Drag start event
7173                        _dispatchEvent(_this, rootEl, "choose", dragEl, rootEl, oldIndex);
7174                    };
7175
7176                    // Disable "draggable"
7177                    options.ignore.split(",").forEach(function (criteria) {
7178                        _find(dragEl, criteria.trim(), _disableDraggable);
7179                    });
7180
7181                    _on(ownerDocument, "mouseup", _this._onDrop);
7182                    _on(ownerDocument, "touchend", _this._onDrop);
7183                    _on(ownerDocument, "touchcancel", _this._onDrop);
7184
7185                    if (options.delay) {
7186                        // If the user moves the pointer or let go the click or touch
7187                        // before the delay has been reached:
7188                        // disable the delayed drag
7189                        _on(ownerDocument, "mouseup", _this._disableDelayedDrag);
7190                        _on(ownerDocument, "touchend", _this._disableDelayedDrag);
7191                        _on(ownerDocument, "touchcancel", _this._disableDelayedDrag);
7192                        _on(ownerDocument, "mousemove", _this._disableDelayedDrag);
7193                        _on(ownerDocument, "touchmove", _this._disableDelayedDrag);
7194
7195                        _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
7196                    } else {
7197                        dragStartFn();
7198                    }
7199                }
7200            },
7201
7202            _disableDelayedDrag: function () {
7203                var ownerDocument = this.el.ownerDocument;
7204
7205                clearTimeout(this._dragStartTimer);
7206                _off(ownerDocument, "mouseup", this._disableDelayedDrag);
7207                _off(ownerDocument, "touchend", this._disableDelayedDrag);
7208                _off(ownerDocument, "touchcancel", this._disableDelayedDrag);
7209                _off(ownerDocument, "mousemove", this._disableDelayedDrag);
7210                _off(ownerDocument, "touchmove", this._disableDelayedDrag);
7211            },
7212
7213            _triggerDragStart: function (/** Touch */ touch) {
7214                if (touch) {
7215                    // Touch device support
7216                    tapEvt = {
7217                        target: dragEl,
7218                        clientX: touch.clientX,
7219                        clientY: touch.clientY,
7220                    };
7221
7222                    this._onDragStart(tapEvt, "touch");
7223                } else if (!this.nativeDraggable) {
7224                    this._onDragStart(tapEvt, true);
7225                } else {
7226                    _on(dragEl, "dragend", this);
7227                    _on(rootEl, "dragstart", this._onDragStart);
7228                }
7229
7230                try {
7231                    if (document.selection) {
7232                        // Timeout neccessary for IE9
7233                        setTimeout(function () {
7234                            document.selection.empty();
7235                        });
7236                    } else {
7237                        window.getSelection().removeAllRanges();
7238                    }
7239                } catch (err) {}
7240            },
7241
7242            _dragStarted: function () {
7243                if (rootEl && dragEl) {
7244                    var options = this.options;
7245
7246                    // Apply effect
7247                    _toggleClass(dragEl, options.ghostClass, true);
7248                    _toggleClass(dragEl, options.dragClass, false);
7249
7250                    Sortable.active = this;
7251
7252                    // Drag start event
7253                    _dispatchEvent(this, rootEl, "start", dragEl, rootEl, oldIndex);
7254                }
7255            },
7256
7257            _emulateDragOver: function () {
7258                if (touchEvt) {
7259                    if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
7260                        return;
7261                    }
7262
7263                    this._lastX = touchEvt.clientX;
7264                    this._lastY = touchEvt.clientY;
7265
7266                    if (!supportCssPointerEvents) {
7267                        _css(ghostEl, "display", "none");
7268                    }
7269
7270                    var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
7271                        parent = target,
7272                        i = touchDragOverListeners.length;
7273
7274                    if (parent) {
7275                        do {
7276                            if (parent[expando]) {
7277                                while (i--) {
7278                                    touchDragOverListeners[i]({
7279                                        clientX: touchEvt.clientX,
7280                                        clientY: touchEvt.clientY,
7281                                        target: target,
7282                                        rootEl: parent,
7283                                    });
7284                                }
7285
7286                                break;
7287                            }
7288
7289                            target = parent; // store last element
7290                        } while (
7291                            /* jshint boss:true */
7292                            (parent = parent.parentNode)
7293                        );
7294                    }
7295
7296                    if (!supportCssPointerEvents) {
7297                        _css(ghostEl, "display", "");
7298                    }
7299                }
7300            },
7301
7302            _onTouchMove: function (/**TouchEvent*/ evt) {
7303                if (tapEvt) {
7304                    var options = this.options,
7305                        fallbackTolerance = options.fallbackTolerance,
7306                        fallbackOffset = options.fallbackOffset,
7307                        touch = evt.touches ? evt.touches[0] : evt,
7308                        dx = touch.clientX - tapEvt.clientX + fallbackOffset.x,
7309                        dy = touch.clientY - tapEvt.clientY + fallbackOffset.
7309y,
7310                        translate3d = evt.touches
7311                            ? "translate3d(" + dx + "px," + dy + "px,0)"
7312                            : "translate(" + dx + "px," + dy + "px)";
7313
7314                    // only set the status to dragging, when we are actually dragging
7315                    if (!Sortable.active) {
7316                        if (
7317                            fallbackTolerance &&
7318                            min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) <
7319                                fallbackTolerance
7320                        ) {
7321                            return;
7322                        }
7323
7324                        this._dragStarted();
7325                    }
7326
7327                    // as well as creating the ghost element on the document body
7328                    this._appendGhost();
7329
7330                    moved = true;
7331                    touchEvt = touch;
7332
7333                    _css(ghostEl, "webkitTransform", translate3d);
7334                    _css(ghostEl, "mozTransform", translate3d);
7335                    _css(ghostEl, "msTransform", translate3d);
7336                    _css(ghostEl, "transform", translate3d);
7337
7338                    evt.preventDefault();
7339                }
7340            },
7341
7342            _appendGhost: function () {
7343                if (!ghostEl) {
7344                    var rect = dragEl.getBoundingClientRect(),
7345                        css = _css(dragEl),
7346                        options = this.options,
7347                        ghostRect;
7348
7349                    ghostEl = dragEl.cloneNode(true);
7350
7351                    _toggleClass(ghostEl, options.ghostClass, false);
7352                    _toggleClass(ghostEl, options.fallbackClass, true);
7353                    _toggleClass(ghostEl, options.dragClass, true);
7354
7355                    _css(ghostEl, "top", rect.top - parseInt(css.marginTop, 10));
7356                    _css(ghostEl, "left", rect.left - parseInt(css.marginLeft, 10));
7357                    _css(ghostEl, "width", rect.width);
7358                    _css(ghostEl, "height", rect.height);
7359                    _css(ghostEl, "opacity", "0.8");
7360                    _css(ghostEl, "position", "fixed");
7361                    _css(ghostEl, "zIndex", "100000");
7362                    _css(ghostEl, "pointerEvents", "none");
7363
7364                    (options.fallbackOnBody && document.body.appendChild(ghostEl)) ||
7365                        rootEl.appendChild(ghostEl);
7366
7367                    // Fixing dimensions.
7368                    ghostRect = ghostEl.getBoundingClientRect();
7369                    _css(ghostEl, "width", rect.width * 2 - ghostRect.width);
7370                    _css(ghostEl, "height", rect.height * 2 - ghostRect.height);
7371                }
7372            },
7373
7374            _onDragStart: function (/**Event*/ evt, /**boolean*/ useFallback) {
7375                var dataTransfer = evt.dataTransfer,
7376                    options = this.options;
7377
7378                this._offUpEvents();
7379
7380                if (activeGroup.checkPull(this, this, dragEl, evt) == "clone") {
7381                    cloneEl = _clone(dragEl);
7382                    _css(cloneEl, "display", "none");
7383                    rootEl.insertBefore(cloneEl, dragEl);
7384                    _dispatchEvent(this, rootEl, "clone", dragEl);
7385                }
7386
7387                _toggleClass(dragEl, options.dragClass, true);
7388
7389                if (useFallback) {
7390                    if (useFallback === "touch") {
7391                        // Bind touch events
7392                        _on(document, "touchmove", this._onTouchMove);
7393                        _on(document, "touchend", this._onDrop);
7394                        _on(document, "touchcancel", this._onDrop);
7395                    } else {
7396                        // Old brwoser
7397                        _on(document, "mousemove", this._onTouchMove);
7398                        _on(document, "mouseup", this._onDrop);
7399                    }
7400
7401                    this._loopId = setInterval(this._emulateDragOver, 50);
7402                } else {
7403                    if (dataTransfer) {
7404                        dataTransfer.effectAllowed = "move";
7405                        options.setData && options.setData.call(this, dataTransfer, dragEl);
7406                    }
7407
7408                    _on(document, "drop", this);
7409                    setTimeout(this._dragStarted, 0);
7410                }
7411            },
7412
7413            _onDragOver: function (/**Event*/ evt) {
7414                var el = this.el,
7415                    target,
7416                    dragRect,
7417                    targetRect,
7418                    revert,
7419                    options = this.options,
7420                    group = options.group,
7421                    activeSortable = Sortable.active,
7422                    isOwner = activeGroup === group,
7423                    canSort = options.sort;
7424
7425                if (evt.preventDefault !== void 0) {
7426                    evt.preventDefault();
7427                    !options.dragoverBubble && evt.stopPropagation();
7428                }
7429
7430                moved = true;
7431
7432                if (
7433                    activeGroup &&
7434                    !options.disabled &&
7435                    (isOwner
7436                        ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
7437                        : putSortable === this ||
7438                          (activeGroup.checkPull(this, activeSortable, dragEl, evt) &&
7439                              group.checkPut(this, activeSortable, dragEl, evt))) &&
7440                    (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
7441                ) {
7442                    // Smart auto-scrolling
7443                    _autoScroll(evt, options, this.el);
7444
7445                    if (_silent) {
7446                        return;
7447                    }
7448
7449                    target = _closest(evt.target, options.draggable, el);
7450                    dragRect = dragEl.getBoundingClientRect();
7451                    putSortable = this;
7452
7453                    if (revert) {
7454                        _cloneHide(true);
7455                        parentEl = rootEl; // actualization
7456
7457                        if (cloneEl || nextEl) {
7458                            rootEl.insertBefore(dragEl, cloneEl || nextEl);
7459                        } else if (!canSort) {
7460                            rootEl.appendChild(dragEl);
7461                        }
7462
7463                        return;
7464                    }
7465
7466                    if (
7467                        el.children.length === 0 ||
7468                        el.children[0] === ghostEl ||
7469                        (el === evt.target && (target = _ghostIsLast(el, evt)))
7470                    ) {
7471                        if (target) {
7472                            if (target.animated) {
7473                                return;
7474                            }
7475
7476                            targetRect = target.getBoundingClientRect();
7477                        }
7478
7479                        _cloneHide(isOwner);
7480
7481                        if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
7482                            if (!dragEl.contains(el)) {
7483                                el.appendChild(dragEl);
7484                                parentEl = el; // actualization
7485                            }
7486
7487                            this._animate(dragRect, dragEl);
7488                            target && this._animate(targetRect, target);
7489                        }
7490                    } else if (
7491                        target &&
7492                        !target.animated &&
7493                        target !== dragEl &&
7494                        target.parentNode[expando] !== void 0
7495                    ) {
7496                        if (lastEl !== target) {
7497                            lastEl = target;
7498                            lastCSS = _css(target);
7499                            lastParentCSS = _css(target.parentNode);
7500                        }
7501
7502                        targetRect = target.getBoundingClientRect();
7503
7504                        var width = targetRect.right - targetRect.left,
7505                            height = targetRect.bottom - targetRect.top,
7506                            floating =
7507                                /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display) ||
7508                                (lastParentCSS.display == "flex" &&
7509                                    lastParentCSS["flex-direction"].indexOf("row") === 0),
7510                            isWide = target.offsetWidth > dragEl.offsetWidth,
7511                            isLong = target.offsetHeight > dragEl.offsetHeight,
7512                            halfway =
7513                                (floating
7514                                    ? (evt.clientX - targetRect.left) / width
7515                                    : (evt.clientY - targetRect.top) / height) > 0.5,
7516                            nextSibling = target.nextElementSibling,
7517                            moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt),
7518                            after;
7519
7520                        if (moveVector !== false) {
7521                            _silent = true;
7522                            setTimeout(_unsilent, 30);
7523
7524                            _cloneHide(isOwner);
7525
7526                            if (moveVector === 1 || moveVector === -1) {
7527                                after = moveVector === 1;
7528                            } else if (floating) {
7529                                var elTop = dragEl.offsetTop,
7530                                    tgTop = target.offsetTop;
7531
7532                                if (elTop === tgTop) {
7533                                    after =
7534                                        (target.previousElementSibling === dragEl && !isWide) ||
7535                                        (halfway && isWide);
7536                                } else if (
7537                                    target.previousElementSibling === dragEl ||
7538                                    dragEl.previousElementSibling === target
7539                                ) {
7540                                    after = (evt.clientY - targetRect.top) / height > 0.5;
7541                                } else {
7542                                    after = tgTop > elTop;
7543                                }
7544                            } else {
7545                                after = (nextSibling !== dragEl && !isLong) || (halfway && isLong);
7546                            }
7547
7548                            if (!dragEl.contains(el)) {
7549                                if (after && !nextSibling) {
7550                                    el.appendChild(dragEl);
7551                                } else {
7552                                    target.parentNode.insertBefore(
7553                                        dragEl,
7554                                        after ? nextSibling : target
7555                                    );
7556                                }
7557                            }
7558
7559                            parentEl = dragEl.parentNode; // actualization
7560
7561                            this._animate(dragRect, dragEl);
7562                            this._animate(targetRect, target);
7563                        }
7564                    }
7565                }
7566            },
7567
7568            _animate: function (prevRect, target) {
7569                var ms = this.options.animation;
7570
7571                if (ms) {
7572                    var currentRect = target.getBoundingClientRect();
7573
7574                    _css(target, "transition", "none");
7575                    _css(
7576                        target,
7577                        "transform",
7578                        "translate3d(" +
7579                            (prevRect.left - currentRect.left) +
7580                            "px," +
7581                            (prevRect.top - currentRect.top) +
7582                            "px,0)"
7583                    );
7584
7585                    target.offsetWidth; // repaint
7586
7587                    _css(target, "transition", "all " + ms + "ms");
7588                    _css(target, "transform", "translate3d(0,0,0)");
7589
7590                    clearTimeout(target.animated);
7591                    target.animated = setTimeout(function () {
7592                        _css(target, "transition", "");
7593                        _css(target, "transform", "");
7594                        target.animated = false;
7595                    }, ms);
7596                }
7597            },
7598
7599            _offUpEvents: function () {
7600                var ownerDocument = this.el.ownerDocument;
7601
7602                _off(document, "touchmove", this._onTouchMove);
7603                _off(ownerDocument, "mouseup", this._onDrop);
7604                _off(ownerDocument, "touchend", this._onDrop);
7605                _off(ownerDocument, "touchcancel", this._onDrop);
7606            },
7607
7608            _onDrop: function (/**Event*/ evt) {
7609                var el = this.el,
7610                    options = this.options;
7611
7612                clearInterval(this._loopId);
7613                clearInterval(autoScroll.pid);
7614                clearTimeout(this._dragStartTimer);
7615
7616                // Unbind events
7617                _off(document, "mousemove", this._onTouchMove);
7618
7619                if (this.nativeDraggable) {
7620                    _off(document, "drop", this);
7621                    _off(el, "dragstart", this._onDragStart);
7622                }
7623
7624                this._offUpEvents();
7625
7626                if (evt) {
7627                    if (moved) {
7628                        evt.preventDefault();
7629                        !options.dropBubble && evt.stopPropagation();
7630                    }
7631
7632                    ghostEl && ghostEl.parentNode.removeChild(ghostEl);
7633
7634                    if (dragEl) {
7635                        if (this.nativeDraggable) {
7636                            _off(dragEl, "dragend", this);
7637                        }
7638
7639                        _disableDraggable(dragEl);
7640                        dragEl.style["will-change"] = "";
7641
7642                        // Remove class's
7643                        _toggleClass(dragEl, this.options.ghostClass, false);
7644                        _toggleClass(dragEl, this.options.chosenClass, false);
7645
7646                        if (rootEl !== parentEl) {
7647                            newIndex = _index(dragEl, options.draggable);
7648
7649                            if (newIndex >= 0) {
7650                                // Add event
7651                                _dispatchEvent(
7652                                    null,
7653                                    parentEl,
7654                                    "add",
7655                                    dragEl,
7656                                    rootEl,
7657                                    oldIndex,
7658                                    newIndex
7659                                );
7660
7661                                // Remove event
7662                                _dispatchEvent(
7663                                    this,
7664                                    rootEl,
7665                                    "remove",
7666                                    dragEl,
7667                                    rootEl,
7668                                    oldIndex,
7669                                    newIndex
7670                                );
7671
7672                                // drag from one list and drop into another
7673                                _dispatchEvent(
7674                                    null,
7675                                    parentEl,
7676                                    "sort",
7677                                    dragEl,
7678                                    rootEl,
7679                                    oldIndex,
7680                                    newIndex
7681                                );
7682                                _dispatchEvent(
7683                                    this,
7684                                    rootEl,
7685                                    "sort",
7686                                    dragEl,
7687                                    rootEl,
7688                                    oldIndex,
7689                                    newIndex
7690                                );
7691                            }
7692                        } else {
7693                            // Remove clone
7694                            cloneEl && cloneEl.parentNode.removeChild(cloneEl);
7695
7696                            if (dragEl.nextSibling !== nextEl) {
7697                                // Get the index of the dragged element within its parent
7698                                newIndex = _index(dragEl, options.draggable);
7699
7700                                if (newIndex >= 0) {
7701                                    // drag & drop within the same list
7702                                    _dispatchEvent(
7703                                        this,
7704                                        rootEl,
7705                                        "update",
7706                                        dragEl,
7707                                        rootEl,
7708                                        oldIndex,
7709                                        newIndex
7710                                    );
7711                                    _dispatchEvent(
7712                                        this,
7713                                        rootEl,
7714                                        "sort",
7715                                        dragEl,
7716                                        rootEl,
7717                                        oldIndex,
7718                                        newIndex
7719                                    );
7720                                }
7721                            }
7722                        }
7723
7724                        if (Sortable.active) {
7725                            /* jshint eqnull:true */
7726                            if (newIndex == null || newIndex === -1) {
7727                                newIndex = oldIndex;
7728                            }
7729
7730                            _dispatchEvent(this, rootEl, "end", dragEl, rootEl, oldIndex, newIndex);
7731
7732                            // Save sorting
7733                            this.save();
7734                        }
7735                    }
7736                }
7737
7738                this._nulling();
7739            },
7740
7741            _nulling: function () {
7742                rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = scrollEl = scrollParentEl = tapEvt = touchEvt = moved = newIndex = lastEl = lastCSS = putSortable = activeGroup = Sortable.active = null;
7743            },
7744
7745            handleEvent: function (/**Event*/ evt) {
7746                var type = evt.type;
7747
7748                if (type === "dragover" || type === "dragenter") {
7749                    if (dragEl) {
7750                        this._onDragOver(evt);
7751                        _globalDragOver(evt);
7752                    }
7753                } else if (type === "drop" || type === "dragend") {
7754                    this._onDrop(evt);
7755                }
7756            },
7757
7758            /**
7759             * Serializes the item into an array of string.
7760             * @returns {String[]}
7761             */
7762            toArray: function () {
7763                var order = [],
7764                    el,
7765                    children = this.el.children,
7766                    i = 0,
7767                    n = children.length,
7768                    options = this.options;
7769
7770                for (; i < n; i++) {
7771                    el = children[i];
7772                    if (_closest(el, options.draggable, this.el)) {
7773                        order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
7774                    }
7775                }
7776
7777                return order;
7778            },
7779
7780            /**
7781             * Sorts the elements according to the array.
7782             * @param  {String[]}  order  order of the items
7783             */
7784            sort: function (order) {
7785                var items = {},
7786                    rootEl = this.el;
7787
7788                this.toArray().forEach(function (id, i) {
7789                    var el = rootEl.children[i];
7790
7791                    if (_closest(el, this.options.draggable, rootEl)) {
7792                        items[id] = el;
7793                    }
7794                }, this);
7795
7796                order.forEach(function (id) {
7797                    if (items[id]) {
7798                        rootEl.removeChild(items[id]);
7799                        rootEl.appendChild(items[id]);
7800                    }
7801                });
7802            },
7803
7804            /**
7805             * Save the current sorting
7806             */
7807            save: function () {
7808                var store = this.options.store;
7809                store && store.set(this);
7810            },
7811
7812            /**
7813             * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
7814             * @param   {HTMLElement}  el
7815             * @param   {String}       [selector]  default: `options.draggable`
7816             * @returns {HTMLElement|null}
7817             */
7818            closest: function (el, selector) {
7819                return _closest(el, selector || this.options.draggable, this.el);
7820            },
7821
7822            /**
7823             * Set/get option
7824             * @param   {string} name
7825             * @param   {*}      [value]
7826             * @returns {*}
7827             */
7828            option: function (name, value) {
7829                var options = this.options;
7830
7831                if (value === void 0) {
7832                    return options[name];
7833                } else {
7834                    options[name] = value;
7835
7836                    if (name === "group") {
7837                        _prepareGroup(options);
7838                    }
7839                }
7840            },
7841
7842            /**
7843             * Destroy
7844             */
7845            destroy: function () {
7846                var el = this.el;
7847
7848                el[expando] = null;
7849
7850                _off(el, "mousedown", this._onTapStart);
7851                _off(el, "touchstart", this._onTapStart);
7852
7853                if (this.nativeDraggable) {
7854                    _off(el, "dragover", this);
7855                    _off(el, "dragenter", this);
7856                }
7857
7858                // Remove draggable attributes
7859                Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function (el) {
7860                    el.removeAttribute("draggable");
7861                });
7862
7863                touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
7864
7865                this._onDrop();
7866
7867                this.el = el = null;
7868            },
7869        };
7870
7871        function _cloneHide(state) {
7872            if (cloneEl && cloneEl.state !== state) {
7873                _css(cloneEl, "display", state ? "none" : "");
7874                !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl);
7875                cloneEl.state = state;
7876            }
7877        }
7878
7879        function _closest(/**HTMLElement*/ el, /**String*/ selector, /**HTMLElement*/ ctx) {
7880            if (el) {
7881                ctx = ctx || document;
7882
7883                do {
7884                    if ((selector === ">*" && el.parentNode === ctx) || _matches(el, selector)) {
7885                        return el;
7886                    }
7887                    /* jshint boss:true */
7888                } while ((el = _getParentOrHost(el)));
7889            }
7890
7891            return null;
7892        }
7893
7894        function _getParentOrHost(el) {
7895            var parent = el.host;
7896
7897            return parent && parent.nodeType ? parent : el.parentNode;
7898        }
7899
7900        function _globalDragOver(/**Event*/ evt) {
7901            if (evt.dataTransfer) {
7902                evt.dataTransfer.dropEffect = "move";
7903            }
7904            evt.preventDefault();
7905        }
7906
7907        function _on(el, event, fn) {
7908            el.addEventListener(event, fn, false);
7909        }
7910
7911        function _off(el, event, fn) {
7912            el.removeEventListener(event, fn, false);
7913        }
7914
7915        function _toggleClass(el, name, state) {
7916            if (el) {
7917                if (el.classList) {
7918                    el.classList[state ? "add" : "remove"](name);
7919                } else {
7920                    var className = (" " + el.className + " ")
7921                        .replace(RSPACE, " ")
7922                        .replace(" " + name + " ", " ");
7923                    el.className = (className + (state ? " " + name : "")).replace(RSPACE, " ");
7924                }
7925            }
7926        }
7927
7928        function _css(el, prop, val) {
7929            var style = el && el.style;
7930
7931            if (style) {
7932                if (val === void 0) {
7933                    if (document.defaultView && document.defaultView.getComputedStyle) {
7934                        val = document.defaultView.getComputedStyle(el, "");
7935                    } else if (el.currentStyle) {
7936                        val = el.currentStyle;
7937                    }
7938
7939                    return prop === void 0 ? val : val[prop];
7940                } else {
7941                    if (!(prop in style)) {
7942                        prop = "-webkit-" + prop;
7943                    }
7944
7945                    style[prop] = val + (typeof val === "string" ? "" : "px");
7946                }
7947            }
7948        }
7949
7950        function _find(ctx, tagName, iterator) {
7951            if (ctx) {
7952                var list = ctx.getElementsByTagName(tagName),
7953                    i = 0,
7954                    n = list.length;
7955
7956                if (iterator) {
7957                    for (; i < n; i++) {
7958                        iterator(list[i], i);
7959                    }
7960                }
7961
7962                return list;
7963            }
7964
7965            return [];
7966        }
7967
7968        function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) {
7969            sortable = sortable || rootEl[expando];
7970
7971            var evt = document.createEvent("Event"),
7972                options = sortable.options,
7973                onName = "on" + name.charAt(0).toUpperCase() + name.substr(1);
7974
7975            evt.initEvent(name, true, true);
7976
7977            evt.to = rootEl;
7978            evt.from = fromEl || rootEl;
7979            evt.item = targetEl || rootEl;
7980            evt.clone = cloneEl;
7981
7982            evt.oldIndex = startIndex;
7983            evt.newIndex = newIndex;
7984
7985            rootEl.dispatchEvent(evt);
7986
7987            if (options[onName]) {
7988                options[onName].call(sortable, evt);
7989            }
7990        }
7991
7992        function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt) {
7993            var evt,
7994                sortable = fromEl[expando],
7995                onMoveFn = sortable.options.onMove,
7996                retVal;
7997
7998            evt = document.createEvent("Event");
7999            evt.initEvent("move", true, true);
8000
8001            evt.to = toEl;
8002            evt.from = fromEl;
8003            evt.dragged = dragEl;
8004            evt.draggedRect = dragRect;
8005            evt.related = targetEl || toEl;
8006            evt.relatedRect = targetRect || toEl.getBoundingClientRect();
8007
8008            fromEl.dispatchEvent(evt);
8009
8010            if (onMoveFn) {
8011                retVal = onMoveFn.call(sortable, evt, originalEvt);
8012            }
8013
8014            return retVal;
8015        }
8016
8017        function _disableDraggable(el) {
8018            el.draggable = false;
8019        }
8020
8021        function _unsilent() {
8022            _silent = false;
8023        }
8024
8025        /** @returns {HTMLElement|false} */
8026        function _ghostIsLast(el, evt) {
8027            var lastEl = el.lastElementChild,
8028                rect = lastEl.getBoundingClientRect();
8029
8030            // 5 — min delta
8031            // abs — нельзя добавлять, а то глюки при наведении сверху
8032            return (
8033                (evt.clientY - (rect.top + rect.height) > 5 ||
8034                    evt.clientX - (rect.right + rect.width) > 5) &&
8035                lastEl
8036            );
8037        }
8038
8039        /**
8040         * Generate id
8041         * @param   {HTMLElement} el
8042         * @returns {String}
8043         * @private
8044         */
8045        function _generateId(el) {
8046            var str = el.tagName + el.className + el.src + el.href + el.textContent,
8047                i = str.length,
8048                sum = 0;
8049
8050            while (i--) {
8051                sum += str.charCodeAt(i);
8052            }
8053
8054            return sum.toString(36);
8055        }
8056
8057        /**
8058         * Returns the index of an element within its parent for a selected set of
8059         * elements
8060         * @param  {HTMLElement} el
8061         * @param  {selector} selector
8062         * @return {number}
8063         */
8064        function _index(el, selector) {
8065            var index = 0;
8066
8067            if (!el || !el.parentNode) {
8068                return -1;
8069            }
8070
8071            while (el && (el = el.previousElementSibling)) {
8072                if (
8073                    el.nodeName.toUpperCase() !== "TEMPLATE" &&
8074                    (selector === ">*" || _matches(el, selector))
8075                ) {
8076                    index++;
8077                }
8078            }
8079
8080            return index;
8081        }
8082
8083        function _matches(/**HTMLElement*/ el, /**String*/ selector) {
8084            if (el) {
8085                selector = selector.split(".");
8086
8087                var tag = selector.shift().toUpperCase(),
8088                    re = new RegExp("\\s(" + selector.join("|") + ")(?=\\s)", "g");
8089
8090                return (
8091                    (tag === "" || el.nodeName.toUpperCase() == tag) &&
8092                    (!selector.length ||
8093                        ((" " + el.className + " ").match(re) || []).length == selector.length)
8094                );
8095            }
8096
8097            return false;
8098        }
8099
8100        function _throttle(callback, ms) {
8101            var args, _this;
8102
8103            return function () {
8104                if (args === void 0) {
8105                    args = arguments;
8106                    _this = this;
8107
8108                    setTimeout(function () {
8109                        if (args.length === 1) {
8110                            callback.call(_this, args[0]);
8111                        } else {
8112                            callback.apply(_this, args);
8113                        }
8114
8115                        args = void 0;
8116                    }, ms);
8117                }
8118            };
8119        }
8120
8121        function _extend(dst, src) {
8122            if (dst && src) {
8123                for (var key in src) {
8124                    if (src.hasOwnProperty(key)) {
8125                        dst[key] = src[key];
8126                    }
8127                }
8128            }
8129
8130            return dst;
8131        }
8132
8133        function _clone(el) {
8134            return $
8135                ? $(el).clone(true)[0]
8136                : Polymer && Polymer.dom
8137                ? Polymer.dom(el).cloneNode(true)
8138                : el.cloneNode(true);
8139        }
8140
8141        // Export utils
8142        Sortable.utils = {
8143            on: _on,
8144            off: _off,
8145            css: _css,
8146            find: _find,
8147            is: function (el, selector) {
8148                return !!_closest(el, selector, el);
8149            },
8150            extend: _extend,
8151            throttle: _throttle,
8152            closest: _closest,
8153            toggleClass: _toggleClass,
8154            clone: _clone,
8155            index: _index,
8156        };
8157
8158        /**
8159         * Create sortable instance
8160         * @param {HTMLElement}  el
8161         * @param {Object}      [options]
8162         */
8163        Sortable.create = function (el, options) {
8164            return new Sortable(el, options);
8165        };
8166
8167        // Export
8168        Sortable.version = "1.4.2";
8169        return Sortable;
8170    });
8171    });
8172
8173    const $$h = jQuery;
8174    class ImagesFormElement extends FormElement {
8175        constructor(options, formBuilder, external) {
8176            super(options, formBuilder, external);
8177            this.searchType = options.searchType || "fulltext";
8178            this.mediaUploader = external.mediaUploader;
8179            this.button_text = options.button_text || "Browse...";
8180            this.db_type = "text";
8181            this.label = options.label || "Images";
8182            this.name = options.name || "images";
8183            this.images = this.value || [];
8184            this.value = JSON.stringify(this.value);
8185        }
8186        init() {
8187            super.init();
8188            this.redrawImages();
8189        }
8190        setDomElements() {
8191            super.setDomElements();
8192        }
8193        getData() {
8194            this.updateData();
8195            return { name: this.name, value: this.images };
8196        }
8197        getSchema() {
8198            const schema = super.getSchema();
8199            schema.button_text = this.button_text;
8200            return schema;
8201        }
8202        updateData() {
8203            const newListOfImages = [];
8204            $$h(this.domElements.main)
8205                .find(".mapsvg-thumbnail-wrap")
8206                .each(function (index, el) {
8207                const imageData = $$h(el).data("image");
8208                newListOfImages.push(imageData);
8209            });
8210            this.images = newListOfImages;
8211            this.value = JSON.stringify(this.images);
8212            $$h(this.domElements.main).find("input").val(this.value);
8213        }
8214        setEventHandlers() {
8215            super.setEventHandlers();
8216            if (this.formBuilder.editMode) {
8217                return;
8218            }
8219            const _this = this;
8220            const imageDOM = $$h(this.domElements.main).find(".mapsvg-data-images");
8221            this.external.mediaUploader.on("select", () => {
8222                if (_this.formBuilder.mediaUploaderisOpenedFor !== _this)
8223                    return false;
8224                const attachments = _this.external.mediaUploader.state().get("selection").toJSON();
8225                attachments.forEach(function (img) {
8226                    const image = { sizes: {} };
8227                    for (const type in img.sizes) {
8228                        image[type] = img.sizes[type].url
8229                            .replace("http://", "//")
8230                            .replace("https://", "//");
8231                        image.sizes[type] = {
8232                            width: img.sizes[type].width,
8233                            height: img.sizes[type].height,
8234                        };
8235                    }
8236                    if (!image.thumbnail) {
8237                        image.thumbnail = image.full;
8238                        image.sizes.thumbnail = {
8239                            width: img.sizes.full.width,
8240                            height: img.sizes.full.height,
8241                        };
8242                    }
8243                    if (!image.medium) {
8244                        image.medium = image.full;
8245                        image.sizes.medium = {
8246                            width: img.sizes.full.width,
8247                            height: img.sizes.full.height,
8248                        };
8249                    }
8250                    image.caption = img.caption;
8251                    image.description = img.description;
8252                    _this.images.push(image);
8253                });
8254                this.setValue(this.images);
8255                _this.redrawImages();
8256            });
8257            $$h(_this.domElements.main).on("click", ".mapsvg-upload-image", function (e) {
8258                e.preventDefault();
8259                _this.formBuilder.mediaUploaderisOpenedFor = _this;
8260                _this.external.mediaUploader.open();
8261            });
8262            $$h(_this.domElements.main).on("click", ".mapsvg-image-delete", function (e) {
8263                e.preventDefault();
8264                $$h(this).closest(".mapsvg-thumbnail-wrap").remove();
8265                _this.updateData();
8266            });
8267            _this.sortable = new sortable_min(imageDOM[0], {
8268                animation: 150,
8269                onStart: function () {
8270                    $$h(_this.domElements.main).addClass("sorting");
8271                },
8272                onEnd: function (evt) {
8273                    _this.images = [];
8274                    $$h(_this.domElements.main)
8275                        .find("img")
8276                        .each(function (i, image) {
8277                        _this.images.push($$h(image).data("image"));
8278                    });
8279                    this.value = JSON.stringify(_this.images);
8280                    $$h(_this.domElements.main).find("input").val(this.value);
8281                    $$h(_this.domElements.main).removeClass("sorting");
8282                },
8283            });
8284        }
8285        redrawImages() {
8286            const imageDOM = $$h(this.domElements.main).find(".mapsvg-data-images");
8287            imageDOM.empty();
8288            this.images &&
8289                this.images.forEach(function (image) {
8290                    const img = $$h('<img class="mapsvg-data-thumbnail" />')
8291                        .attr("src", image.thumbnail)
8292                        .data("image", image);
8293                    const imgContainer = $$h('<div class="mapsvg-thumbnail-wrap"></div>').data("image", image);
8294                    imgContainer.append(img);
8295                    imgContainer.append('<i class="mfa mfa-times  mapsvg-image-delete"></i>');
8296                    imageDOM.append(imgContainer);
8297                });
8298            $$h(this.domElements.main).find("input").val(this.value);
8299        }
8300        destroy() {
8301            super.destroy();
8302            this.external.mediaUploader.off("select");
8303        }
8304    }
8305
8306    const $$i = jQuery;
8307    class LocationFormElement extends FormElement {
8308        constructor(options, formBuilder, external) {
8309            super(options, formBuilder, external);
8310            this.label = this.label || (options.label === undefined ? "Location" : options.label);
8311            this.name = "location";
8312            this.db_type = "text";
8313            this.languages = [
8314                { value: "sq", label: "Albanian" },
8315                { value: "ar", label: "Arabic" },
8316                {
8317                    value: "eu",
8318                    label: "Basque",
8319                },
8320                { value: "be", label: "Belarusian" },
8321                { value: "bg", label: "Bulgarian" },
8322                {
8323                    value: "my",
8324                    label: "Burmese",
8325                },
8326                { value: "bn", label: "Bengali" },
8327                { value: "ca", label: "Catalan" },
8328                {
8329                    value: "zh-cn",
8330                    label: "Chinese (simplified)",
8331                },
8332                { value: "zh-tw", label: "Chinese (traditional)" },
8333                {
8334                    value: "hr",
8335                    label: "Croatian",
8336                },
8337                { value: "cs", label: "Czech" },
8338                { value: "da", label: "Danish" },
8339                {
8340                    value: "nl",
8341                    label: "Dutch",
8342                },
8343                { value: "en", label: "English" },
8344                {
8345                    value: "en-au",
8346                    label: "English (australian)",
8347                },
8348                { value: "en-gb", label: "English (great Britain)" },
8349                {
8350                    value: "fa",
8351                    label: "Farsi",
8352                },
8353                { value: "fi", label: "Finnish" },
8354                { value: "fil", label: "Filipino" },
8355                {
8356                    value: "fr",
8357                    label: "French",
8358                },
8359                { value: "gl", label: "Galician" },
8360                { value: "de", label: "German" },
8361                {
8362                    value: "el",
8363                    label: "Greek",
8364                },
8365                { value: "gu", label: "Gujarati" },
8366                { value: "iw", label: "Hebrew" },
8367                {
8368                    value: "hi",
8369                    label: "Hindi",
8370                },
8371                { value: "hu", label: "Hungarian" },
8372                { value: "id", label: "Indonesian" },
8373                {
8374                    value: "it",
8375                    label: "Italian",
8376                },
8377                { value: "ja", label: "Japanese" },
8378                { value: "kn", label: "Kannada" },
8379                {
8380                    value: "kk",
8381                    label: "Kazakh",
8382                },
8383                { value: "ko", label: "Korean" },
8384                { value: "ky", label: "Kyrgyz" },
8385                {
8386                    value: "lt",
8387                    label: "Lithuanian",
8388                },
8389                { value: "lv", label: "Latvian" },
8390                { value: "mk", label: "Macedonian" },
8391                {
8392                    value: "ml",
8393                    label: "Malayalam",
8394                },
8395                { value: "mr", label: "Marathi" },
8396                { value: "no", label: "Norwegian" },
8397                {
8398                    value: "pl",
8399                    label: "Polish",
8400                },
8401                { value: "pt", label: "Portuguese" },
8402                {
8403                    value: "pt-br",
8404                    label: "Portuguese (brazil)",
8405                },
8406                { value: "pt-pt", label: "Portuguese (portugal)" },
8407                {
8408                    value: "pa",
8409                    label: "Punjabi",
8410                },
8411                { value: "ro", label: "Romanian" },
8412                { value: "ru", label: "Russian" },
8413                {
8414                    value: "sr",
8415                    label: "Serbian",
8416                },
8417                { value: "sk", label: "Slovak" },
8418                { value: "sl", label: "Slovenian" },
8419                {
8420                    value: "es",
8421                    label: "Spanish",
8422                },
8423                { value: "sv", label: "Swedish" },
8424                { value: "tl", label: "Tagalog" },
8425                {
8426                    value: "ta",
8427                    label: "Tamil",
8428                },
8429                { value: "te", label: "Telugu" },
8430                { value: "th", label: "Thai" },
8431                {
8432                    value: "tr",
8433                    label: "Turkish",
8434                },
8435                { value: "uk", label: "Ukrainian" },
8436                { value: "uz", label: "Uzbek" },
8437                {
8438                    value: "vi",
8439                    label: "Vietnamese",
8440                },
8441            ];
8442            this.language = options.language;
8443            this.markerImages = MapSVG.markerImages;
8444            this.markersByField = options.markersByField;
8445            this.markerField = options.markerField;
8446            this.markersByFieldEnabled = MapSVG.parseBoolean(options.markersByFieldEnabled);
8447            this.defaultMarkerPath =
8448                options.defaultMarkerPath ||
8449                    this.formBuilder.mapsvg.getData().options.defaultMarkerImage;
8450            this.templates.marker = Handlebars.compile($$i("#mapsvg-data-tmpl-marker").html());
8451        }
8452        init() {
8453            super.init();
8454            if (this.value) {
8455                this.renderMarker();
8456            }
8457            this.renderMarkerSelector();
8458        }
8459        getSchema() {
8460            const schema = super.getSchema();
8461            schema.language = this.language;
8462            schema.defaultMarkerPath = this.defaultMarkerPath;
8463            schema.markersByField = this.markersByField;
8464            schema.markerField = this.markerField;
8465            schema.markersByFieldEnabled = MapSVG.parseBoolean(this.markersByFieldEnabled);
8466            return schema;
8467        }
8468        getData() {
8469            return { name: this.name, value: this.value };
8470        }
8471        getDataForTemplate() {
8472            const data = super.getDataForTemplate();
8473            if (this.formBuilder.admin) {
8474                data.languages = this.languages;
8475                data.markerImages = MapSVG.markerImages;
8476                data.markersByField = this.markersByField;
8477                data.markerField = this.markerField;
8478                data.markersByFieldEnabled = MapSVG.parseBoolean(this.markersByFieldEnabled);
8479                const _this = this;
8480                data.markerImages.forEach(function (m) {
8481                    if (m.relativeUrl === _this.defaultMarkerPath) {
8482                        m.default = true;
8483                    }
8484                    else {
8485                        m.default = false;
8486                    }
8487                });
8488            }
8489            data.language = this.language;
8490            if (this.value) {
8491                data.location = this.value;
8492                if (data.location.marker) {
8493                    data.location.img =
8494                        (this.value.marker.src.indexOf(MapSVG.urls.uploads) === 0 ? "uploads/" : "") +
8495                            this.value.marker.src.split("/").pop();
8496                }
8497            }
8498            data.showUploadBtn = data.external.filtersMode;
8499            return data;
8500        }
8501        initEditor() {
8502            super.initEditor();
8503            this.renderMarkerSelector();
8504            this.fillMarkersByFieldOptions(this.markerField);
8505        }
8506        setDomElements() {
8507            super.setDomElements();
8508            this.domElements.markerImageButton = $$i(this.domElements.main).find("img")[0];
8509        }
8510        setEventHandlers() {
8511            super.setEventHandlers();
8512            const _this = this;
8513            const server = new Server();
8514            if (_this.formBuilder.mapsvg.isGeo()) {
8515                const locations = new Bloodhound({
8516                    datumTokenizer: Bloodhound.tokenizers.obj.whitespace("formatted_address"),
8517                    queryTokenizer: Bloodhound.tokenizers.whitespace,
8518                    remote: {
8519                        url: server.getUrl("geocoding") + "?address=%QUERY%&language=" + this.language,
8520                        wildcard: "%QUERY%",
8521                        transform: function (response) {
8522                            if (response.error_message) {
8523                                alert(response.error_message);
8524                            }
8525                            return response.results;
8526                        },
8527                        rateLimitWait: 600,
8528                    },
8529                });
8530                const thContainer = $$i(this.domElements.main).find(".typeahead");
8531                const tH = thContainer
8532                    .typeahead({ minLength: 3 }, {
8533                    name: "mapsvg-addresses",
8534                    display: "formatted_address",
8535                    async: true,
8536                    source: (query, sync, async) => {
8537                        const preg = new RegExp(/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/);
8538                        if (preg.test(query)) {
8539                            const latlng = query.split(",").map((item) => item.trim());
8540                            const item = {
8541                                formatted_address: latlng.join(","),
8542                                address_components: [],
8543                                geometry: {
8544                                    location: {
8545                                        lat: () => latlng[0],
8546                                        lng: () => latlng[1],
8547                                    },
8548                                },
8549                            };
8550                            sync([item]);
8551                            return;
8552                        }
8553                        MapSVG.geocode({ address: query }, async);
8554                    },
8555                })
8556                    .on("typeahead:asyncrequest", function (e) {
8557                    $$i(e.target).addClass("tt-loading");
8558                })
8559                    .on("typeahead:asynccancel typeahead:asyncreceive", function (e) {
8560                    $$i(e.target).removeClass("tt-loading");
8561                });
8562                thContainer.on("typeahead:select", (ev, item) => {
8563                    this.setValue(null, false);
8564                    const address = {};
8565                    address.formatted = item.formatted_address;
8566                    item.address_components.forEach((addr_item) => {
8567                        const type = addr_item.types[0];
8568                        address[type] = addr_item.long_name;
8569                        if (addr_item.short_name != addr_item.long_name) {
8570                            address[type + "_short"] = addr_item.short_name;
8571                        }
8572                    });
8573                    const locationData = {
8574                        address: address,
8575                        geoPoint: new GeoPoint(item.geometry.location.lat(), item.geometry.location.lng()),
8576                        img: this.getMarkerImage(this.formBuilder.getData()),
8577                        imagePath: this.getMarkerImage(this.formBuilder.getData()),
8578                    };
8579                    this.setValue(locationData, false);
8580                    thContainer.typeahead("val", "");
8581                    this.triggerChanged();
8582                });
8583            }
8584            $$i(this.domElements.main).on("change", ".marker-file-uploader", function () {
8585                _this.markerIconUpload(this);
8586            });
8587            $$i(this.domElements.main).on("click", ".mapsvg-marker-image-btn-trigger", function (e) {
8588                e.preventDefault();
8589                $$i(this).toggleClass("active");
8590                _this.toggleMarkerSelector();
8591            });
8592            $$i(this.domElements.main).on("click", ".mapsvg-marker-delete", function (e) {
8593                e.preventDefault();
8594                _this.setValue(null);
8595                _this.triggerChanged();
8596            });
8597        }
8598        setEditorEventHandlers() {
8599            super.setEditorEventHandlers();
8600            const _this = this;
8601            $$i(this.domElements.edit).on("change", ".marker-file-uploader", function () {
8602                _this.markerIconUpload(this);
8603            });
8604            $$i(this.domElements.edit).on("change", 'select[name="markerField"]', function () {
8605                const fieldName = $$i(this).val();
8606                _this.resetMarkersByField();
8607                const newOptions = _this.fillMarkersByFieldOptions(fieldName);
8608                _this.setMarkersByField(newOptions);
8609            });
8610            $$i(this.domElements.edit).on("click", ".mapsvg-marker-image-selector button", function (e) {
8611                e.preventDefault();
8612                const src = $$i(this).find("img").attr("src");
8613                $$i(this).parent().find("button").removeClass("active");
8614                $$i(this).addClass("active");
8615                _this.setDefaultMarkerPath(src);
8616            });
8617            $$i(this.domElements.edit).on("click", ".mapsvg-marker-image-btn-trigger", function (e) {
8618                $$i(this).toggleClass("active");
8619                _this.toggleMarkerSelectorInLocationEditor.call(_this, $$i(this), e);
8620            });
8621        }
8622        markerIconUpload(input) {
8623            const uploadBtn = $$i(input).closest(".btn-file").buttonLoading(true);
8624            for (let i = 0; i < input.files.length; i++) {
8625                const data = new FormData();
8626                data.append("file", input.files[0]);
8627                const server = new Server();
8628                server
8629                    .ajax("markers", {
8630                    type: "POST",
8631                    data: data,
8632                    processData: false,
8633                    contentType: false,
8634                })
8635                    .done((resp) => {
8636                    if (resp.error) {
8637                        alert(resp.error);
8638                    }
8639                    else {
8640                        const marker = resp.marker;
8641                        const newMarker = `
8642                            <button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose active">
8643                                <img src="${marker.relativeUrl}" />
8644                            </button>
8645                            </button>
8646                        `;
8647                        $$i(this.domElements.markerSelector)
8648                            .find(".mapsvg-marker-image-btn.active")
8649                            .removeClass("active");
8650                        $$i(newMarker).appendTo(this.domElements.markerSelector);
8651                        this.setMarkerImage(marker.relativeUrl);
8652                        MapSVG.markerImages.push(marker);
8653                    }
8654                })
8655                    .always(function () {
8656                    uploadBtn.buttonLoading(false);
8657                });
8658            }
8659        }
8660        mayBeAddDistanceRow() {
8661            const _this = this;
8662            if (!this.domElements.editDistanceRow) {
8663                this.domElements.editDistanceRow = $$i($$i("#mapsvg-edit-distance-row").html())[0];
8664            }
8665            const z = $$i(this.domElements.edit).find(".mapsvg-edit-distance-row:last-child input");
8666            if (z && z.last() && z.last().val() && (z.last().val() + "").trim().length) {
8667                const newRow = $$i(this.templates.editDistanceRow).clone();
8668                newRow.insertAfter($$i(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child"));
8669            }
8670            const rows = $$i(_this.domElements.edit).find(".mapsvg-edit-distance-row");
8671            const row1 = rows.eq(rows.length - 2);
8672            const row2 = rows.eq(rows.length - 1);
8673            if (row1.length &&
8674                row2.length &&
8675                !row1.find("input:eq(0)").val().toString().trim() &&
8676                !row2.find("input:eq(0)").val().toString().trim()) {
8677                row2.remove();
8678            }
8679        }
8680        fillMarkersByFieldOptions(fieldName) {
8681            const _this = this;
8682            const field = _this.formBuilder.mapsvg.objectsRepository.getSchema().getField(fieldName);
8683            const options = {};
8684            if (field) {
8685                const markerImg = _this.formBuilder.mapsvg.options.defaultMarkerImage;
8686                const rows = [];
8687                field.options.forEach(function (option) {
8688                    const value = field.type === "region" ? option.id : option.value;
8689                    const label = field.type === "region" ? option.title || option.id : option.label;
8690                    const img = _this.markersByField && _this.markersByField[value]
8691                        ? _this.markersByField[value]
8692                        : markerImg;
8693                    rows.push('<tr data-option-id="' +
8694                        value +
8695                        '"><td>' +
8696                        label +
8697                        '</td><td><button class="btn dropdown-toggle btn-outline-secondary mapsvg-marker-image-btn-trigger mapsvg-marker-image-btn"><img src="' +
8698                        img +
8699                        '" class="new-marker-img" /><span class="caret"></span></button></td></tr>');
8700                    options[value] = img;
8701                });
8702                $$i("#markers-by-field").empty().append(rows);
8703            }
8704            return options;
8705        }
8706        renderMarker(marker) {
8707            if (marker && marker.location) {
8708                this.value = marker.location.getData();
8709            }
8710            this.renderMarkerHtml();
8711        }
8712        renderMarkerHtml() {
8713            if (!this.value) {
8714                $$i(this.domElements.main).find(".mapsvg-new-marker").hide();
8715            }
8716            else {
8717                $$i(this.domElements.main)
8718                    .find(".mapsvg-new-marker")
8719                    .show()
8720                    .html(this.templates.marker(this.value));
8721            }
8722        }
8723        toggleMarkerSelector() {
8724            if (this.domElements.markerSelectorWrap &&
8725                $$i(this.domElements.markerSelectorWrap).is(":visible")) {
8726                $$i(this.domElements.markerSelectorWrap).hide();
8727                return;
8728            }
8729            if (this.domElements.markerSelectorWrap &&
8730                $$i(this.domElements.markerSelectorWrap).not(":visible")) {
8731                $$i(this.domElements.markerSelector).find(".active").removeClass("active");
8732                if (this.value && this.value.markerImagePath) {
8733                    $$i(this.domElements.markerSelector)
8734                        .find('[src="' + this.value.markerImagePath + '"]')
8735                        .parent()
8736                        .addClass("active");
8737                }
8738                $$i(this.domElements.markerSelectorWrap).show();
8739                return;
8740            }
8741        }
8742        renderMarkerSelector() {
8743            const _this = this;
8744            const view = this.formBuilder.editMode ? this.domElements.edit : this.domElements.main;
8745            if (!view)
8746                return;
8747            const currentImage = this.value ? this.value.markerImagePath : null;
8748            const images = MapSVG.markerImages.map(function (image) {
8749                return ('<button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose ' +
8750                    (currentImage == image.relativeUrl ? "active" : "") +
8751                    '"><img src="' +
8752                    image.relativeUrl +
8753                    '" /></button>');
8754            });
8755            this.domElements.markerSelectorWrap = $$i(view).find(".mapsvg-marker-image-selector")[0];
8756            this.domElements.markerSelector = $$i(this.domElements.markerSelectorWrap).find(".mapsvg-marker-images")[0];
8757            if (this.domElements.markerSelector) {
8758                $$i(this.domElements.markerSelector).empty();
8759            }
8760            if (!this.formBuilder.editMode) {
8761                this.domElements.markerSelectorWrap.style.display = "none";
8762                $$i(this.domElements.markerSelector).on("click", ".mapsvg-marker-image-btn-choose", function (e) {
8763                    e.preventDefault();
8764                    const src = $$i(this).find("img").attr("src");
8765                    $$i(_this.domElements.markerSelectorWrap).hide();
8766                    $$i(_this.domElements.markerSelector).find(".active").removeClass("active");
8767                    $$i(this).addClass("active");
8768                    $$i(_this.domElements.main)
8769                        .find(".mapsvg-marker-image-btn-trigger")
8770                        .toggleClass("active", false);
8771                    $$i(_this.domElements.markerImageButton).attr("src", src);
8772                    _this.setMarkerImage(src);
8773                });
8774            }
8775            $$i(this.domElements.markerSelector).html(images.join(""));
8776        }
8777        setMarkerImage(src) {
8778            this.setDefaultMarkerPath(src);
8779            const value = this.value;
8780            if (value) {
8781                value.img = src;
8782                value.imagePath = src;
8783                this.setValue(value);
8784                this.triggerChanged();
8785                this.renderMarker();
8786            }
8787        }
8788        toggleMarkerSelectorInLocationEditor(jQueryObj, e) {
8789            e.preventDefault();
8790            const _this = this;
8791            if (jQueryObj.data("markerSelector") && jQueryObj.data("markerSelector").is(":visible")) {
8792                jQueryObj.data("markerSelector").hide();
8793                return;
8794            }
8795            if (jQueryObj.data("markerSelector") && jQueryObj.data("markerSelector").not(":visible")) {
8796                jQueryObj.data("markerSelector").show();
8797                return;
8798            }
8799            const markerBtn = $$i(this).closest("td").find(".mapsvg-marker-image-btn-trigger");
8800            const currentImage = markerBtn.attr("src");
8801            const images = MapSVG.markerImages.map(function (image) {
8802                return ('<button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose ' +
8803                    (currentImage == image.relativeUrl ? "active" : "") +
8804                    '"><img src="' +
8805                    image.relativeUrl +
8806                    '" /></button>');
8807            });
8808            if (!jQueryObj.data("markerSelector")) {
8809                const ms = $$i('<div class="mapsvg-marker-image-selector"></div>');
8810                jQueryObj.closest("td").append(ms);
8811                jQueryObj.data("markerSelector", ms);
8812            }
8813            else {
8814                jQueryObj.data("markerSelector").empty();
8815            }
8816            jQueryObj.data("markerSelector").html(images.join(""));
8817            jQueryObj
8818                .data("markerSelector")
8819                .on("click", ".mapsvg-marker-image-btn-choose", function (e) {
8820                e.preventDefault();
8821                const src = $$i(this).find("img").attr("src");
8822                jQueryObj.data("markerSelector").hide();
8823                const td = $$i(this).closest("td");
8824          
8824      const fieldId = $$i(this).closest("tr").data("option-id");
8825                const btn = td.find(".mapsvg-marker-image-btn-trigger");
8826                btn.toggleClass("active", false);
8827                btn.find("img").attr("src", src);
8828                _this.setMarkerByField(fieldId, src);
8829            });
8830        }
8831        setMarkersByField(options) {
8832            this.markersByField = options;
8833        }
8834        resetMarkersByField() {
8835            this.markersByField = {};
8836        }
8837        setMarkerByField(fieldId, markerImg) {
8838            this.markersByField = this.markersByField || {};
8839            this.markersByField[fieldId] = markerImg;
8840        }
8841        deleteMarker() {
8842            $$i(this.domElements.main).find(".mapsvg-new-marker").hide();
8843            $$i(this.domElements.main).find(".mapsvg-marker-id").attr("disabled", "disabled");
8844        }
8845        destroy() {
8846            if ($$i().mselect2) {
8847                const sel = $$i(this.domElements.main).find(".mapsvg-select2");
8848                if (sel.length) {
8849                    sel.mselect2("destroy");
8850                }
8851            }
8852            this.domElements.markerSelector && $$i(this.domElements.markerSelector).popover("dispose");
8853        }
8854        setDefaultMarkerPath(path) {
8855            this.defaultMarkerPath = path;
8856            this.formBuilder.mapsvg.setDefaultMarkerImage(path);
8857        }
8858        getMarkerImage(data) {
8859            let fieldValue;
8860            if (this.markersByFieldEnabled) {
8861                fieldValue = data[this.markerField];
8862                if (!fieldValue) {
8863                    return this.defaultMarkerPath || MapSVG.defaultMarkerImage;
8864                }
8865                else {
8866                    if (this.markerField === "regions") {
8867                        fieldValue = fieldValue[0] && fieldValue[0].id;
8868                    }
8869                    else if (typeof fieldValue === "object" && fieldValue.length) {
8870                        fieldValue = fieldValue[0].value;
8871                    }
8872                    if (this.markersByField[fieldValue]) {
8873                        return (this.markersByField[fieldValue] ||
8874                            this.defaultMarkerPath ||
8875                            MapSVG.defaultMarkerImage);
8876                    }
8877                }
8878            }
8879            else {
8880                return this.defaultMarkerPath || MapSVG.defaultMarkerImage;
8881            }
8882        }
8883        setValue(value, updateInput = true) {
8884            this.value = value;
8885            if (this.value) {
8886                if (!this.value.address) {
8887                    this.value.address = {};
8888                }
8889                if (Object.keys(this.value.address).length < 2 && this.value.geoPoint) {
8890                    this.value.address.formatted =
8891                        this.value.geoPoint.lat + "," + this.value.geoPoint.lng;
8892                }
8893            }
8894            this.renderMarker();
8895        }
8896    }
8897
8898    const $$j = jQuery;
8899    class ModalFormElement extends FormElement {
8900        constructor(options, formBuilder, external) {
8901            super(options, formBuilder, external);
8902            this.showButtonText = options.showButtonText;
8903        }
8904        getSchema() {
8905            const schema = super.getSchema();
8906            schema.showButtonText = this.showButtonText;
8907            return schema;
8908        }
8909    }
8910
8911    const $$k = jQuery;
8912    class PostFormElement extends FormElement {
8913        constructor(options, formBuilder, external) {
8914            super(options, formBuilder, external);
8915            if (this.formBuilder.admin)
8916                this.post_types = this.formBuilder.admin.getPostTypes();
8917            this.post_type = options.post_type || this.post_types[0];
8918            this.add_fields = MapSVG.parseBoolean(options.add_fields);
8919            this.db_type = "int(11)";
8920            this.name = "post";
8921            this.post = options.post;
8922        }
8923        setDomElements() {
8924            super.setDomElements();
8925            this.inputs.postSelect = ($$k(this.domElements.main).find(".mapsvg-find-post")[0]);
8926        }
8927        getSchema() {
8928            const schema = super.getSchema();
8929            schema.post_type = this.post_type;
8930            schema.add_fields = this.add_fields;
8931            return schema;
8932        }
8933        destroy() {
8934            if ($$k().mselect2) {
8935                const sel = $$k(this.domElements.main).find(".mapsvg-select2");
8936                if (sel.length) {
8937                    sel.mselect2("destroy");
8938                }
8939            }
8940        }
8941        getDataForTemplate() {
8942            const data = super.getDataForTemplate();
8943            if (this.formBuilder.admin)
8944                data.post_types = this.formBuilder.admin.getPostTypes();
8945            data.post_type = this.post_type;
8946            data.post = this.post;
8947            data.add_fields = this.add_fields || 0;
8948            return data;
8949        }
8950        setEventHandlers() {
8951            super.setEventHandlers();
8952            const server = new Server();
8953            $$k(this.inputs.postSelect)
8954                .mselect2({
8955                placeholder: "Search post by title",
8956                allowClear: true,
8957                disabled: this.readonly,
8958                ajax: {
8959                    url: server.getUrl("posts"),
8960                    dataType: "json",
8961                    delay: 250,
8962                    data: (params) => {
8963                        return {
8964                            filters: { post_type: this.post_type },
8965                            search: params.term,
8966                            page: params.page,
8967                        };
8968                    },
8969                    processResults: (data, params) => {
8970                        params.page = params.page || 1;
8971                        return {
8972                            results: data.posts ? data.posts : [],
8973                            pagination: {
8974                                more: false,
8975                            },
8976                        };
8977                    },
8978                    cache: true,
8979                },
8980                escapeMarkup: (markup) => {
8981                    return markup;
8982                },
8983                minimumInputLength: 1,
8984                templateResult: this.formatRepo,
8985                templateSelection: this.formatRepoSelection,
8986            })
8987                .on("select2:select", (e) => {
8988                const post = e.params.data;
8989                this.setValue(post);
8990                this.setInputValue(post);
8991                this.triggerChanged();
8992            })
8993                .on("change", (e) => {
8994                if (e.target.value === "") {
8995                    $$k(this.domElements.main).find(".mapsvg-post-id").text("");
8996                    $$k(this.domElements.main).find(".mapsvg-post-url").text("");
8997                    this.setValue(null, false);
8998                    this.triggerChanged();
8999                }
9000            });
9001        }
9002        formatRepo(repo) {
9003            if (repo.loading) {
9004                return repo.text;
9005            }
9006            else {
9007                return "<div class='select2-result-repository clearfix'>" + repo.post_title + "</div>";
9008            }
9009        }
9010        formatRepoSelection(repo) {
9011            return repo.post_title || repo.text;
9012        }
9013        setValue(post, updateInput = true) {
9014            this.value = post;
9015            if (updateInput) {
9016                this.setInputValue(post);
9017            }
9018        }
9019        setInputValue(post) {
9020            $$k(this.domElements.main).find(".mapsvg-post-id").text(post.id);
9021            $$k(this.domElements.main).find(".mapsvg-post-url").text(post.url).attr("href", post.url);
9022        }
9023    }
9024
9025    const $$l = jQuery;
9026    class RadioFormElement extends FormElement {
9027        constructor(options, formBuilder, external) {
9028            super(options, formBuilder, external);
9029            this.setOptions(options.options);
9030        }
9031        setDomElements() {
9032            super.setDomElements();
9033            this.inputs.radios = this.formBuilder.getForm().elements[this.name];
9034            this.$radios = $$l(this.domElements.main).find('input[type="radio"]');
9035        }
9036        setEventHandlers() {
9037            super.setEventHandlers();
9038            this.$radios.on("change", (e) => {
9039                this.setValue(e.target.value, false);
9040                this.triggerChanged();
9041            });
9042        }
9043        setInputValue(value) {
9044            if (value === null) {
9045                this.$radios.prop("checked", false);
9046            }
9047            else {
9048                this.inputs.radios.value = value;
9049            }
9050        }
9051    }
9052
9053    const $$m = jQuery;
9054    class RegionsFormElement extends FormElement {
9055        constructor(options, formBuilder, external) {
9056            super(options, formBuilder, external);
9057            this.searchable = MapSVG.parseBoolean(options.searchable);
9058            this.options = this.formBuilder.getRegionsList();
9059            this.label = options.label === undefined ? "Regions" : options.label;
9060            this.name = "regions";
9061            this.db_type = "text";
9062            if (typeof this.value === "undefined") {
9063                this.value = [];
9064            }
9065            this.regionsTableName = this.formBuilder.mapsvg.regionsRepository.getSchema().name;
9066        }
9067        setDomElements() {
9068            super.setDomElements();
9069            this.inputs.select = $$m(this.domElements.main).find("select")[0];
9070        }
9071        getData() {
9072            return { name: "regions", value: this.value };
9073        }
9074        getSchema() {
9075            const schema = super.getSchema();
9076            if (schema.multiselect)
9077                schema.db_type = "text";
9078            const opts = $$m.extend(true, {}, { options: this.options });
9079            schema.options = opts.options;
9080            schema.optionsDict = {};
9081            schema.options.forEach(function (option) {
9082                schema.optionsDict[option.id] = option.title || option.id;
9083            });
9084            return schema;
9085        }
9086        getDataForTemplate() {
9087            const data = super.getDataForTemplate();
9088            data.regionsTableName = this.regionsTableName;
9089            data.regionsFromCurrentTable = this.getRegionsForCurrentTable();
9090            return data;
9091        }
9092        getRegionsForCurrentTable() {
9093            return this.value
9094                ? this.value.filter((region) => region.tableName === this.regionsTableName)
9095                : [];
9096        }
9097        setEventHandlers() {
9098            super.setEventHandlers();
9099            $$m(this.inputs.select).on("change", (e) => {
9100                const selectedOptions = Array.from(this.inputs.select.selectedOptions);
9101                const selectedValues = selectedOptions.map((option) => option.value);
9102                this.setValue(selectedValues, false);
9103                this.triggerChanged();
9104            });
9105        }
9106        destroy() {
9107            if ($$m().mselect2) {
9108                const sel = $$m(this.domElements.main).find(".mapsvg-select2");
9109                if (sel.length) {
9110                    sel.mselect2("destroy");
9111                }
9112            }
9113        }
9114        setValue(regionIds, updateInput = true) {
9115            const regionsFromOtherTables = this.value.filter((region) => region.tableName !== this.regionsTableName);
9116            const regions = [];
9117            regionIds.forEach((regionId) => {
9118                const region = this.formBuilder.mapsvg.getRegion(regionId);
9119                regions.push({ id: region.id, title: region.title, tableName: this.regionsTableName });
9120            });
9121            this.value = regions.concat(regionsFromOtherTables);
9122            if (updateInput) {
9123                this.setInputValue(regionIds);
9124            }
9125        }
9126    }
9127
9128    const $$n = jQuery;
9129    class SaveFormElement extends FormElement {
9130        constructor(options, formBuilder, external) {
9131            super(options, formBuilder, external);
9132            this.readonly = true;
9133        }
9134        setDomElements() {
9135            super.setDomElements();
9136            this.inputs.btnSave = $$n(this.domElements.main).find(".btn-save")[0];
9137            this.inputs.btnClose = $$n(this.domElements.main).find(".mapsvg-close")[0];
9138        }
9139        setEventHandlers() {
9140            super.setEventHandlers();
9141            $$n(this.inputs.btnSave).on("click", (e) => {
9142                e.preventDefault();
9143                this.events.trigger("click.btn.save");
9144            });
9145            $$n(this.inputs.btnClose).on("click", (e) => {
9146                e.preventDefault();
9147                this.events.trigger("click.btn.close");
9148            });
9149        }
9150    }
9151
9152    const $$o = jQuery;
9153    class SearchFormElement extends FormElement {
9154        constructor(options, formBuilder, external) {
9155            super(options, formBuilder, external);
9156            this.searchFallback = MapSVG.parseBoolean(options.searchFallback) || false;
9157            this.width = options.width || "100%";
9158            this.name = "search";
9159        }
9160        setDomElements() {
9161            super.setDomElements();
9162            this.inputs.text = $$o(this.domElements.main).find("input")[0];
9163        }
9164        setEventHandlers() {
9165            super.setEventHandlers();
9166            $$o(this.inputs.text).on("change keyup paste", (e) => {
9167                this.setValue(e.target.value, false);
9168                this.triggerChanged();
9169            });
9170        }
9171        setInputValue(value) {
9172            this.inputs.text.value = value;
9173        }
9174        getSchema() {
9175            const schema = super.getSchema();
9176            schema.searchFallback = MapSVG.parseBoolean(this.searchFallback);
9177            schema.placeholder = this.placeholder;
9178            schema.width = this.width;
9179            return schema;
9180        }
9181    }
9182
9183    const $$p = jQuery;
9184    class SelectFormElement extends FormElement {
9185        constructor(options, formBuilder, external) {
9186            super(options, formBuilder, external);
9187            this.searchable = MapSVG.parseBoolean(options.searchable);
9188            this.multiselect = MapSVG.parseBoolean(options.multiselect);
9189            this.optionsGrouped = options.optionsGrouped;
9190            this.db_type = this.multiselect ? "text" : "varchar(255)";
9191            this.setOptions(options.options);
9192        }
9193        setDomElements() {
9194            super.setDomElements();
9195            this.inputs.select = $$p(this.domElements.main).find("select")[0];
9196        }
9197        getSchema() {
9198            const schema = super.getSchema();
9199            schema.multiselect = MapSVG.parseBoolean(this.multiselect);
9200            if (schema.multiselect)
9201                schema.db_type = "text";
9202            schema.optionsGrouped = this.optionsGrouped;
9203            const opts = $$p.extend(true, {}, { options: this.options });
9204            schema.options = opts.options || [];
9205            schema.optionsDict = {};
9206            schema.options.forEach(function (option) {
9207                schema.optionsDict[option.value] = option.label;
9208            });
9209            return schema;
9210        }
9211        setEventHandlers() {
9212            super.setEventHandlers();
9213            $$p(this.inputs.select).on("change", (e) => {
9214                if (this.multiselect) {
9215                    const selectedOptions = Array.from(this.inputs.select.selectedOptions);
9216                    const selectedValues = selectedOptions.map((option) => {
9217                        return { label: option.label, value: option.value };
9218                    });
9219                    this.setValue(selectedValues, false);
9220                    this.triggerChanged();
9221                }
9222                else {
9223                    this.setValue(this.inputs.select.value, false);
9224                    this.triggerChanged();
9225                }
9226            });
9227        }
9228        addSelect2() {
9229            if ($$p().mselect2) {
9230                const select2Options = {};
9231                if (this.formBuilder.filtersMode && this.type == "select") {
9232                    select2Options.placeholder = this.placeholder;
9233                    if (!this.multiselect) {
9234                        select2Options.allowClear = true;
9235                    }
9236                }
9237                $$p(this.domElements.main)
9238                    .find("select")
9239                    .css({ width: "100%", display: "block" })
9240                    .mselect2(select2Options)
9241                    .on("select2:focus", function () {
9242                    $$p(this).mselect2("open");
9243                });
9244                $$p(this.domElements.main)
9245                    .find(".select2-selection--multiple .select2-search__field")
9246                    .css("width", "100%");
9247            }
9248        }
9249        setOptions(options) {
9250            if (options) {
9251                this.options = [];
9252                this.optionsDict = {};
9253                options.forEach((value, key) => {
9254                    this.options.push(value);
9255                    if (this.optionsGrouped) {
9256                        value.options.forEach((value2, key2) => {
9257                            this.optionsDict[value2.value] = value2;
9258                        });
9259                    }
9260                    else {
9261                        this.optionsDict[key] = value;
9262                    }
9263                });
9264                return this.options;
9265            }
9266            else {
9267                return this.setOptions([
9268                    { label: "Option one", name: "option_one", value: 1 },
9269                    { label: "Option two", name: "option_two", value: 2 },
9270                ]);
9271            }
9272        }
9273        setInputValue(value) {
9274            if (this.multiselect) {
9275                if (this.value) {
9276                    $$p(this.inputs.select).val(this.value.map((el) => el.value));
9277                }
9278                else {
9279                    $$p(this.inputs.select).val([]);
9280                }
9281            }
9282            else {
9283                this.inputs.select.value = this.value;
9284            }
9285            $$p(this.inputs.select).trigger("change.select2");
9286        }
9287    }
9288
9289    const $$q = jQuery;
9290    class StatusFormElement extends FormElement {
9291        constructor(options, formBuilder, external) {
9292            super(options, formBuilder, external);
9293            this.label = options.label || "Status";
9294            this.name = "status";
9295            this.setOptions(options.options);
9296        }
9297        setDomElements() {
9298            super.setDomElements();
9299            this.inputs.select = $$q(this.domElements.main).find("select")[0];
9300            if ($$q().colorpicker) {
9301                $$q(this.domElements.main)
9302                    .find(".cpicker")
9303                    .colorpicker()
9304                    .on("changeColor.colorpicker", function (event) {
9305                    const input = $$q(this).find("input");
9306                    if (input.val() == "")
9307                        $$q(this).find("i").css({ "background-color": "" });
9308                });
9309                this.domElements.edit &&
9310                    $$q(this.domElements.edit)
9311                        .find(".cpicker")
9312                        .colorpicker()
9313                        .on("changeColor.colorpicker", function (event) {
9314                        const input = $$q(this).find("input");
9315                        if (input.val() == "")
9316                            $$q(this).find("i").css({ "background-color": "" });
9317                    });
9318            }
9319        }
9320        destroy() {
9321            if ($$q().mselect2) {
9322                const sel = $$q(this.domElements.main).find(".mapsvg-select2");
9323                if (sel.length) {
9324                    sel.mselect2("destroy");
9325                }
9326            }
9327        }
9328        setEditorEventHandlers() {
9329            super.setEditorEventHandlers();
9330            const _this = this;
9331            $$q(this.domElements.edit).on("keyup change paste", ".mapsvg-edit-status-row input", function () {
9332                _this.mayBeAddStatusRow();
9333            });
9334        }
9335        initEditor() {
9336            super.initEditor();
9337            const _this = this;
9338            $$q(_this.domElements.edit)
9339                .find(".cpicker")
9340                .colorpicker()
9341                .on("changeColor.colorpicker", function (event) {
9342                const input = $$q(this).find("input");
9343                const index = $$q(this).closest("tr").index();
9344                if (input.val() == "")
9345                    $$q(this).find("i").css({ "background-color": "" });
9346                _this.options[index] = _this.options[index] || {
9347                    label: "",
9348                    value: "",
9349                    color: "",
9350                    disabled: false,
9351                };
9352                _this.options[index]["color"] = input.val();
9353            });
9354            _this.mayBeAddStatusRow();
9355        }
9356        mayBeAddStatusRow() {
9357            const _this = this;
9358            const editStatusRow = $$q($$q("#mapsvg-edit-status-row").html());
9359            const z = $$q(_this.domElements.edit).find(".mapsvg-edit-status-label:last-child");
9360            if (z && z.last() && z.last().val() && (z.last().val() + "").trim().length) {
9361                const newRow = editStatusRow.clone();
9362                newRow.insertAfter($$q(_this.domElements.edit).find(".mapsvg-edit-status-row:last-child"));
9363                newRow
9364                    .find(".cpicker")
9365                    .colorpicker()
9366                    .on("changeColor.colorpicker", function (event) {
9367                    const input = $$q(this).find("input");
9368                    const index = $$q(this).closest("tr").index();
9369                    if (input.val() == "")
9370                        $$q(this).find("i").css({ "background-color": "" });
9371                    _this.options[index] = _this.options[index] || {
9372                        label: "",
9373                        value: "",
9374                        color: "",
9375                        disabled: false,
9376                    };
9377                    _this.options[index]["color"] = input.val();
9378                });
9379            }
9380            const rows = $$q(_this.domElements.edit).find(".mapsvg-edit-status-row");
9381            const row1 = rows.eq(rows.length - 2);
9382            const row2 = rows.eq(rows.length - 1);
9383            if (row1.length &&
9384                row2.length &&
9385                !(row1.find("input:eq(0)").val().toString().trim() ||
9386                    row1.find("input:eq(1)").val().toString().trim() ||
9387                    row1.find("input:eq(2)").val().toString().trim()) &&
9388                !(row2.find("input:eq(0)").val().toString().trim() ||
9389                    row2.find("input:eq(1)").val().toString().trim() ||
9390                    row2.find("input:eq(2)").val().toString().trim())) {
9391                row2.remove();
9392            }
9393        }
9394        setEventHandlers() {
9395            super.setEventHandlers();
9396            $$q(this.inputs.select).on("change keyup paste", (e) => {
9397                this.setValue(e.target.value, false);
9398                this.triggerChanged();
9399            });
9400        }
9401        getSchema() {
9402            const schema = super.getSchema();
9403            const opts = $$q.extend(true, {}, { options: this.options });
9404            schema.options = opts.options;
9405            schema.optionsDict = {};
9406            schema.options.forEach(function (option, index) {
9407                if (schema.options[index].value === "") {
9408                    schema.options.splice(index, 1);
9409                }
9410                else {
9411                    schema.options[index].disabled = MapSVG.parseBoolean(schema.options[index].disabled);
9412                    schema.optionsDict[option.value] = option;
9413                }
9414            });
9415            return schema;
9416        }
9417        setInputValue(value) {
9418            this.inputs.select.value = value;
9419        }
9420    }
9421
9422    const $$r = jQuery;
9423    class TextareaFormElement extends FormElement {
9424        constructor(options, formBuilder, external) {
9425            super(options, formBuilder, external);
9426            this.searchType = options.searchType || "fulltext";
9427            this.searchable = MapSVG.parseBoolean(options.searchable);
9428            this.autobr = options.autobr;
9429            this.html = options.html;
9430            this.db_type = "text";
9431        }
9432        setDomElements() {
9433            super.setDomElements();
9434            this.inputs.textarea = $$r(this.domElements.main).find("textarea")[0];
9435            if (this.html) {
9436                this.editor = CodeMirror.fromTextArea(this.inputs.textarea, {
9437                    mode: { name: "handlebars", base: "text/html" },
9438                    matchBrackets: true,
9439                    lineNumbers: true,
9440                });
9441                if (this.formBuilder.admin) {
9442                    this.editor.on("change", this.setTextareaValue);
9443                }
9444            }
9445        }
9446        setEventHandlers() {
9447            super.setEventHandlers();
9448            $$r(this.inputs.textarea).on("change keyup paste", (e) => {
9449                this.setValue(e.target.value, false);
9450                this.triggerChanged();
9451            });
9452        }
9453        getSchema() {
9454            const schema = super.getSchema();
9455            schema.autobr = this.autobr;
9456            schema.html = this.html;
9457            return schema;
9458        }
9459        getDataForTemplate() {
9460            const data = super.getDataForTemplate();
9461            data.html = this.html;
9462            return data;
9463        }
9464        setTextareaValue(codemir
9464ror, changeobj) {
9465            const handler = codemirror.getValue();
9466            const textarea = $$r(codemirror.getTextArea());
9467            textarea.val(handler).trigger("change");
9468        }
9469        destroy() {
9470            const cm = $$r(this.domElements.main).find(".CodeMirror");
9471            if (cm.length) {
9472                cm.empty().remove();
9473            }
9474        }
9475    }
9476
9477    const $$s = jQuery;
9478    class TextFormElement extends FormElement {
9479        constructor(options, formBuilder, external) {
9480            super(options, formBuilder, external);
9481            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9482            this.searchType = options.searchType;
9483            this.width =
9484                this.formBuilder.filtersHide && !this.formBuilder.modal
9485                    ? null
9486                    : options.width || "100%";
9487            this.db_type = "varchar(255)";
9488        }
9489        setDomElements() {
9490            super.setDomElements();
9491            this.inputs.text = $$s(this.domElements.main).find('input[type="text"]')[0];
9492        }
9493        getSchema() {
9494            const schema = super.getSchema();
9495            schema.searchType = this.searchType;
9496            return schema;
9497        }
9498        setEventHandlers() {
9499            super.setEventHandlers();
9500            $$s(this.inputs.text).on("change keyup paste", (e) => {
9501                this.setValue(e.target.value, false);
9502                this.triggerChanged();
9503            });
9504        }
9505        setInputValue(value) {
9506            this.inputs.text.value = value;
9507        }
9508    }
9509
9510    const $$t = jQuery;
9511    class TitleFormElement extends FormElement {
9512        constructor(options, formBuilder, external) {
9513            super(options, formBuilder, external);
9514            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9515            this.width =
9516                this.formBuilder.filtersHide && !this.formBuilder.modal
9517                    ? null
9518                    : options.width || "100%";
9519            this.db_type = "varchar(255)";
9520        }
9521        setDomElements() {
9522            super.setDomElements();
9523            this.inputs.text = $$t(this.domElements.main).find('input[type="text"]')[0];
9524        }
9525        getSchema() {
9526            const schema = super.getSchema();
9527            schema.searchType = this.searchType;
9528            return schema;
9529        }
9530        setEventHandlers() {
9531            super.setEventHandlers();
9532            $$t(this.inputs.text).on("change keyup paste", (e) => {
9533                this.setValue(e.target.value, false);
9534                this.triggerChanged();
9535            });
9536        }
9537        setInputValue(value) {
9538            this.inputs.text.value = value;
9539        }
9540    }
9541
9542    const $$u = jQuery;
9543    class ColorPickerFormElement extends FormElement {
9544        constructor(options, formBuilder, external) {
9545            super(options, formBuilder, external);
9546            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9547            this.width =
9548                this.formBuilder.filtersHide && !this.formBuilder.modal
9549                    ? null
9550                    : options.width || "100%";
9551            this.db_type = "varchar(255)";
9552        }
9553        setDomElements() {
9554            super.setDomElements();
9555            this.inputs.text = $$u(this.domElements.main).find("input.cpicker")[0];
9556            $$u(this.domElements.main).find(".colorpicker-element").colorpicker();
9557        }
9558        getSchema() {
9559            const schema = super.getSchema();
9560            schema.searchType = this.searchType;
9561            return schema;
9562        }
9563        setEventHandlers() {
9564            super.setEventHandlers();
9565            $$u(this.inputs.text).on("change keyup paste", (e) => {
9566                this.setValue(e.target.value, false);
9567                this.triggerChanged();
9568            });
9569            $$u(this.domElements.main).find(".colorpicker-element").colorpicker().on("changeColor.colorpicker", (e) => {
9570                this.setValue(this.inputs.text.value, false);
9571                this.triggerChanged();
9572            });
9573        }
9574        setInputValue(value) {
9575            this.inputs.text.value = value;
9576        }
9577    }
9578
9579    const $$v = jQuery;
9580    class FormElementFactory {
9581        constructor(options) {
9582            this.mapsvg = options.mapsvg;
9583            this.editMode = options.editMode;
9584            this.filtersMode = options.filtersMode;
9585            this.namespace = options.namespace;
9586            this.mediaUploader = options.mediaUploader;
9587            this.formBuilder = options.formBuilder;
9588            this.showNames = options.showNames !== false;
9589        }
9590        create(options) {
9591            const types = {
9592                checkbox: CheckboxFormElement,
9593                checkboxes: CheckboxesFormElement,
9594                date: DateFormElement,
9595                distance: DistanceFormElement,
9596                empty: EmptyFormElement,
9597                id: IdFormElement,
9598                image: ImagesFormElement,
9599                location: LocationFormElement,
9600                modal: ModalFormElement,
9601                post: PostFormElement,
9602                radio: RadioFormElement,
9603                region: RegionsFormElement,
9604                save: SaveFormElement,
9605                search: SearchFormElement,
9606                select: SelectFormElement,
9607                status: StatusFormElement,
9608                text: TextFormElement,
9609                textarea: TextareaFormElement,
9610                title: TitleFormElement,
9611                colorpicker: ColorPickerFormElement,
9612            };
9613            const formElement = new types[options.type](options, this.formBuilder, this.getExtraParams());
9614            formElement.init();
9615            return formElement;
9616        }
9617        getExtraParams() {
9618            const databaseFields = [];
9619            const databaseFieldsFilterable = [];
9620            const databaseFieldsFilterableShort = [];
9621            const regionFields = [];
9622            const regionFieldsFilterable = [];
9623            const regions = new ArrayIndexed("id");
9624            let mapIsGeo = false;
9625            if (this.mapsvg) {
9626                mapIsGeo = this.mapsvg.isGeo();
9627                const schemaObjects = this.mapsvg.objectsRepository.getSchema();
9628                if (schemaObjects) {
9629                    schemaObjects.getFields().forEach(function (obj) {
9630                        if (obj.type == "text" ||
9631                            obj.type == "region" ||
9632                            obj.type == "textarea" ||
9633                            obj.type == "post" ||
9634                            obj.type == "select" ||
9635                            obj.type == "radio" ||
9636                            obj.type == "checkbox") {
9637                            if (obj.type == "post") {
9638                                databaseFields.push("Object.post.post_title");
9639                            }
9640                            else {
9641                                databaseFields.push("Object." + obj.name);
9642                            }
9643                        }
9644                        if (obj.type == "region" || obj.type == "select" || obj.type == "radio") {
9645                            databaseFieldsFilterable.push("Object." + obj.name);
9646                            databaseFieldsFilterableShort.push(obj.name);
9647                        }
9648                    });
9649                }
9650                const schemaRegions = this.mapsvg.regionsRepository.getSchema();
9651                if (schemaRegions) {
9652                    schemaRegions.getFieldsAsArray().forEach(function (obj) {
9653                        if (obj.type == "status" ||
9654                            obj.type == "text" ||
9655                            obj.type == "textarea" ||
9656                            obj.type == "post" ||
9657                            obj.type == "select" ||
9658                            obj.type == "radio" ||
9659                            obj.type == "checkbox") {
9660                            if (obj.type == "post") {
9661                                regionFields.push("Region.post.post_title");
9662                            }
9663                            else {
9664                                regionFields.push("Region." + obj.name);
9665                            }
9666                        }
9667                        if (obj.type == "status" || obj.type == "select" || obj.type == "radio") {
9668                            regionFieldsFilterable.push("Region." + obj.name);
9669                        }
9670                    });
9671                }
9672                this.mapsvg.regions.forEach((region) => {
9673                    regions.push({ id: region.id, title: region.title });
9674                });
9675            }
9676            return {
9677                databaseFields: databaseFields,
9678                databaseFieldsFilterable: databaseFieldsFilterable,
9679                databaseFieldsFilterableShort: databaseFieldsFilterableShort,
9680                regionFields: regionFields,
9681                regionFieldsFilterable: regionFieldsFilterable,
9682                regions: regions,
9683                mapIsGeo: mapIsGeo,
9684                mediaUploader: this.mediaUploader,
9685                filtersMode: this.filtersMode,
9686                showNames: this.showNames,
9687            };
9688        }
9689    }
9690
9691    const $$w = jQuery;
9692    class FormBuilder {
9693        constructor(options) {
9694            const _this = this;
9695            this.events = new Events();
9696            this.container = options.container;
9697            this.namespace = options.namespace;
9698            this.mediaUploader = options.mediaUploader;
9699            this.schema = options.schema || [];
9700            this.editMode = options.editMode == undefined ? false : options.editMode;
9701            this.filtersMode = options.filtersMode == undefined ? false : options.filtersMode;
9702            this.filtersHide = options.filtersHide == undefined ? false : options.filtersHide;
9703            this.modal = options.modal == undefined ? false : options.modal;
9704            this.admin = options.admin;
9705            this.mapsvg = options.mapsvg;
9706            this.data = options.data || {};
9707            this.clearButton = options.clearButton || false;
9708            this.clearButtonText = options.clearButtonText || "";
9709            this.searchButton = options.searchButton || false;
9710            this.searchButtonText = options.searchButtonText || "";
9711            this.showButtonText = options.showButtonText || "";
9712            this.scrollable =
9713                typeof options.scrollable !== "undefined"
9714                    ? options.scrollable
9715                    : !_this.editMode && !_this.filtersMode;
9716            this.showNames = typeof options.showNames !== "undefined" ? options.showNames : true;
9717            this.formElementFactory = new FormElementFactory({
9718                mapsvg: this.mapsvg,
9719                formBuilder: this,
9720                mediaUploader: this.mediaUploader,
9721                editMode: this.editMode,
9722                filtersMode: this.filtersMode,
9723                namespace: this.namespace,
9724                showNames: this.showNames,
9725            });
9726            this.events = new Events(this);
9727            if (options.events && Object.keys(options.events).length > 0) {
9728                for (const eventName in options.events) {
9729                    this.events.on(eventName, options.events[eventName]);
9730                }
9731            }
9732            this.template = "form-builder";
9733            this.closeOnSave = options.closeOnSave === true;
9734            this.newRecord = options.newRecord === true;
9735            this.types = options.types || [
9736                "text",
9737                "textarea",
9738                "checkbox",
9739                "radio",
9740                "select",
9741                "image",
9742                "region",
9743                "location",
9744                "post",
9745                "date",
9746            ];
9747            this.templates = {};
9748            this.elements = {};
9749            this.view = $$w("<div />").addClass("mapsvg-form-builder")[0];
9750            if (this.editMode)
9751                $$w(this.view).addClass("full-flex");
9752            if (!this.showNames) {
9753                $$w(this.view).addClass("hide-names");
9754            }
9755            this.formElements = new ArrayIndexed("name");
9756            if (!MapSVG.templatesLoaded[this.template]) {
9757                this.loadTemplates(() => this.init());
9758            }
9759            else {
9760                this.init();
9761            }
9762        }
9763        loadTemplates(callback) {
9764            $$w.get(MapSVG.urls.root + "dist/" + this.template + ".html?v=" + MapSVG.version, (data) => {
9765                $$w(data).appendTo("body");
9766                MapSVG.templatesLoaded[this.template] = true;
9767                Handlebars.registerPartial("dataMarkerPartial", $$w("#mapsvg-data-tmpl-marker").html());
9768                if (this.editMode) {
9769                    Handlebars.registerPartial("markerByFieldPartial", $$w("#mapsvg-markers-by-field-tmpl-partial").html());
9770                }
9771                callback();
9772            });
9773        }
9774        init() {
9775            const _this = this;
9776            MapSVG.formBuilder = this;
9777            this.form = document.createElement("form");
9778            this.form.className = "mapsvg-data-form-view";
9779            if (!this.filtersMode) {
9780                this.form.classList.add("form-horizontal");
9781            }
9782            if (this.editMode) {
9783                const template = document.getElementById("mapsvg-form-editor-tmpl-ui").innerHTML;
9784                const templateCompiled = Handlebars.compile(template);
9785                this.view.innerHTML = templateCompiled({ types: this.types });
9786                this.view.classList.add("edit");
9787                this.form.classList.add("mapsvg-data-flex-full");
9788                this.form.classList.add("mapsvg-data-container");
9789                $$w(this.view).find(".mapsvg-data-preview").prepend(this.form);
9790                this.formEditor = $$w(this.view).find("#mapsvg-data-form-edit")[0];
9791            }
9792            else {
9793                this.view.appendChild(this.form);
9794            }
9795            _this.elements = {
9796                buttons: {
9797                    text: $$w(_this.view).find("#mapsvg-data-btn-text")[0],
9798                    textarea: $$w(_this.view).find("#mapsvg-data-btn-textarea")[0],
9799                    checkbox: $$w(_this.view).find("#mapsvg-data-btn-checkbox")[0],
9800                    radio: $$w(_this.view).find("#mapsvg-data-btn-radio")[0],
9801                    select: $$w(_this.view).find("#mapsvg-data-btn-select")[0],
9802                    image: $$w(_this.view).find("#mapsvg-data-btn-image")[0],
9803                    region: $$w(_this.view).find("#mapsvg-data-btn-region")[0],
9804                    marker: $$w(_this.view).find("#mapsvg-data-btn-marker")[0],
9805                    saveSchema: $$w(_this.view).find("#mapsvg-data-btn-save-schema")[0],
9806                },
9807                containers: {
9808                    buttons_add: $$w(_this.view).find("#mapsvg-data-buttons-add")[0],
9809                },
9810            };
9811            _this.redraw();
9812        }
9813        getForm() {
9814            return this.form;
9815        }
9816        getFormEditor() {
9817            return this.formEditor;
9818        }
9819        viewDidLoad() { }
9820        setEventHandlers() {
9821            const _this = this;
9822            $$w(this.getForm()).on("submit", (e) => {
9823                e.preventDefault();
9824            });
9825            if (this.filtersMode && this.clearButton) {
9826                $$w(this.elements.buttons.clearButton).on("click", (e) => {
9827                    e.preventDefault();
9828                    this.clearAllFields();
9829                });
9830            }
9831            $$w(window)
9832                .off("keydown.form.mapsvg")
9833                .on("keydown.form.mapsvg", function (e) {
9834                if (MapSVG.formBuilder) {
9835                    if ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
9836                        MapSVG.formBuilder.save();
9837                    else if (e.keyCode == 27)
9838                        MapSVG.formBuilder.close();
9839                }
9840            });
9841            if (this.editMode) {
9842                $$w(this.view).on("click", "#mapsvg-data-buttons-add button", function (e) {
9843                    e.preventDefault();
9844                    const type = $$w(this).data("create");
9845                    const formElement = _this.formElementFactory.create({ type: type });
9846                    _this.addField(formElement);
9847                });
9848                $$w(this.view).on("click", "#mapsvg-data-btn-save-schema", function (e) {
9849                    e.preventDefault();
9850                    const fields = _this.getSchema();
9851                    const counts = {};
9852                    _this.formElements.forEach(function (elem) {
9853                        counts[elem.name] = (counts[elem.name] || 0) + 1;
9854                    });
9855                    $$w(_this.getForm()).find(".form-group").removeClass("has-error");
9856                    const errors = [];
9857                    const reservedFields = [
9858                        "lat",
9859                        "lon",
9860                        "lng",
9861                        "location",
9862                        "location_lat",
9863                        "location_lon",
9864                        "location_lng",
9865                        "location_address",
9866                        "location_img",
9867                        "marker",
9868                        "marker_id",
9869                        "regions",
9870                        "region_id",
9871                        "post",
9872                        "post_title",
9873                        "post_url",
9874                        "keywords",
9875                        "status",
9876                    ];
9877                    const reservedFieldsToTypes = {
9878                        regions: "region",
9879                        status: "status",
9880                        post: "post",
9881                        marker: "marker",
9882                        location: "location",
9883                    };
9884                    let errUnique, errEmpty;
9885                    _this.formElements.forEach(function (formElement, index) {
9886                        let err = false;
9887                        if (!_this.filtersMode) {
9888                            if (counts[formElement.name] > 1) {
9889                                if (!errUnique) {
9890                                    errUnique = "Field names should be unique";
9891                                    errors.push(errUnique);
9892                                    err = true;
9893                                }
9894                            }
9895                            else if (formElement.name.length === 0) {
9896                                if (!errEmpty) {
9897                                    errEmpty = "Field name can't be empty";
9898                                    errors.push(errEmpty);
9899                                    err = true;
9900                                }
9901                            }
9902                            else if (reservedFields.indexOf(formElement.name) != -1) {
9903                                if (!reservedFieldsToTypes[formElement.name] ||
9904                                    (reservedFieldsToTypes[formElement.name] &&
9905                                        reservedFieldsToTypes[formElement.name] != formElement.type)) {
9906                                    const msg = 'Field name "' +
9907                                        formElement.name +
9908                                        '" is reserved, please set another name';
9909                                    errors.push(msg);
9910                                    err = true;
9911                                }
9912                            }
9913                        }
9914                        if (formElement.options &&
9915                            formElement.type != "region" &&
9916                            formElement.type != "marker") {
9917                            const vals = formElement.options.map(function (obj) {
9918                                return obj.value;
9919                            });
9920                            const uniq = [...Array.from(new Set(vals).values())];
9921                            if (vals.length != uniq.length) {
9922                                errors.push('Check "Options" list - values should not repeat');
9923                                err = true;
9924                            }
9925                        }
9926                        err && $$w(formElement.domElements.main).addClass("has-error");
9927                    });
9928                    if (errors.length === 0) {
9929                        _this.events.trigger("saveSchema", _this, [_this, fields]);
9930                    }
9931                    else {
9932                        jQuery.growl.error({ title: "Errors", message: errors.join("<br />") });
9933                    }
9934                });
9935                setTimeout(function () {
9936                    const el = _this.getForm();
9937                    _this.sortable = new Sortable(el, {
9938                        animation: 150,
9939                        onStart: function () {
9940                            $$w(_this.getForm()).addClass("sorting");
9941                        },
9942                        onEnd: function () {
9943                            setTimeout(function () {
9944                                $$w(_this.getForm()).removeClass("sorting");
9945                                _this.formElements.clear();
9946                                $$w(el)
9947                                    .find(".form-group")
9948                                    .each(function (index, elem) {
9949                                    _this.formElements.push($$w(elem).data("formElement"));
9950                                });
9951                            }, 500);
9952                        },
9953                    });
9954                }, 1000);
9955            }
9956            new ResizeSensor(this.view, function () {
9957                _this.scrollApi && _this.scrollApi.reinitialise();
9958            });
9959        }
9960        clearAllFields() {
9961            this.formElements.forEach((f) => f.setValue(null));
9962            this.events.trigger("cleared");
9963        }
9964        setFormElementEventHandlers(formElement) {
9965            if (this.editMode) {
9966                formElement.events.on("click", (elem) => {
9967                    this.edit(elem);
9968                });
9969                formElement.events.on("delete", (elem) => {
9970                    this.deleteField(elem);
9971                });
9972            }
9973            else {
9974                formElement.events.on("changed", (_formElement) => {
9975                    const name = _formElement.name;
9976                    const value = _formElement.getValue();
9977                    if (_formElement.type !== "search") {
9978                        this.events.trigger("changed.field", _formElement, [_formElement, name, value]);
9979                    }
9980                    else {
9981                        this.events.trigger("changed.search", _formElement, [_formElement, value]);
9982                    }
9983                });
9984            }
9985        }
9986        save() {
9987            const _this = this;
9988            if (_this.markerBackup) {
9989                const marker = _this.mapsvg.getEditingMarker();
9990                marker.events.off("change");
9991                _this.markerBackup = marker.getOptions();
9992                _this.mapsvg.unsetEditingMarker();
9993            }
9994            const data = _this.getData();
9995            _this.saved = true;
9996            this.events.trigger("save", _this, [_this, data]);
9997        }
9998        getFormElementByType(type) {
9999            return this.formElements.find((el) => el.type === type);
10000        }
10001        getData() {
10002            const data = {};
10003            this.formElements.forEach((formElement) => {
10004                if (formElement.readonly === false || formElement.type === "id") {
10005                    const _formElementData = formElement.getData();
10006                    data[_formElementData.name] = _formElementData.value;
10007                }
10008            });
10009            return data;
10010        }
10011        reset() {
10012            this.formElements.forEach((formElement) => {
10013                formElement.setValue(null);
10014            });
10015        }
10016        update(data) {
10017            this.schema.getFields().forEach((field) => {
10018                const formElement = this.formElements.get(field.name);
10019                if (formElement) {
10020                    if (typeof data[field.name] !== "undefined") {
10021                        if (formElement.getValue() !== data[field.name]) {
10022                            formElement.setValue(data[field.name]);
10023                        }
10024                    }
10025                    else {
10026                        formElement.setValue(null);
10027                    }
10028                }
10029            });
10030        }
10031        redraw() {
10032            const _this = this;
10033            delete _this.markerBackup;
10034            $$w(this.container).empty();
10035            $$w(this.getForm()).empty();
10036            this.formElements.clear();
10037            this.schema &&
10038                this.schema.fields.length > 0 &&
10039                this.schema.fields.forEach((fieldSettings) => {
10040                    if (this.filtersMode) {
10041                        if (fieldSettings.type == "distance") {
10042                            fieldSettings.value = this.data.distance
10043                                ? this.data.distance
10044                                : fieldSettings.value !== undefined
10045                                    ? fieldSettings.value
10046                                    : null;
10047                        }
10048                        else {
10049                            fieldSettings.value = this.data[fieldSettings.parameterNameShort];
10050                        }
10051                    }
10052                    else {
10053                        fieldSettings.value = this.data
10054                            ? this.data[fieldSettings.name]
10055                            : fieldSettings.value !== undefined
10056                                ? fieldSettings.value
10057                                : null;
10058                    }
10059                    if (fieldSettings.type == "location" && !this.editMode) {
10060                        if (fieldSettings.value &&
10061                            fieldSettings.value.marker &&
10062                            fieldSettings.value.marker.id) ;
10063                        this.admin && this.admin.setMode && this.admin.setMode("editMarkers");
10064                        this.admin && this.admin.enableMarkersMode(true);
10065                    }
10066                    else if (fieldSettings.type == "post") {
10067                        fieldSettings.post = this.data["post"];
10068                    }
10069                    else if (fieldSettings.type === "region") {
10070                        fieldSettings.options = new ArrayIndexed("id", this.getRegionsList());
10071                    }
10072                    const formElement = this.formElementFactory.create(fieldSettings);
10073                    if (this.filtersMode) {
10074                        if (!this.filtersHide ||
10075                            (this.filtersHide && this.modal && fieldSettings.type !== "search") ||
10076                            (!this.modal && fieldSettings.type === "search")) {
10077                            this.addField(formElement);
10078                        }
10079                    }
10080                    else {
10081                        this.addField(formElement);
10082                    }
10083                });
10084            if (!_this.editMode) {
10085                if (this.schema.fields.length === 0 && !this.filtersMode) {
10086                    const formElement = this.formElementFactory.create({ type: "empty" });
10087                    _this.addField(formElement);
10088                }
10089                else {
10090                    if (_this.admin && !_this.admin.isMetabox) {
10091                        const formElement = this.formElementFactory.create({ type: "save" });
10092                        formElement.events.on("click.btn.save", () => {
10093                            this.save();
10094                        });
10095                        formElement.events.on("click.btn.close", () => {
10096                            this.close();
10097                        });
10098                        _this.addField(formElement);
10099                    }
10100                }
10101            }
10102            if (_this.filtersMode && _this.filtersHide && !_this.modal) {
10103                const formElement = this.formElementFactory.create({
10104                    type: "modal",
10105                    showButtonText: _this.showButtonText,
10106                });
10107                this.showFiltersButton = _this.addField(formElement);
10108            }
10109            if (this.scrollable) {
10110                const nano = $$w('<div class="nano"></div>');
10111                const nanoContent = $$w('<div class="nano-content"></div>');
10112                nano.append(nanoContent);
10113                nanoContent.append(this.view);
10114                $$w(_this.container).append(nano);
10115                nano.jScrollPane({ contentWidth: "0px", mouseWheelSpeed: 30 });
10116                _this.scrollApi = nano.data("jsp");
10117            }
10118            else {
10119                $$w(_this.container).append(this.view);
10120            }
10121            if (_this.filtersMode && _this.clearButton) {
10122                _this.elements.buttons.clearButton = $$w('<div class="form-group mapsvg-filters-reset-container">' +
10123                    '<button type="button" class="btn btn-outline-secondary mapsvg-filters-reset">' +
10124                    _this.clearButtonText +
10125                    "</button></div>")[0];
10126                $$w(this.getForm()).append(_this.elements.buttons.clearButton);
10127            }
10128            if (_this.filtersMode && _this.searchButton) {
10129                _this.elements.buttons.searchButton = $$w('<div class="form-group mapsvg-filters-reset-container" id="mapsvg-search-container"><button class="btn btn-outline-secondary mapsvg-filters-reset">' +
10130                    _this.searchButtonText +
10131                    "</button></div>")[0];
10132                $$w(this.getForm()).append(_this.elements.buttons.searchButton);
10133            }
10134            if (!this.editMode && !_this.filtersMode)
10135                $$w(this.view).find("input:visible,textarea:visible").not(".tt-hint").first().focus();
10136            const cm = $$w(this.container).find(".CodeMirror");
10137            cm.each(function (index, el) {
10138                el && el.CodeMirror.refresh();
10139            });
10140            _this.setEventHandlers();
10141            this.events.trigger("init", this, [this, this.getData()]);
10142            this.events.trigger("loaded", this, [this]);
10143        }
10144        updateExtraParamsInFormElements() {
10145            this.formElements.forEach((formElement) => {
10146                formElement.setExternal(this.formElementFactory.getExtraParams());
10147                if (formElement.type === "location") {
10148                    formElement.redraw();
10149                }
10150            });
10151        }
10152        deleteField(formElement) {
10153            const _this = this;
10154            _this.formElements.delete(formElement.name);
10155        }
10156        getExtraParams() {
10157            const databaseFields = [];
10158            this.mapsvg.objectsRepository
10159                .getSchema()
10160                .getFields()
10161                .forEach(function (obj) {
10162                if (obj.type == "text" ||
10163                    obj.type == "region" ||
10164                    obj.type == "textarea" ||
10165                    obj.type == "post" ||
10166                    obj.type == "select" ||
10167                    obj.type == "radio" ||
10168                    obj.type == "checkbox") {
10169                    if (obj.type == "post") {
10170                        databaseFields.push("Object.post.post_title");
10171                    }
10172                    else {
10173                        databaseFields.push("Object." + obj.name);
10174                    }
10175                }
10176            });
10177            let databaseFieldsFilterableShort = [];
10178            databaseFieldsFilterableShort = this.mapsvg.objectsRepository
10179                .getSchema()
10180                .getFieldsAsArray()
10181                .filter(function (obj) {
10182                return obj.type == "select" || obj.type == "radio" || obj.type == "region";
10183            })
10184                .map(function (obj) {
10185                return obj.name;
10186            });
10187            let markerFieldsShort = [];
10188            markerFieldsShort = databaseFieldsFilterableShort.filter((o) => o.type === "select" || o.type === "radio");
10189            const regionFields = this.mapsvg.regionsRepository
10190                .getSchema()
10191                .getFieldsAsArray()
10192                .map(function (obj) {
10193                if (obj.type == "status" ||
10194                    obj.type == "text" ||
10195                    obj.type == "textarea" ||
10196                    obj.type == "post" ||
10197                    obj.type == "select" ||
10198                    obj.type == "radio" ||
10199                    obj.type == "checkbox") {
10200                    if (obj.type == "post") {
10201                        return "Region.post.post_title";
10202                    }
10203                    else {
10204                        return "Region." + obj.name;
10205                    }
10206                }
10207            });
10208            return {
10209                databaseFields: databaseFields,
10210                databaseFieldsFilterableShort: databaseFieldsFilterableShort,
10211                regionFields: regionFields,
10212                markerFieldsShort: markerFieldsShort,
10213            };
10214        }
10215        addField(formElement) {
10216            const _this = this;
10217            if (["region", "marker", "post", "status", "distance", "location", "search"].indexOf(formElement.type) != -1) {
10218                let repeat = false;
10219                _this.formElements.forEach(function (control) {
10220                    if (control.type == formElement.type)
10221                        repeat = true;
10222                });
10223                if (repeat) {
10224                    jQuery.growl.error({
10225                        title: "Error",
10226                        message: 'You can add only 1 "' + MapSVG.ucfirst(formElement.type) + '" field',
10227                    });
10228                    return;
10229                }
10230            }
10231            _this.formElements.push(formElement);
10232            _this.getForm().append(formElement.domElements.main);
10233            this.setFormElementEventHandlers(formElement);
10234            if (this.editMode) {
10235                if (formElement.protected) {
10236                    formElement.hide();
10237                }
10238                else {
10239                    this.edit(formElement);
10240                }
10241            }
10242            return formElement;
10243        }
10244        edit(formElement) {
10245            const _this = this;
10246            _this.currentlyEditing && _this.currentlyEditing.destroyEditor();
10247            this.getFormEditor().appendChild(formElement.getEditor());
10248            formElement.initEditor();
10249            _this.currentlyEditing = formElement;
10250            $$w(_this.getForm()).find(".form-group.active").removeClass("active");
10251            $$w(formElement.domElements.main).addClass("active");
10252        }
10253        get() {
10254        }
10255        getSchema() {
10256            return this.formElements.map(function (formElement) {
10257                return formElement.getSchema();
10258            });
10259        }
10260        close() {
10261            this.formElements.forEach((formElement) => formElement.destroy());
10262            this.mediaUploader && this.mediaUploader.off("select");
10263            MapSVG.formBuilder = null;
10264            this.events.trigger("close", this, [this]);
10265        }
10266        destroy() {
10267            $$w(this.view).empty().remove();
10268            this.sortable = null;
10269        }
10270        toJSON(addEmpty) {
10271            const obj = {};
10272            function add(obj, name, value) {
10273                if (!addEmpty && !value)
10274                    return false;
10275                if (name.length == 1) {
10276                    obj[name[0]] = value;
10277                }
10278                else {
10279                    if (obj[name[0]] == null) {
10280                        if (name[1] === "") {
10281                            obj[name[0]] = [];
10282                        }
10283                        else {
10284                            obj[name[0]] = {};
10285                        }
10286                    }
10287                    if (obj[name[0]].length !== undefined) {
10288                        obj[name[0]].push(value);
10289                    }
10290                    else {
10291                        add(obj[name[0]], name.slice(1), value);
10292                    }
10293                }
10294            }
10295            $$w(this.elements.containers.formView)
10296                .find("input, textarea, select")
10297                .each(function () {
10298                if (!$$w(this).data("skip") &&
10299                    !$$w(this).prop("disabled") &&
10300                    $$w(this).attr("name") &&
10301                    !(!addEmpty &&
10302                        $$w(this).attr("type") == "checkbox" &&
10303                        $$w(this).attr("checked") == undefined) &&
10304                    !($$w(this).attr("type") == "radio" && $$w(this).attr("checked") == undefined)) {
10305                    let value;
10306                    if ($$w(this).attr("type") == "checkbox") {
10307                        value = $$w(this).prop("checked");
10308                    }
10309                    else {
10310                        value = $$w(this).val();
10311                    }
10312                    add(obj, $$w(this).attr("name").replace(/]/g, "").split("["), value);
10313                }
10314            });
10315            return obj;
10316        }
10317        getRegionsList() {
10318            return this.mapsvg.regions.map(function (r) {
10319                return { id: r.id, title: r.title };
10320            });
10321        }
10322        getRegionsAsArray() {
10323            return this.mapsvg.regions;
10324        }
10325        setRegions(location) {
10326            const regionsFormElement = this.formElements.get("regions");
10327            if (this.mapsvg.options.source.indexOf("/geo-calibrated/us
10327a.svg") !== -1) {
10328                regionsFormElement.setValue(["US-" + location.address.state_short]);
10329            }
10330            else if (this.mapsvg.options.source.indexOf("/geo-calibrated/world.svg") !== -1) {
10331                if (location.address.country_short) {
10332                    regionsFormElement.setValue([location.address.country_short]);
10333                }
10334            }
10335            else {
10336                if (location.address.administrative_area_level_1) {
10337                    this.mapsvg.regions.forEach((_region) => {
10338                        if (_region.title === location.address.administrative_area_level_1 ||
10339                            _region.title === location.address.administrative_area_level_2 ||
10340                            _region.id ===
10341                                location.address.country_short +
10342                                    "-" +
10343                                    location.address.administrative_area_level_1_short) {
10344                            regionsFormElement.setValue([_region.id]);
10345                        }
10346                    });
10347                }
10348            }
10349        }
10350        setIsLoading(value) {
10351            this.isLoading = value;
10352            if (this.searchButton) {
10353                if (this.isLoading) {
10354                    $$w(this.elements.buttons.searchButton).find("button").attr("disabled", "disabled");
10355                }
10356                else {
10357                    $$w(this.elements.buttons.searchButton).find("button").removeAttr("disabled");
10358                }
10359            }
10360        }
10361    }
10362
10363    const $$x = jQuery;
10364    class FiltersController extends DetailsController {
10365        constructor(options) {
10366            super(options);
10367            this.showButtonText = options.showButtonText;
10368            this.clearButton = options.clearButton;
10369            this.clearButtonText = options.clearButtonText;
10370            this.searchButton = options.searchButton;
10371            this.searchButtonText = options.searchButtonText;
10372            this.padding = options.padding;
10373            this.schema = options.schema;
10374            this.hideFilters = options.hide;
10375            this.query = options.query;
10376        }
10377        viewDidLoad() {
10378            super.viewDidLoad();
10379            const _this = this;
10380            this.formBuilder = new FormBuilder({
10381                container: this.containers.contentView,
10382                filtersMode: true,
10383                schema: this.schema,
10384                modal: this.modal,
10385                filtersHide: this.hideFilters,
10386                showButtonText: this.showButtonText,
10387                clearButton: this.clearButton,
10388                clearButtonText: this.clearButtonText,
10389                searchButton: this.searchButton,
10390                searchButtonText: this.searchButtonText,
10391                editMode: false,
10392                mapsvg: this.mapsvg,
10393                data: {},
10394                admin: false,
10395                events: {
10396                    "changed.field": (formElement, field, value) => {
10397                        const filters = {};
10398                        let _value = value;
10399                        if (field === "regions") {
10400                            _value = {};
10401                            _value.region_ids = value instanceof Array ? value : [value];
10402                            _value.table_name = this.mapsvg.options.database.regionsTableName;
10403                            if (_value.region_ids.length === 0 || _value.region_ids[0] === "") {
10404                                _value = null;
10405                            }
10406                        }
10407                        filters[field] = _value;
10408                        this.query.setFilters(filters);
10409                        _this.events.trigger("changed.field", _this, [field, value]);
10410                        _this.events.trigger("changed.fields", _this, [field, value]);
10411                    },
10412                    "changed.search": (formElement, value) => {
10413                        this.query.setSearch(value);
10414                        _this.events.trigger("changed.search", _this, [value]);
10415                    },
10416                    cleared: (formBuilder) => {
10417                        this.query.clearFilters();
10418                        this.events.trigger("cleared", _this, []);
10419                    },
10420                    loaded: (formBuilder) => {
10421                        $$x(formBuilder.container).find(".mapsvg-form-builder").css({
10422                            padding: _this.padding,
10423                        });
10424                        this.updateScroll();
10425                        this.events.trigger("loaded");
10426                    },
10427                },
10428            });
10429        }
10430        reset() {
10431            this.formBuilder && this.formBuilder.reset();
10432        }
10433        update(query) {
10434            const _query = Object.assign({}, query.filters);
10435            _query.search = query.search;
10436            this.formBuilder && this.formBuilder.update(_query);
10437        }
10438        setFiltersCounter() {
10439            if (this.hideFilters) {
10440                const filtersCounter = Object.keys(this.query.filters).length;
10441                const filtersCounterString = filtersCounter === 0 ? "" : f
10441iltersCounter.toString();
10442                this.formBuilder &&
10443                    this.formBuilder.showFiltersButton &&
10444                    $$x(this.formBuilder.showFiltersButton.domElements.main)
10445                        .find("button")
10446                        .html(this.showButtonText + " <b>" + filtersCounterString + "</b>");
10447            }
10448        }
10449        setEventHandlers() {
10450            super.setEventHandlers();
10451            const _this = this;
10452            $$x(this.containers.view).on("click", ".mapsvg-btn-show-filters", function () {
10453                _this.events.trigger("click.btn.showFilters");
10454            });
10455            $$x(this.containers.view).on("click", "#mapsvg-search-container button", function () {
10456                _this.events.trigger("click.btn.searchButton");
10457            });
10458        }
10459    }
10460
10461    const $$y = jQuery;
10462    class PopoverController extends Controller {
10463        constructor(options) {
10464            super(options);
10465            this.autoresize = true;
10466            this.point = options.point;
10467            this.yShift = options.yShift;
10468            this.mapObject = options.mapObject;
10469            this.id = this.mapObject.id + "_" + Math.random();
10470            $$y(this.containers.main).data("popover-id", this.id);
10471        }
10472        setPoint(point) {
10473            this.point = point;
10474        }
10475        getToolbarTemplate() {
10476            if (this.withToolbar)
10477                return '<div class="mapsvg-popover-close"></div>';
10478            else
10479                return "";
10480        }
10481        viewDidLoad() {
10482            super.viewDidLoad.call(this);
10483            if (MapSVG.isPhone &&
10484                this.mapsvg.options.popovers.mobileFullscreen &&
10485                !this.mobileCloseBtn) {
10486                this.mobileCloseBtn = $$y('<button class="mapsvg-mobile-modal-close">' +
10487                    this.mapsvg.getData().options.mobileView.labelClose +
10488                    "</button>")[0];
10489                $$y(this.containers.view).append(this.mobileCloseBtn);
10490            }
10491            this.adjustScreenPosition();
10492            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", true);
10493            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", true);
10494            this.adjustHeight();
10495            this.updateScroll();
10496            this.autoresize && this.resizeSensor.setScroll();
10497            this.events.trigger("shown", this, [this]);
10498        }
10499        adjustHeight() {
10500            $$y(this.containers.main).height($$y(this.containers.main).find(".mapsvg-auto-height").outerHeight() +
10501                (this.containers.toolbar ? $$y(this.containers.toolbar).outerHeight() : 0));
10502        }
10503        adjustScreenPosition() {
10504            if (this.point) {
10505                const pos = this.mapsvg.converter.convertSVGToPixel(this.point);
10506                pos.y -= this.yShift;
10507                pos.x = Math.round(pos.x);
10508                pos.y = Math.round(pos.y);
10509                this.setScreenPosition(pos.x, pos.y);
10510            }
10511        }
10512        moveSrceenPositionBy(deltaX, deltaY) {
10513            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
10514            this.setScreenPosition(x, y);
10515        }
10516        setScreenPosition(x, y) {
10517            this.screenPoint = new ScreenPoint(x, y);
10518            $$y(this.containers.main).css({
10519                transform: "translateX(-50%) translate(" + x + "px," + y + "px)",
10520            });
10521        }
10522        setEventHandlers() {
10523            $$y("body").off(".popover.mapsvg");
10524            $$y(this.containers.view).on("click touchend", ".mapsvg-popover-close, .mapsvg-mobile-modal-close", (e) => {
10525                e.stopImmediatePropagation();
10526                this.close();
10527            });
10528            $$y("body").on("mouseup.popover.mapsvg touchend.popover.mapsvg", (e) => {
10529                if (this.mapsvg.isScrolling ||
10530                    $$y(e.target).closest(".mapsvg-directory").length ||
10531                    $$y(e.target).closest(".mapsvg-popover").length ||
10532                    $$y(e.target).hasClass("mapsvg-btn-map"))
10533                    return;
10534                this.close();
10535            });
10536        }
10537        close() {
10538            if ($$y(this.containers.main).data("popover-id") != this.id ||
10539                !$$y(this.containers.main).is(":visible"))
10540                return;
10541            this.destroy();
10542            if (this.mapObject instanceof Region) {
10543                this.mapsvg.deselectRegion(this.mapObject);
10544            }
10545            if (this.mapObject instanceof Marker) {
10546                this.mapsvg.deselectAllMarkers();
10547            }
10548            this.events.trigger("closed", this, [this]);
10549        }
10550        destroy() {
10551            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", false);
10552            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", false);
10553            super.destroy.call(this);
10554        }
10555        show() {
10556            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", true);
10557            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", true);
10558        }
10559    }
10560
10561    const $$z = jQuery;
10562    class Tooltip extends Controller {
10563        constructor(options) {
10564            super(options);
10565            this.scrollable = false;
10566            this.withToolbar = false;
10567            this.autoresize = false;
10568            this.screenPoint = new ScreenPoint(0, 0);
10569            this.posOriginal = {};
10570            this.posShifted = {};
10571            this.posShiftedPrev = {};
10572            this.mirror = {};
10573            this.noPadding = true;
10574            this.setPosition(options.position);
10575            this.setSize(options.minWidth, options.maxWidth);
10576        }
10577        setSize(minWidth, maxWidth) {
10578            this.minWidth = minWidth;
10579            this.maxWidth = maxWidth;
10580            this.containers.main.style["min-width"] = this.minWidth + "px";
10581            this.containers.main.style["max-width"] = this.maxWidth + "px";
10582        }
10583        setPosition(position) {
10584            const ex = position.split("-");
10585            if (ex[0].indexOf("top") != -1 || ex[0].indexOf("bottom") != -1) {
10586                this.posOriginal.topbottom = ex[0];
10587            }
10588            if (ex[0].indexOf("left") != -1 || ex[0].indexOf("right") != -1) {
10589                this.posOriginal.leftright = ex[0];
10590            }
10591            if (ex[1]) {
10592                this.posOriginal.leftright = ex[1];
10593            }
10594            this.containers.main.className = this.containers.main.className.replace(/(^|\s)mapsvg-tt-\S+/g, "");
10595            this.containers.main.classList.add("mapsvg-tt-" + position);
10596        }
10597        setScreenPoint(x, y) {
10598            this.screenPoint.x = x;
10599            this.screenPoint.y = y;
10600        }
10601        viewDidLoad() {
10602            super.viewDidLoad.call(this);
10603        }
10604        viewDidAppear() {
10605            super.viewDidAppear();
10606            this.events.trigger("shown", this, [this]);
10607        }
10608        setScreenPosition(x, y) {
10609            this.setScreenPoint(x, y);
10610            this.containers.main.style.transform =
10611                "translateX(-50%) translate(" + x + "px," + y + "px)";
10612        }
10613        setEventHandlers() {
10614            const event = "mousemove.tooltip.mapsvg-" + this.mapsvg.id;
10615            $$z("body")
10616                .off(event)
10617                .on(event, (e) => {
10618                MapSVG.mouse = MapSVG.mouseCoords(e);
10619                this.containers.main.style.left =
10620                    e.clientX +
10621                        $$z(window).scrollLeft() -
10622                        $$z(this.mapsvg.containers.map).offset().left +
10623                        "px";
10624                this.containers.main.style.top =
10625                    e.clientY +
10626                        $$z(window).scrollTop() -
10627                        $$z(this.mapsvg.containers.map).offset().top +
10628                        "px";
10629                const m = new ScreenPoint(e.clientX + $$z(window).scrollLeft(), e.clientY + $$z(window).scrollTop());
10630                const _tbbox = this.containers.main.getBoundingClientRect();
10631                const _mbbox = this.mapsvg.containers.map.getBoundingClientRect();
10632                const tbbox = {
10633                    top: _tbbox.top + $$z(window).scrollTop(),
10634                    bottom: _tbbox.bottom + $$z(window).scrollTop(),
10635                    left: _tbbox.left + $$z(window).scrollLeft(),
10636                    right: _tbbox.right + $$z(window).scrollLeft(),
10637                    width: _tbbox.width,
10638                    height: _tbbox.height,
10639                };
10640                const mbbox = {
10641                    top: _mbbox.top + $$z(window).scrollTop(),
10642                    bottom: _mbbox.bottom + $$z(window).scrollTop(),
10643                    left: _mbbox.left + $$z(window).scrollLeft(),
10644                    right: _mbbox.right + $$z(window).scrollLeft(),
10645                    width: _mbbox.width,
10646                    height: _mbbox.height,
10647                };
10648                if (m.x > mbbox.right ||
10649                    m.y > mbbox.bottom ||
10650                    m.x < mbbox.left ||
10651                    m.y < mbbox.top) {
10652                    return;
10653                }
10654                if (this.mirror.top || this.mirror.bottom) {
10655                    if (this.mirror.top && m.y > this.mirror.top) {
10656                        this.mirror.top = 0;
10657                        delete this.posShifted.topbottom;
10658                    }
10659                    else if (this.mirror.bottom && m.y < this.mirror.bottom) {
10660                        this.mirror.bottom = 0;
10661                        delete this.posShifted.topbottom;
10662                    }
10663                }
10664                else {
10665                    if (tbbox.bottom < mbbox.top + tbbox.height) {
10666                        this.posShifted.topbottom = "bottom";
10667                        this.mirror.top = m.y;
10668                    }
10669                    else if (tbbox.top > mbbox.bottom - tbbox.height) {
10670                        this.posShifted.topbottom = "top";
10671                        this.mirror.bottom = m.y;
10672                    }
10673                }
10674                if (this.mirror.right || this.mirror.left) {
10675                    if (this.mirror.left && m.x > this.mirror.left) {
10676                        this.mirror.left = 0;
10677                        delete this.posShifted.leftright;
10678                    }
10679                    else if (this.mirror.right && m.x < this.mirror.right) {
10680                        this.mirror.right = 0;
10681                        delete this.posShifted.leftright;
10682                    }
10683                }
10684                else {
10685                    if (tbbox.right < mbbox.left + tbbox.width) {
10686                        this.posShifted.leftright = "right";
10687                        this.mirror.left = m.x;
10688                    }
10689                    else if (tbbox.left > mbbox.right - tbbox.width) {
10690                        this.posShifted.leftright = "left";
10691                        this.mirror.right = m.x;
10692                    }
10693                }
10694                let pos = $$z.extend({}, this.posOriginal, this.posShifted);
10695                const _pos = [];
10696                pos.topbottom && _pos.push(pos.topbottom);
10697                pos.leftright && _pos.push(pos.leftright);
10698                pos = _pos.join("-");
10699                if (this.posShifted.topbottom != this.posOriginal.topbottom ||
10700                    this.posShifted.leftright != this.posOriginal.leftright) {
10701                    this.containers.main.className = this.containers.main.className.replace(/(^|\s)mapsvg-tt-\S+/g, "");
10702                    this.containers.main.classList.add("mapsvg-tt-" + pos);
10703                    this.posShiftedPrev = pos;
10704                }
10705            });
10706        }
10707        setContent(template, data) {
10708            this.containers.main.innerHTML = template(data);
10709            return this;
10710        }
10711        show() {
10712            this.containers.main.classList.add("mapsvg-tooltip-visible");
10713            return this;
10714        }
10715        hide() {
10716            this.containers.main.classList.remove("mapsvg-tooltip-visible");
10717            return this;
10718        }
10719    }
10720
10721    const $$A = jQuery;
10722    class MapSVGMap {
10723        constructor(containerId, mapParams, externalParams) {
10724            this.markerOptions = { src: MapSVG.urls.root + "markers/pin1_red.png" };
10725            const options = mapParams.options;
10726            this.updateOutdatedOptions(options);
10727            this.dirtyFields = [];
10728            this.containerId = containerId;
10729            this.options = $$A.extend(true, {}, DefaultOptions, options);
10730            this.options.source = this.urlToRelativePath(this.options.source);
10731            this.editMode = this.options.editMode;
10732            delete this.options.editMode;
10733            this.id = mapParams.id;
10734            this.svgFileLastChanged = mapParams.svgFileLastChanged;
10735            this.regions = new ArrayIndexed("id");
10736            this.objects = new ArrayIndexed("id");
10737            this.events = new Events(this);
10738            this.highlightedRegions = [];
10739            this.editRegions = { on: false };
10740            this.editMarkers = { on: false };
10741            this.editData = { on: false };
10742            this.controllers = {};
10743            this.containers = {
10744                map: document.getElementById(this.containerId),
10745                scrollpane: $$A('<div class="mapsvg-scrollpane"></div>')[0],
10746                scrollpaneWrap: $$A('<div class="mapsvg-scrollpane-wrap"></div>')[0],
10747                layers: $$A('<div class="mapsvg-layers-wrap"></div>')[0],
10748            };
10749            this.containers.map.appendChild(this.containers.layers);
10750            this.containers.map.appendChild(this.containers.scrollpaneWrap);
10751            this.containers.scrollpaneWrap.appendChild(this.containers.scrollpane);
10752            this.whRatio = 0;
10753            this.isScrolling = false;
10754            this.markerOptions = {};
10755            this.svgDefault = {};
10756            this.scale = 1;
10757            this._scale = 1;
10758            this.selected_id = [];
10759            this.regions = new ArrayIndexed("id");
10760            if (!this.options.database.regionsTableName) {
10761                this.options.database.regionsTableName = "regions_" + this.id;
10762            }
10763            if (!this.options.database.objectsTableName) {
10764                this.options.database.objectsTableName = "objects_" + this.id;
10765            }
10766            this.regionsRepository = new Repository("region", "regions/" + this.options.database.regionsTableName);
10767            this.regionsRepository.query.update({ perpage: 0 });
10768            this.objectsRepository = new Repository("object", "objects/" + this.options.database.objectsTableName);
10769            if (this.options.database.noFiltersNoLoad) {
10770                this.objectsRepository.setNoFiltersNoLoad(true);
10771            }
10772            this.objectsRepository.query.update({
10773                perpage: this.options.database.pagination.on
10774                    ? this.options.database.pagination.perpage
10775                    : 0,
10776            });
10777            this.schemaRepository = new SchemaRepository();
10778            this.markers = new ArrayIndexed("id");
10779            this.markersClusters = new ArrayIndexed("id");
10780            this._viewBox = new ViewBox(0, 0, 0, 0);
10781            this.viewBox = new ViewBox(0, 0, 0, 0);
10782            this.zoomLevel = 0;
10783            this.scroll = {
10784                tx: 0,
10785                ty: 0,
10786                vxi: 0,
10787                vyi: 0,
10788                x: 0,
10789                y: 0,
10790                dx: 0,
10791                dy: 0,
10792                vx: 0,
10793                vy: 0,
10794                gx: 0,
10795                gy: 0,
10796                touchScrollStart: 0,
10797            };
10798            this.layers = {};
10799            this.geoCoordinates = false;
10800            this.geoViewBox = new GeoViewBox(new GeoPoint(0, 0), new GeoPoint(0, 0));
10801            this.eventsPreventList = {};
10802            this.googleMaps = {
10803                loaded: false,
10804                initialized: false,
10805                map: null,
10806                zoomLimit: true,
10807                maxZoomService: null,
10808            };
10809            this.afterLoadBlockers = 1;
10810            this.loaded = false;
10811            if (this.id) {
10812                this.afterLoadBlockers += 2;
10813            }
10814            if (this.options.googleMaps.on) {
10815                this.afterLoadBlockers++;
10816            }
10817            if (this.filtersShouldBeShown()) {
10818                this.afterLoadBlockers++;
10819            }
10820            this.init();
10821        }
10822        urlToRelativePath(url) {
10823            if (url.indexOf("//") === 0)
10824                url = url.replace(/^\/\/[^/]+/, "").replace("//", "/");
10825            else
10826                url = url.replace(/^.*:\/\/[^/]+/, "").replace("//", "/");
10827            return url;
10828        }
10829        setGroups(groups) {
10830            const _this = this;
10831            if (!this.groups) {
10832                _this.groups = new ArrayIndexed("id", _this.options.groups, {
10833                    autoId: true,
10834                    unique: true,
10835                });
10836            }
10837            else {
10838                this.options.groups = this.groups;
10839            }
10840            _this.groups.forEach(function (g) {
10841                g.objects &&
10842                    g.objects.length &&
10843                    g.objects.forEach(function (obj) {
10844                        _this.containers.svg
10845                            .querySelector("#" + obj.value)
10846                            .classList.toggle("mapsvg-hidden", !g.visible);
10847                    });
10848            });
10849        }
10850        getGroupSelectOptions() {
10851            const _this = this;
10852            const optionGroups = [];
10853            const options = [];
10854            const options2 = [];
10855            $$A(_this.containers.svg)
10856                .find("g")
10857                .each(function (index) {
10858                const id = $$A(this)[0].getAttribute("id");
10859                if (id) {
10860                    const title = $$A(this)[0].getAttribute("title");
10861                    options.push({ label: title || id, value: id });
10862                }
10863            });
10864            optionGroups.push({ title: "SVG Layers / Groups", options: options });
10865            $$A(_this.containers.svg)
10866                .find("path,ellipse,circle,polyline,polygon,rectangle,img,text")
10867                .each(function (index) {
10868                const id = $$A(this)[0].getAttribute("id");
10869                if (id) {
10870                    const title = $$A(this)[0].getAttribute("title");
10871                    options2.push({ label: title || id, value: id });
10872                }
10873            });
10874            optionGroups.push({ title: "Other SVG objects", options: options2 });
10875            return optionGroups;
10876        }
10877        setLayersControl(options) {
10878            const _this = this;
10879            if (options)
10880                $$A.extend(true, this.options.layersControl, options);
10881            if (this.options.layersControl.on) {
10882                if (!this.containers.layersControl) {
10883                    this.containers.layersControl = document.createElement("div");
10884                    this.containers.layersControl.classList.add("mapsvg-layers-control");
10885                    this.containers.layersControlLabel = document.createElement("div");
10886                    this.containers.layersControlLabel.classList.add("mapsvg-layers-label");
10887                    this.containers.layersControl.appendChild(this.containers.layersControlLabel);
10888                    const layersControlWrap = document.createElement("div");
10889                    layersControlWrap.classList.add("mapsvg-layers-list-wrap");
10890                    this.containers.layersControl.appendChild(layersControlWrap);
10891                    this.containers.layersControlListNano = document.createElement("div");
10892                    this.containers.layersControlListNano.classList.add("nano");
10893                    layersControlWrap.appendChild(this.containers.layersControlListNano);
10894                    this.containers.layersControlList = document.createElement("div");
10895                    this.containers.layersControlList.classList.add("mapsvg-layers-list");
10896                    this.containers.layersControlList.classList.add("nano-content");
10897                    this.containers.layersControlListNano.appendChild(this.containers.layersControlList);
10898                    this.containers.mapContainer.appendChild(this.containers.layersControl);
10899                }
10900                this.containers.layersControl.style.display = "block";
10901                this.containers.layersControlLabel.innerHTML = this.options.layersControl.label;
10902                this.containers.layersControlLabel.style.display = "block";
10903                this.containers.layersControlList.innerHTML = "";
10904                while (this.containers.layersControlList.firstChild) {
10905                    this.containers.layersControlList.removeChild(this.containers.layersControlList.firstChild);
10906                }
10907                this.containers.layersControl.classList.remove("mapsvg-top-left", "mapsvg-top-right", "mapsvg-bottom-left", "mapsvg-bottom-right");
10908                this.containers.layersControl.classList.add("mapsvg-" + this.options.layersControl.position);
10909                if (this.options.menu.on &&
10910                    !this.options.menu.customContainer &&
10911                    this.options.layersControl.position.indexOf("left") !== -1) {
10912                    this.containers.layersControl.style.left = this.options.menu.width;
10913                }
10914                this.containers.layersControl.style.maxHeight = this.options.layersControl.maxHeight;
10915                this.options.groups.forEach((g) => {
10916                    const item = document.createElement("div");
10917                    item.classList.add("mapsvg-layers-item");
10918                    item.setAttribute("data-group-id", g.id);
10919                    item.innerHTML =
10920                        '<input type="checkbox" class="ios8-switch ios8-switch-sm" ' +
10921                            (g.visible ? "checked" : "") +
10922                            " /><label>" +
10923                            g.title +
10924                            "</label>";
10925                    this.containers.layersControlList.appendChild(item);
10926                });
10927                $$A(this.containers.layersControlListNano).nanoScroller({
10928                    preventPageScrolling: true,
10929                    iOSNativeScrolling: true,
10930                });
10931                $$A(this.containers.layersControl).off();
10932                $$A(this.containers.layersControl).on("click", ".mapsvg-layers-item", function () {
10933                    const id = $$A(this).data("group-id");
10934                    const input = $$A(this).find("input");
10935                    input.prop("checked", !input.prop("checked"));
10936                    _this.groups.forEach(function (g) {
10937                        if (g.id === id)
10938                            g.visible = !g.visible;
10939                    });
10940                    _this.setGroups();
10941                });
10942                $$A(this.containers.layersControlLabel).off();
10943                $$A(this.containers.layersControlLabel).on("click", () => {
10944                    $$A(_this.containers.layersControl).toggleClass("closed");
10945                });
10946                $$A(this.containers.layersControl).toggleClass("closed", !this.options.layersControl.expanded);
10947            }
10948            else {
10949                if (this.containers.layersControl) {
10950                    this.containers.layersControl.style.display = "none";
10951                }
10952            }
10953        }
10954        loadDataObjects(params) {
10955            return this.objectsRepository.find(params);
10956        }
10957        loadDirectory() {
10958            if (!this.editMode &&
10959                this.options.menu.source === "database" &&
10960                !this.objectsRepository.loaded) {
10961                return;
10962            }
10963            if (this.options.menu.on) {
10964                this.controllers.directory.loadItemsToDirectory();
10965            }
10966            this.setPagination();
10967        }
10968        setPagination() {
10969            const _this = this;
10970            this.containers.pagerMap && $$A(this.containers.pagerMap).empty().remove();
10971            this.containers.pagerDir && $$A(this.containers.pagerDir).empty().remove();
10972            if (_this.options.database.pagination.on &&
10973                _this.options.database.pagination.perpage !== 0) {
10974                this.containers.directory.classList.toggle("mapsvg-with-pagination", ["directory", "both"].indexOf(_this.options.database.pagination.showIn) !== -1);
10975                this.containers.map.classList.toggle("mapsvg-with-pagination", ["map", "both"].indexOf(_this.options.database.pagination.showIn) !== -1);
10976                if (_this.options.menu.on) {
10977                    this.containers.pagerDir = _this.getPagination();
10978                    _this.controllers.directory.addPagination(this.containers.pagerDir);
10979                }
10980                this.containers.pagerMap = _this.getPagination();
10981                this.containers.map.appendChild(this.containers.pagerMap);
10982            }
10983        }
10984        getPagination(callback) {
10985            const _this = this;
10986            const pager = $$A('<nav class="mapsvg-pagination"><ul class="pager"><!--<li class="mapsvg-first"><a href="#">First</a></li>--><li class="mapsvg-prev"><a href="#">&larr; ' +
10987                _this.options.database.pagination.prev +
10988                " " +
10989                _this.options.database.pagination.perpage +
10990                '</a></li><li class="mapsvg-next"><a href="#">' +
10991                _this.options.database.pagination.next +
10992                " " +
10993                _this.options.database.pagination.perpage +
10994                ' &rarr;</a></li><!--<li class="mapsvg-last"><a href="#">Last</a></li>--></ul></nav>');
10995            if (this.objectsRepository.onFirstPage() && this.objectsRepository.onLastPage()) {
10996                pager.hide();
10997            }
10998            else {
10999                pager.find(".mapsvg-prev").removeClass("disabled");
11000                pager.find(".mapsvg-first").removeClass("disabled");
11001                pager.find(".mapsvg-last").removeClass("disabled");
11002                pager.find(".mapsvg-next").removeClass("disabled");
11003                this.objectsRepository.onLastPage() &&
11004                    pager.find(".mapsvg-next").addClass("disabled") &&
11005                    pager.find(".mapsvg-last").addClass("disabled");
11006                this.objectsRepository.onFirstPage() &&
11007                    pager.find(".mapsvg-prev").addClass("disabled") &&
11008                    pager.find(".mapsvg-first").addClass("disabled");
11009            }
11010            pager
11011                .on("click", ".mapsvg-next:not(.disabled)", (e) => {
11012                e.preventDefault();
11013                if (this.objectsRepository.onLastPage())
11014                    return;
11015                const query = new Query({ page: this.objectsRepository.query.page + 1 });
11016                this.objectsRepository.find(query).done(function () {
11017                    callback && callback();
11018                });
11019            })
11020                .on("click", ".mapsvg-prev:not(.disabled)", function (e) {
11021                e.preventDefault();
11022                if (_this.objectsRepository.onFirstPage())
11023                    return;
11024                const query = new Query({ page: _this.objectsRepository.query.page - 1 });
11025                _this.objectsRepository.find(query).done(function () {
11026                    callback && callback();
11027                });
11028            })
11029                .on("click", ".mapsvg-first:not(.disabled)", function (e) {
11030                e.preventDefault();
11031                if (_this.objectsRepository.onFirstPage())
11032                    return;
11033                const query = new Query({ page: 1 });
11034                _this.objectsRepository.find(query).done(function () {
11035                    callback && callback();
11036                });
11037            })
11038                .on("click", ".mapsvg-last:not(.disabled)", function (e) {
11039                e.preventDefault();
11040                if (_this.objectsRepository.onLastPage())
11041                    return;
11042                const query = new Query({ lastpage: true });
11043                _this.objectsRepository.find(query).done(function () {
11044                    callback && callback();
11045                });
11046            });
11047            return pager[0];
11048        }
11049        deleteMarkers() {
11050            while (this.markers.length) {
11051                this.markerDelete(this.markers[0]);
11052            }
11053        }
11054        deleteClusters() {
11055            if (this.markersClusters) {
11056                this.markersClusters.forEach(function (markerCluster) {
11057                    markerCluster.destroy();
11058                });
11059                this.markersClusters.clear();
11060            }
11061        }
11062        addLocations() {
11063            const _this = this;
11064            this.firstDataLoad = this.firstDataLoad === undefined;
11065            let locationField = this.objectsRepository.getSchema().getFieldByType("location");
11066            if (!locationField) {
11067                return;
11068            }
11069            locationField = locationField.name;
11070            if (locationField) {
11071                if (this.firstDataLoad) {
11072                    this.setMarkerImagesDependency();
11073                }
11074                _this.deleteMarkers();
11075                _this.deleteClusters();
11076                _this.clusters = {};
11077                _this.clustersByZoom = [];
11078                if (this.objectsRepository.getLoaded().length > 0) {
11079                    this.objectsRepository.getLoaded().forEach(function (object) {
11080                        if (object[locationField]) {
11081                            if (object[locationField].img &&
11082                                (object[locationField].geoPoint || object[locationField].svgPoint)) {
11083                                new Marker({
11084                                    location: object[locationField],
11085                                    object: object,
11086                                    mapsvg: _this,
11087                                });
11088                            }
11089                        }
11090                    });
11091                    if (_this.options.clustering.on) {
11092                        _this.startClusterizer();
11093                    }
11094                    else {
11095                        this.objectsRepository.getLoaded().forEach(function (object) {
11096                            if (object.location && object.location.marker) {
11097                                _this.markerAdd(object.location.marker);
11098                            }
11099                        });
11100                        _this.mayBeFitMarkers();
11101                    }
11102                }
11103            }
11104        }
11105        addClustersFromWorker(zoomLevel, clusters) {
11106            const _this = this;
11107            _this.clustersByZoom[zoomLevel] = [];
11108            for (const cell in clusters) {
11109                const markers = clusters[cell].markers.map(function (marker) {
11110                    return _this.objectsRepository.objects.findById(marker.id).location.marker;
11111                });
11112                _this.clustersByZoom[zoomLevel].push(new MarkerCluster({
11113                    markers: markers,
11114                    svgPoint: new SVGPoint(clusters[cell].x, clusters[cell].y),
11115                    cellX: clusters[cell].cellX,
11116                    cellY: clusters[cell].cellY,
11117                }, _this));
11118            }
11119            if (_this.zoomLevel === zoomLevel) {
11120                _this.clusterizeMarkers();
11121            }
11122        }
11123        startClusterizer() {
11124            if (!this.objectsRepository || this.objectsRepository.getLoaded().length === 0) {
11125                return;
11126            }
11127            const locationField = this.objectsRepository.getSchema().getFieldByType("location");
11128            if (!locationField) {
11129                return false;
11130            }
11131            if (!this.clusterizerWorker) {
11132                this.clusterizerWorker = new Worker(MapSVG.urls.root + "js/mapsvg/Core/clustering.js");
11133                this.clusterizerWorker.onmessage = (evt) => {
11134                    if (evt.data.clusters) {
11135                        this.addClustersFromWorker(evt.data.zoomLevel, evt.data.clusters);
11136                    }
11137                };
11138            }
11139            const objectsData = [];
11140            this.objectsRepository
11141                .getLoaded()
11142                .filter((o) => {
11143                return o.location && o.location.marker;
11144            })
11145                .forEach((o) => {
11146                objectsData.push({
11147                    id: o.id,
11148                    x: o.location.marker.svgPoint.x,
11149                    y: o.location.marker.svgPoint.y,
11150                });
11151            });
11152            this.clusterizerWorker.postMessage({
11153                objects: objectsData,
11154                cellSize: 50,
11155                mapWidth: this.containers.map.clientWidth,
11156                zoomLevels: this.zoomLevels,
11157                zoomLevel: this.zoomLevel,
11158                zoomDelta: this.zoomDelta,
11159                svgViewBox: this.svgDefault.viewBox,
11160            });
11161            this.events.on("zoom", () => {
11162                this.clusterizerWorker.postMessage({
11163                    message: "zoom",
11164                    zoomLevel: this.zoomLevel,
11165                });
11166            });
11167        }
11168        clusterizeMarkers(skipFitMarkers) {
11169            $$A(this.layers.markers)
11170                .children()
11171                .each((i, obj) => {
11172                $$A(obj).detach();
11173            });
11174            this.markers.clear();
11175            this.markersClusters.clear();
11176            this.clustersByZoom &&
11177                this.clustersByZoom[this.zoomLevel] &&
11178                this.clustersByZoom[this.zoomLevel].forEach((cluster) => {
11179                    if (this.options.googleMaps.on &&
11180                        this.googleMaps.map &&
11181                        this.googleMaps.map.getZoom() >= 17) {
11182                        this.markerAdd(cluster.markers[0]);
11183                    }
11184                    else {
11185                        if (cluster.markers.length > 1) {
11186                            this.markersClusterAdd(cluster);
11187                        }
11188                        else {
11189                            this.markerAdd(cluster.markers[0]);
11190                        }
11191                    }
11192                });
11193            if (this.editingMarker) {
11194                this.markerAdd(this.editingMarker);
11195            }
11196            if (!skipFitMarkers) {
11197                this.mayBeFitMarkers();
11198            }
11199            if (this.options.labelsMarkers.on) {
11200                this.setLabelsMarkers();
11201            }
11202        }
11203        getCssUrl() {
11204            return MapSVG.urls.root + "css/mapsvg.css";
11205        }
11206        isGeo() {
11207            return this.mapIsGeo;
11208        }
11209        functionFromString(string) {
11210            let func;
11211            let error;
11212            const fn = string.trim();
11213            if (fn.indexOf("{") == -1 || fn.indexOf("function") !== 0 || fn.indexOf("(") == -1) {
11214                return new SyntaxError("MapSVG user function error: no function body.");
11215            }
11216            const fnBody = fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"));
11217            const params = fn.substring(fn.indexOf("(") + 1, fn.indexOf(")"));
11218            try {
11219                func = new Function(params, fnBody);
11220            }
11221            catch (err) {
11222                error = err;
11223            }
11224            if (!error)
11225                return func;
11226            else
11227                return error;
11228        }
11229        getOptions(forTemplate, forWeb) {
11230            const options = $$A.extend(true, {}, this.options);
11231            function clearEmpties(o) {
11232                for (const k in o) {
11233                    if (!o[k] || typeof o[k] !== "object") {
11234                        continue;
11235                    }
11236                    clearEmpties(o[k]);
11237                    if (Object.keys(o[k]).length === 0) {
11238                        delete o[k];
11239                    }
11240                }
11241            }
11242            clearEmpties(options.regions);
11243            $$A.extend(true, options, this.optionsDelta);
11244            options.viewBox = this._viewBox.toArray();
11245            options.filtersSchema = this.filtersSchema.getFieldsAsArray();
11246            if (options.filtersSchema.length > 0) {
11247                options.filtersSchema.forEach((field) => {
11248                    if (field.type === "distance") {
11249                        field.value = "";
11250                    }
11251                });
11252            }
11253            delete options.markers;
11254            if (forTemplate) {
11255                options.svgFilename = options.source.split("/").pop();
11256                options.svgFiles = MapSVG.svgFiles;
11257            }
11258            if (forWeb)
11259                $$A.each(options, (key, val) => {
11260                    if (JSON.stringify(val) == JSON.stringify(this.defaults[key]))
11261                        delete options[key];
11262                });
11263            delete options.backend;
11264            return options;
11265        }
11266        restoreDeltaOptions() {
11267            this.update(this.optionsDelta);
11268            this.optionsDelta = {};
11269        }
11270        setEvents(functions) {
11271            let compiledFunction;
11272            for (const eventName in functions) {
11273                if (typeof functions[eventName] === "string") {
11274                    compiledFunction =
11275                        functions[eventName] != ""
11276                            ? this.functionFromString(functions[eventName])
11277                            : null;
11278                    if (!compiledFunction ||
11279                        compiledFunction.error ||
11280                        compiledFunction instanceof TypeError ||
11281                        compiledFunction instanceof SyntaxError) {
11282                        continue;
11283                    }
11284                }
11285                else if (typeof functions[eventName] === "function") {
11286                    compiledFunction = functions[eventName];
11287                }
11288                this.events.off(eventName);
11289                this.events.on(eventName, compiledFunction);
11290                if (eventName.indexOf("directory") !== -1) {
11291                    const event = eventName.split(".")[0];
11292                    if (this.controllers && this.controllers.directory) {
11293                        this.controllers.directory.events.off(event);
11294                        this.controllers.directory.events.on(event, compiledFunction);
11295                    }
11296                }
11297            }
11298            $$A.extend(true, this.options.events, functions);
11299        }
11300        setActions(options) {
11301            $$A.extend(true, this.options.actions, options);
11302        }
11303        setDetailsView(options) {
11304            options = options || this.options.detailsView || {};
11305            $$A.extend(true, this.options.detailsView, options);
11306            if (this.options.detailsView.location === "top" && this.options.menu.position === "left") {
11307                this.options.detailsView.location = "leftSidebar";
11308            }
11309            else if (this.options.detailsView.location === "top" &&
11310                this.options.menu.position === "right") {
11311                this.options.detailsView.location = "rightSidebar";
11312            }
11313            if (this.options.detailsView.location === "near" ||
11314                this.options.detailsView.location === "mapContainer") {
11315                this.options.detailsView.location = "map";
11316            }
11317            if (!this.containers.detailsView) {
11318                this.containers.detailsView = $$A('<div class="mapsvg-details-container"></div>')[0];
11319            }
11320            $$A(this.containers.detailsView).toggleClass("mapsvg-details-container-relative", !(MapSVG.isPhone && this.options.detailsView.mobileFullscreen) &&
11321                !this.shouldBeScrollable(this.options.detailsView.location));
11322            if (this.options.detailsView.location === "custom") {
11323                $$A("#" + this.options.detailsView.containerId).append($$A(this.containers.detailsView));
11324            }
11325            else {
11326                if (MapSVG.isPhone && this.options.detailsView.mobileFullscreen) {
11327                    $$A("body").append($$A(this.containers.detailsView));
11328                    $$A(this.containers.detailsView).addClass("mapsvg-container-fullscreen");
11329                }
11330                else {
11331                    this.containers[this.options.detailsView.location].append(this.containers.detailsView);
11332                }
11333                if (this.options.detailsView.margin) {
11334                    $$A(this.containers.detailsView).css("margin", this.options.detailsView.margin);
11335                }
11336                $$A(this.containers.detailsView).css("width", this.options.detailsView.width);
11337            }
11338        }
11339        setMobileView(options) {
11340            $$A.extend(true, this.options.mobileView, options);
11341        }
11342        attachDataToRegions(object) {
11343            this.regions.forEach(function (region) {
11344                region.objects = [];
11345            });
11346            this.objectsRepository.getLoaded().forEach((obj, index) => {
11347                const regions = obj.getRegionsForTable(this.options.database.regionsTableName);
11348                if (regions && regions.length) {
11349                    regions.forEach((region) => {
11350                        const r = this.getRegion(region.id);
11351                        if (r)
11352                            r.objects.push(obj);
11353                    });
11354                }
11355            });
11356        }
11357        setTemplates(templates) {
11358            this.templates = this.templates || {};
11359            for (let name in templates) {
11360                if (name != undefined) {
11361                    this.options.templates[name] = templates[name];
11362                    let t = this.options.templates[name];
11363                    if (name == "directoryItem" || name == "directoryCategoryItem") {
11364                        const dirItemTemplate = this.options.templates.directoryItem;
11365                        t =
11366                            '{{#each items}}<div id="mapsvg-directory-item-{{#if id_no_spaces}}{{id_no_spaces}}{{else}}{{id}}{{/if}}" class="mapsvg-directory-item" data-object-id="{{id}}">' +
11367                                dirItemTemplate +
11368                                "</div>{{/each}}";
11369                        if (this.options.menu.categories &&
11370                            this.options.menu.categories.on &&
11371                            this.options.menu.categories.groupBy) {
11372                            const t2 = this.options.templates["directoryCategoryItem"];
11373                            t =
11374                                '{{#each items}}{{#with category}}<div id="mapsvg-category-item-{{value}}" class="mapsvg-category-item" data-category-value="{{value}}">' +
11375                                    t2 +
11376                                    '</div><div class="mapsvg-category-block" data-category-id="{{value}}">{{/with}}' +
11377                                    t +
11378                                    "</div>{{/each}}";
11379                        }
11380                        name = "directory";
11381                    }
11382                    try {
11383                        this.options.templates[name] = t;
11384                        this.templates[name] = Handlebars.compile(t, { strict: false });
11385                    }
11386                    catch (err) {
11387                        console.error(err);
11388                        this.templates[name] = Handlebars.compile("", { strict: false });
11389                    }
11390                    if (this.editMode &&
11391                        (name == "directory" || name == "directoryCategoryItem") &&
11392                        this.controllers &&
11393                        this.controllers.directory) {
11394                        this.controllers.directory.templates.main = this.templates[name];
11395                        this.loadDirectory();
11396                    }
11397                }
11398            }
11399        }
11400        update(options) {
11401            for (const key in options) {
11402                if (key == "regions") {
11403                    for (const id in options.regions) {
11404                        const region = this.getRegion(id);
11405                        region && region.update(options.regions[id]);
11406                        if (options.regions[id].disabled != undefined) {
11407                            this.deselectRegion(region);
11408                            this.options.regions[id] = this.options.regions[id] || {};
11409                            this.options.regions[id].disabled = region.disabled;
11410                        }
11411                    }
11412                }
11413                else {
11414                    const setter = "set" + MapSVG.ucfirst(key);
11415                    if (typeof this[setter] == "function")
11416                        this[setter](options[key]);
11417                    else {
11418                        this.options[key] = options[key];
11419                    }
11420                }
11421            }
11422        }
11423        getDirtyFields() {
11424            return this.getData();
11425        }
11426        clearDirtyFields() {
11427            this.dirtyFields = [];
11428        }
11429        setTitle(title) {
11430            title && (this.options.title = title);
11431        }
11432        setExtension(extension) {
11433            if (extension) {
11434                this.options.extension = extension;
11435            }
11436            else {
11437                delete this.options.extension;
11438            }
11439        }
11440        setDisableLinks(on) {
11441            on = MapSVG.parseBoolean(on);
11442            if (on) {
11443                $$A(this.containers.map).on("click.a.mapsvg", "a", function (e) {
11444                    e.preventDefault();
11445                });
11446            }
11447            else {
11448                $$A(this.containers.map).off("click.a.mapsvg");
11449            }
11450            this.disableLinks = on;
11451        }
11452        setLoadingText(val) {
11453            this.options.loadingText = val;
11454        }
11455        setLockAspectRatio(onoff) {
11456            this.options.lockAspectRatio = MapSVG.parseBoolean(onoff);
11457        }
11458        setMarkerEditHandler(handler) {
11459            this.markerEditHandler = handler;
11460        }
11461        setChoroplethSourceField(field) {
11462            this.options.choropleth.sourceField = field;
11463            this.redrawChoropleth();
11464        }
11465        setRegionEditHandler(handler) {
11466            this.regionEditHandler = handler;
11467        }
11468        setDisableAll(on) {
11469            on = MapSVG.parseBoolean(on);
11470            $$A.extend(true, this.options, { disableAll: on });
11471            $$A(this.containers.map).toggleClass("mapsvg-disabled-regions", on);
11472        }
11473        setRegionStatuses(_statuses) {
11474            this.options.regionStatuses = {};
11475            const colors = {};
11476            _statuses.forEach((statusOptions) => {
11477                this.options.regionStatuses[statusOptions.value] = statusOptions;
11478                colors[statusOptions.value] = statusOptions.color.length
11479                    ? statusOptions.color
11480                    : undefined;
11481            });
11482            this.setColors({ status: colors });
11483        }
11484        setColorsIgnore(val) {
11485            this.options.colorsIgnore = MapSVG.parseBoolean(val);
11486            this.regionsRedrawColors();
11487        }
11488        setColors(colors) {
11489            for (const i in colors) {
11490                if (i === "status") {
11491                    for (const s in colors[i]) {
11492                        MapSVG.fixColorHash(colors[i][s]);
11493                    }
11494                }
11495                else {
11496                    if (typeof colors[i] == "string") {
11497                        MapSVG.fixColorHash(colors[i]);
11498                    }
11499                }
11500            }
11501            $$A.extend(true, this.options, { colors: colors });
11502            if (colors && colors.status)
11503                this.options.colors.status = colors.status;
11504            if (this.options.colors.markers) {
11505                for (const z in this.options.colors.markers) {
11506                    for (const x in this.options.colors.markers[z]) {
11507                        this.options.colors.markers[z][x] = parseInt(this.options.colors.markers[z][x]);
11508                    }
11509                }
11510            }
11511            if (this.options.colors.background)
11512                $$A(this.containers.map).css({ background: this.options.colors.background });
11513            if (this.options.colors.hover) {
11514                this.options.colors.hover = !isNaN(this.options.colors.hover)
11515                    ? parseInt(this.options.colors.hover + "")
11516                    : this.options.colors.hover;
11517            }
11518            if (this.options.colors.selected) {
11519                this.options.colors.selected = !isNaN(this.options.colors.selected)
11520                    ? parseInt(this.options.colors.selected + "")
11521                    : this.options.colors.selected;
11522            }
11523            $$A(this.containers.leftSidebar).css({
11524                "background-color": this.options.colors.leftSidebar,
11525            });
11526            $$A(this.containers.rightSidebar).css({
11527                "background-color": this.options.colors.rightSidebar,
11528            });
11529            $$A(this.containers.header).css({ "background-color": this.options.colors.header });
11530            $$A(this.containers.footer).css({ "background-color": this.options.colors.footer });
11531            if ($$A(this.containers.detailsView) && this.options.colors.detailsView !== undefined) {
11532                $$A(this.containers.detailsView).css({
11533                    "background-color": this.options.colors.detailsView,
11534                });
11535            }
11536            if ($$A(this.containers.directory) && this.options.colors.directory !== undefined) {
11537                $$A(this.containers.directory).css({
11538                    "background-color": this.options.colors.directory,
11539                });
11540            }
11541            if ($$A(this.containers.filtersModal) && this.options.colors.modalFilters !== undefined) {
11542                $$A(this.containers.filtersModal).css({
11543                    "background-color": this.options.colors.modalFilters,
11544                });
11545            }
11546            if ($$A(this.containers.filters) && this.options.colors.directorySearch) {
11547                $$A(this.containers.filters).css({
11548                    "background-color": this.options.colors.directorySearch,
11549                });
11550            }
11551            else if ($$A(this.containers.filters)) {
11552                $$A(this.containers.filters).css({
11553                    "background-color": "",
11554                });
11555            }
11556            if (!this.containers.clustersCss) {
11557                this.containers.clustersCss = ($$A("<style></style>").appendTo("body")[0]);
11558            }
11559            let css = "";
11560            if (this.options.colors.clusters) {
11561                css += "background-color: " + this.options.colors.clusters + ";";
11562            }
11563            if (this.options.colors.clustersBorders) {
11564                css += "border-color: " + this.options.colors.clustersBorders + ";";
11565            }
11566            if (this.options.colors.clustersText) {
11567                css += "color: " + this.options.colors.clustersText + ";";
11568            }
11569            $$A(this.containers.clustersCss).html(".mapsvg-marker-cluster {" + css + "}");
11570            if (!this.containers.clustersHoverCss) {
11571                this.containers.clustersHoverCss = ($$A("<style></style>").appendTo("body")[0]);
11572            }
11573            let cssHover = "";
11574            if (this.options.colors.clustersHover) {
11575                cssHover += "background-color: " + this.options.colors.clustersHover + ";";
11576            }
11577            if (this.options.colors.clustersHoverBorders) {
11578                cssHover += "border-color: " + this.options.colors.clustersHoverBorders + ";";
11579            }
11580            if (this.options.colors.clustersHoverText) {
11581                cssHover += "color: " + this.options.colors.clustersHoverText + ";";
11582            }
11583            $$A(this.containers.clustersHoverCss).html(".mapsvg-marker-cluster:hover {" + cssHover + "}");
11584            if (!this.containers.markersCss) {
11585                this.containers.markersCss = $$A("<style></style>").appendTo("head")[0];
11586            }
11587            const markerCssText = ".mapsvg-with-marker-active .mapsvg-marker {\n" +
11588                "  opacity: " +
11589                this.options.colors.markers.inactive.opacity / 100 +
11590                ";\n" +
11591                "  -webkit-filter: grayscale(" +
11592                (100 - this.options.colors.markers.inactive.saturation) +
11593                "%);\n" +
11594                "  filter: grayscale(" +
11595                (100 - this.options.colors.markers.inactive.saturation) +
11596                "%);\n" +
11597                "}\n" +
11598                ".mapsvg-with-marker-active .mapsvg-marker-active {\n" +
11599                "  opacity: " +
11600                this.options.colors.markers.active.opacity / 100 +
11601                ";\n" +
11602                "  -webkit-filter: grayscale(" +
11603                (100 - this.options.colors.markers.active.saturation) +
11604                "%);\n" +
11605                "  filter: grayscale(" +
11606                (100 - this.options.colors.markers.active.saturation) +
11607                "%);\n" +
11608                "}\n" +
11609                ".mapsvg-with-marker-hover .mapsvg-marker {\n" +
11610                "  opacity: " +
11611                this.options.colors.markers.unhovered.opacity / 100 +
11612                ";\n" +
11613                "  -webkit-filter: grayscale(" +
11614                (100 - this.options.colors.markers.unhovered.saturation) +
11615                "%);\n" +
11616                "  filter: grayscale(" +
11617                (100 - this.options.colors.markers.unhovered.saturation) +
11618                "%);\n" +
11619                "}\n" +
11620                ".mapsvg-with-marker-hover .mapsvg-marker-hover {\n" +
11621                "  opacity: " +
11622                this.options.colors.markers.hovered.opacity / 100 +
11623                ";\n" +
11624                "  -webkit-filter: grayscale(" +
11625                (100 - this.options.colors.markers.hovered.saturation) +
11626                "%);\n" +
11627                "  filter: grayscale(" +
11628                (100 - this.options.colors.markers.hovered.saturation) +
11629                "%);\n" +
11630                "}\n";
11631            $$A(this.containers.markersCss).html(markerCssText);
11632            $$A.each(this.options.colors, (key, color) => {
11633                if (color === null || color == "")
11634                    delete this.options.colors[key];
11635            });
11636            this.regionsRedrawColors();
11637        }
11638        setTooltips(options) {
11639            if (options.on !== undefined)
11640                options.on = MapSVG.parseBoolean(options.on);
11641            $$A.extend(true, this.options, { tooltips: options });
11642            if (!this.containers.tooltip) {
11643                this.containers.tooltip = $$A("<div />").addClass("mapsvg-tooltip")[0];
11644                $$A(this.containers.map).append(this.containers.tooltip);
11645                this.controllers.tooltip = new Tooltip({
11646                    mapsvg: this,
11647                    container: this.containers.tooltip,
11648                    position: this.options.tooltips.position,
11649                    maxWidth: this.options.tooltips.maxWidth,
11650                    minWidth: this.options.tooltips.minWidth,
11651                });
11652                this.controllers.tooltip._init();
11653            }
11654            if (typeof this.options.tooltips.position !== "undefined") {
11655                this.controllers.tooltip.setPosition(this.options.tooltips.position);
11656            }
11657            if (typeof this.options.tooltips.maxWidth !== "undefined" ||
11658                typeof this.options.tooltips.minWidth !== "undefined") {
11659                this.controllers.tooltip.setSize(this.options.tooltips.minWidth, this.options.tooltips.maxWidth);
11660            }
11661        }
11662        setPopovers(options) {
11663            if (options.on !== undefined)
11664                options.on = MapSVG.parseBoolean(options.on);
11665            $$A.extend(this.options.popovers, options);
11666            if (!this.containers.popover) {
11667                this.containers.popover = $$A("<div />").addClass("mapsvg-popover")[0];
11668                this.layers.popovers.append(this.containers.popover);
11669            }
11670            $$A(this.containers.popover).css({
11671                width: this.options.popovers.width + (this.options.popovers.width == "auto" ? "" : "px"),
11672                "max-width": this.options.popovers.maxWidth + "%",
11673                "max-height": (this.options.popovers.maxHeight * $$A(this.containers.wrap).outerHeight()) / 100 +
11674                    "px",
11675            });
11676            if (this.options.popovers.mobileFullscreen && MapSVG.
11676isPhone) {
11677                $$A("body").toggleClass("mapsvg-fullscreen-popovers", true);
11678                $$A(this.containers.popover).appendTo("body");
11679            }
11680        }
11681        setRegionPrefix(prefix) {
11682            this.options.regionPrefix = prefix;
11683        }
11684        setInitialViewBox(v) {
11685            if (typeof v == "string")
11686                v = v
11687                    .trim()
11688                    .split(" ")
11689                    .map(function (v) {
11690                    return parseFloat(v);
11691                });
11692            this._viewBox.update(new ViewBox(v));
11693            if (this.options.googleMaps.on) {
11694                this.options.googleMaps.center = this.googleMaps.map.getCenter().toJSON();
11695                this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
11696            }
11697            this.zoomLevel = 0;
11698            this.setZoomLevels();
11699        }
11700        setViewBoxOnStart() {
11701            this.viewBoxFull = this.svgDefault.viewBox;
11702            this.viewBoxFake = this.viewBox;
11703            this.whRatioFull = this.viewBoxFull.width / this.viewBox.width;
11704            this.containers.svg.setAttribute("viewBox", this.viewBoxFull.toString());
11705            if ((MapSVG.device.ios || MapSVG.device.android) && this.svgDefault.viewBox.width > 1500) {
11706                this.iosDownscaleFactor = this.svgDefault.viewBox.width > 9999 ? 100 : 10;
11707                this.containers.svg.style.width =
11708                    (this.svgDefault.viewBox.width / this.iosDownscaleFactor).toString() + "px";
11709            }
11710            else {
11711                this.containers.svg.style.width = this.svgDefault.viewBox.width + "px";
11712            }
11713            this.vbStart = true;
11714        }
11715        setViewBox(viewBox, adjustGoogleMap = true) {
11716            let initial = false;
11717            if (typeof viewBox === "undefined" || (viewBox.width === 0 && viewBox.height === 0)) {
11718                viewBox = this.svgDefault.viewBox;
11719                initial = true;
11720            }
11721            const isZooming = viewBox.width != this.viewBox.width || viewBox.height != this.viewBox.height;
11722            this.viewBox.update(viewBox);
11723            this.whRatio = this.viewBox.width / this.viewBox.height;
11724            !this.vbStart && this.setViewBoxOnStart();
11725            if (initial) {
11726                if (this._viewBox.width === 0 && this._viewBox.height === 0) {
11727                    this._viewBox.update(this.viewBox);
11728                }
11729                this._scale = 1;
11730            }
11731            this.scale = this.getScale();
11732            this.superScale = (this.whRatioFull * this.svgDefault.viewBox.width) / this.viewBox.width;
11733            const w = this.svgDefault.viewBox.width / this.containers.map.clientWidth;
11734            this.superScale = this.superScale / w;
11735            if ((MapSVG.device.ios || MapSVG.device.android) && this.svgDefault.viewBox.width > 1500) {
11736                this.superScale *= this.iosDownscaleFactor;
11737            }
11738            this.scroll.tx = Math.round((this.svgDefault.viewBox.x - this.viewBox.x) * this.scale);
11739            this.scroll.ty = Math.round((this.svgDefault.viewBox.y - this.viewBox.y) * this.scale);
11740            if (this.googleMaps.map && adjustGoogleMap !== false) {
11741                const googlePrevZoom = this.googleMaps.map.getZoom();
11742                this.googleMaps.map.setCenter(this.getCenterGeoPoint());
11743                this.googleMaps.map.setZoom(this.getZoomForGoogle());
11744            }
11745            else {
11746                this.containers.scrollpane.style.transform =
11747                    "translate(" + this.scroll.tx + "px," + this.scroll.ty + "px)";
11748                this.containers.svg.style.transform = "scale(" + this.superScale + ")";
11749                this.syncZoomLevelWithGoogle();
11750            }
11751            this.movingItemsAdjustScreenPosition();
11752            if (isZooming) {
11753                this.adjustStrokes();
11754                this.toggleSvgLayerOnZoom();
11755                if (this.options.clustering.on) {
11756                    this.throttle(this.clusterizeOnZoom, 400, this);
11757                }
11758                else {
11759                    this.events.trigger("zoom");
11760                }
11761            }
11762            return true;
11763        }
11764        syncZoomLevelWithGoogle() {
11765            if (this.googleMaps.map &&
11766                this.googleMaps.map.getZoom() !== this.getZoomForGoogle() &&
11767                typeof this.zoomDelta !== "undefined") {
11768                this.zoomLevel = this.googleMaps.map.getZoom() - this.zoomDelta;
11769            }
11770        }
11771        getCenterGeoPoint() {
11772            return this.converter.convertSVGToGeo(this.getCenterSvgPoint());
11773        }
11774        getCenterSvgPoint() {
11775            return new SVGPoint(this.viewBox.x + this.viewBox.width / 2, this.viewBox.y + this.viewBox.height / 2);
11776        }
11777        getZoomForGoogle() {
11778            if (typeof this.zoomLevel === "string") {
11779                this.zoomLevel = parseInt(this.zoomLevel);
11780            }
11781            return this.zoomLevel + this.zoomDelta;
11782        }
11783        getZoomRange() {
11784            const range = { min: 0, max: 0 };
11785            if (this.options.googleMaps.on) {
11786                range.min = Math.max(0, this.options.zoom.limit[0] + this.zoomDelta) - this.zoomDelta;
11787                range.max = Math.min(22, this.options.zoom.limit[1] + this.zoomDelta) - this.zoomDelta;
11788            }
11789            else {
11790                range.min = this.options.zoom.limit[0];
11791                range.max = this.options.zoom.limit[1];
11792            }
11793            return range;
11794        }
11795        enableMovingElementsAnimation() {
11796            $$A(this.containers.map).removeClass("no-transitions-markers no-transitions-labels no-transitions-bubbles");
11797        }
11798        disableMovingElementsAnimation() {
11799            $$A(this.containers.map).addClass("no-transitions-markers no-transitions-labels no-transitions-bubbles");
11800        }
11801        clusterizeOnZoom() {
11802            if (this.options.googleMaps.on && this.googleMaps.map && this.zoomDelta) {
11803                this.zoomLevel = this.googleMaps.map.getZoom() - this.zoomDelta;
11804            }
11805            this.events.trigger("zoom");
11806            this.clusterizeMarkers(true);
11807        }
11808        throttle(method, delay, scope, params) {
11809            clearTimeout(method._tId);
11810            method._tId = setTimeout(function () {
11811                method.apply(scope, params);
11812            }, delay);
11813        }
11814        setViewBoxByGoogleMapBounds() {
11815            const googleMapBounds = this.googleMaps.map.getBounds();
11816            if (!googleMapBounds)
11817                return;
11818            const googleMapBoundsJSON = googleMapBounds.toJSON();
11819            if (googleMapBoundsJSON.west == -180 && googleMapBoundsJSON.east == 180) {
11820                const center = this.googleMaps.map.getCenter().toJSON();
11821            }
11822            const ne = new GeoPoint(googleMapBounds.getNorthEast().lat(), googleMapBounds.getNorthEast().lng());
11823            const sw = new GeoPoint(googleMapBounds.getSouthWest().lat(), googleMapBounds.getSouthWest().lng());
11824            const xyNE = this.converter.convertGeoToSVG(ne);
11825            const xySW = this.converter.convertGeoToSVG(sw);
11826            if (xyNE.x < xySW.y) {
11827                const mapPointsWidth = (this.svgDefault.viewBox.width / this.converter.mapLonDelta) * 360;
11828                xySW.x = -(mapPointsWidth - xySW.y);
11829            }
11830            const width = xyNE.x - xySW.x;
11831            const height = xySW.y - xyNE.y;
11832            const viewBox = new ViewBox(xySW.x, xyNE.y, width, height);
11833            this.setViewBox(viewBox);
11834        }
11835        redraw() {
11836            this.disableAnimation();
11837            if (MapSVG.browser.ie) {
11838                $$A(this.containers.svg).css({ height: this.svgDefault.viewBox.height });
11839            }
11840            if (this.options.googleMaps.on && this.googleMaps.map) {
11841                google.maps.event.trigger(this.googleMaps.map, "resize");
11842            }
11843            else {
11844                this.setViewBox(this.viewBox);
11845            }
11846            $$A(this.containers.popover) &&
11847                $$A(this.containers.popover).css({
11848                    "max-height": (this.options.popovers.maxHeight * $$A(this.containers.wrap).outerHeight()) /
11849                        100 +
11850                        "px",
11851                });
11852            if (this.controllers && this.controllers.directory) {
11853                this.controllers.directory.updateTopShift();
11854                this.controllers.directory.updateScroll();
11855            }
11856            this.movingItemsAdjustScreenPosition();
11857            this.adjustStrokes();
11858            this.enableAnimation();
11859        }
11860        setSize(width, height, responsive) {
11861            this.options.width = width;
11862            this.options.height = height;
11863            this.options.responsive =
11864                responsive != null && responsive != undefined
11865                    ? MapSVG.parseBoolean(responsive)
11866                    : this.options.responsive;
11867            if (!this.options.width && !this.options.height) {
11868                this.options.width = this.svgDefault.width;
11869                this.options.height = this.svgDefault.height;
11870            }
11871            else if (!this.options.width && this.options.height) {
11872                this.options.width =
11873                    (this.options.height * this.svgDefault.width) / this.svgDefault.height;
11874            }
11875            else if (this.options.width && !this.options.height) {
11876                this.options.height =
11877                    (this.options.width * this.svgDefault.height) / this.svgDefault.width;
11878            }
11879            this.whRatio = this.options.width / this.options.height;
11880            this.scale = this.getScale();
11881            this.setResponsive(responsive);
11882            if (this.options.choropleth.on && this.options.choropleth.bubbleMode) {
11883                this.redrawBubbles();
11884            }
11885            this.movingItemsAdjustScreenPosition();
11886        }
11887        setResponsive(on) {
11888            on = on != undefined ? MapSVG.parseBoolean(on) : this.options.responsive;
11889            $$A(this.containers.map).css({
11890                width: "100%",
11891                height: "0",
11892                "padding-bottom": (this.viewBox.height * 100) / this.viewBox.width + "%",
11893            });
11894            if (on) {
11895                $$A(this.containers.wrap).css({
11896                    width: "100%",
11897                    height: "auto",
11898                });
11899            }
11900            else {
11901                $$A(this.containers.wrap).css({
11902                    width: this.options.width + "px",
11903                    height: this.options.height + "px",
11904                });
11905            }
11906            $$A.extend(true, this.options, { responsive: on });
11907            if (!this.resizeSensor) {
11908                this.resizeSensor = new ResizeSensor(this.containers.map, () => {
11909                    this.redraw();
11910                });
11911            }
11912            this.redraw();
11913        }
11914        setScroll(options, skipEvents) {
11915            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11916            options.limit != undefined && (options.limit = MapSVG.parseBoolean(options.limit));
11917            $$A.extend(true, this.options, { scroll: options });
11918            !skipEvents && this.setEventHandlers();
11919        }
11920        setZoom(options) {
11921            options = options || {};
11922            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11923            options.fingers != undefined && (options.fingers = MapSVG.parseBoolean(options.fingers));
11924            options.mousewheel != undefined &&
11925                (options.mousewheel = MapSVG.parseBoolean(options.mousewheel));
11926            options.delta = 2;
11927            if (options.limit) {
11928                if (typeof options.limit == "string")
11929                    options.limit = options.limit.split(";");
11930                options.limit = [parseInt(options.limit[0]), parseInt(options.limit[1])];
11931            }
11932            if (!this.zoomLevels) {
11933                this.setZoomLevels();
11934            }
11935            $$A.extend(true, this.options, { zoom: options });
11936            $$A(this.containers.scrollpaneWrap).off("wheel.mapsvg");
11937            if (this.options.zoom.mousewheel) {
11938                if (MapSVG.browser.firefox) {
11939                    this.firefoxScroll = { insideIframe: false, scrollX: 0, scrollY: 0 };
11940                    $$A(this.containers.scrollpaneWrap)
11941                        .on("mouseenter", () => {
11942                        this.firefoxScroll.insideIframe = true;
11943                        this.firefoxScroll.scrollX = window.scrollX;
11944                        this.firefoxScroll.scrollY = window.scrollY;
11945                    })
11946                        .on("mouseleave", () => {
11947                        this.firefoxScroll.insideIframe = false;
11948                    });
11949                    $$A(document).scroll(() => {
11950                        if (this.firefoxScroll.insideIframe)
11951                            window.scrollTo(this.firefoxScroll.scrollX, this.firefoxScroll.scrollY);
11952                    });
11953                }
11954                $$A(this.containers.scrollpaneWrap).on("wheel.mapsvg", (event) => {
11955                    event.preventDefault();
11956                    this.mouseWheelZoom(event);
11957                    return false;
11958                });
11959                $$A(this.layers.markers).on("wheel.mapsvg", (event) => {
11960                    event.preventDefault();
11961                    this.mouseWheelZoom(event);
11962                    return false;
11963                });
11964            }
11965            this.canZoom = true;
11966        }
11967        mouseWheelZoom(event) {
11968            event.preventDefault();
11969            const d = Math.sign(-event.originalEvent.deltaY);
11970            const center = this.getSvgPointAtClick(event.originalEvent);
11971            d > 0 ? this.zoomIn(center) : this.zoomOut(center);
11972        }
11973        setControls(options) {
11974            options = options || {};
11975            $$A.extend(true, this.options, { controls: options });
11976            this.options.controls.zoom = MapSVG.parseBoolean(this.options.controls.zoom);
11977            this.options.controls.zoomReset = MapSVG.parseBoolean(this.options.controls.zoomReset);
11978            this.options.controls.userLocation = MapSVG.parseBoolean(this.options.controls.userLocation);
11979            this.options.controls.previousMap = MapSVG.parseBoolean(this.options.controls.previousMap);
11980            const loc = this.options.controls.location || "right";
11981            if (!this.containers.controls) {
11982                const buttons = $$A("<div />").addClass("mapsvg-buttons");
11983                const zoomGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11984                const zoomIn = $$A("<div />").addClass("mapsvg-btn-map mapsvg-in");
11985                zoomIn.on("touchend click", (e) => {
11986                    if (e.cancelable) {
11987                        e.preventDefault();
11988                    }
11989                    e.stopPropagation();
11990                    this.zoomIn();
11991                });
11992                const zoomOut = $$A("<div />").addClass("mapsvg-btn-map mapsvg-out");
11993                zoomOut.on("touchend click", (e) => {
11994                    if (e.cancelable) {
11995                        e.preventDefault();
11996                    }
11997                    e.stopPropagation();
11998                    this.zoomOut();
11999                });
12000                zoomGroup.append(zoomIn).append(zoomOut);
12001                const location = $$A("<div />").addClass("mapsvg-btn-map mapsvg-btn-location");
12002                location.on("touchend click", (e) => {
12003                    if (e.cancelable) {
12004                        e.preventDefault();
12005                    }
12006                    e.stopPropagation();
12007                    this.showUserLocation((location) => {
12008                        if (this.options.scroll.on) {
12009                            this.centerOn(location.marker);
12010                        }
12011                    });
12012                });
12013                const userLocationIcon = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 447.342 447.342" style="enable-background:new 0 0 447.342 447.342;" xml:space="preserve"><path d="M443.537,3.805c-3.84-3.84-9.686-4.893-14.625-2.613L7.553,195.239c-4.827,2.215-7.807,7.153-7.535,12.459 c0.254,5.305,3.727,9.908,8.762,11.63l129.476,44.289c21.349,7.314,38.125,24.089,45.438,45.438l44.321,129.509 c1.72,5.018,6.325,8.491,11.63,8.762c5.306,0.271,10.244-2.725,12.458-7.535L446.15,18.429 C448.428,13.491,447.377,7.644,443.537,3.805z"/></svg>';
12014                location.html(userLocationIcon);
12015                const locationGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
12016                locationGroup.append(location);
12017                const zoomResetIcon = '<svg height="14px" version="1.1" viewBox="0 0 14 14" width="14px" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" xmlns:xlink="http://www.w3.org/1999/xlink"><g fill="none" fill-rule="evenodd" id="Page-1" stroke="none" stroke-width="1"><g fill="#000000" transform="translate(-215.000000, -257.000000)"><g id="fullscreen" transform="translate(215.000000, 257.000000)"><path d="M2,9 L0,9 L0,14 L5,14 L5,12 L2,12 L2,9 L2,9 Z M0,5 L2,5 L2,2 L5,2 L5,0 L0,0 L0,5 L0,5 Z M12,12 L9,12 L9,14 L14,14 L14,9 L12,9 L12,12 L12,12 Z M9,0 L9,2 L12,2 L12,5 L14,5 L14,0 L9,0 L9,0 Z" /></g></g></g></svg>';
12018                const zoomResetButton = $$A("<div />")
12019                    .html(zoomResetIcon)
12020                    .addClass("mapsvg-btn-map mapsvg-btn-zoom-reset");
12021                zoomResetButton.on("touchend click", (e) => {
12022                    if (e.cancelable) {
12023                        e.preventDefault();
12024                    }
12025                    e.stopPropagation();
12026                    this.viewBoxReset(true);
12027                });
12028                const zoomResetGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
12029                zoomResetGroup.append(zoomResetButton);
12030                const previousMapIcon = '<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" id="mapsvg-previous-map-icon" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" sodipodi:docname="undo.svg" inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata id="metadata19"><rdf:RDF><cc:Work rdf:about="">' +
12031                    '<dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs id="defs17" /><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="1017" id="namedview15" showgrid="false" inkscape:zoom="1.0103686" inkscape:cx="181.33521" inkscape:cy="211.70893" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:current-layer="Capa_1" /> <g id="g6" transform="matrix(0.53219423,0,0,0.52547259,122.72749,106.63302)">' +
12032                    '<g id="g4">
12032<path d="m 142.716,293.147 -94,-107.602 94,-107.602 c 7.596,-8.705 6.71,-21.924 -1.995,-29.527 -8.705,-7.596 -21.917,-6.703 -29.527,1.995 L 5.169,171.782 c -6.892,7.882 -6.892,19.65 0,27.532 l 106.026,121.372 c 4.143,4.729 9.94,7.157 15.771,7.157 4.883,0 9.786,-1.702 13.755,-5.169 8.706,-7.603 9.598,-20.822 1.995,-29.527 z" id="path2" inkscape:connector-curvature="0" /></g></g><g id="g12" transform="matrix(0.53219423,0,0,0.52547259,122.72749,106.63302)"><g id="g10"> <path d="M 359.93,164.619 H 20.926 C 9.368,164.619 0,173.986 0,185.545 c 0,11.558 9.368,20.926 20.926,20.926 H 359.93 c 60.776,0 110.218,49.441 110.218,110.211 0,60.77 -49.442,110.211 -110.218,110.211 H 48.828 c -11.558,0 -20.926,9.368 -20.926,20.926 0,11.558 9.368,20.926 20.926,20.926 H 359.93 C 443.774,468.745 512,400.526 512,316.682 512,232.838 443.781,164.619 359.93,164.619 Z" ' +
12033                    'id="path8" inkscape:connector-curvature="0" /></g></g></svg>';
12034                const previousMapButton = $$A("<div />")
12035                    .html(previousMapIcon)
12036                    .addClass("mapsvg-btn-map mapsvg-btn-previous-map");
12037                previousMapButton.on("touchend click", (e) => {
12038                    if (e.cancelable) {
12039                        e.preventDefault();
12040                    }
12041                    e.stopPropagation();
12042                    this.loadPreviousMap();
12043                });
12044                const previousMapGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
12045                previousMapGroup.append(previousMapButton);
12046                this.containers.controls = buttons[0];
12047                this.controls = {
12048                    zoom: zoomGroup[0],
12049                    userLocation: locationGroup[0],
12050                    zoomReset: zoomResetGroup[0],
12051                    previousMap: previousMapGroup[0],
12052                };
12053                $$A(this.containers.map).append($$A(this.containers.controls));
12054            }
12055            $$A(this.controls.zoom).toggle(this.options.controls.zoom);
12056            $$A(this.controls.userLocation).toggle(this.options.controls.userLocation);
12057            $$A(this.controls.zoomReset).toggle(this.options.controls.zoomReset);
12058            $$A(this.controls.previousMap).toggle(this.options.controls.previousMap && this.options.previousMapsIds.length > 0);
12059            $$A(this.containers.controls).removeClass("left");
12060            $$A(this.containers.controls).removeClass("right");
12061            (loc == "right" && $$A(this.containers.controls).addClass("right")) ||
12062                (loc == "left" && $$A(this.containers.controls).addClass("left"));
12063        }
12064        setZoomLevels() {
12065            if (!this.zoomLevels) {
12066                this.zoomLevels = new ArrayIndexed("zoomLevel");
12067            }
12068            else {
12069                this.zoomLevels.clear();
12070            }
12071            for (let i = -20; i < 0; i++) {
12072                const _scale = 1 / Math.pow(this.options.zoom.delta, Math.abs(i));
12073                this.zoomLevels.push({
12074                    zoomLevel: i,
12075                    _scale: _scale,
12076                    viewBox: new ViewBox(0, 0, this._viewBox.width / _scale, this._viewBox.height / _scale),
12077                });
12078            }
12079            for (let z = 0; z <= 20; z++) {
12080                const _scale = Math.pow(this.options.zoom.delta, Math.abs(z));
12081                this.zoomLevels.push({
12082                    zoomLevel: z,
12083                    _scale: _scale,
12084                    viewBox: new ViewBox(0, 0, this._viewBox.width / _scale, this._viewBox.height / _scale),
12085                });
12086            }
12087        }
12088        setCursor(type) {
12089            type = type == "pointer" ? "pointer" : "default";
12090            this.options.cursor = type;
12091            if (type == "pointer")
12092                $$A(this.containers.map).addClass("mapsvg-cursor-pointer");
12093            else
12094                $$A(this.containers.map).removeClass("mapsvg-cursor-pointer");
12095        }
12096        setMultiSelect(on, deselect) {
12097            this.options.multiSelect = MapSVG.parseBoolean(on);
12098            if (deselect !== false)
12099                this.deselectAllRegions();
12100        }
12101        _new_setChoropleth(options) {
12102            options = options || this.options.choropleth;
12103            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12104            if (typeof options.coloring === "undefined" ||
12105                typeof options.coloring.palette === "undefined" ||
12106                typeof options.coloring.palette.colors === "undefined") {
12107                if (typeof options.sourceFieldSelect === "undefined" ||
12108                    typeof options.sourceFieldSelect.variants === "undefined") {
12109                    $$A.extend(true, this.options.choropleth, options);
12110                }
12111                else {
12112                    this.options.choropleth.sourceFieldSelect.variants =
12113                        options.sourceFieldSelect.variants;
12114                }
12115            }
12116            else {
12117                const paletteColorsIndexes = Object.keys(options.coloring.palette.colors);
12118                if (paletteColorsIndexes.length > 1 ||
12119                    (paletteColorsIndexes[0] == "0" &&
12120                        Object.keys(options.coloring.palette.colors[0]).length > 1)) {
12121                    this.options.choropleth.coloring.palette.colors = options.coloring.palette.colors;
12122                }
12123                else {
12124                    const paletteColorIndex = Object.keys(options.coloring.palette.colors)[0];
12125                    $$A.extend(true, this.options.choropleth.coloring.palette.colors[paletteColorIndex], options.coloring.palette.colors[paletteColorIndex]);
12126                }
12127            }
12128            this.updateChoroplethMinMax();
12129            if (this.options.choropleth.on &&
12130                this.options.choropleth.sourceFieldSelect.on &&
12131                this.options.choropleth.sourceFieldSelect.variants) {
12132                if (!this.containers.choroplethSourceSelect) {
12133                    const sourceSelectOptions = [];
12134                    this.options.choropleth.sourceFieldSelect.variants.forEac
12134h((variant) => {
12135                        sourceSelectOptions.push($$A('<option value="' +
12136                            variant +
12137                            '" ' +
12138                            (variant === this.options.choropleth.sourceField
12139                                ? "selected"
12140                                : "") +
12141                            ">" +
12142                            variant +
12143                            "</option>"));
12144                    });
12145                    this.containers.choroplethSourceSelect = {
12146                        container: $$A('<div class="mapsvg-choropleth-source-field"></div>')[0],
12147                        select: $$A('<select id="mapsvg-choropleth-source-field-select" class="mapsvg-select2"></select>')[0],
12148                        options: sourceSelectOptions,
12149                    };
12150                    $$A(this.containers.choroplethSourceSelect.select).append(this.containers.choroplethSourceSelect.options);
12151                    $$A(this.containers.choroplethSourceSelect.container).append($$A(this.containers.choroplethSourceSelect.select));
12152                    $$A(this.containers.map).append($$A(this.containers.choroplethSourceSelect.container));
12153                    $$A(this.containers.choroplethSourceSelect.select).mselect2();
12154                    $$A(this.containers.choroplethSourceSelect.select)
12155                        .mselect2()
12156                        .on("select2:select select2:unselecting", (e) => {
12157                        if (e.cancelable) {
12158                            e.preventDefault();
12159                        }
12160                        e.stopPropagation();
12161                        this.setChoropleth({ sourceField: $$A(e.target).mselect2().val() });
12162                    });
12163                }
12164                else {
12165                    $$A(this.containers.choroplethSourceSelect.select).mselect2("destroy");
12166                    $$A(this.containers.choroplethSourceSelect.select).find("option").remove();
12167                    this.containers.choroplethSourceSelect.options = [];
12168                    this.options.choropleth.sourceFieldSelect.variants.forEac
12168h((variant) => {
12169                        this.containers.choroplethSourceSelect.options.push($$A('<option value="' +
12170                            variant +
12171                            '" ' +
12172                            (variant === this.options.choropleth.sourceField
12173                                ? "selected"
12174                                : "") +
12175                            ">" +
12176                            variant +
12177                            "</option>")[0]);
12178                    });
12179                    $$A(this.containers.choroplethSourceSelect.select).append(this.containers.choroplethSourceSelect.options);
12180                    $$A(this.containers.choroplethSourceSelect.select).mselect2({ width: "100%" });
12181                }
12182            }
12183            if ((!this.options.choropleth.on || !this.options.choropleth.sourceFieldSelect.on) &&
12184                this.containers.choroplethSourceSelect &&
12185                $$A(this.containers.choroplethSourceSelect.container).is(":visible")) {
12186                $$A(this.containers.choroplethSourceSelect.container).hide();
12187            }
12188            else if (this.options.choropleth.on &&
12189                this.options.choropleth.sourceFieldSelect.on &&
12190                this.containers.choroplethSourceSelect &&
12191                !$$A(this.containers.choroplethSourceSelect.container).is(":visible")) {
12192                $$A(this.containers.choroplethSourceSelect.container).show();
12193            }
12194            $$A(this.containers.map).find(".mapsvg-choropleth-legend").remove();
12195            if (this.options.choropleth.on && this.options.choropleth.coloring.legend.on) {
12196                const legend = this.options.choropleth.coloring.legend;
12197                let coloring = "";
12198                if (this.options.choropleth.coloring.mode === "gradient") {
12199                    coloring +=
12200                        '<div class="mapsvg-choropleth-legend-gradient-no-data">' +
12201                            this.options.choropleth.coloring.noData.description +
12202                            "</div>";
12203                    let legendGradient = "";
12204                    for (let chunkIdx = 1; chunkIdx < 5; chunkIdx++) {
12205                        legendGradient +=
12206                            '<div class="mapsvg-choropleth-legend-gradient-chunk">' +
12207                                ((this.options.choropleth.coloring.gradient.values.maxAdjusted * chunkIdx) /
12208                                    5 +
12209                                    this.options.choropleth.coloring.gradient.values.min) +
12210                                "</div>";
12211                    }
12212                    coloring +=
12213                        '<div class="mapsvg-choropleth-legend-gradient-colors">' +
12214                            legendGradient +
12215                            "</div>";
12216                }
12217                else {
12218                    coloring +=
12219                        '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="no-data">' +
12220                            '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
12221                            '<div class="mapsvg-choropleth-legend-palette-color-description">' +
12222                            this.options.choropleth.coloring.noData.description +
12223                            "</div>" +
12224                            "</div>";
12225                    coloring +=
12226                        '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="out-of-range">' +
12227                            '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
12228                            '<div class="mapsvg-choropleth-legend-palette-color-description">' +
12229                            this.options.choropleth.coloring.palette.outOfRange.description +
12230                            "</div>" +
12231                            "</div>";
12232                    const paletteColors = this.options.choropleth.coloring.palette.colors;
12233                    paletteColors.forEach((paletteColor, idx) => {
12234                        let paletteColorElementText = "";
12235                        if (paletteColor.description) {
12236                            paletteColorElementText = paletteColor.description;
12237                        }
12238                        else {
12239                            if (idx === 0 && !paletteColor.valueFrom && paletteColor.valueFrom !== 0) {
12240                                if (legend.layout === "vertical") {
12241                                    paletteColorElementText = "Less then " + paletteColor.valueTo;
12242                                }
12243                                else {
12244                                    paletteColorElementText = "< " + paletteColor.valueTo;
12245                                }
12246                            }
12247                            else if (idx === paletteColors.length - 1 && !paletteColor.valueTo) {
12248                                if (legend.layout === "vertical") {
12249                                    paletteColorElementText = paletteColor.valueFrom + " or more";
12250                                }
12251                                else {
12252                                    paletteColorElementText = paletteColor.valueFrom + " <";
12253                                }
12254                            }
12255                            else {
12256                                paletteColorElementText =
12257                                    paletteColor.valueFrom + " &#8804; " + paletteColor.valueTo;
12258                            }
12259                        }
12260                        coloring +=
12261                            '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="' +
12262                                idx +
12263                                '">' +
12264                                '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
12265                                '<div class="mapsvg-choropleth-legend-palette-color-description">' +
12266                                paletteColorElementText +
12267                                "</div>" +
12268                                "</div>";
12269                    });
12270                }
12271                this.containers.legend = {
12272                    title: $$A('<div class="mapsvg-choropleth-legend-title">' + legend.title + "</div>")[0],
12273                    text: $$A('<div class="mapsvg-choropleth-legend-text">' + legend.text + "</div>")[0],
12274                    coloring: $$A('<div class="mapsvg-choropleth-legend-' +
12275                        this.options.choropleth.coloring.mode +
12276                        '">' +
12277                        coloring +
12278                        "</div>")[0],
12279                    description: $$A('<div class="mapsvg-choropleth-legend-description">' +
12280                        legend.description +
12281                        "</div>")[0],
12282                    container: $$A("<div />").addClass("mapsvg-choropleth-legend mapsvg-choropleth-legend-" +
12283                        legend.layout +
12284                        " mapsvg-choropleth-legend-container-" +
12285                        legend.container)[0],
12286                };
12287                $$A(this.containers.legend.container)
12288                    .append(this.containers.legend.title)
12289                    .append(this.containers.legend.text)
12290                    .append(this.containers.legend.coloring)
12291                    .append(this.containers.legend.description);
12292                $$A(this.containers.map).append(this.containers.legend.container);
12293                this.setChoroplethLegendCSS();
12294                this.regionsRepository.events.on("updated", () => {
12295                    this.redrawChoropleth();
12296                });
12297                this.objectsRepository.events.on("updated", () => {
12298                    this.redrawChoropleth();
12299                });
12300            }
12301            if (this.options.choropleth.on && this.options.choropleth.coloring.mode === "gradient") {
12302                const colors = this.options.choropleth.coloring.gradient.colors;
12303                if (colors) {
12304                    colors.lowRGB = tinycolor(colors.low).toRgb();
12305                    colors.highRGB = tinycolor(colors.high).toRgb();
12306                    colors.diffRGB = {
12307                        r: colors.highRGB.r - colors.lowRGB.r,
12308                        g: colors.highRGB.g - colors.lowRGB.g,
12309                        b: colors.highRGB.b - colors.lowRGB.b,
12310                        a: colors.highRGB.a - colors.lowRGB.a,
12311                    };
12312                    this.containers.legend && this.setChoroplethLegendCSS();
12313                }
12314            }
12315            this.redrawChoropleth();
12316        }
12317        redrawChoropleth() {
12318            this.updateChoroplethMinMax();
12319            this.redrawBubbles();
12320            this.regionsRedrawColors();
12321        }
12322        updateChoroplethMinMax() {
12323            if (this.options.choropleth.on) {
12324                const gradient = this.options.choropleth.coloring.gradient, values = [];
12325                gradient.values.min = 0;
12326                gradient.values.max = null;
12327                if (this.options.choropleth.source === "regions") {
12328                    this.regions.forEach((region) => {
12329                        const choropleth = region.data && region.data[this.options.choropleth.sourceField];
12330                        choropleth != undefined && choropleth !== "" && values.push(choropleth);
12331                    });
12332                }
12333                else {
12334                    this.objectsRepository.objects.forEach((object) => {
12335                        const choropleth = object[this.options.choropleth.sourceField];
12336                        choropleth != undefined && choropleth !== "" && values.push(choropleth);
12337                    });
12338                }
12339                if (values.length > 0) {
12340                    gradient.values.min = Math.min.apply(null, values);
12341                    gradient.values.max = Math.max.apply(null, values);
12342                    gradient.values.maxAdjusted = gradient.values.max - gradient.values.min;
12343                }
12344            }
12345        }
12346        setChoroplethLegendCSS() {
12347            const gradient = this.options.choropleth.coloring.gradient, legend = this.options.choropleth.coloring.legend, noData = this.options.choropleth.coloring.noData, outOfRange = this.options.choropleth.coloring.palette.outOfRange;
12348            $$A(".mapsvg-choropleth-legend").css({
12349                width: legend.width,
12350                height: legend.height,
12351            });
12352            if (this.options.choropleth.coloring.mode === "gradient") {
12353                if (legend.layout === "horizontal") {
12354                    $$A(".mapsvg-choropleth-legend-horizontal .mapsvg-choropleth-legend-gradient-colors").css({
12355                        background: "linear-gradient(to right," +
12356                            gradient.colors.low +
12357                            " 1%," +
12358                            gradient.colors.high +
12359                            " 100%)",
12360                    });
12361                }
12362                else {
12363                    $$A(".mapsvg-choropleth-legend-vertical .mapsvg-choropleth-legend-gradient-colors").css({
12364                        background: "linear-gradient(to bottom," +
12365                            gradient.colors.low +
12366                            " 1%," +
12367                            gradient.colors.high +
12368                            " 100%)",
12369                    });
12370                }
12371                $$A(".mapsvg-choropleth-legend-gradient-no-data").css({
12372                    "background-color": noData.color,
12373                });
12374            }
12375            else {
12376                const paletteColors = this.options.choropleth.coloring.palette.colors;
12377                paletteColors.forEach(function (paletteColor, idx) {
12378                    $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="' +
12379                        idx +
12380                        '"] .mapsvg-choropleth-legend-palette-color').css({
12381                        "background-color": paletteColor.color,
12382                    });
12383                });
12384                $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="no-data"] .mapsvg-choropleth-legend-palette-color').css({
12385                    "background-color": noData.color,
12386                });
12387                $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="out-of-range"] .mapsvg-choropleth-legend-palette-color').css({
12388                    "background-color": outOfRange.color,
12389                });
12390            }
12391        }
12392        setCss(css) {
12393            this.options.css =
12394                css || (this.options.css ? this.options.css.replace(/%id%/g, "" + this.id) : "");
12395            this.liveCss = this.liveCss || $$A("<style></style>").appendTo("head")[0];
12396            $$A(this.liveCss).html(this.options.css);
12397        }
12398        setFilters(options) {
12399            options = options || this.options.filters;
12400            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12401            options.hide != undefined && (options.hide = MapSVG.parseBoolean(options.hide));
12402            $$A.extend(true, this.options, { filters: options });
12403            if (!MapSVG.googleMapsApiLoaded &&
12404                this.options.filters.on &&
12405                this.filtersSchema.getField("distance")) {
12406                this.loadGoogleMapsAPI(() => {
12407                    return 1;
12408                }, () => {
12409                    return 1;
12410                });
12411            }
12412            if (["leftSidebar", "rightSidebar", "header", "footer", "custom", "map"].indexOf(this.options.filters.location) === -1) {
12413                this.options.filters.location = "leftSidebar";
12414            }
12415            if (this.options.filters.on) {
12416                if (this.formBuilder) {
12417                    this.formBuilder.destroy();
12418                }
12419                if (!this.containers.filters) {
12420                    this.containers.filters = $$A('<div class="mapsvg-filters-wrap"></div>')[0];
12421                }
12422                else {
12423                    $$A(this.containers.filters).empty();
12424                    $$A(this.containers.filters).show();
12425                }
12426                $$A(this.containers.filters).css({
12427                    "background-color": this.options.colors.directorySearch,
12428                });
12429                if ($$A(this.containers.filtersModal)) {
12430                    $$A(this.containers.filtersModal).css({ width: this.options.filters.width });
12431                }
12432                if (this.options.filters.location === "custom") {
12433                    $$A(this.containers.filters)
12434                        .removeClass("mapsvg-filter-container-custom")
12435                        .addClass("mapsvg-filter-container-custom");
12436                    if ($$A("#" + this.options.filters.containerId).length) {
12437                        $$A("#" + this.options.filters.containerId).append(this.containers.filters);
12438                    }
12439                    else {
12440                        $$A(this.containers.filters).hide();
12441                        console.error("MapSVG: filter container #" +
12442                            this.options.filters.containerId +
12443                            " does not exists");
12444                    }
12445                }
12446                else {
12447                    if (MapSVG.isPhone) {
12448                        $$A(this.containers.header).append($$A(this.containers.filters));
12449                        this.setContainers({ header: { on: true } });
12450                    }
12451                    else {
12452                        const location = MapSVG.isPhone ? "header" : this.options.filters.location;
12453                        if (this.options.menu.on &&
12454                            this.controllers.directory &&
12455                            this.options.menu.location === this.options.filters.location) {
12456                            $$A(this.controllers.directory.containers.view)
12457                                .find(".mapsvg-directory-filter-wrap")
12458                                .append($$A(this.containers.filters));
12459                            this.controllers.directory.updateTopShift();
12460                        }
12461                        else {
12462                            $$A(this.containers[location]).append($$A(this.containers.filters));
12463                            this.controllers.directory && this.controllers.directory.updateTopShift();
12464                        }
12465                    }
12466                }
12467                this.loadFiltersController(this.containers.filters, false);
12468                this.updateFiltersState();
12469            }
12470            else {
12471                if ($$A(this.containers.filters)) {
12472                    $$A(this.containers.filters).empty();
12473                    $$A(this.containers.filters).hide();
12474                }
12475            }
12476            if (this.options.menu.on &&
12477                this.controllers.directory &&
12478                this.options.menu.location === this.options.filters.location) {
12479                this.controllers.directory.updateTopShift();
12480            }
12481        }
12482        updateFiltersState() {
12483            if (this.options.filters && this.options.filters.on && this.controllers.filters) {
12484                this.controllers.filters.update(this.objectsRepository.query);
12485                this.updateFilterTags();
12486            }
12487        }
12488        setGlobalDistanceFilter() {
12489            if (this.objectsRepository &&
12490                this.objectsRepository.query.filters &&
12491                this.objectsRepository.query.filters.distance) {
12492                const dist = this.objectsRepository.query.filters.distance;
12493                MapSVG.distanceSearch = this.objectsRepository.query.filters.distance;
12494            }
12495            else {
12496                MapSVG.distanceSearch = null;
12497            }
12498        }
12499        updateFilterTags() {
12500            $$A(this.containers.filterTags) && $$A(this.containers.filterTags).empty();
12501            for (const field_name in this.objectsRepository.query.filters) {
12502                let field_value = this.objectsRepository.query.filters[field_name];
12503                let _field_name = field_name;
12504                const filterField = this.filtersSchema.getField(_field_name);
12505                if (field_name == "regions") {
12506                    _field_name = "";
12507                    field_value = field_value.region_ids.map((id) => this.getRegion(id).title);
12508                }
12509                else {
12510                    _field_name = filterField && filterField.label;
12511                }
12512                if (field_name !== "distance") {
12513                    if (!this.containers.filterTags) {
12514                        this.containers.filterTags = $$A('<div class="mapsvg-filter-tags"></div>')[0];
12515                        if ($$A(this.containers.filters)) ;
12516                        else {
12517                            if (this.options.menu.on && this.controllers.directory) {
12518                                $$A(this.controllers.directory.containers.toolbar).append(this.containers.filterTags);
12519                                this.controllers.directory.updateTopShift();
12520                            }
12521                            else {
12522                                $$A(this.containers.map).append(this.containers.filterTags);
12523                                if (this.options.zoom.buttons.on) {
12524                                    if (this.options.layersControl.on) {
12525                                        if (this.options.layersControl.position == "top-left") {
12526                                            $$A(this.containers.filterTags).css({
12527                                                right: 0,
12528                                                bottom: 0,
12529                                            });
12530                                        }
12531                                        else {
12532                                            $$A(this.containers.filterTags).css({
12533                                                bottom: 0,
12534                                            });
12535                                        }
12536                                    }
12537                                    else {
12538                                        if (this.options.zoom.buttons.location == "left") {
12539                                            $$A(this.containers.filterTags).css({
12540                                                right: 0,
12541                                            });
12542                                        }
12543                                    }
12544                                }
12545                            }
12546                        }
12547                        $$A(this.containers.filterTags).on("click", ".mapsvg-filter-delete", (e) => {
12548                            const filterField = $$A(e.target).data("filter");
12549                            $$A(e.target).parent().remove();
12550                            this.objectsRepository.query.removeFilter(filterField);
12551                            this.deselectAllRegions();
12552                            this.loadDataObjects();
12553                        });
12554                    }
12555                    $$A(this.containers.filterTags).append('<div class="mapsvg-filter-tag">' +
12556                        (_field_name ? _field_name + ": " : "") +
12557                        field_value +
12558                        ' <span class="mapsvg-filter-delete" data-filter="' +
12559                        field_name +
12560                        '">
12560×</span></div>');
12561                }
12562            }
12563        }
12564        setContainers(options) {
12565            const _this = this;
12566            if (!this.containersCreated) {
12567                this.containers.wrapAll = document.createElement("div");
12568                this.containers.wrapAll.classList.add("mapsvg-wrap-all");
12569                this.containers.wrapAll.id = "mapsvg-map-" + this.id;
12570                this.containers.wrapAll.setAttribute("data-map-id", this.id ? this.id.toString() : "");
12571                this.containers.wrap = document.createElement("div");
12572                this.containers.wrap.classList.add("mapsvg-wrap");
12573                this.containers.mapContainer = document.createElement("div");
12574                this.containers.mapContainer.classList.add("mapsvg-map-container");
12575                this.containers.leftSidebar = document.createElement("div");
12576                this.containers.leftSidebar.className =
12577                    "mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-left";
12578                this.containers.rightSidebar = document.createElement("div");
12579                this.containers.rightSidebar.className =
12580                    "mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-right";
12581                this.containers.header = document.createElement("div");
12582                this.containers.header.className = "mapsvg-header mapsvg-top-container";
12583                this.containers.footer = document.createElement("div");
12584                this.containers.footer.className = "mapsvg-footer mapsvg-top-container";
12585                _this.containers.wrapAll = $$A('<div class="mapsvg-wrap-all"></div>')
12586                    .attr("id", "mapsvg-map-" + this.id)
12587                    .attr("data-map-id", this.id)[0];
12588                _this.containers.wrap = $$A('<div class="mapsvg-wrap"></div>')[0];
12589                _this.containers.mapContainer = $$A('<div class="mapsvg-map-container"></div>')[0];
12590                _this.containers.leftSidebar = $$A('<div class="mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-left"></div>')[0];
12591                _this.containers.rightSidebar = $$A('<div class="mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-right"></div>')[0];
12592                _this.containers.header = $$A('<div class="mapsvg-header mapsvg-top-container"></div>')[0];
12593                _this.containers.footer = $$A('<div class="mapsvg-footer mapsvg-top-container"></div>')[0];
12594                $$A(_this.containers.wrapAll).insertBefore(_this.containers.map);
12595                $$A(_this.containers.wrapAll).append(_this.containers.header);
12596                $$A(_this.containers.wrapAll).append(_this.containers.wrap);
12597                $$A(_this.containers.wrapAll).append(_this.containers.footer);
12598                $$A(_this.containers.mapContainer).append(_this.containers.map);
12599                $$A(_this.containers.wrap).append(_this.containers.leftSidebar);
12600                $$A(_this.containers.wrap).append(_this.containers.mapContainer);
12601                $$A(_this.containers.wrap).append(_this.containers.rightSidebar);
12602                _this.containersCreated = true;
12603            }
12604            options = options || _this.options.containers || {};
12605            for (const contName in options) {
12606                if (options[contName].on !== undefined) {
12607                    options[contName].on = MapSVG.parseBoolean(options[contName].on);
12608                }
12609                if (options[contName].width) {
12610                    if (typeof options[contName].width != "string" ||
12611                        (options[contName].width.indexOf("px") === -1 &&
12612                            options[contName].width.indexOf("%") === -1 &&
12613                            options[contName].width !== "auto")) {
12614                        options[contName].width = options[contName].width + "px";
12615                    }
12616                    $$A(_this.containers[contName]).css({ "flex-basis": options[contName].width });
12617                }
12618                if (options[contName].height) {
12619                    if (typeof options[contName].height != "string" ||
12620                        (options[contName].height.indexOf("px") === -1 &&
12621                            options[contName].height.indexOf("%") === -1 &&
12622                            options[contName].height !== "auto")) {
12623                        options[contName].height = options[contName].height + "px";
12624                    }
12625                    $$A(_this.containers[contName]).css({
12626                        "flex-basis": options[contName].height,
12627                        height: options[contName].height,
12628                    });
12629                }
12630                $$A.extend(true, _this.options, { containers: options });
12631                let on = _this.options.containers[contName].on;
12632                if (MapSVG.isPhone &&
12633                    _this.options.menu.hideOnMobile &&
12634                    _this.options.menu.location === contName &&
12635                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12636                    on = false;
12637                }
12638                else if (MapSVG.isPhone &&
12639                    _this.options.menu.location === "custom" &&
12640                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12641                    on = false;
12642                    $$A(_this.containers.wrapAll).addClass("mapsvg-hide-map-list-buttons");
12643                }
12644                else if (MapSVG.isPhone &&
12645                    !_this.options.menu.hideOnMobile &&
12646                    _this.options.menu.location === contName &&
12647                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12648                    $$A(_this.containers.wrapAll).addClass("mapsvg-hide-map-list-buttons");
12649                    $$A(_this.containers.wrapAll).addClass("mapsvg-directory-visible");
12650                }
12651                $$A(_this.containers[contName]).toggle(on);
12652            }
12653            _this.setDetailsView();
12654        }
12655        shouldBeScrollable(container) {
12656            const _this = this;
12657            switch (container) {
12658                case "map":
12659                case "leftSidebar":
12660                case "rightSidebar":
12661                    return true;
12662                case "custom":
12663                    return false;
12664                case "header":
12665                case "footer":
12666                    if (_this.options.containers[container].height &&
12667                        _this.options.containers[container].height !== "auto" &&
12668                        _this.options.containers[container].height !== "100%") {
12669                        return true;
12670                    }
12671                    else {
12672                        return false;
12673                    }
12674                default:
12675                    return false;
12676            }
12677        }
12678        setDirectory(options) {
12679            return this.setMenu(options);
12680        }
12681        setMenu(options) {
12682            options = options || this.options.menu;
12683            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12684            options.search != undefined && (options.search = MapSVG.parseBoolean(options.search));
12685            options.showMapOnClick != undefined &&
12686                (options.showMapOnClick = MapSVG.parseBoolean(options.showMapOnClick));
12687            options.searchFallback != undefined &&
12688                (options.searchFallback = MapSVG.parseBoolean(options.searchFallback));
12689            options.customContainer != undefined &&
12690                (options.customContainer = MapSVG.parseBoolean(options.customContainer));
12691            $$A.extend(true, this.options, { menu: options });
12692            this.controllers = this.controllers || {};
12693            if (!this.containers.directory) {
12694                this.containers.directory = $$A('<div class="mapsvg-directory"></div>')[0];
12695            }
12696            $$A(this.containers.directory).toggleClass("flex", this.shouldBeScrollable(this.options.menu.location));
12697            if (this.options.menu.on) {
12698                if (!this.controllers.directory) {
12699                    this.controllers.directory = new DirectoryController({
12700                        container: this.containers.directory,
12701                        template: this.options.templates.directory,
12702                        mapsvg: this,
12703                        repository: this.options.menu.source === "regions"
12704                            ? this.regionsRepository
12705                            : this.objectsRepository,
12706                        scrollable: this.shouldBeScrollable(this.options.menu.location),
12707                        events: {
12708                            click: (e, regionOrObject, mapsvg) => {
12709                                this.events.trigger("click.directoryItem", this, [
12710                                    e,
12711                                    regionOrObject,
12712                                    mapsvg,
12713                                ]);
12714                            },
12715                            mouseover: (e, regionOrObject, mapsvg) => {
12716                                this.events.trigger("mouseover.directoryItem", this, [
12717                                    e,
12718                                    regionOrObject,
12719                                    mapsvg,
12720                                ]);
12721                            },
12722                            mouseout: (e, regionOrObject, mapsvg) => {
12723                                this.events.trigger("mouseout.directoryItem", this, [
12724                                    e,
12725                                    regionOrObject,
12726                                    mapsvg,
12727                                ]);
12728                            },
12729                        },
12730                    });
12731                    this.controllers.directory._init();
12732                }
12733                if (options.source) {
12734                    this.controllers.directory.repository =
12735                        this.options.menu.source === "regions"
12736                            ? this.regionsRepository
12737                            : this.objectsRepository;
12738                }
12739                if (options.sortBy || options.sortDirection) {
12740                    this.controllers.directory.repository.query.update({
12741                        sort: [
12742                            {
12743                                field: this.options.menu.sortBy,
12744                                order: this.options.menu.sortDirection,
12745                            },
12746                        ],
12747                    });
12748                }
12749                this.setFilterOut();
12750                if (options.location) {
12751                    this.controllers.directory.scrollable = this.shouldBeScrollable(this.options.menu.location);
12752                }
12753                let $container;
12754                if (MapSVG.isPhone && this.options.menu.hideOnMobile) {
12755                    $container = $$A(this.containers.leftSidebar);
12756                }
12757                else {
12758                    $container =
12759                        this.options.menu.location !== "custom"
12760                            ? $$A(this.containers[this.options.menu.location])
12761                            : $$A("#" + this.options.menu.containerId);
12762                }
12763                $container.append(this.containers.directory);
12764                if (this.options.colors.directory) {
12765                    $$A(this.containers.directory).css({
12766                        "background-color": this.options.colors.directory,
12767                    });
12768                }
12769                this.setFilters();
12770                this.setTemplates({ directoryItem: this.options.templates.directoryItem });
12771                if ((this.options.menu.source === "regions" && this.regionsRepository.loaded) ||
12772                    (this.options.menu.source === "database" && this.objectsRepository.loaded)) {
12773                    if (this.editMode &&
12774                        (options.sortBy || options.sortDirection || options.filterout)) {
12775                        this.controllers.directory.repository.reload();
12776                    }
12777                    this.loadDirectory();
12778                }
12779            }
12780            else {
12781                this.controllers.directory && this.controllers.directory.destroy();
12782                this.controllers.directory = null;
12783            }
12784        }
12785        setDatabase(options) {
12786            options = options || this.options.database;
12787            if (options.pagination) {
12788                if (options.pagination.on != undefined) {
12789                    options.pagination.on = MapSVG.parseBoolean(options.pagination.on);
12790                }
12791                if (options.pagination.perpage != undefined) {
12792                    options.pagination.perpage = parseInt(options.pagination.perpage);
12793                }
12794            }
12795            $$A.extend(true, this.options, { database: options });
12796            if (options.pagination) {
12797                if (options.pagination.on !== undefined || options.pagination.perpage) {
12798                    const query = new Query({
12799                        perpage: this.options.database.pagination.on
12800                            ? this.options.database.pagination.perpage
12801                            : 0,
12802                    });
12803                    this.objectsRepository.find(query);
12804                }
12805                else {
12806                    this.setPagination();
12807                }
12808            }
12809        }
12810        updateGoogleMapsMaxZoom(geoPoint) {
12811            this.googleMaps.maxZoomService.getMaxZoomAtLatLng(geoPoint, (result) => {
12812                if (result.status === "OK") {
12813                    this.googleMaps.currentMaxZoom = result.zoom;
12814                }
12815            });
12816        }
12817        setGoogleMaps(options) {
12818            options = options || this.options.googleMaps;
12819            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12820            if (!this.googleMaps) {
12821                this.googleMaps = { loaded: false, initialized: false, map: null, overlay: null };
12822            }
12823            $$A.extend(true, this.options, { googleMaps: options });
12824            if (this.options.googleMaps.on) {
12825                $$A(this.containers.map).toggleClass("mapsvg-with-google-map", true);
12826                if (!MapSVG.googleMapsApiLoaded) {
12827                    this.loadGoogleMapsAPI(() => {
12828                        this.setGoogleMaps();
12829                    }, () => {
12830                        this.setGoogleMaps({ on: false });
12831                    });
12832                }
12833                else {
12834                    if (!this.googleMaps.map) {
12835                        this.containers.googleMaps = $$A('<div class="mapsvg-layer mapsvg-layer-gm" id="mapsvg-google-maps-' +
12836                            this.id +
12837                            '"></div>').prependTo(this.containers.map)[0];
12838                        $$A(this.containers.googleMaps).css({
12839                            position: "absolute",
12840                            top: 0,
12841                            left: 0,
12842                            bottom: 0,
12843                            right: 0,
12844                            "z-index": "0",
12845                        });
12846                        this.googleMaps.map = new google.maps.Map(this.containers.googleMaps, {
12847                            mapTypeId: options.type,
12848                            fullscreenControl: false,
12849                            keyboardShortcuts: false,
12850                            mapTypeControl: false,
12851                            scaleControl: false,
12852                            scrollwheel: false,
12853                            streetViewControl: false,
12854                            zoomControl: false,
12855                            styles: options.styleJSON,
12856                            tilt: 0,
12857                        });
12858                        const southWest = new google.maps.LatLng(this.geoViewBox.sw.lat, this.geoViewBox.sw.lng);
12859                        const northEast = new google.maps.LatLng(this.geoViewBox.ne.lat, this.geoViewBox.ne.lng);
12860                        const bounds = new google.maps.LatLngBounds(southWest, northEast);
12861                        this.googleMaps.overlay = this.createGoogleMapOverlay(bounds, this.googleMaps.map);
12862                        if (!this.options.googleMaps.center || !this.options.googleMaps.zoom) {
12863                            this.googleMaps.map.fitBounds(bounds, 0);
12864                        }
12865                        else {
12866                            this.googleMaps.map.setZoom(this.options.googleMaps.zoom);
12867                            this.googleMaps.map.setCenter(this.options.googleMaps.center);
12868                        }
12869                        this.googleMaps.initialized = true;
12870                        this.googleMaps.maxZoomService = new google.maps.MaxZoomService();
12871                        this.googleMaps.map.addListener("idle", () => {
12872                            this.isZooming = false;
12873                        });
12874                        google.maps.event.addListenerOnce(this.googleMaps.map, "idle", () => {
12875                            setTimeout(() => {
12876                                $$A(this.containers.map).addClass("mapsvg-fade-in");
12877                                setTimeout(() => {
12878                                    $$A(this.containers.map).removeClass("mapsvg-google-map-loading");
12879                                    $$A(this.containers.map).removeClass("mapsvg-fade-in");
12880                                    if (!this.options.googleMaps.center ||
12881                                        !this.options.googleMaps.zoom) {
12882                                        this.options.googleMaps.center = this.googleMaps.map
12883                                            .getCenter()
12884                                            .toJSON();
12885                                        this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
12886                                    }
12887                                    this.zoomDelta = this.options.googleMaps.zoom - this.zoomLevel;
12888                                    this.updateGoogleMapsMaxZoom(this.options.googleMaps.center);
12889                                    this.setInitialViewBox(this.viewBox);
12890                                    this.toggleSvgLayerOnZoom();
12891                                    this.events.trigger("googleMapsLoaded");
12892                                    this.afterLoadBlockers--;
12893                                    this.finalizeMapLoading();
12894                                }, 300);
12895                            }, 1);
12896                        });
12897                        this.events.on("googleMapsBoundsChanged", (bounds) => {
12898                            this.setViewBoxByGoogleMapsOverlay();
12899                        });
12900                    }
12901                    else {
12902                        $$A(this.containers.map).toggleClass("mapsvg-with-google-map", true);
12903                        $$A(this.containers.googleMaps) && $$A(this.containers.googleMaps).show();
12904                        if (options.type) {
12905                            this.googleMaps.map.setMapTypeId(options.type);
12906                        }
12907                        this.setViewBoxByGoogleMapsOverlay();
12908                    }
12909                }
12910            }
12911            else {
12912                $$A(this.containers.map).toggleClass("mapsvg-with-google-map", false);
12913                $$A(this.containers.googleMaps) && $$A(this.containers.googleMaps).hide();
12914                this.googleMaps.initialized = false;
12915            }
12916            if (this.converter) {
12917                this.converter.setWorldShift(this.options.googleMaps.on);
12918            }
12919        }
12920        createGoogleMapOverlay(bounds, map) {
12921            class GoogleMapsOverlay extends google.maps.OverlayView {
12922                constructor(bounds, googleMapInstance, mapsvg) {
12923                    super();
12924                    this.bounds_ = bounds;
12925                    this.map_ = googleMapInstance;
12926                    this.mapsvg = mapsvg;
12927                    this.setMap(googleMapInstance);
12928                    this.prevCoords = {
12929                        sw: { x: 0, y: 0 },
12930                        sw2: { x: 0, y: 0 },
12931                        ne: { x: 0, y: 0 },
12932                        ne2: { x: 0, y: 0 },
12933                    };
12934                }
12935                draw() {
12936                    this.mapsvg.events.trigger("googleMapsBoundsChanged", this.map_, [
12937                        this.getPixelBounds(),
12938                        this.map_,
12939                    ]);
12940                }
12941                onAdd() {
12942                    this.element = document.createElement("div");
12943                    this.element.style.borderStyle = "none";
12944                    this.element.style.borderWidth = "0px";
12945                    this.element.style.position = "absolute";
12946                    const panes = this.getPanes();
12947                    panes.overlayLayer.appendChild(this.element);
12948                }
12949                getPixelBounds() {
12950                    const overlayProjection = this.getProjection();
12951                    if (!overlayProjection)
12952                        return;
12953                    const geoSW = this.bounds_.getSouthWest();
12954                    const geoNE = this.bounds_.getNorthEast();
12955                    const coords = {
12956                        sw: overlayProjection.fromLatLngToDivPixel(geoSW),
12957                        ne: overlayProjection.fromLatLngToDivPixel(geoNE),
12958                        sw2: overlayProjection.fromLatLngToContainerPixel(geoSW),
12959                        ne2: overlayProjection.fromLatLngToContainerPixel(geoNE),
12960                    };
12961                    const ww = overlayProjection.getWorldWidth();
12962                    if (this.prevCoords.sw) {
12963                        if (coords.ne.x < coords.sw.x) {
12964                            if (Math.abs(this.prevCoords.sw.x - coords.sw.x) >
12965                                Math.abs(this.prevCoords.ne.x - coords.ne.x)) {
12966                                coords.sw.x = coords.sw.x - ww;
12967                            }
12968                            else {
12969                                coords.ne.x = coords.ne.x + ww;
12970                            }
12971                            if (Math.abs(this.prevCoords.sw2.x - coords.sw2.x) >
12972                                Math.abs(this.prevCoords.ne2.x - coords.ne2.x)) {
12973                                coords.sw2.x = coords.sw2.x - ww;
12974                            }
12975                            else {
12976                                coords.ne2.x = coords.ne2.x + ww;
12977                            }
12978                        }
12979                    }
12980                    this.prevCoords = coords;
12981                    return { sw: coords.sw2, ne: coords.ne2 };
12982                }
12983            }
12984            return new GoogleMapsOverlay(bounds, map, this);
12985        }
12986        loadGoogleMapsAPI(callback, fail) {
12987            if (!this.options.googleMaps.apiKey) {
12988                console.error("MapSVG: can't load Google API because no API key has been provided");
12989                return;
12990            }
12991            if (window.google !== undefined && google.maps) {
12992                MapSVG.googleMapsApiLoaded = true;
12993            }
12994            if (MapSVG.googleMapsApiLoaded) {
12995                if (typeof callback == "function") {
12996                    callback();
12997                }
12998                return;
12999            }
13000            MapSVG.googleMapsLoadCallbacks = MapSVG.googleMapsLoadCallbacks || [];
13001            if (typeof callback == "function") {
13002                MapSVG.googleMapsLoadCallbacks.push(callback);
13003            }
13004            if (MapSVG.googleMapsApiIsLoading) {
13005                return;
13006            }
13007            MapSVG.googleMapsApiIsLoading = true;
13008            window.gm_authFailure = () => {
13009                if (MapSVG.GoogleMapBadApiKey) {
13010                    MapSVG.GoogleMapBadApiKey();
13011                }
13012                else {
13013                    if (this.editMode) {
13014                        alert("Google maps API key is incorrect.");
13015                    }
13016                    else {
13017                        console.error("MapSVG: Google maps API key is incorrect.");
13018                    }
13019                }
13020            };
13021            this.googleMapsScript = document.createElement("script");
13022            this.googleMapsScript.onload = () => {
13023                MapSVG.googleMapsApiLoaded = true;
13024                MapSVG.googleMapsLoadCallbacks.forEach((_callback) => {
13025                    if (typeof callback == "function")
13026                        _callback();
13027                });
13028            };
13029            const gmLibraries = [];
13030            if (this.options.googleMaps.drawingTools) {
13031                gmLibraries.push("drawing");
13032            }
13033            if (this.options.googleMaps.geometry) {
13034                gmLibraries.push("geometry");
13035            }
13036            let libraries = "";
13037            if (gmLibraries.length > 0) {
13038                libraries = "&libraries=" + gmLibraries.join(",");
13039            }
13040            this.googleMapsScript.src =
13041                "https://maps.googleapis.com/maps/api/js?language=" +
13042                    this.options.googleMaps.language +
13043                    "&key=" +
13044                    this.options.googleMaps.apiKey +
13045                    libraries;
13046            document.head.appendChild(this.googleMapsScript);
13047        }
13048        loadDetailsView(obj) {
13049            this.controllers.popover && this.controllers.popover.close();
13050            if (this.controllers.detailsView)
13051                this.controllers.detailsView.destroy();
13052            this.controllers.detailsView = new DetailsController({
13053                autoresize: MapSVG.isPhone &&
13054                    this.options.detailsView.mobileFullscreen &&
13055                    this.options.detailsView.location !== "custom"
13056                    ? false
13057                    : this.options.detailsView.autoresize,
13058                container: this.containers.detailsView,
13059                template: obj instanceof Region
13060                    ? this.options.templates.detailsViewRegion
13061                    : this.options.templates.detailsView,
13062                mapsvg: this,
13063                data: obj.getData(),
13064                modal: MapSVG.isPhone &&
13065                    this.options.detailsView.mobileFullscreen &&
13066                    this.options.detailsView.location !== "custom",
13067                scrollable: (MapSVG.isPhone &&
13068                    this.options.detailsView.mobileFullscreen &&
13069                    this.options.detailsView.location !== "custom") ||
13070                    this.shouldBeScrollable(this.options.detailsView.location),
13071                withToolbar: !(MapSVG.isPhone &&
13072                    this.options.detailsView.mobileFullscreen &&
13073                    this.options.detailsView.location !== "custom") && this.shouldBeScrollable(this.options.detailsView.location),
13074                events: {
13075                    shown: (detailsController) => {
13076                        this.events.trigger("shown.detailsView", this, [this, detailsController]);
13077                        $$A(window).trigger("shown.detailsView", [this, detailsController]);
13078                    },
13079                    closed: (detailsController) => {
13080                        this.deselectAllRegions();
13081                        this.deselectAllMarkers();
13082                        this.controllers &&
13083                            this.controllers.directory &&
13084                            this.controllers.directory.deselectItems();
13085                        this.events.trigger("closed.detailsView", [this, detailsController]);
13086                    },
13087                },
13088            });
13089            this.controllers.detailsView._init();
13090        }
13091        loadFiltersModal() {
13092            if (this.options.filters.modalLocation != "custom") {
13093                if (!this.containers.filtersModal) {
13094                    this.containers.filtersModal = $$A('<div class="mapsvg-details-container mapsvg-filters-wrap"></div>')[0];
13095                }
13096                this.setColors();
13097                $$A(this.containers.filtersModal).css({ width: this.options.filters.width });
13098                if (MapSVG.isPhone) {
13099                    $$A("body").append($$A(this.containers.filtersModal));
13100                    $$A(this.containers.filtersModal).css({ width: "" });
13101                }
13102                else {
13103                    $$A(this.containers[this.options.filters.modalLocation]).append($$A(this.containers.filtersModal));
13104                }
13105            }
13106            else {
13107                this.containers.filtersModal = $$A("#" + this.options.filters.containerId)[0];
13108                $$A(this.containers.filtersModal).css({ width: "" });
13109            }
13110            this.loadFiltersController(this.containers.filtersModal, true);
13111        }
13112        loadFiltersController(container, modal = false) {
13113            if (!this.filtersShouldBeShown()) {
13114                return;
13115            }
13116            let filtersInDirectory, filtersHide;
13117            if (MapSVG.isPhone) {
13118                filtersInDirectory = true;
13119                filtersHide = this.options.filters.hideOnMobile;
13120            }
13121            else {
13122                filtersInDirectory =
13123                    this.options.menu.on &&
13124                        this.controllers.directory &&
13125                        this.options.menu.location === this.options.filters.location;
13126                filtersHide = this.options.filters.hide;
13127            }
13128            const scrollable = modal ||
13129                (!filtersInDirectory &&
13130                    ["leftSidebar", "rightSidebar"].indexOf(this.options.filters.location) !== -1);
13131            this.filtersRepository =
13132                this.options.filters.source === "regions"
13133                    ? this.regionsRepository
13134                    : this.objectsRepository;
13135            if (this.options.filters.searchButton) {
13136                this.changedFields = null;
13137                this.changedSearch = null;
13138            }
13139            else {
13140                this.changedSearch = () => {
13141                    this.filtersRepository.query.searchFallback = this.filtersSchema.getFieldByType("search").searchFallback;
13142                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
13143                };
13144                this.changedFields = () => {
13145                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
13146                };
13147            }
13148            this.controllers.filters = new FiltersController({
13149                container: container,
13150                query: this.filtersRepository.query,
13151                mapsvg: this,
13152                schema: this.filtersSchema,
13153                template: '<div class="mapsvg-filters-container"></div>',
13154                scrollable: scrollable,
13155                modal: modal,
13156                withToolbar: MapSVG.isPhone ? false : modal,
13157                width: $$A(container).hasClass("mapsvg-map-container")
13158                    ? this.options.filters.width
13159                    : "100%",
13160                hide: this.options.filters.hide,
13161                hideOnMobile: this.options.filters.hideOnMobile,
13162                showButtonText: this.options.filters.showButtonText,
13163                clearButton: this.options.filters.clearButton,
13164                clearButtonText: this.options.filters.clearButtonText,
13165                searchButton: this.options.filters.searchButton,
13166                searchButtonText: this.options.filters.searchButtonText,
13167                padding: this.options.filters.padding,
13168                events: {
13169                    cleared: () => {
13170                        this.deselectAllRegions();
13171                        this.filtersRepository.reload();
13172                    },
13173                    "changed.fields": this.changedFields,
13174                    "changed.search": this.changedSearch,
13175                    "click.btn.searchButton": () => {
13176                        this.filtersRepository.reload();
13177                    },
13178                    loaded: () => {
13179                        this.controllers.directory && this.controllers.directory.updateTopShift();
13180                        this.afterLoadBlockers--;
13181                        this.finalizeMapLoading();
13182                    },
13183                    "click.btn.showFilters": () => {
13184                        this.loadFiltersModal();
13185                    },
13186                },
13187            });
13188            this.controllers.filters._init();
13189        }
13190        filtersShouldBeShown() {
13191            return (this.options.filters.on &&
13192                this.options.filtersSchema &&
13193                this.options.filtersSchema.length > 0);
13194        }
13195        textSearch(text, fallback = false) {
13196            const query = new Query({
13197                filters: { search: text },
13198                searchFallback: fallback,
13199            });
13200            this.filtersRepository.find(query);
13201        }
13202        getRegion(id) {
13203            return this.regions.findById(id);
13204        }
13205        getRegions() {
13206            return this.regions;
13207        }
13208        getMarker(id) {
13209            return this.markers.findById(id);
13210        }
13211        checkId(id) {
13212            if (this.getRegion(id))
13213                return { canUse: false, error: "This ID is already being used by a Region" };
13214            else if (this.getMarker(id))
13215                return { canUse: false, error: "This ID is already being used by another Marker" };
13216            else
13217                return { canUse: true, error: "" };
13218        }
13219        regionsRedrawColors() {
13220            this.regions.forEach((region) => {
13221                region.setFill();
13222            });
13223        }
13224        redrawBubbles() {
13225            $$A(this.containers.map).removeClass("bubbles-regions-on bubbles-database-on");
13226            if (this.options.choropleth.on && this.options.choropleth.bubbleMode) {
13227                $$A(this.containers.map).addClass("bubbles-" + this.options.choropleth.source + "-on");
13228            }
13229            this.regions.forEach(function (region) {
13230                region.drawBubble();
13231            });
13232            const markersBubbleMode = this.options.choropleth.on &&
13233                this.options.choropleth.source == "database" &&
13234                this.options.choropleth.bubbleMode;
13235            this.markers.forEach(function (marker) {
13236                marker.setBubbleMode(markersBubbleMode);
13237            });
13238        }
13239        destroy() {
13240            if (this.controllers && this.controllers.directory) {
13241                this.controllers.directory.mobileButtons.remove();
13242            }
13243            $$A(this.containers.map)
13244                .empty()
13245                .insertBefore($$A(this.containers.wrapAll))
13246                .attr("style", "")
13247                .removeClass("mapsvg mapsvg-responsive");
13248            this.controllers.popover && this.controllers.popover.close();
13249            if (this.controllers.detailsView)
13250                this.controllers.detailsView.destroy();
13251            $$A(this.containers.detailsView).remove();
13252            $$A(this.containers.popover).remove();
13253            $$A(this.containers.tooltip).remove();
13254            $$A(this.containers.wrapAll).remove();
13255        }
13256        getData() {
13257            return {
13258                id: this.id,
13259                title: this.options.title,
13260                options: this.getOptions(false, false),
13261            };
13262        }
13263        mayBeFitMarkers() {
13264            if (!this.lastTimeFitWas) {
13265                this.lastTimeFitWas = Date.now() - 99999;
13266            }
13267            this.fitDelta = Date.now() - this.lastTimeFitWas;
13268            if (this.fitDelta > 1000 &&
13269                !this.firstDataLoad &&
13270                !this.fitOnDataLoadDone &&
13271                this.options.fitMarkers) {
13272                this.fitMarkers();
13273                this.fitOnDataLoadDone = true;
13274            }
13275            if (this.firstDataLoad &&
13276                (this.options.fitMarkersOnStart ||
13277                    (this.options.fitMarkers && this.options.database.loadOnStart === false))) {
13278                this.firstDataLoad = false;
13279                if (this.options.googleMaps.on && !this.googleMaps.map) {
13280                    this.events.on("googleMapsLoaded", () => {
13281                        this.fitMarkers();
13282                    });
13283                }
13284                else {
13285                    this.fitMarkers();
13286                }
13287            }
13288            this.lastTimeFitWas = Date.now();
13289        }
13290        fitMarkers() {
13291            const dbObjects = this.objectsRepository.getLoaded();
13292            if (!dbObjects || dbObjects.length === 0) {
13293                return;
13294            }
13295            if (this.options.googleMaps.on && typeof google !== "undefined") {
13296                const lats = [];
13297                const lngs = [];
13298                if (dbObjects.length > 1) {
13299                    dbObjects.forEach((object) => {
13300                        if (object.location && object.location.geoPoint) {
13301                            lats.push(object.location.geoPoint.lat);
13302                            lngs.push(object.location.geoPoint.lng);
13303                        }
13304                    });
13305                    const minlat = Math.min.apply(null, lats), maxlat = Math.max.apply(null, lats);
13306                    const minlng = Math.min.apply(null, lngs), maxlng = Math.max.apply(null, lngs);
13307                    const bbox = new google.maps.LatLngBounds({ lat: minlat, lng: minlng }, { lat: maxlat, lng: maxlng });
13308                    this.googleMaps.map.fitBounds(bbox, 0);
13309                }
13310                else {
13311                    if (dbObjects[0].location &&
13312                        dbObjects[0].location.geoPoint.lat &&
13313                        dbObjects[0].location.geoPoint.lng) {
13314                        const coords = {
13315                            lat: dbObjects[0].location.geoPoint.lat,
13316                            lng: dbObjects[0].location.geoPoint.lng,
13317                        };
13318                        if (this.googleMaps.map) {
13319                            this.googleMaps.map.setCenter(coords);
13320                            this.googleMaps.map.setZoom(this.options.fitSingleMarkerZoom);
13321                        }
13322                    }
13323                }
13324            }
13325            else {
13326                if (this.options.clustering.on) {
13327                    const arr = [];
13328                    this.markersClusters.forEach((c) => {
13329                        arr.push(c);
13330                    });
13331                    this.markers.forEach((m) => {
13332                        arr.push(m);
13333                    });
13334                    this.zoomTo(arr);
13335                    return;
13336                }
13337                else {
13338                    this.zoomTo(this.markers);
13339                    return;
13340                }
13341            }
13342        }
13343        setFitSingleMarkerZoom(zoom) {
13344            this.options.fitSingleMarkerZoom = parseInt(zoom);
13345        }
13346        showUserLocation(callback) {
13347            this.getUserLocation((geoPoint) => {
13348                this.userLocation = null;
13349                this.userLocation = new Location({
13350                    geoPoint: geoPoint,
13351                    img: MapSVG.urls.root + "/markers/user-location.svg",
13352                });
13353                this.userLocationMarker && this.userLocationMarker.delete();
13354                this.userLocationMarker = new Marker({
13355                    location: this.userLocation,
13356                    mapsvg: this,
13357                    width: 15,
13358                    height: 15,
13359                });
13360                $$A(this.userLocationMarker.element).addClass("mapsvg-user-location");
13361                this.userLocationMarker.centered = true;
13362                this.getLayer("markers").append(this.userLocationMarker.element);
13363                this.userLocationMarker.adjustScreenPosition();
13364                callback && callback(this.userLocation);
13365            });
13366        }
13367        getUserLocation(callback) {
13368            if (navigator.geolocation) {
13369                navigator.geolocation.getCurrentPosition(function (position) {
13370                    const pos = new GeoPoint(position.coords.latitude, position.coords.longitude);
13371                    callback && callback(pos);
13372                });
13373            }
13374            else {
13375                return false;
13376            }
13377        }
13378        getScale() {
13379            const scale2 = this.containers.map.clientWidth / this.viewBox.width;
13380            return scale2 || 1;
13381        }
13382        getViewBox() {
13383            return this.viewBox;
13384        }
13385        viewBoxSetBySize(width, height) {
13386            this.setSize(width, height);
13387            this._viewBox.update(this.viewBoxGetBySize(width, height));
13388            this.setViewBox(this._viewBox);
13389            $$A(window).trigger("resize");
13390            this.setSize(width, height);
13391            this.setZoomLevels();
13392            return this.viewBox;
13393        }
13394        viewBoxGetBySize(width, height) {
13395            const new_ratio = width / height;
13396            const old_ratio = this.svgDefault.viewBox.width / this.svgDefault.viewBox.height;
13397            const vb = this.svgDefault.viewBox.clone();
13398            if (new_ratio != old_ratio) {
13399                if (new_ratio > old_ratio) {
13400                    vb.width = this.svgDefault.viewBox.height * new_ratio;
13401                    vb.x = this.svgDefault.viewBox.x - (vb.width - this.svgDefault.viewBox.width) / 2;
13402                }
13403                else {
13404                    vb.height = this.svgDefault.viewBox.width / new_ratio;
13405                    vb.y = this.svgDefault.viewBox.y - (vb.height - this.svgDefault.viewBox.height) / 2;
13406                }
13407            }
13408            return vb;
13409        }
13410        viewBoxReset(toInitial) {
13411            if (this.options.googleMaps.on && this.googleMaps.map) {
13412                if (!toInitial) {
13413                    this.options.googleMaps.center = null;
13414                    this.options.googleMaps.zoom = null;
13415                }
13416                if (!this.options.googleMaps.center || !this.options.googleMaps.zoom) {
13417                    const southWest = new google.maps.LatLng(this.geoViewBox.sw.lat, this.geoViewBox.sw.lng);
13418                    const northEast = new google.maps.LatLng(this.geoViewBox.ne.lat, this.geoViewBox.ne.lng);
13419                    const bounds = new google.maps.LatLngBounds(southWest, northEast);
13420                    this.googleMaps.map.fitBounds(bounds, 0);
13421                    this.options.googleMaps.center = this.googleMaps.map.getCenter().toJSON();
13422                    this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
13423                }
13424                else {
13425                    this.googleMaps.map.setZoom(this.options.googleMaps.zoom);
13426                    this.googleMaps.map.setCenter(this.options.googleMaps.center);
13427                }
13428            }
13429            else {
13430                if (toInitial) {
13431                    const v = this._viewBox || this.svgDefault.viewBox;
13432                    this.zoomLevel = 0;
13433                    this._scale = 1;
13434                    this.setViewBox(v);
13435                }
13436                else {
13437                    this.setViewBox();
13438                }
13439            }
13440            return this.viewBox;
13441        }
13442        getGeoViewBox() {
13443            const v = this.viewBox;
13444            const p1 = new SVGPoint(v.x, v.y);
13445            const p2 = new SVGPoint(v.x + v.width, v.y);
13446            const p3 = new SVGPoint(v.x, v.y);
13447            const p4 = new SVGPoint(v.x, v.y + v.height);
13448            const leftLon = this.converter.convertSVGToGeo(p1).lng;
13449            const rightLon = this.converter.convertSVGToGeo(p2).lng;
13450            const topLat = this.converter.convertSVGToGeo(p3).lat;
13451            const bottomLat = this.converter.convertSVGToGeo(p4).lat;
13452            return [leftLon, topLat, rightLon, bottomLat];
13453        }
13454        setStrokes() {
13455            $$A(this.containers.svg)
13456                .find("path, polygon, circle, ellipse, rect, line, polyline")
13457                .each((index, elem) => {
13458                const width = MapObject.getComputedStyle("stroke-width", elem);
13459                if (width) {
13460                    $$A(elem).attr("data-stroke-width", width.replace("px", ""));
13461                }
13462            });
13463        }
13464        adjustStrokes() {
13465            $$A(this.containers.svg)
13466                .find("path, polygon, circle, ellipse, rect, line, polyline")
13467                .each((index, elem) => {
13468                const width = elem.getAttribute("data-stroke-width");
13469                if (width) {
13470                    $$A(elem).css("stroke-width", Number(width) / this.scale);
13471                }
13472            });
13473        }
13474        zoomIn(center) {
13475            if (this.canZoom) {
13476                this.isZooming = true;
13477                this.canZoom = false;
13478                setTimeout(() => {
13479                    this.isZooming = false;
13480                    this.canZoom = true;
13481                }, 700);
13482                this.zoom(1, center);
13483            }
13484        }
13485        zoomOut(center) {
13486            if (this.canZoom) {
13487                this.isZooming = true;
13488                this.canZoom = false;
13489                setTimeout(() => {
13490                    this.isZooming = false;
13491                    this.canZoom = true;
13492                }, 700);
13493                this.zoom(-1, center);
13494            }
13495        }
13496        zoomTo(mapObjects, zoomToLevel) {
13497            if (mapObjects instanceof Marker || mapObjects instanceof MarkerCluster) {
13498                return this.zoomToMarkerOrCluster(mapObjects, zoomToLevel);
13499            }
13500            else {
13501                const convertedObjects = !Array.isArray(mapObjects) ? [mapObjects] : mapObjects;
13502                const bbox = this.getGroupBBox(convertedObjects);
13503                return this.fitViewBox(bbox, zoomToLevel);
13504            }
13505        }
13506        zoomToMarkerOrCluster(mapObject, zoomToLevel) {
13507            this.zoomLevel = zoomToLevel || 1;
13508            const foundZoomLevel = this.zoomLevels.get(this.zoomLevel);
13509            if (!foundZoomLevel) {
13510                return false;
13511            }
13512            const vb = foundZoomLevel.viewBox;
13513            if (this.canZoom) {
13514                this.isZooming = true;
13515                this.canZoom = false;
13516                setTimeout(() => {
13517                    this.isZooming = false;
13518                    this.canZoom = true;
13519                }, 700);
13520                const vbNew = new ViewBox(mapObject.svgPoint.x - vb.width / 2, mapObject.svgPoint.y - vb.height / 2, vb.width, vb.height);
13521                this.setViewBox(vbNew);
13522                this._scale = foundZoomLevel._scale;
13523                return true;
13524            }
13525            return false;
13526        }
13527        getGroupBBox(mapObjects) {
13528            let _bbox;
13529            const xmax = [];
13530            const ymax = [];
13531            const xmin = [];
13532            const ymin = [];
13533            for (let i = 0; i < mapObjects.length; i++) {
13534                _bbox = mapObjects[i].getBBox();
13535                xmin.push(_bbox.x);
13536                ymin.push(_bbox.y);
13537                const _w = _bbox.x + _bbox.width;
13538                const _h = _bbox.y + _bbox.height;
13539                xmax.push(_w);
13540                ymax.push(_h);
13541            }
13542            const _xmin = Math.min(...xmin);
13543            const _ymin = Math.min(...ymin);
13544            const width = Math.max(...xmax) - _xmin;
13545            const height = Math.max(...ymax) - _ymin;
13546            let padding = 10;
13547            const point1 = new ScreenPoint(padding, 0);
13548            const point2 = new ScreenPoint(0, 0);
13549            padding =
13550                this.converter.convertPixelToSVG(point1).x - this.converter.convertPixelToSVG(point2).x;
13551            return new ViewBox(_xmin - padding, _ymin - padding, width + padding * 2, height + padding * 2);
13552        }
13553        fitViewBox(fitViewBox, forceZoomLevel) {
13554            let viewBoxPrev;
13555            let foundZoomLevelNumber = 0;
13556            let foundZoomLevel;
13557            let newViewBox;
13558            this.zoomLevels.forEach((zoomLevel) => {
13559                if (viewBoxPrev && viewBoxPrev.x !== undefined) {
13560                    if (fitViewBox.fitsInViewBox(viewBoxPrev) &&
13561                        zoomLevel.viewBox.fitsInViewBox(fitViewBox, true)) {
13562                        foundZoomLevelNumber = forceZoomLevel ? forceZoomLevel : zoomLevel.zoomLevel;
13563                        foundZoomLevel = this.zoomLevels.get(foundZoomLevelNumber);
13564                        newViewBox = new ViewBox(fitViewBox.x - foundZoomLevel.viewBox.width / 2 + fitViewBox.width / 2, fitViewBox.y - foundZoomLevel.viewBox.height / 2 + fitViewBox.height / 2, foundZoomLevel.viewBox.width, foundZoomLevel.viewBox.height);
13565                    }
13566                }
13567                viewBoxPrev = zoomLevel && zoomLevel.viewBox;
13568            });
13569            if (foundZoomLevel) {
13570                if (this.canZoom) {
13571                    this.isZooming = true;
13572                    this.canZoom = false;
13573                    setTimeout(() => {
13574                        this.isZooming = false;
13575                        this.canZoom = true;
13576                    }, 700);
13577                    this.zoomLevel = foundZoomLevelNumber;
13578                    this._scale = foundZoomLevel._scale;
13579                    this.setViewBox(newViewBox);
13580                    return true;
13581                }
13582            }
13583            else {
13584                return false;
13585            }
13586        }
13587        zoomToRegion(region, zoomToLevel) {
13588            this.fitViewBox(region.getBBox(), zoomToLevel);
13589            return true;
13590        }
13591        centerOn(region, yShift) {
13592            if (this.options.googleMaps.on) {
13593                yShift = yShift ? (yShift + 12) / this.getScale() : 0;
13594                $$A(this.containers.map).addClass("scrolling");
13595                const latLng = region.getCenterLatLng(yShift);
13596                this.googleMaps.map.panTo(latLng);
13597                setTimeout(() => {
13598                    $$A(this.containers.map).removeClass("scrolling");
13599                }, 100);
13600            }
13601            else {
13602                yShift = yShift ? (yShift + 12) / this.getScale() : 0;
13603                const bbox = region.getBBox();
13604                const vb = this.viewBox;
13605                const newViewBox = new ViewBox(bbox.x - vb.width / 2 + bbox.width / 2, bbox.y - vb.height / 2 + bbox.height / 2 - yShift, vb.width, vb.height);
13606                this.setViewBox(newViewBox);
13607            }
13608        }
13609        zoom(delta, center) {
13610            let newViewBox = new ViewBox(0, 0, 0, 0);
13611            const d = delta > 0 ? 1 : -1;
13612            if (!this.zoomLevels.get(this.zoomLevel + d))
13613                return;
13614            const newZoomLevel = this.zoomLevel + d;
13615            const zoomIn = d > 0;
13616            const zoomOut = d < 0;
13617            const zoomRange = this.getZoomRange();
13618            const isInZoomRange = this.zoomLevel >= zoomRange.min && this.zoomLevel <= zoomRange.max;
13619            const goingOutOfZoomRange = isInZoomRange && (newZoomLevel > zoomRange.max || newZoomLevel < zoomRange.min);
13620            const outOfRangeAndMovingAway = !isInZoomRange &&
13621                ((zoomIn && newZoomLevel > zoomRange.max) || (zoomOut && newZoomLevel < zoomRange.min));
13622            if (goingOutOfZoomRange || outOfRangeAndMovingAway) {
13623                return;
13624            }
13625            this.zoomLevel = newZoomLevel;
13626            const z = this.zoomLevels.get(this.zoomLevel);
13627            this._scale = z._scale;
13628            newViewBox = z.viewBox;
13629            let shift = [];
13630            if (center) {
13631                const koef = zoomIn ? 0.5 : -1;
13632                newViewBox.x = this.viewBox.x + (center.x - this.viewBox.x) * koef;
13633                newViewBox.y = this.viewBox.y + (center.y - this.viewBox.y) * koef;
13634            }
13635            else {
13636                shift = [
13637                    (this.viewBox.width - newViewBox.width) / 2,
13638                    (this.viewBox.height - newViewBox.height) / 2,
13639                ];
13640                newViewBox.x = this.viewBox.x + shift[0];
13641                newViewBox.y = this.viewBox.y + shift[1];
13642            }
13643            this.shiftViewBoxToScrollBoundaries(newViewBox);
13644            this.setViewBox(newViewBox);
13645        }
13646        toggleSvgLayerOnZoom() {
13647            if (this.options.googleMaps.on &&
13648                this.googleMaps.map &&
13649                this.options.zoom.hideSvg &&
13650                this.googleMaps.map.getZoom() >= this.options.zoom.hideSvgZoomLevel) {
13651                if (!$$A(this.containers.svg).hasClass("mapsvg-invisible")) {
13652                    $$A(this.containers.svg).animate({ opacity: 0 }, 400, "linear", () => {
13653                        $$A(this.containers.svg).addClass("mapsvg-invisible");
13654                    });
13655                }
13656            }
13657            else {
13658                if ($$A(this.containers.svg).hasClass("mapsvg-invisible")) {
13659                    $$A(this.containers.svg).animate({ opacity: 1 }, 400, "linear", () => {
13660                        $$A(this.containers.svg).removeClass("mapsvg-invisible");
13661                    });
13662                }
13663            }
13664        }
13665        shiftViewBoxToScrollBoundaries(newViewBox) {
13666            if (this.options.scroll.limit) {
13667                if (newViewBox.x < this.svgDefault.viewBox.x)
13668                    newViewBox.x = this.svgDefault.viewBox.x;
13669                else if (newViewBox.x + newViewBox.width >
13670                    this.svgDefault.viewBox.x + this.svgDefault.viewBox.width)
13671                    newViewBox.x =
13672                        this.svgDefault.viewBox.x + this.svgDefault.viewBox.width - newViewBox.width;
13673                if (newViewBox.y < this.svgDefault.viewBox.y)
13674                    newViewBox.y = this.svgDefault.viewBox.y;
13675                else if (newViewBox.y + newViewBox.height >
13676                    this.svgDefault.viewBox.y + this.svgDefault.viewBox.height)
13677                    newViewBox.y =
13678                        this.svgDefault.viewBox.y + this.svgDefault.viewBox.height - newViewBox.height;
13679            }
13680            return newViewBox;
13681        }
13682        markerDelete(marker) {
13683            if (this.editingMarker && this.editingMarker.id == marker.id) {
13684                this.unsetEditingMarker();
13685            }
13686            if (this.markers.findById(marker.id)) {
13687                this.markers.delete(marker.id);
13688            }
13689            marker.delete();
13690            marker = null;
13691            if (this.markers.length === 0)
13692                this.options.markerLastID = 0;
13693        }
13694        markersClusterAdd(markersCluster) {
13695            this.layers.markers.append(markersCluster.elem);
13696            this.markersClusters.push(markersCluster);
13697            markersCluster.adjustScreenPosition();
13698        }
13699        markerAdd(marker) {
13700            $$A(marker.element).hide();
13701            marker.adjustScreenPosition();
13702            this.layers.markers.append(marker.element);
13703            this.markers.push(marker);
13704            marker.mapped = true;
13705            setTimeout(function () {
13706                $$A(marker.element).show();
13707            }, 100);
13708        }
13709        markerRemove(marker) {
13710            if (this.editingMarker && this.editingMarker.id == marker.id) {
13711                this.editingMarker = null;
13712                delete this.editingMarker;
13713            }
13714            if (this.markers.findById(marker.id)) {
13715                this.markers.findById(marker.id).element.remove();
13716                this.markers.delete(marker.id);
13717                marker = null;
13718            }
13719            if (this.markers.length === 0)
13720                this.options.markerLastID = 0;
13721        }
13722        markerId() {
13723            this.options.markerLastID = this.options.markerLastID + 1;
13724            const id = "marker_" + this.options.markerLastID;
13725            if (this.getMarker(id))
13726                return this.markerId();
13727            else
13728                return id;
13729        }
13730        movingItemsAdjustScreenPosition() {
13731            this.markersAdjustScreenPosition();
13732            this.popoverAdjustScreenPosition();
13733            this.bubblesRegionsAdjustScreenPosition();
13734            this.labelsRegionsAdjustScreenPosition();
13735        }
13736        movingItemsMoveScreenPositionBy(deltaX, deltaY) {
13737            this.markersMoveScreenPositionBy(deltaX, deltaY);
13738            this.popoverMoveScreenPositionBy(deltaX, deltaY);
13739            this.bubblesRegionsMoveScreenPositionBy(deltaX, deltaY);
13740            this.labelsRegionsMoveScreenPositionBy(deltaX, deltaY);
13741        }
13742        labelsRegionsAdjustScreenPosition() {
13743            if ($$A(this.containers.map).is(":visible")) {
13744                this.regions.forEach(function (region) {
13745                    region.adjustLabelScreenPosition();
13746                });
13747            }
13748        }
13749        bubblesRegionsAdjustScreenPosition() {
13750            if ($$A(this.containers.map).is(":visible")) {
13751                this.regions.forEach(function (region) {
13752                    region.adjustBubbleScreenPosition();
13753                });
13754            }
13755        }
13756        labelsRegionsMoveScreenPositionBy(deltaX, deltaY) {
13757            if ($$A(this.containers.map).is(":visible")) {
13758                this.regions.forEach(function (region) {
13759                    region.moveLabelScreenPositionBy(deltaX, deltaY);
13760                });
13761            }
13762        }
13763        bubblesRegionsMoveScreenPositionBy(deltaX, deltaY) {
13764            if ($$A(this.containers.map).is(":visible")) {
13765                this.regions.forEach((region) => {
13766                    region.moveBubbleScreenPositionBy(deltaX, deltaY);
13767                });
13768            }
13769        }
13770        markersAdjustScreenPosition() {
13771            this.markers.forEach((marker) => {
13772                marker.adjustScreenPosition();
13773            });
13774            this.markersClusters.forEach((cluster) => {
13775                cluster.adjustScreenPosition();
13776            });
13777            if (this.userLocationMarker) {
13778                this.userLocationMarker.adjustScreenPosition();
13779            }
13780        }
13781        markersMoveScreenPositionBy(deltaX, deltaY) {
13782            this.markers.forEach((marker) => {
13783                marker.moveSrceenPositionBy(deltaX, deltaY);
13784            });
13785            this.markersClusters.forEach((cluster) => {
13786                cluster.moveSrceenPositionBy(deltaX, deltaY);
13787            });
13788            if (this.userLocationMarker) {
13789                this.userLocationMarker.moveSrceenPositionBy(deltaX, deltaY);
13790            }
13791        }
13792        setEditingMarker(marker) {
13793            this.editingMarker = marker;
13794            if (!this.editingMarker.mapped) {
13795                this.editingMarker.needToRemove = true;
13796                this.markerAdd(this.editingMarker);
13797            }
13798        }
13799        unsetEditingMarker() {
13800            if (this.editingMarker && this.editingMarker.needToRemove) {
13801                this.markerRemove(this.editingMarker);
13802            }
13803            this.editingMarker = null;
13804        }
13805        getEditingMarker() {
13806            return this.editingMarker;
13807        }
13808        scrollStart(e, mapsvg) {
13809            if ($$A(e.target).hasClass("mapsvg-btn-map") ||
13810                $$A(e.target).closest(".mapsvg-choropleth").length)
13811                return;
13812            if (this.editMarkers.on && $$A(e.target).hasClass("mapsvg-marker"))
13813                return;
13814            e.preventDefault();
13815            $$A(this.containers.map).addClass("no-transitions");
13816            const ce = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]
13817                ? e.originalEvent.touches[0]
13818                : e;
13819            this.scrollStarted = true;
13820            this.scroll = {
13821                tx: this.scroll.tx || 0,
13822                ty: this.scroll.ty || 0,
13823                vxi: this.viewBox.x,
13824                vyi: this.viewBox.y,
13825                x: ce.clientX,
13826                y: ce.clientY,
13827                dx: 0,
13828                dy: 0,
13829                vx: 0,
13830                vy: 0,
13831                gx: ce.clientX,
13832                gy: ce.clientY,
13833                touchScrollStart: 0,
13834            };
13835            if (e.type.indexOf("mouse") === 0) {
13836                $$A(document).on("mousemove.scroll.mapsvg", (e) => {
13837                    this.scrollMove(e);
13838                });
13839                if (this.options.scroll.spacebar) {
13840                    $$A(document).on("keyup.scroll.mapsvg", (e) => {
13841                        if (e.keyCode == 32) {
13842                            this.scrollEnd(e, mapsvg);
13843                        }
13844                    });
13845                }
13846                else {
13847                    $$A(document).on("mouseup.scroll.mapsvg", (e) => {
13848                        this.scrollEnd(e, mapsvg);
13849                    });
13850                }
13851            }
13852        }
13853        scrollMove(e) {
13854            e.preventDefault();
13855            if (!this.isScrolling) {
13856                this.isScrolling = true;
13857                $$A(this.containers.map).addClass("scrolling");
13858            }
13859            const ce = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]
13860                ? e.originalEvent.touches[0]
13861                : e;
13862            this.panBy(this.scroll.gx - ce.clientX, this.scroll.gy - ce.clientY);
13863            this.scroll.gx = ce.clientX;
13864            this.scroll.gy = ce.clientY;
13865            this.scroll.dx = this.scroll.x - ce.clientX;
13866            this.scroll.dy = this.scroll.y - ce.clientY;
13867            let vx = this.scroll.vxi + this.scroll.dx / this.scale;
13868            let vy = this.scroll.vyi + this.scroll.dy / this.scale;
13869            if (this.options.scroll.limit) {
13870                if (vx < this.svgDefault.viewBox.x)
13871                    vx = this.svgDefault.viewBox.x;
13872                else if (this.viewBox.width + vx >
13873                    this.svgDefault.viewBox.x + this.svgDefault.viewBox.width)
13874                    vx = this.svgDefault.viewBox.x + this.svgDefault.viewBox.width - this.viewBox.width;
13875                if (vy < this.svgDefault.viewBox.y)
13876                    vy = this.svgDefault.viewBox.y;
13877                else if (this.viewBox.height + vy >
13878                    this.svgDefault.viewBox.y + this.svgDefault.viewBox.height)
13879                    vy =
13880                        this.svgDefault.viewBox.y +
13881                            this.svgDefault.viewBox.height -
13882                            this.viewBox.height;
13883            }
13884            this.scroll.vx = vx;
13885            this.scroll.vy = vy;
13886        }
13887        scrollEnd(e, mapsvg, noClick) {
13888            setTimeout(() => {
13889                this.enableAnimation();
13890                this.scrollStarted = false;
13891                this.isScrolling = false;
13892            }, 100);
13893            if (this.googleMaps && this.googleMaps.overlay) {
13894                this.googleMaps.overlay.draw();
13895            }
13896            $$A(this.containers.map).removeClass("scrolling");
13897            $$A(document).off("keyup.scroll.mapsvg");
13898            $$A(document).off("mousemove.scroll.mapsvg");
13899            $$A(document).off("mouseup.scroll.mapsvg");
13900            if (noClick !== true && Math.abs(this.scroll.dx) < 5 && Math.abs(this.scroll.dy) < 5) {
13901                if (this.editMarkers.on)
13902                    this.clickAddsMarker && this.markerAddClickHandler(e);
13903                else if (this.objectClickedBeforeScroll)
13904                    if (this.objectClickedBeforeScroll instanceof Marker) {
13905                        this.markerClickHandler(e, this.objectClickedBeforeScroll);
13906                    }
13907                    else if (this.objectClickedBeforeScroll instanceof Region) {
13908                        this.regionClickHandler(e, this.objectClickedBeforeScroll);
13909                    }
13910                    else if (this.objectClickedBeforeScroll instanceof MarkerCluster) {
13911                        this.markerClusterClickHandler(e, this.objectClickedBeforeScroll);
13912                    }
13913            }
13914            this.viewBox.x = this.scroll.vx || this.viewBox.x;
13915            this.viewBox.y = this.scroll.vy || this.viewBox.y;
13916        }
13917        setViewBoxByGoogleMapsOverlay() {
13918            const bounds = this.googleMaps.overlay.getPixelBounds();
13919            const scale = (bounds.ne.x - bounds.sw.x) / this.svgDefault.viewBox.width;
13920            const vb = new ViewBox(this.svgDefault.viewBox.x - bounds.sw.x / scale, this.svgDefault.viewBox.y - bounds.ne.y / scale, this.containers.map.offsetWidth / scale, this.containers.map.offsetHeight / scale);
13921            this.setViewBox(vb, false);
13922        }
13923        panBy(x, y) {
13924            let tx = this.scroll.tx - x;
13925            let ty = this.scroll.ty - y;
13926            const scrolled = { x: true, y: true };
13927            if (this.options.scroll.limit) {
13928                const svg = $$A(this.containers.svg)[0].getBoundingClientRect();
13929                const bounds = $$A(this.containers.map)[0].getBoundingClientRect();
13930                if ((svg.left - x > bounds.left && x < 0) || (svg.right - x < bounds.right && x > 0)) {
13931                    tx = this.scroll.tx;
13932                    scrolled.x = false;
13933                }
13934                if ((svg.top - y > bounds.top && y < 0) || (svg.bottom - y < bounds.bottom && y > 0)) {
13935                    ty = this.scroll.ty;
13936                    scrolled.y = false;
13937                }
13938            }
13939            $$A(this.containers.scrollpane).css({
13940                transform: "translate(" + tx + "px," + ty + "px)",
13941            });
13942            this.scroll.tx = tx;
13943            this.scroll.ty = ty;
13944            if (scrolled.x || scrolled.y) {
13945                const moveX = scrolled.x ? x : 0;
13946                const moveY = scrolled.y ? y : 0;
13947                this.movingItemsMoveScreenPositionBy(moveX, moveY);
13948                if (this.googleMaps.map) {
13949                    let point = this.googleMaps.map.getCenter();
13950                    const projection = this.googleMaps.overlay.getProjection();
13951                    const pixelpoint = projection.fromLatLngToDivPixel(point);
13952                    pixelpoint.x += moveX;
13953                    pixelpoint.y += moveY;
13954                    point = projection.fromDivPixelToLatLng(pixelpoint);
13955                    this.googleMaps.map.setCenter(point);
13956                }
13957            }
13958            return scrolled;
13959        }
13960        setObjectClickedBeforeScroll(object) {
13961            this.objectClickedBeforeScroll = object;
13962        }
13963        touchStart(_e, mapsvg) {
13964            _e.preventDefault();
13965            if (this.scrollStarted) {
13966                this.scrollEnd(_e, mapsvg, true);
13967            }
13968            const e = _e.originalEvent;
13969            if (this.options.zoom.fingers && e.touches && e.touches.length == 2) {
13970                this.touchZoomStart = true;
13971                this.scaleDistStart = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY);
13972            }
13973            else if (e.touches && e.touches.length == 1) {
13974                this.scrollStart(_e, mapsvg);
13975            }
13976            $$A(document)
13977                .on("touchmove.scroll.mapsvg", (e) => {
13978                e.preventDefault();
13979                this.touchMove(e, this);
13980            })
13981                .on("touchend.scroll.mapsvg", (e) => {
13982                e.preventDefault();
13983                this.touchEnd(e, this);
13984            });
13985        }
13986        touchMove(_e, mapsvg) {
13987            _e.preventDefault();
13988            const e = _e.originalEvent;
13989            if (this.options.zoom.fingers && e.touches && e.touches.length == 2) {
13990                if (!MapSVG.ios) {
13991                    e.scale =
13992                        Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY) / this.scaleDistStart;
13993                }
13994                if (e.scale != 1 && this.canZoom) {
13995                    const d = e.scale > 1 ? 1 : -1;
13996                    const cx = e.touches[0].pageX >= e.touches[1].pageX
13997                        ? e.touches[0].pageX -
13998                            (e.touches[0].pageX - e.touches[1].pageX) / 2 -
13999                            $$A(this.containers.map).offset().left
14000                        : e.touches[1].pageX -
14001                            (e.touches[1].pageX - e.touches[0].pageX) / 2 -
14002                            $$A(this.containers.map).offset().left;
14003                    const cy = e.touches[0].pageY >= e.touches[1].pageY
14004                        ? e.touches[0].pageY -
14005                            (e.touches[0].pageY - e.touches[1].pageY) -
14006                            $$A(this.containers.map).offset().top
14007                        : e.touches[1].pageY -
14008                            (e.touches[1].pageY - e.touches[0].pageY) -
14009                            $$A(this.containers.map).offset().top;
14010                    const center = this.converter.convertPixelToSVG(new ScreenPoint(cx, cy));
14011                    if (d > 0)
14012                        this.zoomIn(center);
14013                    else
14014                        this.zoomOut(center);
14015                }
14016            }
14017            else if (e.touches && e.touches.length == 1) {
14018                this.scrollMove(_e);
14019            }
14020        }
14021        touchEnd(_e, mapsvg) {
14022            _e.preventDefault();
14023            const e = _e.originalEvent;
14024            if (this.touchZoomStart) {
14025                this.touchZoomStart = false;
14026            }
14027            else if (this.scrollStarted) {
14028                this.scrollEnd(_e, mapsvg);
14029            }
14030            $$A(document).off("touchmove.scroll.mapsvg");
14031            $$A(document).off("touchend.scroll.mapsvg");
14032        }
14033        getSelected() {
14034            return this.selected_id;
14035        }
14036        selectRegion(id, skipDirectorySelection) {
14037            let region;
14038            if (typeof id == "string") {
14039                region = this.getRegion(id);
14040            }
14041            else {
14042                region = id;
14043            }
14044            if (!region)
14045                return;
14046            let ids;
14047            if (this.options.multiSelect && !this.editRegions.on) {
14048                if (region.selected) {
14049                    this.deselectRegion(region);
14050                    if (!skipDirectorySelection && this.options.menu.on) {
14051                        if (this.options.menu.source == "database") {
14052                            if (region.objects && region.objects.length) {
14053                                ids = region.objects.map((obj) => {
14054                                    return obj.id.toString();
14055                                });
14056                            }
14057                        }
14058                        else {
14059                            ids = [region.id];
14060                        }
14061                        this.controllers.directory.deselectItems();
14062                    }
14063                    return;
14064                }
14065            }
14066            else if (this.selected_id.length > 0) {
14067                this.deselectAllRegions();
14068                if (!skipDirectorySelection && this.options.menu.on) {
14069                    if (this.options.menu.source == "database") {
14070                        if (region.objects && region.objects.length) {
14071                            ids = region.objects.map((obj) => {
14072                                return obj.id.toString();
14073                            });
14074                        }
14075                    }
14076                    else {
14077                        ids = [region.id];
14078                    }
14079                    this.controllers.directory.deselectItems();
14080                }
14081            }
14082            this.selected_id.push(region.id);
14083            region.select();
14084            const skip = this.options.actions.region.click.filterDirectory;
14085            if (!skip &&
14086                !skipDirectorySelection &&
14087                this.options.menu.on &&
14088                this.controllers &&
14089                this.controllers.directory) {
14090                if (this.options.menu.source == "database") {
14091                    if (region.objects && region.objects.length) {
14092                        ids = region.objects.map((obj) => {
14093                            return obj.id.toString();
14094                        });
14095                    }
14096                    else {
14097                        ids = [region.id];
14098                    }
14099                }
14100                else {
14101                    ids = [region.id];
14102                }
14103                this.controllers.directory.selectItems(ids);
14104            }
14105            if (this.options.actions.region.click.addIdToUrl &&
14106                !this.options.actions.region.click.showAnotherMap) {
14107                window.location.hash = "/m/" + region.id;
14108            }
14109        }
14110        deselectAllRegions() {
14111            $$A.each(this.selected_id, (index, id) => {
14112                this.deselectRegion(this.getRegion(id));
14113            });
14114        }
14115        deselectRegion(region) {
14116            if (!region)
14117                region = this.getRegion(this.selected_id[0]);
14118            if (region) {
14119                region.deselect();
14120                const i = $$A.inArray(region.id, this.selected_id);
14121                this.selected_id.splice(i, 1);
14122            }
14123            if (this.options.actions.region.click.addIdToUrl) {
14124                if (window.location.hash.indexOf(region.id) !== -1) {
14125                    history.replaceState(null, null, " ");
14126                }
14127            }
14128        }
14129        highlightRegions(regions) {
14130            regions.forEach((region) => {
14131                if (region && !region.selected && !region.disabled) {
14132                    this.highlightedRegions.push(region);
14133                    region.highlight();
14134                }
14135            });
14136        }
14137        unhighlightRegions() {
14138            this.highlightedRegions.forEach((region) => {
14139                if (region && !region.selected && !region.disabled)
14140                    region.unhighlight();
14141            });
14142            this.highlightedRegions = [];
14143        }
14144        selectMarker(marker) {
14145            if (!(marker instanceof Marker))
14146                return;
14147            this.deselectAllMarkers();
14148            marker.select();
14149            this.selected_marker = marker;
14150            $$A(this.layers.markers).addClass("mapsvg-with-marker-active");
14151            if (this.options.menu.on && this.options.menu.source == "database") {
14152                this.controllers.directory.deselectItems();
14153                this.controllers.directory.selectItems(marker.object.id);
14154            }
14155        }
14156        deselectAllMarkers() {
14157            this.selected_marker && this.selected_marker.deselect();
14158            $$A(this.layers.markers).removeClass("mapsvg-with-marker-active");
14159        }
14160        deselectMarker(marker) {
14161            if (marker) {
14162                marker.deselect();
14163            }
14164        }
14165        highlightMarker(marker) {
14166            $$A(this.layers.markers).addClass("mapsvg-with-marker-hover");
14167            marker.highlight();
14168            this.highlighted_marker = marker;
14169        }
14170        unhighlightMarker() {
14171            $$A(this.layers.markers).removeClass("mapsvg-with-marker-hover");
14172            this.highlighted_marker && this.highlighted_marker.unhighlight();
14173        }
14174        convertMouseToSVG(e) {
14175            const mc = MapSVG.mouseCoords(e);
14176            const x = mc.x - $$A(this.containers.map).offset().left;
14177            const y = mc.y - $$A(this.containers.map).offset().top;
14178            const screenPoint = new ScreenPoint(x, y);
14179            return this.converter.convertPixelToSVG(screenPoint);
14180        }
14181        pickChoroplethColor(choroplethValue) {
14182            const w = (choroplethValue - this.options.choropleth.coloring.gradient.values.min) /
14183                this.options.choropleth.coloring.gradient.values.maxAdjusted;
14184            const rgba = {
14185                r: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.r * w +
14186                    this.options.choropleth.coloring.gradient.colors.lowRGB.r),
14187                g: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.g * w +
14188                    this.options.choropleth.coloring.gradient.colors.lowRGB.g),
14189                b: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.b * w +
14190                    this.options.choropleth.coloring.gradient.colors.lowRGB.b),
14191                a: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.a * w +
14192                    this.options.choropleth.coloring.gradient.colors.lowRGB.a),
14193            };
14194            return rgba;
14195        }
14196        isRegionDisabled(id, svgfill) {
14197            if (this.options.regions[id] && (this.options.regions[id].disabled || svgfill == "none")) {
14198                return true;
14199            }
14200            else if ((this.options.regions[id] == undefined ||
14201                MapSVG.parseBoolean(this.options.regions[id].disabled)) &&
14202                (this.options.disableAll || svgfill == "none" || id == "labels" || id == "Labels")) {
14203                return true;
14204            }
14205            else {
14206                return false;
14207            }
14208        }
14209        loadMap(id, container) {
14210            if (!(container instanceof HTMLElement)) {
14211                console.error("Can't load a new map: container was not provided.");
14212                return;
14213            }
14214            const previousMapsIds = [...this.options.previousMapsIds];
14215            const currentMapId = this.id;
14216            if (previousMapsIds[previousMapsIds.length - 1] !== id) {
14217                previousMapsIds.push(currentMapId);
14218            }
14219            else {
14220                previousMapsIds.pop();
14221            }
14222            let showPreviousMapButton;
14223            if (typeof this.options.actions.region.click.showAnotherMapContainerId !== "undefined" &&
14224                this.options.actions.region.click.showAnotherMapContainerId !== "") {
14225                showPreviousMapButton = false;
14226            }
14227            else {
14228                showPreviousMapButton = this.options.controls.previousMap;
14229            }
14230            const mapsRepo = new MapsRepository();
14231            const sameContainer = container === this.containers.map;
14232            mapsRepo.findById(id).done((map) => {
14233                sameContainer && this.destroy();
14234                const newMap = new MapSVGMap(container.getAttribute("id"), map);
14235                newMap.events.on("afterLoad", function () {
14236                    this.options.previousMapsIds = previousMapsIds;
14237                    this.options.controls.previousMap = showPreviousMapButton;
14238                    this.setControls(this.options.controls);
14239                });
14240            });
14241        }
14242        loadPreviousMap() {
14243            const previousMapId = this.options.previousMapsIds[this.options.previousMapsIds.length - 1];
14244            const container = document.getElementById(this.containerId);
14245            this.loadMap(previousMapId, container);
14246        }
14247        markerClusterClickHandler(e, markerCluster) {
14248            this.objectClickedBeforeScroll = null;
14249            if (this.eventsPreventList["click"])
14250                return;
14251            this.zoomTo(markerCluster.markers);
14252            return;
14253        }
14254        regionClickHandler(e, region) {
14255            this.objectClickedBeforeScroll = null;
14256            if (this.eventsPreventList["click"])
14257                return;
14258            this.selectRegion(region.id);
14259            if (this.editRegions.on) {
14260                this.regionEditHandler.call(region);
14261                return;
14262            }
14263            const actions = this.options.actions;
14264            if (actions.region.click.zoom) {
14265                this.zoomTo(region, parseInt(actions.region.click.zoomToLevel));
14266            }
14267            if (actions.region.click.filterDirectory) {
14268                const query = new Query({
14269                    filters: {
14270                        regions: {
14271                            table_name: this.regionsRepository.getSchema().name,
14272                            region_ids: [region.id],
14273                        },
14274                    },
14275                });
14276                this.objectsRepository.query.resetFilters();
14277                this.setFilterOut();
14278                this.objectsRepository.find(query).done(() => {
14279                    if (this.controllers.popover) {
14280                        this.controllers.popover.redraw(region.forTemplate());
14281                    }
14282                    if (this.controllers.detailsView) {
14283                        this.controllers.detailsView.redraw(region.forTemplate());
14284                    }
14285                });
14286                this.updateFiltersState();
14287            }
14288            if (actions.region.click.showDetails) {
14289                this.loadDetailsView(region);
14290            }
14291            if (actions.region.click.showPopover) {
14292                if (actions.region.click.zoom) {
14293                    setTimeout(() => {
14294                        this.showPopover(region);
14295                    }, 400);
14296                }
14297                else {
14298                    this.showPopover(region);
14299                }
14300            }
14301            else if (e && e.type.indexOf("touch") !== -1 && actions.region.touch.showPopover) {
14302                if (actions.region.click.zoom) {
14303                    setTimeout(() => {
14304                        this.showPopover(region);
14305                    }, 400);
14306                }
14307                else {
14308                    this.showPopover(region);
14309                }
14310            }
14311            if (actions.region.click.goToLink) {
14312                const linkParts = actions.region.click.linkField.split(".");
14313                let url;
14314                if (linkParts.length > 1) {
14315                    const obj = linkParts.shift();
14316                    const attr = "." + linkParts.join(".");
14317                    if (obj == "Region") {
14318                        if (region.data) {
14319                            try {
14320                                url = eval("region.data" + attr);
14321                            }
14322                            catch (err) {
14323                                console.log("No such field as region.data" + attr);
14324                            }
14325                        }
14326                    }
14327                    else {
14328                        if (region.objects && region.objects[0]) {
14329                            try {
14330                                url = eval("region.objects[0]" + attr);
14331                            }
14332                            catch (err) {
14333                                console.log("No such field as region.objects[0]" + attr);
14334                            }
14335                        }
14336                    }
14337                    if (url && !this.disableLinks) {
14338                        if (this.editMode) {
14339                            alert("Redirect: " + url + "\nLinks are disabled in the preview.");
14340                            return;
14341                        }
14342                        if (actions.region.click.newTab) {
14343                            const win = window.open(url, "_blank");
14344                            win.focus();
14345                        }
14346                        else {
14347                            window.location.href = url;
14348                        }
14349                    }
14350                }
14351            }
14352            if (actions.region.click.showAnotherMap) {
14353                if (this.editMode) {
14354                    alert('"Show another map" action is disabled in the preview');
14355                    return;
14356                }
14357                const linkParts = actions.region.click.showAnotherMapField.split(".");
14358                if (linkParts.length > 1) {
14359                    const obj = linkParts.shift();
14360                    const attr = "." + linkParts.join(".");
14361                    let map_id;
14362                    if (obj == "Region") {
14363                        if (region.data)
14364                            map_id = eval("region.data" + attr);
14365                    }
14366                    else {
14367                        if (region.objects && region.objects[0])
14368                            map_id = eval("region.objects[0]" + attr);
14369                    }
14370                    if (map_id) {
14371                        const container = actions.region.click.showAnotherMapContainerId
14372                            ? $$A("#" + actions.region.click.showAnotherMapContainerId)[0]
14373                            : $$A(this.containers.map)[0];
14374                        this.loadMap(map_id, container);
14375                    }
14376                }
14377            }
14378            this.events.trigger("click.region", region, [e, region, this]);
14379        }
14380        markerClickHandler(e, marker) {
14381            this.objectClickedBeforeScroll = null;
14382            if (this.eventsPreventList["click"])
14383                return;
14384            const actions = this.options.actions;
14385            this.selectMarker(marker);
14386            const passingObject = marker.object;
14387            if (actions.marker.click.zoom) {
14388                this.zoomTo(marker, parseInt(actions.marker.click.zoomToLevel));
14389            }
14390            if (actions.marker.click.filterDirectory) {
14391                const query = new Query({ filters: { id: marker.object.id } });
14392                this.objectsRepository.find(query);
14393                this.updateFiltersState();
14394            }
14395            if (actions.marker.click.showDetails)
14396                this.loadDetailsView(passingObject);
14397            if (actions.marker.click.showPopover) {
14398                if (actions.marker.click.zoom) {
14399                    setTimeout(() => {
14400                        this.showPopover(passingObject);
14401                    }, 500);
14402                }
14403                else {
14404                    this.showPopover(passingObject);
14405                }
14406            }
14407            else if (e && e.type.indexOf("touch") !== -1 && actions.marker.touch.showPopover) {
14408                if (actions.marker.click.zoom) {
14409                    setTimeout(() => {
14410                        this.showPopover(passingObject);
14411                    }, 500);
14412                }
14413                else {
14414                    this.showPopover(passingObject);
14415                }
14416            }
14417            if (actions.marker.click.goToLink) {
14418                const linkParts = actions.marker.click.linkField.split(".");
14419                let url;
14420                if (linkParts.length > 1) {
14421                    const obj = linkParts.shift();
14422                    const attr = "." + linkParts.join(".");
14423                    try {
14424                        url = eval("passingObject" + attr);
14425                    }
14426                    catch (err) {
14427                        console.log("MapSVG: No such field as passingObject" + attr);
14428                    }
14429                    if (url && !this.disableLinks)
14430                        if (this.editMode) {
14431                            alert("Redirect: " + url + "\nLinks are disabled in the preview.");
14432                            return;
14433                        }
14434                    if (actions.marker.click.newTab) {
14435                        const win = window.open(url, "_blank");
14436                        win.focus();
14437                    }
14438                    else {
14439                        window.location.href = url;
14440                    }
14441                }
14442            }
14443            this.events.trigger("click.marker", marker, [e, marker, this]);
14444        }
14445        fileExists(url) {
14446            if (url.substr(0, 4) == "data")
14447                return true;
14448            const http = new XMLHttpRequest();
14449            http.open("HEAD", url, false);
14450            http.send();
14451            return http.status != 404;
14452        }
14453        hideMarkers() {
14454            this.markers.forEach(function (marker) {
14455                marker.hide();
14456            });
14457            $$A(this.containers.wrap).addClass("mapsvg-edit-marker-mode");
14458        }
14459        hideMarkersExceptOne(id) {
14460            this.markers.forEach(function (marker) {
14461                if (typeof id === "undefined" || (marker.object && id != marker.object.id)) {
14462                    marker.hide();
14463                }
14464            });
14465            $$A(this.containers.wrap).addClass("mapsvg-edit-marker-mode");
14466        }
14467        showMarkers() {
14468            this.markers.forEach(function (m) {
14469                m.show();
14470            });
14471            this.deselectAllMarkers();
14472            $$A(this.containers.wrap).removeClass("mapsvg-edit-marker-mode");
14473        }
14474        markerAddClickHandler(e) {
14475            if ($$A(e.target).hasClass("mapsvg-marker"))
14476                return;
14477            const svgPoint = this.getSvgPointAtClick(e);
14478            const geoPoint = this.isGeo() ? this.converter.convertSVGToGeo(svgPoint) : null;
14479            if (!$$A.isNumeric(svgPoint.x) || !$$A.isNumeric(svgPoint.y))
14480                return;
14481            if (this.editingMarker) {
14482                if (geoPoint) {
14483                    this.editingMarker.location.setGeoPoint(geoPoint);
14484                }
14485                else {
14486                    this.editingMarker.location.setSvgPoint(svgPoint);
14487                }
14488                return;
14489            }
14490            const location = new Location({
14491                svgPoint: svgPoint,
14492                geoPoint: geoPoint,
14493                img: this.options.defaultMarkerImage,
14494            });
14495            const marker = new Marker({
14496                location: location,
14497                mapsvg: this,
14498            });
14499            this.markerAdd(marker);
14500            this.markerEditHandler && this.markerEditHandler.call(location, location);
14501        }
14502        getSvgPointAtClick(e) {
14503            const mc = MapSVG.mouseCoords(e);
14504            const x = mc.x - $$A(this.containers.map).offset().left;
14505            const y = mc.y - $$A(this.containers.map).offset().top;
14506            const screenPoint = new ScreenPoint(x, y);
14507            return this.converter.convertPixelToSVG(screenPoint);
14508        }
14509        setDefaultMarkerImage(src) {
14510            this.options.defaultMarkerImage = src;
14511        }
14512        setMarkerImagesDependency() {
14513            this.locationField = this.objectsRepository.schema.getFieldByType("location");
14514            if (this.locationField &&
14515                this.locationField.markersByFieldEnabled &&
14516                this.locationField.markerField &&
14517                Object.values(this.locationField.markersByField).length > 0) {
14518                this.setMarkersByField = true;
14519            }
14520            else {
14521                this.setMarkersByField = false;
14522            }
14523        }
14524        getMarkerImage(fieldValueOrObject, location) {
14525            let fieldValue;
14526            if (this.setMarkersByField) {
14527                if (typeof fieldValueOrObject === "object") {
14528                    fieldValue = fieldValueOrObject[this.locationField.markerField];
14529                    if (this.locationField.markerField === "regions") {
14530                        fieldValue = fieldValue[0] && fieldValue[0].id;
14531                    }
14532                    else if (typeof fieldValue === "object" && fieldValue.length) {
14533                        fieldValue = fieldValue[0].value;
14534                    }
14535                }
14536                else {
14537                    fieldValue = fieldValueOrObject;
14538                }
14539                if (this.locationField.markersByField[fieldValue]) {
14540                    return this.locationField.markersByField[fieldValue];
14541                }
14542            }
14543            return location && location.imagePath
14544                ? location.imagePath
14545                : this.options.defaultMarkerImage
14546                    ? this.options.defaultMarkerImage
14547                    : MapSVG.urls.root + "markers/_pin_default.png";
14548        }
14549        setMarkersEditMode(on, clickAddsMarker) {
14550            this.editMarkers.on = MapSVG.parseBoolean(on);
14551            this.clickAddsMarker = this.editMarkers.on;
14552            this.setEventHandlers();
14553        }
14554        setRegionsEditMode(on) {
14555            this.editRegions.on = MapSVG.parseBoolean(on);
14556            this.deselectAllRegions();
14557            this.setEventHandlers();
14558        }
14559        setEditMode(on) {
14560            this.editMode = on;
14561        }
14562        setDataEditMode(on) {
14563            this.editData.on = MapSVG.parseBoolean(on);
14564            this.deselectAllRegions();
14565            this.setEventHandlers();
14566        }
14567        download() {
14568            window.location.href = window.location.origin + this.options.source;
14569        }
14570        popoverAdjustScreenPosition() {
14571            if (this.controllers.popover instanceof PopoverController) {
14572                this.controllers.popover.adjustScreenPosition();
14573            }
14574        }
14575        popoverMoveScreenPositionBy(deltaX, deltaY) {
14576            if (this.controllers.popover instanceof PopoverController) {
14577                this.controllers.popover.moveSrceenPositionBy(deltaX, deltaY);
14578            }
14579        }
14580        showPopover(object) {
14581            const mapObject = object instanceof Region
14582                ? object
14583                : object.location && object.location.marker
14584                    ? object.location.marker
14585                    : null;
14586            if (!mapObject)
14587                return;
14588            let point;
14589            if (mapObject instanceof Marker) {
14590                point = mapObject.svgPoint;
14591            }
14592            else {
14593                point = mapObject.getCenterSVG();
14594            }
14595            this.controllers.popover && this.controllers.popover.destroy();
14596            this.controllers.popover = new PopoverController({
14597                container: this.containers.popover,
14598                point: point,
14599                yShift: mapObject instanceof Marker ? mapObject.height : 0,
14600                template: object instanceof Region
14601                    ? this.options.templates.popoverRegion
14602                    : this.options.templates.popoverMarker,
14603                mapsvg: this,
14604                data: object.getData(),
14605                mapObject: mapObject,
14606                scrollable: true,
14607                withToolbar: !(MapSVG.isPhone && this.options.popovers.mobileFullscreen),
14608                events: {
14609                    shown: (popover) => {
14610                        if (this.options.popovers.centerOn) {
14611                            const shift = popover.containers.main.offsetHeight / 2;
14612                            if (this.options.popovers.centerOn &&
14613                                !(MapSVG.isPhone && this.options.popovers.mobileFullscreen)) {
14614                                this.centerOn(mapObject, shift);
14615                            }
14616                        }
14617                        this.popoverShowingFor = mapObject;
14618                        this.events.trigger("shown.popover", this, [this, popover]);
14619                        $$A(window).trigger("shown.popover", [this, popover]);
14620                    },
14621                    closed: (popover) => {
14622                        this.options.popovers.resetViewboxOnClose && this.viewBoxReset(true);
14623                        this.popoverShowingFor = null;
14624                        this.events.trigger("closed.popover", this, [this, popover]);
14625                    },
14626                    resize: (popover) => {
14627                        if (this.options.popovers.centerOn) {
14628                            const shift = popover.containers.main.offsetHeight / 2;
14629                            if (this.options.popovers.centerOn &&
14630                                !(MapSVG.isPhone && this.options.popovers.mobileFullscreen)) {
14631                                this.centerOn(mapObject, shift);
14632                            }
14633                        }
14634                    },
14635                },
14636            });
14637            this.controllers.popover._init();
14638        }
14639        hidePopover() {
14640            this.controllers.popover && this.controllers.popover.close();
14641        }
14642        popoverOffHandler(e) {
14643            if (this.isScrolling ||
14644                $$A(e.target).closest(".mapsvg-popover").length ||
14645                $$A(e.target).hasClass("mapsvg-btn-map"))
14646                return;
14647            this.controllers.popover && this.controllers.popover.close();
14648        }
14649        mouseOverHandler(e, object) {
14650            if (this.eventsPreventList["mouseover"]) {
14651                return;
14652            }
14653            if (object instanceof Marker) {
14654                if (this.options.actions.marker.mouseover.showTooltip) {
14655                    this.showTooltip(object);
14656                }
14657            }
14658            if (object instanceof Region) {
14659                if (this.options.actions.region.mouseover.showTooltip) {
14660                    this.showTooltip(object);
14661                }
14662            }
14663            let ids;
14664            if (this.options.menu.on) {
14665                if (this.options.menu.source == "database") {
14666                    if (object instanceof Region && object.objects.length) {
14667                        ids = object.objects.map((obj) => {
14668                            return obj.id;
14669                        });
14670                    }
14671                    if (object instanceof Marker) {
14672                        ids = object.object ? [object.object.id] : [];
14673                    }
14674                }
14675                else {
14676                    if (object instanceof Region) {
14677                        ids = [object.id];
14678                    }
14679                    if (this instanceof Marker &&
14680                        object.object.regions &&
14681                        object.object.regions.length) {
14682                        ids = object.object.regions.map((obj) => {
14683                            return obj.id;
14684                        });
14685                    }
14686                }
14687                this.controllers.directory.highlightItems(ids);
14688            }
14689            if (object instanceof Region) {
14690                if (!object.selected)
14691                    object.highlight();
14692                this.events.trigger("mouseover.region", object, [e, this]);
14693            }
14694            else {
14695                this.highlightMarker(object);
14696                this.events.trigger("mouseover.marker", object, [e, this]);
14697            }
14698        }
14699        showTooltip(object) {
14700            let name, _object;
14701            if (object instanceof Region) {
14702                name = "tooltipRegion";
14703                _object = object;
14704            }
14705            else if (object instanceof Marker) {
14706                name = "tooltipMarker";
14707                _object = object.object;
14708            }
14709            else {
14710                name = "tooltipMarker";
14711                _object = object;
14712            }
14713            if (_object != null && this.popoverShowingFor !== object) {
14714                this.controllers.tooltip.setMainTemplate(this.options.templates[name]);
14715                this.controllers.tooltip.redraw(_object.getData());
14716                this.controllers.tooltip.show();
14717            }
14718        }
14719        mouseOutHandler(e, object) {
14720            if (this.eventsPreventList["mouseout"]) {
14721                return;
14722            }
14723            if (this.controllers.tooltip)
14724                this.controllers.tooltip.hide();
14725            if (object instanceof Region) {
14726                if (!object.selected)
14727                    object.unhighlight();
14728                this.events.trigger("mouseout.region", object, [e, this]);
14729            }
14730            else {
14731                this.unhighlightMarker();
14732                this.events.trigger("mouseout.marker", object, [e, this]);
14733            }
14734            let ids;
14735            if (this.options.menu.on) {
14736                if (this.options.menu.source == "database") {
14737                    if (object instanceof Marker) {
14738                        const marker = object;
14739                        ids = marker.object ? [marker.object.id] : [];
14740                    }
14741                }
14742                this.controllers.directory.unhighlightItems();
14743            }
14744        }
14745        eventsPrevent(event) {
14746            this.eventsPreventList[event] = true;
14747        }
14748        eventsRestore(event) {
14749            if (event) {
14750                this.eventsPreventList[event] = false;
14751            }
14752            else {
14753                this.eventsPreventList = {};
14754            }
14755        }
14756        setEventHandlers() {
14757            const _this = this;
14758            $$A(_this.containers.map).off(".common.mapsvg");
14759            $$A(_this.containers.scrollpane).off(".common.mapsvg");
14760            $$A(document).off(".scroll.mapsvg");
14761            $$A(document).off(".scrollInit.mapsvg");
14762            if (_this.editMarkers.on) {
14763                $$A(_this.containers.map).on("touchstart.common.mapsvg mousedown.common.mapsvg", ".mapsvg-marker", function (e) {
14764                    e.originalEvent.preventDefault();
14765                    const marker = _this.getMarker($$A(this).attr("id"));
14766                    const startCoords = MapSVG.mouseCoords(e);
14767                    marker.drag(startCoords, _this.scale);
14768                });
14769            }
14770            if (!_this.editMarkers.on) {
14771                $$A(_this.containers.map)
14772                    .on("mouseover.common.mapsvg", ".mapsvg-region", function (e) {
14773                    const id = $$A(this).attr("id");
14774                    _this.mouseOverHandler.call(_this, e, _this.getRegion(id));
14775                })
14776                    .on("mouseleave.common.mapsvg", ".mapsvg-region", function (e) {
14777                    const id = $$A(this).attr("id");
14778                    _this.mouseOutHandler.call(_this, e, _this.getRegion(id));
14779                });
14780            }
14781            if (!_this.editRegions.on) {
14782                $$A(_this.containers.map)
14783                    .on("mouseover.common.mapsvg", ".mapsvg-marker", function (e) {
14784                    const id = $$A(this).attr("id");
14785                    _this.mouseOverHandler.call(_this, e, _this.getMarker(id));
14786                })
14787                    .on("mouseleave.common.mapsvg", ".mapsvg-marker", function (e) {
14788                    const id = $$A(this).attr("id");
14789                    _this.mouseOutHandler.call(_this, e, _this.getMarker(id));
14790                });
14791            }
14792            if (_this.options.scroll.spacebar) {
14793                $$A(document).on("keydown.scroll.mapsvg", function (e) {
14794                    if (!(document.activeElement.tagName === "INPUT" &&
14795                        $$A(document.activeElement).attr("type") === "text") &&
14796                        !_this.isScrolling &&
14797                        e.keyCode == 32) {
14798                        e.preventDefault();
14799                        $$A(_this.containers.map).addClass("mapsvg-scrollable");
14800                        $$A(document)
14801                            .on("mousemove.scrollInit.mapsvg", function (e) {
14802                            _this.isScrolling = true;
14803                            $$A(document).off("mousemove.scrollInit.mapsvg");
14804                            _this.scrollStart(e, _this);
14805                        })
14806                            .on("keyup.scroll.mapsvg", function (e) {
14807                            if (e.keyCode == 32) {
14808                                $$A(document).off("mousemove.scrollInit.mapsvg");
14809                                $$A(_this.containers.map).removeClass("mapsvg-scrollable");
14810                            }
14811                        });
14812                    }
14813                });
14814            }
14815            else if (!_this.options.scroll.on) {
14816                if (!_this.editMarkers.on) {
14817                    $$A(_this.containers.map).on("touchstart.common.mapsvg", ".mapsvg-region", function (e) {
14818                        _this.scroll.touchScrollStart = $$A(window).scrollTop();
14819                    });
14820                    $$A(_this.containers.map).on("touchstart.common.mapsvg", ".mapsvg-marker", function (e) {
14821                        _this.scroll.touchScrollStart = $$A(window).scrollTop();
14822                    });
14823                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-region", function (e) {
14824                        if (e.cancelable) {
14825                            e.preventDefault();
14826                        }
14827                        if (!_this.scroll.touchScrollStart ||
14828                            _this.scroll.touchScrollStart === $$A(window).scrollTop()) {
14829                            _this.regionClickHandler(e, _this.getRegion($$A(this).attr("id")));
14830                        }
14831                    });
14832                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-marker", function (e) {
14833                        if (e.cancelable) {
14834                            e.preventDefault();
14835                        }
14836                        if (!_this.scroll.touchScrollStart ||
14837                            _this.scroll.touchScrollStart === $$A(window).scrollTop()) {
14838                            _this.markerClickHandler.call(_this, e, _this.getMarker($$A(this).attr("id")));
14839                        }
14840                    });
14841                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-marker-cluster", function (e) {
14842                        if (e.cancelable) {
14843                            e.preventDefault();
14844                        }
14845                        if (!_this.scroll.touchScrollStart ||
14846                            _this.scroll.touchScrollStart == $$A(window).scrollTop()) {
14847                            const cluster = $$A(this).data("cluster");
14848                            _this.zoomTo(cluster.markers);
14849                        }
14850                    });
14851                }
14852                else {
14853                    if (_this.clickAddsMarker)
14854                        $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", function (e) {
14855                            if (e.cancelable) {
14856                                e.preventDefault();
14857                            }
14858                            _this.markerAddClickHandler(e);
14859                        });
14860                }
14861            }
14862            else {
14863                $$A(_this.containers.map).on("touchstart.common.mapsvg mousedown.common.mapsvg", function (e) {
14864                    if ($$A(e.target).hasClass("mapsvg-popover") ||
14865                        $$A(e.target).closest(".mapsvg-popover").length) {
14866                        if ($$A(e.target).hasClass("mapsvg-popover-close")) {
14867                            if (e.type == "touchstart") {
14868                                if (e.cancelable) {
14869                                    e.preventDefault();
14870                                }
14871                            }
14872                        }
14873                        return;
14874                    }
14875                    if (e.type == "touchstart") {
14876                        if (e.cancelable) {
14877                            e.preventDefault();
14878                        }
14879                    }
14880                    let obj;
14881                    if (e.target &&
14882                        $$A(e.target).attr("class") &&
14883                        $$A(e.target).attr("class").indexOf("mapsvg-region") != -1) {
14884                        obj = _this.getRegion($$A(e.target).attr("id"));
14885                        _this.setObjectClickedBeforeScroll(obj);
14886                    }
14887                    else if (e.target &&
14888                        $$A(e.target).attr("class") &&
14889                        $$A(e.target).attr("class").indexOf("mapsvg-marker") != -1 &&
14890                        $$A(e.target).attr("class").indexOf("mapsvg-marker-cluster") 
14890=== -1) {
14891                        if (_this.editMarkers.on) {
14892                            return;
14893                        }
14894                        obj = _this.getMarker($$A(e.target).attr("id"));
14895                        _this.setObjectClickedBeforeScroll(obj);
14896                    }
14897                    else if (e.target &&
14898                        $$A(e.target).attr("class") &&
14899                        $$A(e.target).attr("class").indexOf("mapsvg-marker-cluster") != -1) {
14900                        if (_this.editMarkers.on) {
14901                            return;
14902                        }
14903                        obj = $$A(e.target).data("cluster");
14904                        _this.setObjectClickedBeforeScroll(obj);
14905                    }
14906                    if (e.type == "mousedown") {
14907                        _this.scrollStart(e, _this);
14908                    }
14909                    else {
14910                        _this.touchStart(e, _this);
14911                    }
14912                });
14913            }
14914            $$A(_this.containers.map).on("mouseleave.common.mapsvg", ".mapsvg-choropleth-gradient-wrap", (e) => {
14915                this.controllers.tooltip.hide();
14916            });
14917        }
14918        setLabelsRegions(options) {
14919            options = options || this.options.labelsRegions;
14920            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14921            $$A.extend(true, this.options, { labelsRegions: options });
14922            if (this.options.labelsRegions.on) {
14923                this.regions.forEach((region) => {
14924                    if (!region.label) {
14925                        region.label = jQuery('<div class="mapsvg-region-label" />')[0];
14926                        $$A(this.layers.labels).append(region.label);
14927                    }
14928                    try {
14929                        $$A(region.label).html(this.templates.labelRegion(region.forTemplate()));
14930                    }
14931                    catch (err) {
14932                        console.error('MapSVG: Error in the "Region Label" template');
14933                    }
14934                });
14935                this.labelsRegionsAdjustScreenPosition();
14936            }
14937            else {
14938                this.regions.forEach((region) => {
14939                    if (region.label) {
14940                        $$A(region.label).remove();
14941                        region.label = null;
14942                        delete region.label;
14943                    }
14944                });
14945            }
14946        }
14947        setLabelsMarkers(options) {
14948            options = options || this.options.labelsMarkers;
14949            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14950            $$A.extend(true, this.options, { labelsMarkers: options });
14951            if (this.options.labelsMarkers.on) {
14952                this.markers.forEach((marker) => {
14953                    try {
14954                        marker.setLabel(this.templates.labelMarker(marker.object));
14955                    }
14956                    catch (err) {
14957                        console.error('MapSVG: Error in the "Marker Label" template');
14958                    }
14959                });
14960            }
14961            else {
14962                this.markers.forEach((marker) => {
14963                    marker.setLabel("");
14964                });
14965            }
14966        }
14967        addLayer(name) {
14968            this.layers[name] = $$A('<div class="mapsvg-layer mapsvg-layer-' + name + '"></div>')[0];
14969            this.containers.layers.appendChild(this.layers[name]);
14970            return this.layers[name];
14971        }
14972        getLayer(name) {
14973            return this.layers[name];
14974        }
14975        getDb() {
14976            return this.objectsRepository;
14977        }
14978        getDbRegions() {
14979            return this.regionsRepository;
14980        }
14981        regionAdd(svgObject) {
14982            const region = new Region(svgObject, this);
14983            region.setStatus(1);
14984            this.regions.push(region);
14985            this.regions.sort(function (a, b) {
14986                return a.id == b.id ? 0 : +(a.id > b.id) || -1;
14987            });
14988            return region;
14989        }
14990        regionDelete(id) {
14991            if (this.regions.findById(id)) {
14992                this.regions.findById(id).elem.remove();
14993                this.regions.delete(id);
14994            }
14995            else if ($$A("#" + id).length) {
14996                $$A("#" + id).remove();
14997            }
14998        }
14999        reloadRegions() {
15000            this.regions.clear();
15001            $$A(this.containers.svg).find(".mapsvg-region").removeClass("mapsvg-region");
15002            $$A(this.containers.svg)
15003                .find(".mapsvg-region-disabled")
15004                .removeClass("mapsvg-region-disabled");
15005            $$A(this.containers.svg)
15006                .find("path, polygon, circle, ellipse, rect")
15007                .each((index, element) => {
15008                const elem = element;
15009                if ($$A(elem).closest("defs").length)
15010                    return;
15011                if (elem.getAttribute("data-stroke-width")) {
15012                    elem.style["stroke-width"] = elem.getAttribute("data-stroke-width");
15013                }
15014                if (elem.getAttribute("id")) {
15015                    if (!this.options.regionPrefix ||
15016                        (this.options.regionPrefix &&
15017                            elem.getAttribute("id").indexOf(this.options.regionPrefix) === 0)) {
15018                        const region = new Region(elem, this);
15019                        this.regions.push(region);
15020                    }
15021                }
15022            });
15023        }
15024        reloadRegionsFull() {
15025            const statuses = this.regionsRepository.getSchema().getFieldByType("status");
15026            this.regions.forEach((region) => {
15027                const _region = this.regionsRepository.getLoaded().findById(region.id);
15028                if (_region) {
15029                    region.setData(_region);
15030                    if (statuses && _region.status !== undefined && _region.status !== null) {
15031                        region.setStatus(_region.status);
15032                    }
15033                }
15034                else {
15035                    if (this.options.filters.filteredRegionsStatus ||
15036                        this.options.filters.filteredRegionsStatus === 0 ||
15037                        (this.options.menu.source === "regions" &&
15038                            this.options.menu.filterout &&
15039                            this.options.menu.filterout.field === "status" &&
15040                            this.options.menu.filterout.val) ||
15041                        this.options.menu.filterout.val === 0) {
15042                        const status = this.options.filters.filteredRegionsStatus ||
15043                            this.options.filters.filteredRegionsStatus === 0
15044                            ? this.options.filters.filteredRegionsStatus
15045                            : this.options.menu.filterout.val;
15046                        region.setStatus(status);
15047                    }
15048                }
15049            });
15050            this.loadDirectory();
15051            this.setChoropleth();
15052            this.setLayersControl();
15053            this.setGroups();
15054            if (this.options.labelsRegions.on) {
15055                this.setLabelsRegions();
15056            }
15057        }
15058        fixMarkersWorldScreen() {
15059            if (this.googleMaps.map)
15060                setTimeout(() => {
15061                    const markers = { left: 0, right: 0, leftOut: 0, rightOut: 0 };
15062                    if (this.markers.length > 1) {
15063                        this.markers.forEach((m) => {
15064                            if ($$A(m.element).offset().left <
15065                                $$A(this.containers.map).offset().left +
15066                                    this.containers.map.clientWidth / 2) {
15067                                markers.left++;
15068                                if ($$A(m.element).offset().left < $$A(this.containers.map).offset().left) {
15069                                    markers.leftOut++;
15070                                }
15071                            }
15072                            else {
15073                                markers.right++;
15074                                if ($$A(m.element).offset().left >
15075                                    $$A(this.containers.map).offset().left +
15076                                        this.containers.map.clientWidth) {
15077                                    markers.rightOut++;
15078                                }
15079                            }
15080                        });
15081                        if ((markers.left === 0 && markers.rightOut) ||
15082                            (markers.right === 0 && markers.leftOut)) {
15083                            const k = markers.left === 0 ? 1 : -1;
15084                            const ww = (this.svgDefault.viewBox.width / this.converter.mapLonDelta) *
15085                                360 *
15086                                this.getScale();
15087                            this.googleMaps.map.panBy(k * ww, 0);
15088                        }
15089                    }
15090                }, 600);
15091        }
15092        updateOutdatedOptions(options) {
15093            if (options.menu && (options.menu.position || options.menu.customContainer)) {
15094                if (options.menu.customContainer) {
15095                    options.menu.location = "custom";
15096                }
15097                else {
15098                    options.menu.position = options.menu.position === "left" ? "left" : "right";
15099                    options.menu.location =
15100                        options.menu.position === "left" ? "leftSidebar" : "rightSidebar";
15101                    if (!options.containers || !options.containers[options.menu.location]) {
15102                        options.containers = options.containers || {};
15103                        options.containers[options.menu.location] = { on: false, width: "200px" };
15104                    }
15105                    options.containers[options.menu.location].width = options.menu.width;
15106                    if (MapSVG.parseBoolean(options.menu.on)) {
15107                        options.containers[options.menu.location].on = true;
15108                    }
15109                }
15110                delete options.menu.position;
15111                delete options.menu.width;
15112                delete options.menu.customContainer;
15113            }
15114            if (options.detailsView &&
15115                (options.detailsView.location === "mapContainer" ||
15116                    options.detailsView.location === "near" ||
15117                    options.detailsView.location === "top")) {
15118                options.detailsView.location = "map";
15119            }
15120            if (!options.controls) {
15121                options.controls = {};
15122                options.controls.zoom =
15123                    options.zoom &&
15124                        options.zoom.on &&
15125                        (!options.zoom.buttons || options.zoom.buttons.location !== "hide");
15126                options.controls.location =
15127                    options.zoom && options.zoom.buttons && options.zoom.buttons.location !== "hide"
15128                        ? options.zoom.buttons.location
15129                        : "right";
15130            }
15131            if (options.colors && !options.colors.markers) {
15132                options.colors.markers = {
15133                    base: { opacity: 100, saturation: 100 },
15134                    hovered: { opacity: 100, saturation: 100 },
15135                    unhovered: { opacity: 100, saturation: 100 },
15136                    active: { opacity: 100, saturation: 100 },
15137                    inactive: { opacity: 100, saturation: 100 },
15138                };
15139            }
15140            if (options.tooltipsMode) {
15141                options.tooltips.mode = options.tooltipsMode;
15142                delete options.tooltipsMode;
15143            }
15144            if (options.popover) {
15145                options.popovers = options.popover;
15146                delete options.popover;
15147            }
15148        }
15149        init() {
15150            MapSVG.addInstance(this);
15151            if (this.options.source === "") {
15152                throw new Error("MapSVG: please provide SVG file source.");
15153            }
15154            this.disableAnimation();
15155            this.setEvents(this.options.events);
15156            this.events.trigger("beforeLoad");
15157            if (this.options.googleMaps.apiKey &&
15158                (this.editMode ||
15159                    this.options.googleMaps.on ||
15160                    (this.options.filters.on &&
15161                        this.options.filtersSchema &&
15162                        this.options.filtersSchema.find((f) => f.type === "distance")))) {
15163                this.loadGoogleMapsAPI(() => {
15164                    return 1;
15165                }, () => {
15166                    return 1;
15167                });
15168            }
15169            this.containers.map.classList.add("mapsvg");
15170            this.setCss();
15171            if (this.options.colors && this.options.colors.background) {
15172                this.containers.map.style.background = this.options.colors.background;
15173            }
15174            this.setContainers(this.options.containers);
15175            this.setColors();
15176            this.addLoadingMessage();
15177            this.addLayer("markers");
15178            this.addLayer("labels");
15179            this.addLayer("bubbles");
15180            this.addLayer("popovers");
15181            this.addLayer("scrollpane");
15182            this.loadExtensions();
15183            $$A.ajax({ url: this.options.source + "?v=" + this.svgFileLastChanged })
15184                .fail((resp) => {
15185                this.svgLoadingFailed(resp);
15186            })
15187                .done((xmlData) => {
15188                this.renderSvgData(xmlData);
15189            });
15190            return this;
15191        }
15192        getContainer(name) {
15193            return this.containers[name];
15194        }
15195        renderSvgData(xmlData) {
15196            const svgTag = $$A(xmlData).find("svg");
15197            this.containers.svg = svgTag[0];
15198            if (svgTag.attr("width") && svgTag.attr("height")) {
15199                this.svgDefault.width = parseFloat(svgTag.attr("width").replace(/px/g, ""));
15200                this.svgDefault.height = parseFloat(svgTag.attr("height").replace(/px/g, ""));
15201                this.svgDefault.viewBox = svgTag.attr("viewBox")
15202                    ? new ViewBox(svgTag.attr("viewBox").split(" "))
15203                    : new ViewBox(0, 0, this.svgDefault.width, this.svgDefault.height);
15204            }
15205            else if (svgTag.attr("viewBox")) {
15206                this.svgDefault.viewBox = new ViewBox(svgTag.attr("viewBox").split(" "));
15207                this.svgDefault.width = this.svgDefault.viewBox.width;
15208                this.svgDefault.height = this.svgDefault.viewBox.height;
15209            }
15210            else {
15211                const msg = "MapSVG: width/height and viewBox are missing in the SVG file. Can't parse the file because of that.";
15212                if (this.editMode) {
15213                    alert(msg);
15214                }
15215                else {
15216                    console.error(msg);
15217                }
15218                return false;
15219            }
15220            this.geoViewBox = this.getGeoViewBoxFromSvgTag(this.containers.svg);
15221            if (this.options.viewBox && this.options.viewBox.length == 4) {
15222                this._viewBox = new ViewBox(this.options.viewBox);
15223            }
15224            else {
15225                this._viewBox = new ViewBox(this.svgDefault.viewBox);
15226            }
15227            svgTag.attr("preserveAspectRatio", "xMidYMid meet");
15228            svgTag.removeAttr("width");
15229            svgTag.removeAttr("height");
15230            $$A(this.containers.scrollpane).append(svgTag);
15231            this.setStrokes();
15232            this.reloadRegions();
15233            this.setSize(this.options.width, this.options.height, this.options.responsive);
15234            if (this.options.disableAll) {
15235                this.setDisableAll(true);
15236            }
15237            this.setViewBox(this._viewBox);
15238            this.converter = new Converter(this.containers.map, this.svgDefault.viewBox, this.viewBox);
15239            if (this.geoViewBox) {
15240                this.converter.setGeoViewBox(this.geoViewBox);
15241            }
15242            this.setResponsive(this.options.responsive);
15243            this.setScroll(this.options.scroll, true);
15244            this.setZoom(this.options.zoom);
15245            this.setControls(this.options.controls);
15246            this.setGoogleMaps();
15247            this.setTooltips(this.options.tooltips);
15248            this.setPopovers(this.options.popovers);
15249            if (this.options.cursor)
15250                this.setCursor(this.options.cursor);
15251            this.setTemplates(this.options.templates);
15252            this.loadExtensions();
15253            this.filtersSchema = new Schema({ fields: this.options.filtersSchema });
15254            this.objectsRepository.events.on("load", () => {
15255                this.showLoadingMessage();
15256            });
15257            this.objectsRepository.events.on("loaded", () => {
15258                this.setGlobalDistanceFilter();
15259                this.fitOnDataLoadDone = false;
15260                this.addLocations();
15261                this.fixMarkersWorldScreen();
15262                this.attachDataToRegions();
15263                this.loadDirectory();
15264                if (this.options.labelsMarkers.on) {
15265                    this.setLabelsMarkers();
15266                }
15267                if (this.options.templates.labelRegion.indexOf("{{objects") !== -1) {
15268                    this.setLabelsRegions();
15269                }
15270                if (this.options.filters.on &&
15271                    this.options.filters.source === "database" &&
15272                    this.controllers.filters &&
15273                    this.controllers.filters.hideFilters) {
15274                    this.controllers.filters.setFiltersCounter();
15275                }
15276                this.hideLoadingMessage();
15277                this.events.trigger("databaseLoaded");
15278                this.updateFiltersState();
15279                this.setChoropleth();
15280            });
15281            this.objectsRepository.events.on("schemaChanged", () => {
15282                this.objectsRepository.reload();
15283            });
15284            this.objectsRepository.events.on("updated", (obj) => {
15285                this.attachDataToRegions(obj);
15286                this.reloadRegionsFull();
15287            });
15288            this.objectsRepository.events.on("created", (obj) => {
15289                this.attachDataToRegions(obj);
15290                this.reloadRegionsFull();
15291            });
15292            this.objectsRepository.events.on("deleted", (id) => {
15293                this.attachDataToRegions();
15294                this.reloadRegionsFull();
15295            });
15296            this.regionsRepository.events.on("load", () => {
15297                this.showLoadingMessage();
15298            });
15299            this.regionsRepository.events.on("loaded", () => {
15300                this.hideLoadingMessage();
15301                this.reloadRegionsFull();
15302                if (this.options.filters.on &&
15303                    this.options.filters.source === "regions" &&
15304                    this.controllers.filters &&
15305                    this.controllers.filters.hideFilters) {
15306                    this.controllers.filters.setFiltersCounter();
15307                }
15308                this.events.trigger("regionsLoaded");
15309            });
15310            this.regionsRepository.events.on("updated", (regionData) => {
15311                this.reloadRegionsFull();
15312            });
15313            this.regionsRepository.events.on("created", (regionData) => {
15314                this.reloadRegionsFull();
15315            });
15316            this.regionsRepository.events.on("deleted", (regionData) => {
15317                this.reloadRegionsFull();
15318            });
15319            this.setMenu();
15320            this.setFilters();
15321            this.setFilterOut();
15322            this.setEventHandlers();
15323            this.afterLoadBlockers--;
15324            if (!this.id) {
15325                this.finalizeMapLoading();
15326                return;
15327            }
15328            if (!this.options.data_regions) {
15329                this.regionsRepository.find().done((data) => {
15330                    this.afterLoadBlockers--;
15331                    this.finalizeMapLoading();
15332                });
15333            }
15334            else {
15335                this.regionsRepository.loadDataFromResponse(this.options.data_regions);
15336                this.afterLoadBlockers--;
15337            }
15338            if (!this.options.data_objects) {
15339                if (this.options.database.loadOnStart || this.editMode) {
15340                    this.objectsRepository.find().done((data) => {
15341                        this.afterLoadBlockers--;
15342                        this.finalizeMapLoading();
15343                    });
15344                }
15345                else {
15346                    this.afterLoadBlockers--;
15347                    this.finalizeMapLoading();
15348                }
15349            }
15350            else {
15351                if (this.editMode || this.options.database.loadOnStart) {
15352                    this.objectsRepository.loadDataFromResponse(this.options.data_objects);
15353                    this.afterLoadBlockers--;
15354                }
15355                else {
15356                    this.afterLoadBlockers--;
15357                }
15358                delete this.options.data_regions;
15359                delete this.options.data_objects;
15360                this.finalizeMapLoading();
15361            }
15362        }
15363        setFilterOut() {
15364            if (this.options.menu.filterout.field) {
15365                const f = {};
15366                f[this.options.menu.filterout.field] = this.options.menu.filterout.val;
15367                if (this.options.menu.source == "regions") ;
15368                else {
15369                    this.objectsRepository.query.setFilterOut(f);
15370                }
15371            }
15372            else {
15373                this.objectsRepository.query.setFilterOut(null);
15374            }
15375        }
15376        getGeoViewBoxFromSvgTag(svgTag) {
15377            const geo = $$A(svgTag).attr("mapsvg:geoViewBox") || $$A(svgTag).attr("mapsvg:geoviewbox");
15378            if (geo) {
15379                const geoParts = geo.split(" ").map((p) => parseFloat(p));
15380                if (geoParts.length == 4) {
15381                    this.mapIsGeo = true;
15382                    this.geoCoordinates = true;
15383                    const sw = new GeoPoint(geoParts[3], geoParts[0]);
15384                    const ne = new GeoPoint(geoParts[1], geoParts[2]);
15385                    return new GeoViewBox(sw, ne);
15386                }
15387            }
15388            else {
15389                return null;
15390            }
15391        }
15392        svgLoadingFailed(resp) {
15393            if (resp.status == 404) {
15394                let msg = "MapSVG: file not found - " +
15395                    this.options.source +
15396                    "\n\nIf you moved MapSVG from another server please read the following docs page: https://mapsvg.com/docs/installation/moving";
15397                if (this.editMode) {
15398                    msg +=
15399                        "\n\nIf you know the correct path for the SVG file, please write it and press OK:";
15400                    const oldSvgPath = this.options.source;
15401                    const userSvgPath = prompt(msg, oldSvgPath);
15402                    if (userSvgPath !== null) {
15403                        $$A.ajax({ url: userSvgPath + "?v=" + this.svgFileLastChanged })
15404                            .fail(function () {
15405                            location.reload();
15406                        })
15407                            .done((xmlData) => {
15408                            this.options.source = userSvgPath;
15409                            this.renderSvgData(xmlData);
15410                            const mapsRepo = new MapsRepository();
15411                            mapsRepo.update(this);
15412                        });
15413                    }
15414                    else {
15415                        location.reload();
15416                    }
15417                }
15418                else {
15419                    console.error(msg);
15420                }
15421            }
15422            else {
15423                const msg = "MapSVG: can't load SVG file for unknown reason. Please contact support: https://mapsvg.ticksy.com";
15424                if (this.editMode) {
15425                    alert(msg);
15426                }
15427                else {
15428                    console.error(msg);
15429                }
15430            }
15431        }
15432        addLoadingMessage() {
15433            this.containers.loading = document.createElement("div");
15434            this.containers.loading.className = "mapsvg-loading";
15435            const loadingTextBlock = document.createElement("div");
15436            loadingTextBlock.className = "mapsvg-loading-text";
15437            loadingTextBlock.innerHTML = this.options.loadingText;
15438            const spinner = document.createElement("div");
15439            spinner.className = "spinner-border spinner-border-sm";
15440            this.containers.loading.appendChild(spinner);
15441            this.containers.loading.appendChild(loadingTextBlock);
15442            this.containers.map.appendChild(this.containers.loading);
15443            if (this.options.googleMaps.on) {
15444                $$A(this.containers.map).addClass("mapsvg-google-map-loading");
15445            }
15446        }
15447        hideLoadingMessage() {
15448            $$A(this.containers.loading).hide();
15449        }
15450        showLoadingMessage() {
15451            $$A(this.containers.loading).show();
15452        }
15453        disableAnimation() {
15454            this.containers.map.classList.add("no-transitions");
15455        }
15456        enableAnimation() {
15457            $$A(this.containers.map).removeClass("no-transitions");
15458        }
15459        loadExtensions() {
15460            if (this.options.extension &&
15461                $$A().mapSvg.extensions &&
15462                $$A().mapSvg.extensions[_this.options.extension]) {
15463                const ext = $$A().mapSvg.extensions[_this.options.extension];
15464                ext && ext.common(this);
15465            }
15466        }
15467        finalizeMapLoading() {
15468            if (this.afterLoadBlockers > 0 || this.loaded) {
15469                return;
15470            }
15471            this.selectRegionByIdFromUrl();
15472            setTimeout(() => {
15473                this.movingItemsAdjustScreenPosition();
15474                this.adjustStrokes();
15475                setTimeout(() => {
15476                    this.hideLoadingMessage();
15477                    $$A(this.containers.loading).find(".mapsvg-loading-text").hide();
15478                    this.enableAnimation();
15479                }, 200);
15480            }, 100);
15481            this.loaded = true;
15482            this.events.trigger("afterLoad");
15483        }
15484        selectRegionByIdFromUrl() {
15485            const match = RegExp("[?&]mapsvg_select=([^&]*)").exec(window.location.search);
15486            if (match) {
15487                const select = decodeURIComponent(match[1].replace(/\+/g, " "));
15488                this.selectRegion(select);
15489            }
15490            if (window.location.hash) {
15491                const query = window.location.hash.replace("#/m/", "");
15492                const region = this.getRegion(query);
15493                if (region && this.options.actions.map.afterLoad.selectRegion) {
15494                    this.regionClickHandler(null, region);
15495                }
15496            }
15497        }
15498        createForm(options) {
15499            return new FormBuilder(options);
15500        }
15501        getApiUrl(path) {
15502            const server = new Server();
15503            return server.getUrl(path);
15504        }
15505        getConverter() {
15506            return this.converter;
15507        }
15508        setChoropleth(options) {
15509            const _this = this;
15510            options = options || _this.options.choropleth;
15511            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
15512            $$A.extend(true, _this.options, { choropleth: options });
15513            let needsRedraw = false;
15514            if (!_this.$gauge) {
15515                _this.$gauge = {};
15516                _this.$gauge.gradient = $$A("<td>&nbsp;</td>").addClass("mapsvg-gauge-gradient");
15517                _this.setGaugeGradientCSS();
15518                _this.$gauge.container = $$A("<div />").addClass("mapsvg-gauge").hide();
15519                _this.$gauge.table = $$A("<table />");
15520                const tr = $$A("<tr />");
15521                _this.$gauge.labelLow = $$A("<td>" + _this.options.choropleth.labels.low + "</td>");
15522                _this.$gauge.labelHigh = $$A("<td>" + _this.options.choropleth.labels.high + "</td>");
15523                tr.append(_this.$gauge.labelLow);
15524                tr.append(_this.$gauge.gradient);
15525                tr.append(_this.$gauge.labelHigh);
15526                _this.$gauge.table.append(tr);
15527                _this.$gauge.container.append(_this.$gauge.table);
15528                $$A(_this.containers.map).append(_this.$gauge.container);
15529            }
15530            if (!_this.options.choropleth.on && _this.$gauge.container.is(":visible")) {
15531                _this.$gauge.container.hide();
15532                needsRedraw = true;
15533            }
15534            else if (_this.options.choropleth.on && !_this.$gauge.container.is(":visible")) {
15535                _this.$gauge.container.show();
15536                needsRedraw = true;
15537                _this.regionsRepository.events.on("change", function () {
15538                    _this.redrawGauge();
15539                });
15540            }
15541            if (options.colors) {
15542                _this.options.choropleth.colors.lowRGB = tinycolor(_this.options.choropleth.colors.low).toRgb();
15543                _this.options.choropleth.colors.highRGB = tinycolor(_this.options.choropleth.colors.high).toRgb();
15544                _this.options.choropleth.colors.diffRGB = {
15545                    r: _this.options.choropleth.colors.highRGB.r -
15546                        _this.options.choropleth.colors.lowRGB.r,
15547                    g: _this.options.choropleth.colors.highRGB.g -
15548                        _this.options.choropleth.colors.lowRGB.g,
15549                    b: _this.options.choropleth.colors.highRGB.b -
15550                        _this.options.choropleth.colors.lowRGB.b,
15551                    a: _this.options.choropleth.colors.highRGB.a -
15552                        _this.options.choropleth.colors.lowRGB.a,
15553                };
15554                needsRedraw = true;
15555                _this.$gauge && _this.setGaugeGradientCSS();
15556            }
15557            if (options.labels) {
15558                _this.$gauge.labelLow.html(_this.options.choropleth.labels.low);
15559                _this.$gauge.labelHigh.html(_this.options.choropleth.labels.high);
15560            }
15561            needsRedraw && _this.redrawGauge();
15562        }
15563        redrawGauge() {
15564            const _this = this;
15565            _this.updateGaugeMinMax();
15566            _this.regionsRedrawColors();
15567        }
15568        updateGaugeMinMax() {
15569            const _this = this;
15570            _this.options.choropleth.min = 0;
15571            _this.options.choropleth.max = false;
15572            const values = [];
15573            _this.regions.forEach(function (r) {
15574                const gauge = r.data && r.data[_this.options.regionChoroplethField];
15575                gauge != undefined && values.push(gauge);
15576            });
15577            if (values.length > 0) {
15578                _this.options.choropleth.min = values.length == 1 ? 0 : Math.min.apply(null, values);
15579                _this.options.choropleth.max = Math.max.apply(null, values);
15580                _this.options.choropleth.maxAdjusted =
15581                    _this.options.choropleth.max - _this.options.choropleth.min;
15582            }
15583        }
15584        setGaugeGradientCSS() {
15585            const _this = this;
15586            _this.$gauge.gradient.css({
15587                background: "linear-gradient(to right," +
15588                    _this.options.choropleth.colors.low +
15589                    " 1%," +
15590                    _this.options.choropleth.colors.high +
15591                    " 100%)",
15592                filter: 'progid:DXImageTransform.Microsoft.gradient( startColorstr="' +
15593                    _this.options.choropleth.colors.low +
15594                    '", endColorstr="' +
15595                    _this.options.choropleth.colors.high +
15596                    '",GradientType=1 )',
15597            });
15598        }
15599        get $map() {
15600            return $$A(this.getContainer("map"));
15601        }
15602        get $svg() {
15603            return $$A(this.getContainer("svg"));
15604        }
15605        get $popover() {
15606            return $$A(this.getContainer("popover"));
15607        }
15608        get $details() {
15609            return $$A(this.getContainer("detailsView"));
15610        }
15611        get $directory() {
15612            return $$A(this.getContainer("directory"));
15613        }
15614        get database() {
15615            return this.objectsRepository;
15616        }
15617        get regionsDatabase() {
15618            return this.regionsRepository;
15619        }
15620    }
15621
15622    exports.MapSVGMap = MapSVGMap;
15623    exports.arrayIndexed = ArrayIndexed;
15624    exports.customObject = CustomObject;
15625    exports.formBuilder = FormBuilder;
15626    exports.geoPoint = GeoPoint;
15627    exports.globals = MapSVG;
15628    exports.location = Location;
15629    exports.map = MapSVGMap;
15630    exports.mapsRepository = MapsRepository;
15631    exports.mapsV2Repository = MapsV2Repository;
15632    exports.marker = Marker;
15633    exports.query = Query;
15634    exports.repository = Repository;
15635    exports.schema = Schema;
15636    exports.schemaRepository = SchemaRepository;
15637    exports.screenPoint = ScreenPoint;
15638    exports.server = Server;
15639    exports.svgPoint = SVGPoint;
15640
15641    Object.defineProperty(exports, '__esModule', { value: true });
15642
15643})));
15644//# sourceMappingURL=mapsvg-front.umd.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.