PageSourceSearch

https://resolvelawgroup.com/wp-content/plugins/mapsvg/dist/mapsvg-front.umd.js?ver=6.2.14

js resolvelawgroup.com collected 2026-10-08 07:56:15 UTC 651,184 bytes, 15,564 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
140    /**
141     * Contains device information
142     * @type {object}
143     * @static
144     * @property
145     */
146    var ua = window.navigator.userAgent;
147    MapSVG.device = {};
148    MapSVG.device.ios = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
149    MapSVG.device.android = !!ua.match(/Android/i);
150
151    if (!String.prototype.trim) {
152        String.prototype.trim = function () {
153            return this.replace(/^\s+|\s+$/g, "");
154        };
155    }
156
157    /**
158     * Converts mouse event object to x/y coordinates
159     * @param e
160     * @returns {{x: *, y: *}}
161     */
162    MapSVG.mouseCoords = function (e) {
163        if (e.clientX) {
164            return { x: e.clientX + $(document).scrollLeft(), y: e.clientY + $(document).scrollTop() };
165        }
166        if (e.pageX) {
167            return { x: e.pageX, y: e.pageY };
168        } else if (MapSVG.touchDevice) {
169            e = e.originalEvent || e;
170            return e.touches && e.touches[0]
171                ? { x: e.touches[0].pageX, y: e.touches[0].pageY }
172                : { x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY };
173        }
174    };
175
176    /**
177     * Adds new instance of the map
178     * @param {MapSVG.Map} mapsvg
179     */
180    MapSVG.addInstance = function (mapsvg) {
181        MapSVG.instances.push(mapsvg);
182    };
183
184    MapSVG.get = function (index) {
185        return MapSVG.instances[index];
186    };
187
188    MapSVG.getById = function (id) {
189        var instance = MapSVG.instances.filter(function (i) {
190            return i.id == id;
191        });
192        if (instance.length > 0) {
193            return instance[0];
194        }
195    };
196
197    MapSVG.getByContainerId = function (id) {
198        var instance = MapSVG.instances.filter(function (i) {
199            return i.$map.attr("id") == id;
200        });
201        if (instance.length > 0) {
202            return instance[0];
203        }
204    };
205
206    MapSVG.extend = function (sub, base) {
207        sub.prototype = Object.create(base.prototype);
208        sub.prototype.constructor = sub;
209    };
210
211    MapSVG.ucfirst = function (string) {
212        return string.charAt(0).toUpperCase() + string.slice(1);
213    };
214    MapSVG.parseBoolean = function (string) {
215        switch (String(string).toLowerCase()) {
216            case "on":
217            case "true":
218            case "1":
219            case "yes":
220            case "y":
221                return true;
222            case "off":
223            case "false":
224            case "0":
225            case "no":
226            case "n":
227                return false;
228            default:
229                return undefined;
230        }
231    };
232    MapSVG.isNumber = function (n) {
233        return !isNaN(parseFloat(n)) && isFinite(n);
234    };
235
236    MapSVG.safeURL = function (url) {
237        if (url.indexOf("http://") == 0 || url.indexOf("https://") == 0)
238            url = "//" + url.split("://").pop();
239        return url.replace(/^.*\/\/[^\/]+/, "");
240    };
241
242    MapSVG.convertToText = function (obj) {
243        //create an array that will later be joined into a string.
244        var string = [];
245
246        //is object
247        //    Both arrays and objects seem to return "object"
248        //    when typeof(obj) is applied to them. So instead
249        //    I am checking to see if they have the property
250        //    join, which normal objects don't have but
251        //    arrays do.
252        if (obj === null) {
253            return null;
254        }
255        if (obj === undefined) {
256            return '""';
257        } else if (typeof obj == "object" && obj.join == undefined) {
258            var prop;
259            for (prop in obj) {
260                if (obj.hasOwnProperty(prop)) {
261                    var key = '"' + prop.replace(/\"/g, '\\"') + '"'; //prop.search(/[^a-zA-Z]+/) === -1 ?  prop : ...
262                    string.push(key + ": " + MapSVG.convertToText(obj[prop]));
263                }
264            }
265            return "{" + string.join(",") + "}";
266
267            //is array
268        } else if (typeof obj == "object" && !(obj.join == undefined)) {
269            var prop;
270            for (prop in obj) {
271                string.push(MapSVG.convertToText(obj[prop]));
272            }
273            return "[" + string.join(",") + "]";
274
275            //is function
276        } else if (typeof obj == "function") {
277            return obj.toString().replace("function anonymous", "function");
278            // string.push(obj.toString().replace('function anonymous','function'));
279
280            //all other values can be done with JSON.stringify
281        } else {
282            return JSON.stringify(obj);
283            // var s = JSON.stringify(obj);
284            // string.push(s);
285        }
286    };
287
288    // Create Element.remove() function if not exists
289    if (!("remove" in Element.prototype)) {
290        Element.prototype.remove = function () {
291            if (this.parentNode) {
292                this.parentNode.removeChild(this);
293            }
294        };
295    }
296
297    Math.hypot =
298        Math.hypot ||
299        function () {
300            var y = 0;
301            var length = arguments.length;
302
303            for (var i = 0; i < length; i++) {
304                if (arguments[i] === Infinity || arguments[i] === -Infinity) {
305                    return Infinity;
306                }
307                y += arguments[i] * arguments[i];
308            }
309            return Math.sqrt(y);
310        };
311    SVGElement.prototype.getTransformToElement =
312        SVGElement.prototype.getTransformToElement ||
313        function (toElement) {
314            let value;
315            try {
316                value = toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
317            } catch (e) {
318                return;
319            }
320            return value;
321        };
322
323    Map.prototype.toArray = function () {
324        return Array.from(this, ([name, value]) => value);
325    };
326
327    MapSVG.ResizeSensor = class ResizeSensor {
328        constructor(element, callback) {
329            var _this = this;
330            _this.element = element;
331            _this.callback = callback;
332            var style = getComputedStyle(element);
333            var zIndex = parseInt(style.zIndex);
334            if (isNaN(zIndex)) {
335                zIndex = 0;
336            }
337            zIndex--;
338            _this.expand = document.createElement("div");
339            _this.expand.style.position = "absolute";
340            _this.expand.style.left = "0px";
341            _this.expand.style.top = "0px";
342            _this.expand.style.right = "0px";
343            _this.expand.style.bottom = "0px";
344            _this.expand.style.overflow = "hidden";
345            _this.expand.style.zIndex = zIndex.toString();
346            _this.expand.style.visibility = "hidden";
347            var expandChild = document.createElement("div");
348            expandChild.style.position = "absolute";
349            expandChild.style.left = "0px";
350            expandChild.style.top = "0px";
351            expandChild.style.width = "10000000px";
352            expandChild.style.height = "10000000px";
353            _this.expand.appendChild(expandChild);
354            _this.shrink = document.createElement("div");
355            _this.shrink.style.position = "absolute";
356            _this.shrink.style.left = "0px";
357            _this.shrink.style.top = "0px";
358            _this.shrink.style.right = "0px";
359            _this.shrink.style.bottom = "0px";
360            _this.shrink.style.overflow = "hidden";
361            _this.shrink.style.zIndex = zIndex.toString();
362            _this.shrink.style.visibility = "hidden";
363            var shrinkChild = document.createElement("div");
364            shrinkChild.style.position = "absolute";
365            shrinkChild.style.left = "0px";
366            shrinkChild.style.top = "0px";
367            shrinkChild.style.width = "200%";
368            shrinkChild.style.height = "200%";
369            _this.shrink.appendChild(shrinkChild);
370            _this.element.appendChild(_this.expand);
371            _this.element.appendChild(_this.shrink);
372            var size = element.getBoundingClientRect();
373            _this.currentWidth = size.width;
374            _this.currentHeight = size.height;
375            _this.setScroll();
376            _this.expand.addEventListener("scroll", function () {
377                _this.onScroll();
378            });
379            _this.shrink.addEventListener("scroll", function () {
380                _this.onScroll();
381            });
382        }
383        onScroll() {
384            var _this = this;
385            var size = _this.element.getBoundingClientRect();
386            var newWidth = size.width;
387            var newHeight = size.height;
388            if (newWidth != _this.currentWidth || newHeight != _this.currentHeight) {
389                _this.currentWidth = newWidth;
390                _this.currentHeight = newHeight;
391                _this.callback();
392            }
393            this.setScroll();
394        }
395        setScroll() {
396            this.expand.scrollLeft = 10000000;
397            this.expand.scrollTop = 10000000;
398            this.shrink.scrollLeft = 10000000;
399            this.shrink.scrollTop = 10000000;
400        }
401        destroy() {
402            this.expand.remove();
403            this.shrink.remove();
404        }
405    };
406
407    MapSVG.nonce = function () {
408        return mapsvg_runtime_vars.nonce;
409    };
410
411    /**
412     * Adds # hash at the beginning of HEX color value
413     * @param {String} color
414     * @returns {String}
415     * @private
416     */
417    MapSVG.fixColorHash = (color) => {
418        const hexColorNoHash = new RegExp(/^([0-9a-f]{3}|[0-9a-f]{6})$/i);
419        if (color && color.match(hexColorNoHash) !== null) {
420            color = "#" + color;
421        }
422        return color;
423    };
424
425    /**
426     * Delays method execution.
427     * For example, it can be used in search input fields to prevent sending
428     * an ajax request on each key press.
429     * @param {Function} method
430     * @param {number} delay
431     * @param {object} scope
432     * @param {array} params
433     * @private
434     */
435    MapSVG.throttle = (method, delay, scope, params) => {
436        clearTimeout(method._tId);
437        method._tId = setTimeout(function () {
438            method.apply(scope, params);
439        }, delay);
440    };
441    MapSVG.geocode = (query, callback) => {
442        if (!window.google) {
443            console.error("MapSVG: can't do Geocoding - Google Maps API is not loaded.");
444            jQuery.growl.error({
445                title: "Error",
446                message: "Google Maps API files are not loaded",
447            });
448            return false;
449        }
450        // if (!MapSVG.options.google_api_key) {
451        //     jQuery.growl.error({
452        //         title: "Error",
453        //         message: "Google Maps API key is not provided",
454        //     });
455        //     return false;
456        // }
457        if (!MapSVG.geocoder) {
458            MapSVG.geocoder = new google.maps.Geocoder();
459        }
460
461        MapSVG.throttle(MapSVG.geocoder.geocode, 500, MapSVG.geocoder, [
462            query,
463            function (results, status) {
464                if (status === "OK") {
465                    callback(results);
466                } else {
467                    jQuery.growl.error({
468                        title: "Error: " + status,
469                        message:
470                            "There is some problem with Google API keys. See browser's console for more details",
471                    });
472                }
473            },
474        ]);
475    };
476
477    MapSVG.handleFailedRequest = (response) => {
478        var message = "";
479
480        if (response.status === 403) {
481            if (response.responseText.indexOf("Wordfence") !== -1) {
482                message +=
483                    "The request has been blocked by Wordfence. " +
484                    'Switch Wordfence to "Learning mode", and save the map settings again. ' +
485                    "If the settings are saved successfully, you can switch Wordfence back to normal mode.";
486            } else {
487                message +=
488                    "The request has been blocked by your server. " +
489                    "Do you have mod_sec Apache's module enabled? If that's the case you need to change its settings.";
490            }
491        } else {
492            if (response && response.responseText) {
493                try {
494                    var _response = JSON.parse(response.responseText);
495                    if (_response && _response.data && _response.data.error) {
496                        message = _response.data.error;
497                    }
498                } catch (e) {
499                }
500            }
501        }
502
503        $.growl.error({
504            title: "Error: " + response.status + " " + response.statusText,
505            message: message,
506            duration: 30000,
507        });
508    };
509
510    if (!Object.values) {
511        Object.values = function (object) {
512            return Object.keys(object).map(function (k) {
513                return object[k];
514            });
515        };
516    }
517
518    window.MapSVG = MapSVG;
519
520    const defRegionTemplate = "<div>\n" +
521        "  <p>This is the demo content of the <strong>Region %templateType%</strong>.</p>\n" +
522        '  <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' +
523        '  <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' +
524        "</div>\n" +
525        "<hr />\n\n" +
526        "<!-- Region fields are available in this template -->\n" +
527        "<h5>{{#if title}} {{title}} {{else}} {{id}} {{/if}}</h5>\n" +
528        "<p>Status: {{status_text}}</p>\n\n" +
529        "<!-- Show all linked Database Objects: -->\n" +
530        "{{#each objects}}\n\n" +
531        "  <!-- DB Object are available inside of this block -->\n\n" +
532        "  <h5>{{title}}</h5>\n" +
533        "  <!-- When you need to render a field as HTML, use 3 curly braces instead of 2:-->\n" +
534        "  <p>{{{description}}}</p>\n" +
535        "  <p><em>{{location.address.formatted}}</em></p>\n\n" +
536        "  <!-- Show all images: -->\n" +
537        "  {{#each images}}\n" +
538        '    <!-- Image fields "thumbnail", "medium", "full" -->\n' +
539        "    <!-- are available in this block                -->\n" +
540        '    <img src="{{thumbnail}}" />\n' +
541        "  {{/each}}\n\n" +
542        "{{/each}}";
543    const defDBTemplate = "<div>\n" +
544        "  <p>This is the demo content of the <strong>DB Object %templateType%</strong>.</p>\n" +
545        '  <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' +
546        '  <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' +
547        "</div>\n" +
548        "<hr />\n\n" +
549        "<!-- DB Object fields are available in this template. -->\n" +
550        "<h5>{{title}}</h5>\n" +
551        "<!-- When you need to render a fields as HTML, use 3 curly braces instead of 2:-->\n" +
552        "<p>{{{description}}}</p>\n" +
553        "<p><em>{{location.address.formatted}}</em></p>\n\n" +
554        "<!-- Show all images: -->\n" +
555        "{{#each images}}\n" +
556        '  <!-- Image fields "thumbnail", "medium", "full" -->\n' +
557        "  <!-- are available in this block                -->\n" +
558        '  <img src="{{thumbnail}}" />\n' +
559        "{{/each}}\n\n" +
560        "<!-- Show all linked Regions, comma-separated: -->\n" +
561        "<p> Regions: \n" +
562        "  {{#each regions}}\n" +
563        "    <!-- Region fields are available in this block -->\n" +
564        "    {{#if title}}\n" +
565        "      {{title}}\n" +
566        "    {{else}}\n" +
567        "      {{id}}\n" +
568        "    {{/if}}{{#unless @last}}, {{/unless}}\n" +
569        "  {{/each}}\n" +
570        "</p>";
571    const dirItemItemTemplate = "<!-- If Directory Source = Database: DB Object fields are available in this template -->\n" +
572        "<!-- If Directory Source = Regions: Region fields are available in this template -->\n" +
573        "{{title}}";
574    const DefaultOptions = {
575        source: "",
576        markerLastID: 0,
577        regionLastID: 0,
578        dataLastID: 1,
579        disableAll: false,
580        width: null,
581        height: null,
582        lockAspectRatio: false,
583        padding: { top: 0, left: 0, right: 0, bottom: 0 },
584        maxWidth: null,
585        maxHeight: null,
586        minWidth: null,
587        minHeight: null,
588        loadingText: "Loading map...",
589        colorsIgnore: false,
590        colors: {
591            baseDefault: "#000000",
592            background: "#eeeeee",
593            selected: 40,
594            hover: 20,
595            directory: "#fafafa",
596            detailsView: "",
597            status: {},
598            clusters: "",
599            clustersBorders: "",
600            clustersText: "",
601            clustersHover: "",
602            clustersHoverBorders: "",
603            clustersHoverText: "",
604            markers: {
605                base: { opacity: 100, saturation: 100 },
606                hovered: { opacity: 100, saturation: 100 },
607                unhovered: { opacity: 40, saturation: 100 },
608                active: { opacity: 100, saturation: 100 },
609                inactive: { opacity: 40, saturation: 100 },
610            },
611        },
612        regions: {},
613        clustering: { on: false },
614        viewBox: [],
615        cursor: "default",
616        manualRegions: false,
617        onClick: null,
618        mouseOver: null,
619        mouseOut: null,
620        menuOnClick: null,
621        beforeLoad: null,
622        afterLoad: null,
623        zoom: {
624            on: true,
625            limit: [0, 22],
626            delta: 2,
627            buttons: { on: true, location: "right" },
628            mousewheel: true,
629            fingers: true,
630            hideSvg: false,
631            hideSvgZoomLevel: 7,
632        },
633        scroll: { on: true, limit: false, background: false, spacebar: false },
634        responsive: true,
635        tooltips: { on: false, position: "bottom-right", template: "", maxWidth: "", minWidth: 100 },
636        popovers: {
637            on: false,
638            position: "top",
639            template: "",
640            centerOn: true,
641            width: 300,
642            maxWidth: 50,
643            maxHeight: 50,
644        },
645        multiSelect: false,
646        regionStatuses: {
647            "1": { label: "Enabled", value: "1", color: "", disabled: false },
648            "0": { label: "Disabled", value: "0", color: "", disabled: true },
649        },
650        events: {
651            afterLoad: "function(){\n" +
652                "  // var mapsvg = this;\n" +
653                "  // var regions = mapsvg.regions;\n" +
654                "  // var dbObjects = mapsvg.database.getLoaded();\n" +
655                "}",
656            beforeLoad: "function(){\n" +
657                "  // var mapsvg = this;\n" +
658                "  // var settings = mapsvg.options;\n" +
659                "  // console.log(settings);\n" +
660                "}",
661            databaseLoaded: "function (){\n" +
662                "  // var mapsvg = this;\n" +
663                "  // var dbObjects = mapsvg.database.getLoaded();\n" +
664                "}",
665            "click.region": "function (e, mapsvg){\n" +
666                "  // var region = this;\n" +
667                "  // console.log(region);\n" +
668                "}",
669            "mouseover.region": "function (e, mapsvg){\n" +
670                "  // var region = this;\n" +
671                "  // console.log(region);\n" +
672                "}",
673            "mouseout.region": "function (e, mapsvg){\n" +
674                "  // var region = this;\n" +
675                "  // console.log(region);\n" +
676                "}",
677            "click.marker": "function (e, mapsvg){\n" +
678                "  // var marker = this;\n" +
679                "  // console.log(marker);\n" +
680                "}",
681            "mouseover.marker": "function (e, mapsvg){\n" +
682                "  // var marker = this;\n" +
683                "  // console.log(marker);\n" +
684                "}",
685            "mouseout.marker": "function (e, mapsvg){\n" +
686                "  // var marker = this;\n" +
687                "  // console.log(marker);\n" +
688                "}",
689            "click.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
690            "mouseover.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
691            "mouseout.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
692            "shown.popover": "function (mapsvg){\n" + "  // var popoverjQueryObject = this;\n" + "}",
693            "closed.popover": "function (mapsvg){\n" + "  // var popoverjQueryObject = this;\n" + "}",
694            "closed.detailsView": "function (mapsvg){\n" + "  // var detailsjQueryObject = this;\n" + "}",
695            "shown.detailsView": "function (mapsvg){\n" + "  // var detailsjQueryObject = this;\n" + "}",
696        },
697        css: "#mapsvg-map-%id% .mapsvg-tooltip {\n\n}\n" +
698            "#mapsvg-map-%id% .mapsvg-popover {\n\n}\n" +
699            "#mapsvg-map-%id% .mapsvg-details-container {\n\n}\n" +
700            "#mapsvg-map-%id% .mapsvg-directory-item {\n\n}\n" +
701            "#mapsvg-map-%id% .mapsvg-region-label {\n" +
702            "  /* background-color: rgba(255,255,255,.6); */\n" +
703            "  font-size: 11px;\n" +
704            "  padding: 3px 5px;\n" +
705            "  border-radius: 4px;\n" +
706            "}\n" +
707            "#mapsvg-map-%id% .mapsvg-marker-label {\n" +
708            "  padding: 3px 5px;\n" +
709            "  /*\n" +
710            "  border-radius: 4px;\n" +
711            "  background-color: white;\n" +
712            "  margin-top: -4px;\n" +
713            "  */\n}\n" +
714            "#mapsvg-map-%id% .mapsvg-filters-wrap {\n\n}\n" +
715            "\n\n\n\n\n\n",
716        templates: {
717            popoverRegion: defRegionTemplate
718                .replace(/%templateType%/g, "Popover")
719                .replace(/%templateTypeSnake%/g, "popover"),
720            popoverMarker: defDBTemplate
721                .replace(/%templateType%/g, "Popover")
722                .replace(/%templateTypeSnake%/g, "popover"),
723            tooltipRegion: "<!-- Region fields are available in this template -->\n{{id}} - {{title}}",
724            tooltipMarker: "<!-- DB Object fields are available in this template -->\n{{title}}",
725            directoryItem: dirItemItemTemplate,
726            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>',
727            detailsView: defDBTemplate
728                .replace(/%templateType%/g, "Details View")
729                .replace(/%templateTypeSnake%/g, "detailsView"),
730            detailsViewRegion: defRegionTemplate
731                .replace(/%templateType%/g, "Details View")
732                .replace(/%templateTypeSnake%/g, "detailsView"),
733            labelMarker: "<!-- DB Object fields are available in this template -->\n{{title}}",
734            labelRegion: "<!-- Region fields are available in this template -->\n{{title}}",
735            labelLocation: "You are here!",
736        },
737        choropleth: {
738            on: false,
739            source: "regions",
740            sourceFieldSelect: {
741                on: false,
742                variants: [],
743            },
744            bubbleMode: false,
745            bubbleSize: {
746                min: 20,
747                max: 40,
748            },
749            labels: { low: "low", high: "high" },
750            colors: { lowRGB: null, highRGB: null, low: "#550000", high: "#ee0000", noData: "#333333" },
751            min: 0,
752            max: 0,
753            coloring: {
754                mode: "gradient",
755                noData: {
756                    color: "#999999",
757                    description: "No data",
758                },
759                gradient: {
760                    colors: {
761                        lowRGB: null,
762                        highRGB: null,
763                        diffRGB: null,
764                        low: "#550000",
765                        high: "#ee0000",
766                    },
767                    labels: {
768                        low: "low",
769                        high: "high",
770                    },
771                    values: {
772                        min: null,
773                        max: null,
774                        maxAdjusted: null,
775                    },
776                },
777                palette: {
778                    outOfRange: {
779                        color: "#ececec",
780                        description: "Out of range",
781                    },
782                    colors: [
783                        {
784                            color: "#550000",
785                            valueFrom: 0,
786                            valueTo: 50,
787                            description: "",
788                        },
789                    ],
790                },
791                legend: {
792                    on: true,
793                    layout: "vertical",
794                    container: "bottom-left",
795                    title: "Choropleth map",
796                    text: "",
797                    description: "",
798                    width: "20%",
799                    height: "20%",
800                },
801            },
802        },
803        filters: {
804            on: true,
805            source: "database",
806            location: "header",
807            modalLocation: "map",
808            width: "100%",
809            hide: false,
810            showButtonText: "Filters",
811            clearButtonText: "Clear all",
812            clearButton: false,
813            searchButton: false,
814            searchButtonText: "Search",
815            padding: "",
816        },
817        menu: {
818            on: false,
819            hideOnMobile: true,
820            location: "leftSidebar",
821            locationMobile: "leftSidebar",
822            search: false,
823            containerId: "",
824            searchPlaceholder: "Search...",
825            searchFallback: false,
826            source: "database",
827            showFirst: "map",
828            showMapOnClick: true,
829            minHeight: "400",
830            sortBy: "id",
831            sortDirection: "desc",
832            categories: {
833                on: false,
834                groupBy: "",
835                hideEmpty: true,
836                collapse: true,
837                collapseOther: true,
838            },
839            clickActions: {
840                region: "default",
841                marker: "default",
842                directoryItem: {
843                    triggerClick: true,
844                    showPopover: false,
845                    showDetails: true,
846                },
847            },
848            detailsViewLocation: "overDirectory",
849            noResultsText: "No results found",
850            filterout: { field: "", cond: "=", val: "" },
851        },
852        database: {
853            pagination: {
854                on: true,
855                perpage: 30,
856                next: "Next",
857                prev: "Prev.",
858                showIn: "both",
859            },
860            loadOnStart: true,
861            table: "",
862        },
863        actions: {
864            map: {
865                afterLoad: {
866                    selectRegion: false,
867                },
868            },
869            region: {
870                mouseover: {
871                    showTooltip: false,
872                },
873                click: {
874                    addIdToUrl: false,
875                    showDetails: true,
876                    showDetailsFor: "region",
877                    filterDirectory: false,
878                    loadObjects: false,
879                    showPopover: false,
880                    showPopoverFor: "region",
881                    goToLink: false,
882                    linkField: "Region.link",
883                },
884                touch: {
885                    showPopover: false,
886                },
887            },
888            marker: {
889                mouseover: {
890                    showTooltip: false,
891                },
892                click: {
893                    showDetails: true,
894                    showPopover: false,
895                    goToLink: false,
896                    linkField: "Object.link",
897                },
898                touch: {
899                    showPopover: false,
900                },
901            },
902            directoryItem: {
903                click: {
904                    showDetails: true,
905                    showPopover: false,
906                    goToLink: false,
907                    selectRegion: true,
908                    fireRegionOnClick: true,
909                    linkField: "Object.link",
910                },
911                hover: {
912                    centerOnMarker: false,
913                },
914            },
915        },
916        detailsView: {
917            location: "map",
918            containerId: "",
919            width: "100%",
920            mobileFullscreen: true,
921        },
922        mobileView: {
923            labelMap: "Map",
924            labelList: "List",
925            labelClose: "Close",
926        },
927        googleMaps: {
928            on: false,
929            apiKey: "",
930            loaded: false,
931            center: "auto",
932            type: "roadmap",
933            minZoom: 1,
934            style: "default",
935            styleJSON: [],
936            language: "en",
937        },
938        groups: [],
939        floors: [],
940        layersControl: {
941            on: false,
942            position: "top-left",
943            label: "Show on map",
944            expanded: true,
945            maxHeight: "100%",
946        },
947        floorsControl: {
948            on: false,
949            position: "top-left",
950            label: "Floors",
951            expanded: false,
952            maxHeight: "100%",
953        },
954        containers: {
955            leftSidebar: { on: false, width: "250px" },
956            rightSidebar: { on: false, width: "250px" },
957            header: { on: true, height: "auto" },
958            footer: { on: false, height: "auto" },
959        },
960        labelsMarkers: { on: false },
961        labelsRegions: { on: false },
962        svgFileVersion: 1,
963        fitMarkers: false,
964        fitMarkersOnStart: false,
965        fitSingleMarkerZoom: 20,
966        controls: {
967            location: "right",
968            zoom: true,
969            zoomReset: false,
970            userLocation: false,
971            previousMap: false,
972        },
973        previousMapsIds: [],
974    };
975
976    // TinyColor v1.4.1
977    // https://github.com/bgrins/TinyColor
978    // Brian Grinstead, MIT License
979
980    //(function(Math) {
981
982    var trimLeft = /^\s+/,
983        trimRight = /\s+$/,
984        tinyCounter = 0,
985        mathRound = Math.round,
986        mathMin = Math.min,
987        mathMax = Math.max,
988        mathRandom = Math.random;
989
990    function tinycolor(color, opts) {
991        color = color ? color : "";
992        opts = opts || {};
993
994        // If input is already a tinycolor, return itself
995        if (color instanceof tinycolor) {
996            return color;
997        }
998        // If we are called as a function, call using new instead
999        if (!(this instanceof tinycolor)) {
1000            return new tinycolor(color, opts);
1001        }
1002
1003        var rgb = inputToRGB(color);
1004        (this._originalInput = color),
1005            (this._r = rgb.r),
1006            (this._g = rgb.g),
1007            (this._b = rgb.b),
1008            (this._a = rgb.a),
1009            (this._roundA = mathRound(100 * this._a) / 100),
1010            (this._format = opts.format || rgb.format);
1011        this._gradientType = opts.gradientType;
1012
1013        // Don't let the range of [0,255] come back in [0,1].
1014        // Potentially lose a little bit of precision here, but will fix issues where
1015        // .5 gets interpreted as half of the total, instead of half of 1
1016        // If it was supposed to be 128, this was already taken care of b
vendor: 11,167 bytes, lines 1016-1334
1016y `inputToRgb`
1017        if (this._r < 1) {
1018            this._r = mathRound(this._r);
1019        }
1020        if (this._g < 1) {
1021            this._g = mathRound(this._g);
1022        }
1023        if (this._b < 1) {
1024            this._b = mathRound(this._b);
1025        }
1026
1027        this._ok = rgb.ok;
1028        this._tc_id = tinyCounter++;
1029    }
1030
1031    tinycolor.prototype = {
1032        isDark: function () {
1033            return this.getBrightness() < 128;
1034        },
1035        isLight: function () {
1036            return !this.isDark();
1037        },
1038        isValid: function () {
1039            return this._ok;
1040        },
1041        getOriginalInput: function () {
1042            return this._originalInput;
1043        },
1044        getFormat: function () {
1045            return this._format;
1046        },
1047        getAlpha: function () {
1048            return this._a;
1049        },
1050        getBrightness: function () {
1051            //http://www.w3.org/TR/AERT#color-contrast
1052            var rgb = this.toRgb();
1053            return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
1054        },
1055        getLuminance: function () {
1056            //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
1057            var rgb = this.toRgb();
1058            var RsRGB, GsRGB, BsRGB, R, G, B;
1059            RsRGB = rgb.r / 255;
1060            GsRGB = rgb.g / 255;
1061            BsRGB = rgb.b / 255;
1062
1063            if (RsRGB <= 0.03928) {
1064                R = RsRGB / 12.92;
1065            } else {
1066                R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);
1067            }
1068            if (GsRGB <= 0.03928) {
1069                G = GsRGB / 12.92;
1070            } else {
1071                G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);
1072            }
1073            if (BsRGB <= 0.03928) {
1074                B = BsRGB / 12.92;
1075            } else {
1076                B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);
1077            }
1078            return 0.2126 * R + 0.7152 * G + 0.0722 * B;
1079        },
1080        setAlpha: function (value) {
1081            this._a = boundAlpha(value);
1082            this._roundA = mathRound(100 * this._a) / 100;
1083            return this;
1084        },
1085        toHsv: function () {
1086            var hsv = rgbToHsv(this._r, this._g, this._b);
1087            return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
1088        },
1089        toHsvString: function () {
1090            var hsv = rgbToHsv(this._r, this._g, this._b);
1091            var h = mathRound(hsv.h * 360),
1092                s = mathRound(hsv.s * 100),
1093                v = mathRound(hsv.v * 100);
1094            return this._a == 1
1095                ? "hsv(" + h + ", " + s + "%, " + v + "%)"
1096                : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")";
1097        },
1098        toHsl: function () {
1099            var hsl = rgbToHsl(this._r, this._g, this._b);
1100            return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
1101        },
1102        toHslString: function () {
1103            var hsl = rgbToHsl(this._r, this._g, this._b);
1104            var h = mathRound(hsl.h * 360),
1105                s = mathRound(hsl.s * 100),
1106                l = mathRound(hsl.l * 100);
1107            return this._a == 1
1108                ? "hsl(" + h + ", " + s + "%, " + l + "%)"
1109                : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")";
1110        },
1111        toHex: function (allow3Char) {
1112            return rgbToHex(this._r, this._g, this._b, allow3Char);
1113        },
1114        toHexString: function (allow3Char) {
1115            return "#" + this.toHex(allow3Char);
1116        },
1117        toHex8: function (allow4Char) {
1118            return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
1119        },
1120        toHex8String: function (allow4Char) {
1121            return "#" + this.toHex8(allow4Char);
1122        },
1123        toRgb: function () {
1124            return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
1125        },
1126        toRgbString: function () {
1127            return this._a == 1
1128                ? "rgb(" +
1129                      mathRound(this._r) +
1130                      ", " +
1131                      mathRound(this._g) +
1132                      ", " +
1133                      mathRound(this._b) +
1134                      ")"
1135                : "rgba(" +
1136                      mathRound(this._r) +
1137                      ", " +
1138                      mathRound(this._g) +
1139                      ", " +
1140                      mathRound(this._b) +
1141                      ", " +
1142                      this._roundA +
1143                      ")";
1144        },
1145        toPercentageRgb: function () {
1146            return {
1147                r: mathRound(bound01(this._r, 255) * 100) + "%",
1148                g: mathRound(bound01(this._g, 255) * 100) + "%",
1149                b: mathRound(bound01(this._b, 255) * 100) + "%",
1150                a: this._a,
1151            };
1152        },
1153        toPercentageRgbString: function () {
1154            return this._a == 1
1155                ? "rgb(" +
1156                      mathRound(bound01(this._r, 255) * 100) +
1157                      "%, " +
1158                      mathRound(bound01(this._g, 255) * 100) +
1159                      "%, " +
1160                      mathRound(bound01(this._b, 255) * 100) +
1161                      "%)"
1162                : "rgba(" +
1163                      mathRound(bound01(this._r, 255) * 100) +
1164                      "%, " +
1165                      mathRound(bound01(this._g, 255) * 100) +
1166                      "%, " +
1167                      mathRound(bound01(this._b, 255) * 100) +
1168                      "%, " +
1169                      this._roundA +
1170                      ")";
1171        },
1172        toName: function () {
1173            if (this._a === 0) {
1174                return "transparent";
1175            }
1176
1177            if (this._a < 1) {
1178                return false;
1179            }
1180
1181            return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
1182        },
1183        toFilter: function (secondColor) {
1184            var hex8String = "#" + rgbaToArgbHex(this._r, this._g, this._b, this._a);
1185            var secondHex8String = hex8String;
1186            var gradientType = this._gradientType ? "GradientType = 1, " : "";
1187
1188            if (secondColor) {
1189                var s = tinycolor(secondColor);
1190                secondHex8String = "#" + rgbaToArgbHex(s._r, s._g, s._b, s._a);
1191            }
1192
1193            return (
1194                "progid:DXImageTransform.Microsoft.gradient(" +
1195                gradientType +
1196                "startColorstr=" +
1197                hex8String +
1198                ",endColorstr=" +
1199                secondHex8String +
1200                ")"
1201            );
1202        },
1203        toString: function (format) {
1204            var formatSet = !!format;
1205            format = format || this._format;
1206
1207            var formattedString = false;
1208            var hasAlpha = this._a < 1 && this._a >= 0;
1209            var needsAlphaFormat =
1210                !formatSet &&
1211                hasAlpha &&
1212                (format === "hex" ||
1213                    format === "hex6" ||
1214                    format === "hex3" ||
1215                    format === "hex4" ||
1216                    format === "hex8" ||
1217                    format === "name");
1218
1219            if (needsAlphaFormat) {
1220                // Special case for "transparent", all other non-alpha formats
1221                // will return rgba when there is transparency.
1222                if (format === "name" && this._a === 0) {
1223                    return this.toName();
1224                }
1225                return this.toRgbString();
1226            }
1227            if (format === "rgb") {
1228                formattedString = this.toRgbString();
1229            }
1230            if (format === "prgb") {
1231                formattedString = this.toPercentageRgbString();
1232            }
1233            if (format === "hex" || format === "hex6") {
1234                formattedString = this.toHexString();
1235            }
1236            if (format === "hex3") {
1237                formattedString = this.toHexString(true);
1238            }
1239            if (format === "hex4") {
1240                formattedString = this.toHex8String(true);
1241            }
1242            if (format === "hex8") {
1243                formattedString = this.toHex8String();
1244            }
1245            if (format === "name") {
1246                formattedString = this.toName();
1247            }
1248            if (format === "hsl") {
1249                formattedString = this.toHslString();
1250            }
1251            if (format === "hsv") {
1252                formattedString = this.toHsvString();
1253            }
1254
1255            return formattedString || this.toHexString();
1256        },
1257        clone: function () {
1258            return tinycolor(this.toString());
1259        },
1260
1261        _applyModification: function (fn, args) {
1262            var color = fn.apply(null, [this].concat([].slice.call(args)));
1263            this._r = color._r;
1264            this._g = color._g;
1265            this._b = color._b;
1266            this.setAlpha(color._a);
1267            return this;
1268        },
1269        lighten: function () {
1270            return this._applyModification(lighten, arguments);
1271        },
1272        brighten: function () {
1273            return this._applyModification(brighten, arguments);
1274        },
1275        darken: function () {
1276            return this._applyModification(darken, arguments);
1277        },
1278        desaturate: function () {
1279            return this._applyModification(desaturate, arguments);
1280        },
1281        saturate: function () {
1282            return this._applyModification(saturate, arguments);
1283        },
1284        greyscale: function () {
1285            return this._applyModification(greyscale, arguments);
1286        },
1287        spin: function () {
1288            return this._applyModification(spin, arguments);
1289        },
1290
1291        _applyCombination: function (fn, args) {
1292            return fn.apply(null, [this].concat([].slice.call(args)));
1293        },
1294        analogous: function () {
1295            return this._applyCombination(analogous, arguments);
1296        },
1297        complement: function () {
1298            return this._applyCombination(complement, arguments);
1299        },
1300        monochromatic: function () {
1301            return this._applyCombination(monochromatic, arguments);
1302        },
1303        splitcomplement: function () {
1304            return this._applyCombination(splitcomplement, arguments);
1305        },
1306        triad: function () {
1307            return this._applyCombination(triad, arguments);
1308        },
1309        tetrad: function () {
1310            return this._applyCombination(tetrad, arguments);
1311        },
1312    };
1313
1314    // If input is an object, force 1 into "1.0" to handle ratios properly
1315    // String input requires "1.0" as input, so 1 will be treated as 1
1316    tinycolor.fromRatio = function (color, opts) {
1317        if (typeof color == "object") {
1318            var newColor = {};
1319            for (var i in color) {
1320                if (color.hasOwnProperty(i)) {
1321                    if (i === "a") {
1322                        newColor[i] = color[i];
1323                    } else {
1324                        newColor[i] = convertToPercentage(color[i]);
1325                    }
1326                }
1327            }
1328            color = newColor;
1329        }
1330
1331        return tinycolor(color, opts);
1332    };
1333
1334    // Given a string or object, convert that input to RGB
vendor: 8,705 bytes, lines 1335-1615
1335    // Possible string inputs:
1336    //
1337    //     "red"
1338    //     "#f00" or "f00"
1339    //     "#ff0000" or "ff0000"
1340    //     "#ff000000" or "ff000000"
1341    //     "rgb 255 0 0" or "rgb (255, 0, 0)"
1342    //     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1343    //     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1344    //     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1345    //     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1346    //     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1347    //     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1348    //
1349    function inputToRGB(color) {
1350        var rgb = { r: 0, g: 0, b: 0 };
1351        var a = 1;
1352        var s = null;
1353        var v = null;
1354        var l = null;
1355        var ok = false;
1356        var format = false;
1357
1358        if (typeof color == "string") {
1359            color = stringInputToObject(color);
1360        }
1361
1362        if (typeof color == "object") {
1363            if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
1364                rgb = rgbToRgb(color.r, color.g, color.b);
1365                ok = true;
1366                format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1367            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
1368                s = convertToPercentage(color.s);
1369                v = convertToPercentage(color.v);
1370                rgb = hsvToRgb(color.h, s, v);
1371                ok = true;
1372                format = "hsv";
1373            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
1374                s = convertToPercentage(color.s);
1375                l = convertToPercentage(color.l);
1376                rgb = hslToRgb(color.h, s, l);
1377                ok = true;
1378                format = "hsl";
1379            }
1380
1381            if (color.hasOwnProperty("a")) {
1382                a = color.a;
1383            }
1384        }
1385
1386        a = boundAlpha(a);
1387
1388        return {
1389            ok: ok,
1390            format: color.format || format,
1391            r: mathMin(255, mathMax(rgb.r, 0)),
1392            g: mathMin(255, mathMax(rgb.g, 0)),
1393            b: mathMin(255, mathMax(rgb.b, 0)),
1394            a: a,
1395        };
1396    }
1397
1398    // Conversion Functions
1399    // --------------------
1400
1401    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1402    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1403
1404    // `rgbToRgb`
1405    // Handle bounds / percentage checking to conform to CSS color spec
1406    // <http://www.w3.org/TR/css3-color/>
1407    // *Assumes:* r, g, b in [0, 255] or [0, 1]
1408    // *Returns:* { r, g, b } in [0, 255]
1409    function rgbToRgb(r, g, b) {
1410        return {
1411            r: bound01(r, 255) * 255,
1412            g: bound01(g, 255) * 255,
1413            b: bound01(b, 255) * 255,
1414        };
1415    }
1416
1417    // `rgbToHsl`
1418    // Converts an RGB color value to HSL.
1419    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1420    // *Returns:* { h, s, l } in [0,1]
1421    function rgbToHsl(r, g, b) {
1422        r = bound01(r, 255);
1423        g = bound01(g, 255);
1424        b = bound01(b, 255);
1425
1426        var max = mathMax(r, g, b),
1427            min = mathMin(r, g, b);
1428        var h,
1429            s,
1430            l = (max + min) / 2;
1431
1432        if (max == min) {
1433            h = s = 0; // achromatic
1434        } else {
1435            var d = max - min;
1436            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1437            switch (max) {
1438                case r:
1439                    h = (g - b) / d + (g < b ? 6 : 0);
1440                    break;
1441                case g:
1442                    h = (b - r) / d + 2;
1443                    break;
1444                case b:
1445                    h = (r - g) / d + 4;
1446                    break;
1447            }
1448
1449            h /= 6;
1450        }
1451
1452        return { h: h, s: s, l: l };
1453    }
1454
1455    // `hslToRgb`
1456    // Converts an HSL color value to RGB.
1457    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1458    // *Returns:* { r, g, b } in the set [0, 255]
1459    function hslToRgb(h, s, l) {
1460        var r, g, b;
1461
1462        h = bound01(h, 360);
1463        s = bound01(s, 100);
1464        l = bound01(l, 100);
1465
1466        function hue2rgb(p, q, t) {
1467            if (t < 0) t += 1;
1468            if (t > 1) t -= 1;
1469            if (t < 1 / 6) return p + (q - p) * 6 * t;
1470            if (t < 1 / 2) return q;
1471            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
1472            return p;
1473        }
1474
1475        if (s === 0) {
1476            r = g = b = l; // achromatic
1477        } else {
1478            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1479            var p = 2 * l - q;
1480            r = hue2rgb(p, q, h + 1 / 3);
1481            g = hue2rgb(p, q, h);
1482            b = hue2rgb(p, q, h - 1 / 3);
1483        }
1484
1485        return { r: r * 255, g: g * 255, b: b * 255 };
1486    }
1487
1488    // `rgbToHsv`
1489    // Converts an RGB color value to HSV
1490    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1491    // *Returns:* { h, s, v } in [0,1]
1492    function rgbToHsv(r, g, b) {
1493        r = bound01(r, 255);
1494        g = bound01(g, 255);
1495        b = bound01(b, 255);
1496
1497        var max = mathMax(r, g, b),
1498            min = mathMin(r, g, b);
1499        var h,
1500            s,
1501            v = max;
1502
1503        var d = max - min;
1504        s = max === 0 ? 0 : d / max;
1505
1506        if (max == min) {
1507            h = 0; // achromatic
1508        } else {
1509            switch (max) {
1510                case r:
1511                    h = (g - b) / d + (g < b ? 6 : 0);
1512                    break;
1513                case g:
1514                    h = (b - r) / d + 2;
1515                    break;
1516                case b:
1517                    h = (r - g) / d + 4;
1518                    break;
1519            }
1520            h /= 6;
1521        }
1522        return { h: h, s: s, v: v };
1523    }
1524
1525    // `hsvToRgb`
1526    // Converts an HSV color value to RGB.
1527    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1528    // *Returns:* { r, g, b } in the set [0, 255]
1529    function hsvToRgb(h, s, v) {
1530        h = bound01(h, 360) * 6;
1531        s = bound01(s, 100);
1532        v = bound01(v, 100);
1533
1534        var i = Math.floor(h),
1535            f = h - i,
1536            p = v * (1 - s),
1537            q = v * (1 - f * s),
1538            t = v * (1 - (1 - f) * s),
1539            mod = i % 6,
1540            r = [v, q, p, p, t, v][mod],
1541            g = [t, v, v, q, p, p][mod],
1542            b = [p, p, t, v, v, q][mod];
1543
1544        return { r: r * 255, g: g * 255, b: b * 255 };
1545    }
1546
1547    // `rgbToHex`
1548    // Converts an RGB color to hex
1549    // Assumes r, g, and b are contained in the set [0, 255]
1550    // Returns a 3 or 6 character hex
1551    function rgbToHex(r, g, b, allow3Char) {
1552        var hex = [
1553            pad2(mathRound(r).toString(16)),
1554            pad2(mathRound(g).toString(16)),
1555            pad2(mathRound(b).toString(16)),
1556        ];
1557
1558        // Return a 3 character hex if possible
1559        if (
1560            allow3Char &&
1561            hex[0].charAt(0) == hex[0].charAt(1) &&
1562            hex[1].charAt(0) == hex[1].charAt(1) &&
1563            hex[2].charAt(0) == hex[2].charAt(1)
1564        ) {
1565            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1566        }
1567
1568        return hex.join("");
1569    }
1570
1571    // `rgbaToHex`
1572    // Converts an RGBA color plus alpha transparency to hex
1573    // Assumes r, g, b are contained in the set [0, 255] and
1574    // a in [0, 1]. Returns a 4 or 8 character rgba hex
1575    function rgbaToHex(r, g, b, a, allow4Char) {
1576        var hex = [
1577            pad2(mathRound(r).toString(16)),
1578            pad2(mathRound(g).toString(16)),
1579            pad2(mathRound(b).toString(16)),
1580            pad2(convertDecimalToHex(a)),
1581        ];
1582
1583        // Return a 4 character hex if possible
1584        if (
1585            allow4Char &&
1586            hex[0].charAt(0) == hex[0].charAt(1) &&
1587            hex[1].charAt(0) == hex[1].charAt(1) &&
1588            hex[2].charAt(0) == hex[2].charAt(1) &&
1589            hex[3].charAt(0) == hex[3].charAt(1)
1590        ) {
1591            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
1592        }
1593
1594        return hex.join("");
1595    }
1596
1597    // `rgbaToArgbHex`
1598    // Converts an RGBA color to an ARGB Hex8 string
1599    // Rarely used, but required for "toFilter()"
1600    function rgbaToArgbHex(r, g, b, a) {
1601        var hex = [
1602            pad2(convertDecimalToHex(a)),
1603            pad2(mathRound(r).toString(16)),
1604            pad2(mathRound(g).toString(16)),
1605            pad2(mathRound(b).toString(16)),
1606        ];
1607
1608        return hex.join("");
1609    }
1610
1611    // `equals`
1612    // Can be called with any tinycolor input
1613    tinycolor.equals = function (color1, color2) {
1614        if (!color1 || !color2) {
1615            return false;
vendor: 4,315 bytes, lines 1616-1753
1616        }
1617        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1618    };
1619
1620    tinycolor.random = function () {
1621        return tinycolor.fromRatio({
1622            r: mathRandom(),
1623            g: mathRandom(),
1624            b: mathRandom(),
1625        });
1626    };
1627
1628    // Modification Functions
1629    // ----------------------
1630    // Thanks to less.js for some of the basics here
1631    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1632
1633    function desaturate(color, amount) {
1634        amount = amount === 0 ? 0 : amount || 10;
1635        var hsl = tinycolor(color).toHsl();
1636        hsl.s -= amount / 100;
1637        hsl.s = clamp01(hsl.s);
1638        return tinycolor(hsl);
1639    }
1640
1641    function saturate(color, amount) {
1642        amount = amount === 0 ? 0 : amount || 10;
1643        var hsl = tinycolor(color).toHsl();
1644        hsl.s += amount / 100;
1645        hsl.s = clamp01(hsl.s);
1646        return tinycolor(hsl);
1647    }
1648
1649    function greyscale(color) {
1650        return tinycolor(color).desaturate(100);
1651    }
1652
1653    function lighten(color, amount) {
1654        amount = amount === 0 ? 0 : amount || 10;
1655        var hsl = tinycolor(color).toHsl();
1656        hsl.l += amount / 100;
1657        hsl.l = clamp01(hsl.l);
1658        return tinycolor(hsl);
1659    }
1660
1661    function brighten(color, amount) {
1662        amount = amount === 0 ? 0 : amount || 10;
1663        var rgb = tinycolor(color).toRgb();
1664        rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * -(amount / 100))));
1665        rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * -(amount / 100))));
1666        rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * -(amount / 100))));
1667        return tinycolor(rgb);
1668    }
1669
1670    function darken(color, amount) {
1671        amount = amount === 0 ? 0 : amount || 10;
1672        var hsl = tinycolor(color).toHsl();
1673        hsl.l -= amount / 100;
1674        hsl.l = clamp01(hsl.l);
1675        return tinycolor(hsl);
1676    }
1677
1678    // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
1679    // Values outside of this range will be wrapped into this range.
1680    function spin(color, amount) {
1681        var hsl = tinycolor(color).toHsl();
1682        var hue = (hsl.h + amount) % 360;
1683        hsl.h = hue < 0 ? 360 + hue : hue;
1684        return tinycolor(hsl);
1685    }
1686
1687    // Combination Functions
1688    // ---------------------
1689    // Thanks to jQuery xColor for some of the ideas behind these
1690    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1691
1692    function complement(color) {
1693        var hsl = tinycolor(color).toHsl();
1694        hsl.h = (hsl.h + 180) % 360;
1695        return tinycolor(hsl);
1696    }
1697
1698    function triad(color) {
1699        var hsl = tinycolor(color).toHsl();
1700        var h = hsl.h;
1701        return [
1702            tinycolor(color),
1703            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1704            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }),
1705        ];
1706    }
1707
1708    function tetrad(color) {
1709        var hsl = tinycolor(color).toHsl();
1710        var h = hsl.h;
1711        return [
1712            tinycolor(color),
1713            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1714            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1715            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }),
1716        ];
1717    }
1718
1719    function splitcomplement(color) {
1720        var hsl = tinycolor(color).toHsl();
1721        var h = hsl.h;
1722        return [
1723            tinycolor(color),
1724            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }),
1725            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l }),
1726        ];
1727    }
1728
1729    function analogous(color, results, slices) {
1730        results = results || 6;
1731        slices = slices || 30;
1732
1733        var hsl = tinycolor(color).toHsl();
1734        var part = 360 / slices;
1735        var ret = [tinycolor(color)];
1736
1737        for (hsl.h = (hsl.h - ((part * results) >> 1) + 720) % 360; --results; ) {
1738            hsl.h = (hsl.h + part) % 360;
1739            ret.push(tinycolor(hsl));
1740        }
1741        return ret;
1742    }
1743
1744    function monochromatic(color, results) {
1745        results = results || 6;
1746        var hsv = tinycolor(color).toHsv();
1747        var h = hsv.h,
1748            s = hsv.s,
1749            v = hsv.v;
1750        var ret = [];
1751        var modification = 1 / results;
1752
1753        while (results--) {
vendor: 4,157 bytes, lines 1754-1862
1754            ret.push(tinycolor({ h: h, s: s, v: v }));
1755            v = (v + modification) % 1;
1756        }
1757
1758        return ret;
1759    }
1760
1761    // Utility Functions
1762    // ---------------------
1763
1764    tinycolor.mix = function (color1, color2, amount) {
1765        amount = amount === 0 ? 0 : amount || 50;
1766
1767        var rgb1 = tinycolor(color1).toRgb();
1768        var rgb2 = tinycolor(color2).toRgb();
1769
1770        var p = amount / 100;
1771
1772        var rgba = {
1773            r: (rgb2.r - rgb1.r) * p + rgb1.r,
1774            g: (rgb2.g - rgb1.g) * p + rgb1.g,
1775            b: (rgb2.b - rgb1.b) * p + rgb1.b,
1776            a: (rgb2.a - rgb1.a) * p + rgb1.a,
1777        };
1778
1779        return tinycolor(rgba);
1780    };
1781
1782    // Readability Functions
1783    // ---------------------
1784    // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
1785
1786    // `contrast`
1787    // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
1788    tinycolor.readability = function (color1, color2) {
1789        var c1 = tinycolor(color1);
1790        var c2 = tinycolor(color2);
1791        return (
1792            (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) /
1793            (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05)
1794        );
1795    };
1796
1797    // `isReadable`
1798    // Ensure that foreground and background color combinations meet WCAG2 guidelines.
1799    // The third argument is an optional Object.
1800    //      the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
1801    //      the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
1802    // If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
1803
1804    // *Example*
1805    //    tinycolor.isReadable("#000", "#111") => false
1806    //    tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
1807    tinycolor.isReadable = function (color1, color2, wcag2) {
1808        var readability = tinycolor.readability(color1, color2);
1809        var wcag2Parms, out;
1810
1811        out = false;
1812
1813        wcag2Parms = validateWCAG2Parms(wcag2);
1814        switch (wcag2Parms.level + wcag2Parms.size) {
1815            case "AAsmall":
1816            case "AAAlarge":
1817                out = readability >= 4.5;
1818                break;
1819            case "AAlarge":
1820                out = readability >= 3;
1821                break;
1822            case "AAAsmall":
1823                out = readability >= 7;
1824                break;
1825        }
1826        return out;
1827    };
1828
1829    // `mostReadable`
1830    // Given a base color and a list of possible foreground or background
1831    // colors for that base, returns the most readable color.
1832    // Optionally returns Black or White if the most readable color is unreadable.
1833    // *Example*
1834    //    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
1835    //    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString();  // "#ffffff"
1836    //    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
1837    //    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
1838    tinycolor.mostReadable = function (baseColor, colorList, args) {
1839        var bestColor = null;
1840        var bestScore = 0;
1841        var readability;
1842        var includeFallbackColors, level, size;
1843        args = args || {};
1844        includeFallbackColors = args.includeFallbackColors;
1845        level = args.level;
1846        size = args.size;
1847
1848        for (var i = 0; i < colorList.length; i++) {
1849            readability = tinycolor.readability(baseColor, colorList[i]);
1850            if (readability > bestScore) {
1851                bestScore = readability;
1852                bestColor = tinycolor(colorList[i]);
1853            }
1854        }
1855
1856        if (
1857            tinycolor.isReadable(baseColor, bestColor, { level: level, size: size }) ||
1858            !includeFallbackColors
1859        ) {
1860            return bestColor;
1861        } else {
1862            args.includeFallbackColors = false;
vendor: 12,185 bytes, lines 1863-2236
1863            return tinycolor.mostReadable(baseColor, ["#fff", "#000"], args);
1864        }
1865    };
1866
1867    // Big List of Colors
1868    // ------------------
1869    // <http://www.w3.org/TR/css3-color/#svg-color>
1870    var names = (tinycolor.names = {
1871        aliceblue: "f0f8ff",
1872        antiquewhite: "faebd7",
1873        aqua: "0ff",
1874        aquamarine: "7fffd4",
1875        azure: "f0ffff",
1876        beige: "f5f5dc",
1877        bisque: "ffe4c4",
1878        black: "000",
1879        blanchedalmond: "ffebcd",
1880        blue: "00f",
1881        blueviolet: "8a2be2",
1882        brown: "a52a2a",
1883        burlywood: "deb887",
1884        burntsienna: "ea7e5d",
1885        cadetblue: "5f9ea0",
1886        chartreuse: "7fff00",
1887        chocolate: "d2691e",
1888        coral: "ff7f50",
1889        cornflowerblue: "6495ed",
1890        cornsilk: "fff8dc",
1891        crimson: "dc143c",
1892        cyan: "0ff",
1893        darkblue: "00008b",
1894        darkcyan: "008b8b",
1895        darkgoldenrod: "b8860b",
1896        darkgray: "a9a9a9",
1897        darkgreen: "006400",
1898        darkgrey: "a9a9a9",
1899        darkkhaki: "bdb76b",
1900        darkmagenta: "8b008b",
1901        darkolivegreen: "556b2f",
1902        darkorange: "ff8c00",
1903        darkorchid: "9932cc",
1904        darkred: "8b0000",
1905        darksalmon: "e9967a",
1906        darkseagreen: "8fbc8f",
1907        darkslateblue: "483d8b",
1908        darkslategray: "2f4f4f",
1909        darkslategrey: "2f4f4f",
1910        darkturquoise: "00ced1",
1911        darkviolet: "9400d3",
1912        deeppink: "ff1493",
1913        deepskyblue: "00bfff",
1914        dimgray: "696969",
1915        dimgrey: "696969",
1916        dodgerblue: "1e90ff",
1917        firebrick: "b22222",
1918        floralwhite: "fffaf0",
1919        forestgreen: "228b22",
1920        fuchsia: "f0f",
1921        gainsboro: "dcdcdc",
1922        ghostwhite: "f8f8ff",
1923        gold: "ffd700",
1924        goldenrod: "daa520",
1925        gray: "808080",
1926        green: "008000",
1927        greenyellow: "adff2f",
1928        grey: "808080",
1929        honeydew: "f0fff0",
1930        hotpink: "ff69b4",
1931        indianred: "cd5c5c",
1932        indigo: "4b0082",
1933        ivory: "fffff0",
1934        khaki: "f0e68c",
1935        lavender: "e6e6fa",
1936        lavenderblush: "fff0f5",
1937        lawngreen: "7cfc00",
1938        lemonchiffon: "fffacd",
1939        lightblue: "add8e6",
1940        lightcoral: "f08080",
1941        lightcyan: "e0ffff",
1942        lightgoldenrodyellow: "fafad2",
1943        lightgray: "d3d3d3",
1944        lightgreen: "90ee90",
1945        lightgrey: "d3d3d3",
1946        lightpink: "ffb6c1",
1947        lightsalmon: "ffa07a",
1948        lightseagreen: "20b2aa",
1949        lightskyblue: "87cefa",
1950        lightslategray: "789",
1951        lightslategrey: "789",
1952        lightsteelblue: "b0c4de",
1953        lightyellow: "ffffe0",
1954        lime: "0f0",
1955        limegreen: "32cd32",
1956        linen: "faf0e6",
1957        magenta: "f0f",
1958        maroon: "800000",
1959        mediumaquamarine: "66cdaa",
1960        mediumblue: "0000cd",
1961        mediumorchid: "ba55d3",
1962        mediumpurple: "9370db",
1963        mediumseagreen: "3cb371",
1964        mediumslateblue: "7b68ee",
1965        mediumspringgreen: "00fa9a",
1966        mediumturquoise: "48d1cc",
1967        mediumvioletred: "c71585",
1968        midnightblue: "191970",
1969        mintcream: "f5fffa",
1970        mistyrose: "ffe4e1",
1971        moccasin: "ffe4b5",
1972        navajowhite: "ffdead",
1973        navy: "000080",
1974        oldlace: "fdf5e6",
1975        olive: "808000",
1976        olivedrab: "6b8e23",
1977        orange: "ffa500",
1978        orangered: "ff4500",
1979        orchid: "da70d6",
1980        palegoldenrod: "eee8aa",
1981        palegreen: "98fb98",
1982        paleturquoise: "afeeee",
1983        palevioletred: "db7093",
1984        papayawhip: "ffefd5",
1985        peachpuff: "ffdab9",
1986        peru: "cd853f",
1987        pink: "ffc0cb",
1988        plum: "dda0dd",
1989        powderblue: "b0e0e6",
1990        purple: "800080",
1991        rebeccapurple: "663399",
1992        red: "f00",
1993        rosybrown: "bc8f8f",
1994        royalblue: "4169e1",
1995        saddlebrown: "8b4513",
1996        salmon: "fa8072",
1997        sandybrown: "f4a460",
1998        seagreen: "2e8b57",
1999        seashell: "fff5ee",
2000        sienna: "a0522d",
2001        silver: "c0c0c0",
2002        skyblue: "87ceeb",
2003        slateblue: "6a5acd",
2004        slategray: "708090",
2005        slategrey: "708090",
2006        snow: "fffafa",
2007        springgreen: "00ff7f",
2008        steelblue: "4682b4",
2009        tan: "d2b48c",
2010        teal: "008080",
2011        thistle: "d8bfd8",
2012        tomato: "ff6347",
2013        turquoise: "40e0d0",
2014        violet: "ee82ee",
2015        wheat: "f5deb3",
2016        white: "fff",
2017        whitesmoke: "f5f5f5",
2018        yellow: "ff0",
2019        yellowgreen: "9acd32",
2020    });
2021
2022    // Make it easy to access colors via `hexNames[hex]`
2023    var hexNames = (tinycolor.hexNames = flip(names));
2024
2025    // Utilities
2026    // ---------
2027
2028    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
2029    function flip(o) {
2030        var flipped = {};
2031        for (var i in o) {
2032            if (o.hasOwnProperty(i)) {
2033                flipped[o[i]] = i;
2034            }
2035        }
2036        return flipped;
2037    }
2038
2039    // Return a valid alpha value [0,1] with all invalid values being set to 1
2040    function boundAlpha(a) {
2041        a = parseFloat(a);
2042
2043        if (isNaN(a) || a < 0 || a > 1) {
2044            a = 1;
2045        }
2046
2047        return a;
2048    }
2049
2050    // Take input from [0, n] and return it as [0, 1]
2051    function bound01(n, max) {
2052        if (isOnePointZero(n)) {
2053            n = "100%";
2054        }
2055
2056        var processPercent = isPercentage(n);
2057        n = mathMin(max, mathMax(0, parseFloat(n)));
2058
2059        // Automatically convert percentage into number
2060        if (processPercent) {
2061            n = parseInt(n * max, 10) / 100;
2062        }
2063
2064        // Handle floating point rounding errors
2065        if (Math.abs(n - max) < 0.000001) {
2066            return 1;
2067        }
2068
2069        // Convert into [0, 1] range if it isn't already
2070        return (n % max) / parseFloat(max);
2071    }
2072
2073    // Force a number between 0 and 1
2074    function clamp01(val) {
2075        return mathMin(1, mathMax(0, val));
2076    }
2077
2078    // Parse a base-16 hex value into a base-10 integer
2079    function parseIntFromHex(val) {
2080        return parseInt(val, 16);
2081    }
2082
2083    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
2084    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
2085    function isOnePointZero(n) {
2086        return typeof n == "string" && n.indexOf(".") != -1 && parseFloat(n) === 1;
2087    }
2088
2089    // Check to see if string passed in is a percentage
2090    function isPercentage(n) {
2091        return typeof n === "string" && n.indexOf("%") != -1;
2092    }
2093
2094    // Force a hex value to have 2 characters
2095    function pad2(c) {
2096        return c.length == 1 ? "0" + c : "" + c;
2097    }
2098
2099    // Replace a decimal with it's percentage value
2100    function convertToPercentage(n) {
2101        if (n <= 1) {
2102            n = n * 100 + "%";
2103        }
2104
2105        return n;
2106    }
2107
2108    // Converts a decimal to a hex value
2109    function convertDecimalToHex(d) {
2110        return Math.round(parseFloat(d) * 255).toString(16);
2111    }
2112    // Converts a hex value to a decimal
2113    function convertHexToDecimal(h) {
2114        return parseIntFromHex(h) / 255;
2115    }
2116
2117    var matchers = (function () {
2118        // <http://www.w3.org/TR/css3-values/#integers>
2119        var CSS_INTEGER = "[-\\+]?\\d+%?";
2120
2121        // <http://www.w3.org/TR/css3-values/#number-value>
2122        var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2123
2124        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
2125        var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2126
2127        // Actual matching.
2128        // Parentheses and commas are optional, but not required.
2129        // Whitespace can take the place of commas or opening paren
2130        var PERMISSIVE_MATCH3 =
2131            "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2132        var PERMISSIVE_MATCH4 =
2133            "[\\s|\\(]+(" +
2134            CSS_UNIT +
2135            ")[,|\\s]+(" +
2136            CSS_UNIT +
2137            ")[,|\\s]+(" +
2138            CSS_UNIT +
2139            ")[,|\\s]+(" +
2140            CSS_UNIT +
2141            ")\\s*\\)?";
2142
2143        return {
2144            CSS_UNIT: new RegExp(CSS_UNIT),
2145            rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
2146            rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
2147            hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
2148            hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
2149            hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
2150            hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
2151            hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2152            hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2153            hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2154            hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2155        };
2156    })();
2157
2158    // `isValidCSSUnit`
2159    // Take in a single string / number and check to see if it looks like a CSS unit
2160    // (see `matchers` above for definition).
2161    function isValidCSSUnit(color) {
2162        return !!matchers.CSS_UNIT.exec(color);
2163    }
2164
2165    // `stringInputToObject`
2166    // Permissive string parsing.  Take in a number of formats, and output an object
2167    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2168    function stringInputToObject(color) {
2169        color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase();
2170        var named = false;
2171        if (names[color]) {
2172            color = names[color];
2173            named = true;
2174        } else if (color == "transparent") {
2175            return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2176        }
2177
2178        // Try to match string input using regular expressions.
2179        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2180        // Just return an object and let the conversion functions handle that.
2181        // This way the result will be the same whether the tinycolor is initialized with string or object.
2182        var match;
2183        if ((match = matchers.rgb.exec(color))) {
2184            return { r: match[1], g: match[2], b: match[3] };
2185        }
2186        if ((match = matchers.rgba.exec(color))) {
2187            return { r: match[1], g: match[2], b: match[3], a: match[4] };
2188        }
2189        if ((match = matchers.hsl.exec(color))) {
2190            return { h: match[1], s: match[2], l: match[3] };
2191        }
2192        if ((match = matchers.hsla.exec(color))) {
2193            return { h: match[1], s: match[2], l: match[3], a: match[4] };
2194        }
2195        if ((match = matchers.hsv.exec(color))) {
2196            return { h: match[1], s: match[2], v: match[3] };
2197        }
2198        if ((match = matchers.hsva.exec(color))) {
2199            return { h: match[1], s: match[2], v: match[3], a: match[4] };
2200        }
2201        if ((match = matchers.hex8.exec(color))) {
2202            return {
2203                r: parseIntFromHex(match[1]),
2204                g: parseIntFromHex(match[2]),
2205                b: parseIntFromHex(match[3]),
2206                a: convertHexToDecimal(match[4]),
2207                format: named ? "name" : "hex8",
2208            };
2209        }
2210        if ((match = matchers.hex6.exec(color))) {
2211            return {
2212                r: parseIntFromHex(match[1]),
2213                g: parseIntFromHex(match[2]),
2214                b: parseIntFromHex(match[3]),
2215                format: named ? "name" : "hex",
2216            };
2217        }
2218        if ((match = matchers.hex4.exec(color))) {
2219            return {
2220                r: parseIntFromHex(match[1] + "" + match[1]),
2221                g: parseIntFromHex(match[2] + "" + match[2]),
2222                b: parseIntFromHex(match[3] + "" + match[3]),
2223                a: convertHexToDecimal(match[4] + "" + match[4]),
2224                format: named ? "name" : "hex8",
2225            };
2226        }
2227        if ((match = matchers.hex3.exec(color))) {
2228            return {
2229                r: parseIntFromHex(match[1] + "" + match[1]),
2230                g: parseIntFromHex(match[2] + "" + match[2]),
2231                b: parseIntFromHex(match[3] + "" + match[3]),
2232                format: named ? "name" : "hex",
2233            };
2234        }
2235
2236        return false;
2237    }
2238
2239    function validateWCAG2Parms(parms) {
2240        // return valid WCAG2 parms for isReadable.
2241        // If input parms are invalid, return {"level":"AA", "size":"small"}
2242        var level, size;
2243        parms = parms || { level: "AA", size: "small" };
2244        level = (parms.level || "AA").toUpperCase();
2245        size = (parms.size || "small").toLowerCase();
2246        if (level !== "AA" && level !== "AAA") {
2247            level = "AA";
2248        }
2249        if (size !== "small" && size !== "large") {
2250            size = "small";
2251        }
2252        return { level: level, size: size };
2253    }
2254
2255    const $$1 = jQuery;
2256    class Server {
2257        constructor() {
2258            this.apiUrl = MapSVG.urls.api;
2259        }
2260        getUrl(path) {
2261            return this.apiUrl + path;
2262        }
2263        get(path, data) {
2264            return $$1.ajax({
2265                url: this.apiUrl + path,
2266                type: "GET",
2267                data: data,
2268                beforeSend: function (xhr) {
2269                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2270                },
2271            });
2272        }
2273        post(path, data) {
2274            const ajaxParams = {
2275                url: this.apiUrl + path,
2276                type: "POST",
2277                data: data,
2278                beforeSend: function (xhr) {
2279                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2280                },
2281            };
2282            if (data instanceof FormData) {
2283                ajaxParams["processData"] = false;
2284                ajaxParams["contentType"] = false;
2285            }
2286            return $$1.ajax(ajaxParams);
2287        }
2288        put(path, data) {
2289            const ajaxParams = {
2290                url: this.apiUrl + path,
2291                type: "POST",
2292                data: data,
2293                beforeSend: function (xhr) {
2294                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2295                    xhr.setRequestHeader("X-HTTP-Method-Override", "PUT");
2296                },
2297            };
2298            if (data instanceof FormData) {
2299                ajaxParams["processData"] = false;
2300                ajaxParams["contentType"] = false;
2301            }
2302            return $$1.ajax(ajaxParams);
2303        }
2304        delete(path, data) {
2305            return $$1.ajax({
2306                url: this.apiUrl + path,
2307                type: "POST",
2308                data: data,
2309                beforeSend: function (xhr) {
2310                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2311                    xhr.setRequestHeader("X-HTTP-Method-Override", "DELETE");
2312                },
2313            });
2314        }
2315        ajax(path, data) {
2316            data.url = this.getUrl(path);
2317            data.beforeSend = function (xhr) {
2318                xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2319            };
2320            return $$1.ajax(data);
2321        }
2322    }
2323
2324    class Events {
2325        constructor(context) {
2326            this.events = {};
2327            this.context = context;
2328        }
2329        on(event, callbackOrObjectType, callback) {
2330            if (!this.events[event])
2331                this.events[event] = [];
2332            let callbackFunction;
2333            if (typeof callbackOrObjectType === "string") {
2334                callbackFunction = callback;
2335            }
2336            else {
2337                callbackFunction = callbackOrObjectType;
2338            }
2339            this.events[event].push(callbackFunction);
2340            return this;
2341        }
2342        off(event, callback) {
2343            const _this = this;
2344            if (this.events[event] && this.events[event].length) {
2345                this.events[event].forEach(function (_callback, index) {
2346                    if (typeof callback === "undefined") {
2347                        _this.events[event].splice(index, 1);
2348                    }
2349                    else if (_callback === callback) {
2350                        _this.events[event].splice(index, 1);
2351                    }
2352                });
2353            }
2354            return this;
2355        }
2356        trigger(event, thisArg, args) {
2357            if (this.events[event] && this.events[event].length)
2358                this.events[event].forEach((callback) => {
2359                    try {
2360                        callback && callback.apply(thisArg || this.context, args || [this.context]);
2361                    }
2362                    catch (err) {
2363                        console.error(err);
2364                    }
2365                });
2366            return this;
2367        }
2368    }
2369
2370    class ArrayIndexed extends Array {
2371        constructor(indexKey, items, options) {
2372            if (items) {
2373                super(...items);
2374            }
2375            else {
2376                super();
2377            }
2378            this.key = indexKey;
2379            this.dict = {};
2380            this.nextId = 1;
2381            if (options) {
2382                this.options = options;
2383            }
2384            else {
2385                this.options = { autoId: false, unique: false };
2386            }
2387            if (this.length > 0) {
2388                let i = 0;
2389                const _this = this;
2390                if (this.options.autoId) {
2391                    let maxId = 0;
2392                    let missingIds = false;
2393                    this.forEach(function (item) {
2394                        if (item[_this.key] != null) {
2395                            if (item[_this.key] > maxId) {
2396                                maxId = item[_this.key];
2397                            }
2398                        }
2399                        else {
2400                            missingIds = true;
2401                        }
2402                    });
2403                    this.nextId = ++maxId;
2404                    if (missingIds) {
2405                        this.forEach(function (item) {
2406                            if (item[_this.key] == null) {
2407                                item[_this.key] = _this.nextId;
2408                                _this.nextId++;
2409                            }
2410                        });
2411                    }
2412                }
2413                this.forEach(function (item) {
2414                    _this.dict[item[_this.key]] = i;
2415                    i++;
2416                });
2417            }
2418        }
2419        push(item) {
2420            const length = super.push(item);
2421            if (this.options.autoId === true) {
2422                item[this.key] = this.nextId;
2423                this.nextId++;
2424            }
2425            this.dict[item[this.key]] = length - 1;
2426            return length;
2427        }
2428        pop() {
2429            const item = this[this.length - 1];
2430            const id = item[this.key];
2431            const length = super.pop();
2432            delete this.dict[id];
2433            this.reindex();
2434            return super.pop();
2435        }
2436        update(data) {
2437            if (data[this.key] != null) {
2438                const obj = this.get(data[this.key]);
2439                for (const i in data) {
2440                    obj[i] = data[i];
2441                }
2442                return obj;
2443            }
2444            return false;
2445        }
2446        get(id) {
2447            return this.findById(id);
2448        }
2449        findById(id) {
2450            return this[this.dict[id]];
2451        }
2452        deleteById(id) {
2453            const index = this.dict[id];
2454            if (typeof index !== "undefined") {
2455                delete this.dict[id];
2456                this.splice(index, 1);
2457            }
2458        }
2459        delete(id) {
2460            this.deleteById(id);
2461        }
2462        clear() {
2463            this.length = 0;
2464            this.reindex();
2465        }
2466        reindex() {
2467            const _this = this;
2468            this.dict = {};
2469            this.forEach(function (item, index) {
2470                _this.dict[item[_this.key]] = index;
2471            });
2472        }
2473        sort(compareFn) {
2474            super.sort(compareFn);
2475            this.reindex();
2476            return this;
2477        }
2478        splice(start, deleteCount) {
2479            const res = super.splice(start, deleteCount);
2480            this.reindex();
2481            return res;
2482        }
2483    }
2484
2485    class SchemaField {
2486        constructor(field) {
2487            const booleans = ["visible", "searchable", "readonly", "protected"];
2488            for (const key in field) {
2489                this[key] = field[key];
2490            }
2491            booleans.forEach((paramName) => {
2492                if (typeof this[paramName] !== "undefined") {
2493                    this[paramName] = MapSVG.parseBoolean(this[paramName]);
2494                }
2495                else {
2496                    this[paramName] = false;
2497                }
2498            });
2499            if (typeof this.options !== "undefined") {
2500                if (!(this.options instanceof ArrayIndexed)) {
2501                    this.options = new ArrayIndexed("value", this.options);
2502                }
2503            }
2504        }
2505    }
2506
2507    class Schema {
2508        constructor(options) {
2509            this.fields = new ArrayIndexed("name");
2510            this.build(options);
2511            this.lastChangeTime = Date.now();
2512            this.events = new Events(this);
2513        }
2514        build(options) {
2515            const allowedParams = ["id", "title", "type", "name", "fields"];
2516            allowedParams.forEach((paramName) => {
2517                const setter = "set" + MapSVG.ucfirst(paramName);
2518                if (typeof options[paramName] !== "undefined" && typeof this[setter] == "function") {
2519                    this[setter](options[paramName]);
2520                }
2521            });
2522        }
2523        update(options) {
2524            this.build(options);
2525        }
2526        setId(id) {
2527            this.id = id;
2528        }
2529        setTitle(title) {
2530            this.title = title;
2531        }
2532        setName(name) {
2533            this.name = name;
2534        }
2535        loaded() {
2536            return this.fields.length !== 0;
2537        }
2538        setFields(fields) {
2539            if (fields) {
2540                this.fields.clear();
2541                fields.forEach((fieldParams) => {
2542                    this.fields.push(new SchemaField(fieldParams));
2543                });
2544            }
2545        }
2546        getFields() {
2547            return this.fields;
2548        }
2549        getFieldsAsArray() {
2550            return this.fields;
2551        }
2552        getFieldNames() {
2553            return this.fields.map((f) => f.name);
2554        }
2555        getField(field) {
2556            return this.fields.findById(field);
2557        }
2558        getFieldByType(type) {
2559            let f = null;
2560            this.fields.forEach(function (field) {
2561                if (field.type === type)
2562                    f = field;
2563            });
2564            return f;
2565        }
2566        getColumns(filters) {
2567            filters = filters || {};
2568            const columns = this.fields;
2569            const needfilters = Object.keys(filters).length !== 0;
2570            let results = [];
2571            if (needfilters) {
2572                let filterpass;
2573                columns.forEach(function (obj) {
2574                    filterpass = true;
2575                    for (const param in filters) {
2576                        filterpass = obj[param] == filters[param];
2577                    }
2578                    filterpass && results.push(obj);
2579                });
2580            }
2581            else {
2582                results = columns;
2583            }
2584            return results;
2585        }
2586        getData() {
2587            const data = {
2588                id: this.id,
2589                title: this.title,
2590                name: this.name,
2591                fields: this.fields,
2592                type: this.type,
2593            };
2594            return data;
2595        }
2596    }
2597
2598    class Query {
2599        constructor(options) {
2600            this.filters = {};
2601            this.filterout = {};
2602            this.page = 1;
2603            if (options) {
2604                for (const i in options) {
2605                    if (typeof options[i] !== "undefined") {
2606                        this[i] = options[i];
2607                    }
2608                }
2609            }
2610        }
2611        setFields(fields) {
2612            const _this = this;
2613            for (const key in fields) {
2614                if (key == "filters") {
2615                    _this.setFilters(fields[key]);
2616                }
2617                else {
2618                    _this[key] = fields[key];
2619                }
2620            }
2621        }
2622        update(query) {
2623            for (const i in query) {
2624                if (typeof query[i] !== "undefined") {
2625                    if (i === "filters") {
2626                        this.setFilters(query[i]);
2627                    }
2628                    else {
2629                        this[i] = query[i];
2630                    }
2631                }
2632            }
2633        }
2634        get() {
2635            return {
2636                search: this.search,
2637                searchField: this.searchField,
2638                searchFallback: this.searchFallback,
2639                filters: this.filters,
2640                filterout: this.filterout,
2641                page: this.page,
2642                sort: this.sort,
2643                perpage: this.perpage,
2644                lastpage: this.lastpage,
2645            };
2646        }
2647        clearFilters() {
2648            this.resetFilters();
2649        }
2650        setFilters(fields) {
2651            const _this = this;
2652            for (const key in fields) {
2653                if (fields[key] === null || fields[key] === "" || fields[key] === undefined) {
2654                    if (_this.filters[key]) {
2655                        delete _this.filters[key];
2656                    }
2657                }
2658                else {
2659                    _this.filters[key] = fields[key];
2660                }
2661            }
2662        }
2663        setSearch(search) {
2664            this.search = search;
2665        }
2666        setFilterOut(fields) {
2667            this.filterout = fields;
2668        }
2669        resetFilters(fields) {
2670            this.filters = {};
2671            this.setSearch("");
2672        }
2673        setFilterField(field, value) {
2674            this.filters[field] = value;
2675        }
2676        hasFilters() {
2677            return Object.keys(this.filters).length > 0 || this.search.length > 0;
2678        }
2679        removeFilter(fieldName) {
2680            this.filters[fieldName] = null;
2681            delete this.filters[fieldName];
2682        }
2683        requestSchema(requestSchema) {
2684            this.withSchema = requestSchema ? requestSchema : true;
2685        }
2686    }
2687
2688    class LocationAddress {
2689        constructor(fields) {
2690            for (const i in fields) {
2691                this[i] = fields[i];
2692            }
2693        }
2694        getData() {
2695            const copy = {};
2696            [
2697                "route",
2698                "address_formatted",
2699                "administrative_area_level_1",
2700                "administrative_area_level_1_short",
2701                "administrative_area_level_2",
2702                "administrative_area_level_2_short",
2703                "country",
2704                "country_short",
2705                "postal_code",
2706            ].forEach((field) => {
2707                if (this[field]) {
2708                    copy[field] = this[field];
2709                }
2710            });
2711            return copy;
2712        }
2713        get state() {
2714            return this.country_short === "US" ? this.administrative_area_level_1 : null;
2715        }
2716        get state_short() {
2717            return this.country_short === "US" ? this.administrative_area_level_1_short : null;
2718        }
2719        get county() {
2720            return this.country_short === "US" ? this.administrative_area_level_2 : null;
2721        }
2722        get zip() {
2723            return this.postal_code;
2724        }
2725    }
2726
2727    class ScreenPoint {
2728        constructor(x, y) {
2729            this.x = x;
2730            this.y = y;
2731        }
2732    }
2733    class SVGPoint {
2734        constructor(x, y) {
2735            let _x, _y;
2736            if (typeof x === "object") {
2737                if (x.x && x.y) {
2738                    _x = parseFloat(x.x + "");
2739                    _y = parseFloat(x.y + "");
2740                }
2741                else {
2742                    console.error("MapSVG: incorrect format of {x, y} object for SVGPoint.");
2743                    _x = 0;
2744                    _y = 0;
2745                }
2746            }
2747            else {
2748                _x = parseFloat(x + "");
2749                _y = parseFloat(y + "");
2750            }
2751            this.x = _x;
2752            this.y = _y;
2753        }
2754        toString() {
2755            return this.x + "," + this.y;
2756        }
2757    }
2758    class GeoPoint {
2759        constructor(lat, lng) {
2760            let _lat, _lng;
2761            if (typeof lat === "object") {
2762                if (lat.lat && lat.lng) {
2763                    _lat = parseFloat(lat.lat + "");
2764                    _lng = parseFloat(lat.lng + "");
2765                }
2766                else {
2767                    console.error("MapSVG: incorrect format of {lat, lng} object for GeoPoint.");
2768                    _lat = 0;
2769                    _lng = 0;
2770                }
2771            }
2772            else {
2773                _lat = parseFloat(lat + "");
2774                _lng = parseFloat(lng + "");
2775            }
2776            this.lat = _lat;
2777            this.lng = _lng;
2778        }
2779        toString() {
2780            return this.lat + "," + this.lng;
2781        }
2782    }
2783    class Location {
2784        constructor(options) {
2785            this.update(options);
2786        }
2787        update(options) {
2788            if (options.object) {
2789                this.setObject(options.object);
2790            }
2791            if (options.img) {
2792                this.setImage(options.img);
2793            }
2794            if (options.address) {
2795                this.setAddress(options.address);
2796            }
2797            if (options.svgPoint) {
2798                this.setSvgPoint(options.svgPoint);
2799            }
2800            if (options.geoPoint) {
2801                this.setGeoPoint(options.geoPoint);
2802            }
2803        }
2804        setObject(object) {
2805            this.object = object;
2806        }
2807        setImage(imgUrl) {
2808            if (typeof imgUrl !== "string") {
2809                return;
2810            }
2811            let src = imgUrl.split("/").pop();
2812            if (imgUrl.indexOf("uploads") !== -1) {
2813                src = "uploads/" + src;
2814            }
2815            this.img = src;
2816            this.imagePath = this.getImageUrl();
2817            this.marker && this.marker && this.marker.setImage(this.imagePath);
2818        }
2819        getImageUrl() {
2820            if (this.img && this.img.indexOf("uploads/") === 0) {
2821                return MapSVG.urls.uploads + "markers/" + this.img.replace("uploads/", "");
2822            }
2823            else {
2824                return MapSVG.urls.root + "markers/" + (this.img || "_pin_default.png");
2825            }
2826        }
2827        setAddress(address) {
2828            this.address = new LocationAddress(address);
2829        }
2830        setSvgPoint(svgPoint) {
2831            this.svgPoint = svgPoint instanceof SVGPoint ? svgPoint : new SVGPoint(svgPoint);
2832            if (this.marker) {
2833                this.marker.setSvgPointFromLocation();
2834            }
2835        }
2836        setGeoPoint(geoPoint) {
2837            this.geoPoint = geoPoint instanceof GeoPoint ? geoPoint : new GeoPoint(geoPoint);
2838            if (this.marker) {
2839                this.marker.setSvgPointFromLocation();
2840            }
2841        }
2842        getMarkerImage() {
2843            if (this.img && this.img.indexOf("uploads/") === 0) {
2844                return MapSVG.urls.uploads + "markers/" + this.img.replace("uploads/", "");
2845            }
2846            else {
2847                return MapSVG.urls.root + "markers/" + (this.img || "_pin_default.png");
2848            }
2849        }
2850        getData() {
2851            const data = {
2852                img: this.img,
2853                imagePath: this.imagePath,
2854                markerImagePath: this.marker && this.marker.object
2855                    ? this.marker.object.getMarkerImage()
2856                    : this.imagePath,
2857                address: this.address,
2858            };
2859            if (this.geoPoint) {
2860                data.geoPoint = { lat: this.geoPoint.lat, lng: this.geoPoint.lng };
2861            }
2862            if (this.svgPoint) {
2863                data.svgPoint = { x: this.svgPoint.x, y: this.svgPoint.y };
2864            }
2865            return data;
2866        }
2867    }
2868
2869    class CustomObject {
2870        constructor(params, schema) {
2871            this.initialLoad = true;
2872            this.setSchema(schema);
2873            this.dirtyFields = [];
2874            this.regions = [];
2875            this._regions = {};
2876            if (params.id !== undefined) {
2877                this.id = params.id;
2878            }
2879            this.initialLoad = true;
2880            this.build(params);
2881            this.initialLoad = false;
2882            if (this.id) {
2883                this.clearDirtyFields();
2884            }
2885        }
2886        setSchema(schema) {
2887            this.schema = schema;
2888            this.schema.events.on("changed", () => this.setLocationField());
2889            this.fields = schema.getFieldNames();
2890            this.setLocationField();
2891        }
2892        build(params) {
2893            for (const fieldName in params) {
2894                const field = this.schema.getField(fieldName);
2895                if (field) {
2896                    if (!this.initialLoad) {
2897                        this.dirtyFields.push(fieldName);
2898                    }
2899                    switch (field.type) {
2900                        case "region":
2901                            this.regions = params[fieldName];
2902                            break;
2903                        case "location":
2904                            if (params[fieldName] != null &&
2905                                params[fieldName] != "" &&
2906                                Object.keys(params[fieldName]).length !== 0) {
2907                                const data = {
2908                                    img: this.isMarkersByFieldEnabled()
2909                                        ? this.getMarkerImage()
2910                                        : params[fieldName].img,
2911                                    address: new LocationAddress(params[fieldName].address),
2912                                };
2913                                if (params[fieldName].geoPoint &&
2914                                    params[fieldName].geoPoint.lat &&
2915                                    params[fieldName].geoPoint.lng) {
2916                                    data.geoPoint = new GeoPoint(params[fieldName].geoPoint);
2917                                }
2918                                else if (params[fieldName].svgPoint &&
2919                                    params[fieldName].svgPoint.x &&
2920                                    params[fieldName].svgPoint.y) {
2921                                    data.svgPoint = new SVGPoint(params[fieldName].svgPoint);
2922                                }
2923                                if (this.location != null) {
2924                                    this.location.update(data);
2925                                }
2926                                else {
2927                                    this.location = new Location(data);
2928                                }
2929                            }
2930                            else {
2931                                this.location = null;
2932                            }
2933                            break;
2934                        case "post":
2935                            if (params.post) {
2936                                this.post = params.post;
2937                            }
2938                            break;
2939                        case "select":
2940                            this[fieldName] = params[fieldName];
2941                            if (!field.multiselect) {
2942                                this[fieldName + "_text"] = this.getEnumLabel(field, params, fieldName);
2943                            }
2944                            break;
2945                        case "radio":
2946                            this[fieldName] = params[fieldName];
2947                            this[fieldName + "_text"] = this.getEnumLabel(field, params, fieldName);
2948                            break;
2949                        default:
2950                            this[fieldName] = params[fieldName];
2951                            break;
2952                    }
2953                }
2954            }
2955            const locationField = this.getLocationField();
2956            if (locationField && this.isMarkersByFieldEnabled() && this.isMarkerFieldChanged(params)) {
2957                this.reloadMarkerImage();
2958            }
2959        }
2960        isMarkerFieldChanged(params) {
2961            return Object.keys(params).indexOf(this.getLocationField().markerField) !== -1;
2962        }
2963        setLocationField() {
2964        }
2965        getLocationField() {
2966            return this.schema.getFieldByType("location");
2967        }
2968        reloadMarkerImage() {
2969            this.location && this.location.setImage(this.getMarkerImage());
2970        }
2971        getMarkerImage() {
2972            let fieldValue;
2973            if (this.isMarkersByFieldEnabled()) {
2974                const locationField = this.getLocationField();
2975                fieldValue = this[locationField.markerField];
2976                if (!fieldValue) {
2977                    return locationField.defaultMarkerPath || MapSVG.defaultMarkerImage;
2978                }
2979                else {
2980                    if (locationField.markerField === "regions") {
2981                        fieldValue = fieldValue[0] && fieldValue[0].id;
2982                    }
2983                    else if (typeof fieldValue === "object" && fieldValue.length) {
2984                        fieldValue = fieldValue[0].value;
2985                    }
2986                    return (locationField.markersByField[fieldValue] ||
2987                        locationField.defaultMarkerPath ||
2988                        MapSVG.defaultMarkerImage);
2989                }
2990            }
2991            else {
2992                return this.location.imagePath;
2993            }
2994        }
2995        isMarkersByFieldEnabled() {
2996            const locationField = this.getLocationField();
2997            if (!locationField) {
2998                return false;
2999            }
3000            if (locationField.markersByFieldEnabled &&
3001                locationField.markerField &&
3002                Object.values(locationField.markersByField).length > 0) {
3003                return true;
3004            }
3005            else {
3006                return false;
3007            }
3008        }
3009        clone() {
3010            const data = this.getData();
3011            return new CustomObject(data, this.schema);
3012        }
3013        getEnumLabel(field, params, fieldName) {
3014            const value = field.options.get(params[fieldName]);
3015            if (typeof value !== "undefined") {
3016                return value.label;
3017            }
3018            else {
3019                return "";
3020            }
3021        }
3022        update(params) {
3023            this.build(params);
3024        }
3025        getDirtyFields() {
3026            const data = {};
3027            this.dirtyFields.forEach((field) => {
3028                data[field] = this[field];
3029            });
3030            data.id = this.id;
3031            if (data.location != null) {
3032                data.location = data.location.getData();
3033            }
3034            if (this.schema.getFieldByType("region")) {
3035                data.regions = this.regions;
3036            }
3037            return data;
3038        }
3039        clearDirtyFields() {
3040            this.dirtyFields = [];
3041        }
3042        getData() {
3043            const data = {};
3044            const fields = this.schema.getFields();
3045            fields.forEach((field) => {
3046                switch (field.type) {
3047                    case "region":
3048                        data[field.name] = this[field.name];
3049                        break;
3050                    case "select":
3051                        data[field.name] = this[field.name];
3052                        if (!field.multiselect) {
3053                            data[field.name + "_text"] = this[field.name + "_text"];
3054                        }
3055                        break;
3056                    case "post":
3057                        data[field.name] = this[field.name];
3058                        data["post"] = this.post;
3059                        break;
3060                    case "status":
3061                    case "radio":
3062                        data[field.name] = this[field.name];
3063                        data[field.name + "_text"] = this[field.name + "_text"];
3064                        break;
3065                    case "location":
3066                        data[field.name] = this[field.name] ? this[field.name].getData() : null;
3067                        break;
3068                    default:
3069                        data[field.name] = this[field.name];
3070                        break;
3071                }
3072            });
3073            return data;
3074        }
3075        getRegions(regionsTableName) {
3076            return this.regions;
3077        }
3078        getRegionsForTable(regionsTableName) {
3079            return this.regions
3080                ? this.regions.filter((region) => !region.tableName || region.tableName === regionsTableName)
3081                : [];
3082        }
3083    }
3084
3085    const $$2 = jQuery;
3086    class Repository {
3087        constructor(objectName, path) {
3088            this.server = new Server();
3089            this.query = new Query();
3090            this.events = new Events(this);
3091            this.className = "";
3092            this.objectNameSingle = objectName;
3093            this.objectNameMany = objectName + "s";
3094            this.setPath(path);
3095            this.objects = new ArrayIndexed("id");
3096            this.completeChunks = 0;
3097        }
3098        setNoFiltersNoLoad(value) {
3099            this.noFiltersNoLoad = value;
3100        }
3101        setDataSource(path) {
3102            this.setPath(path);
3103            this.query = new Query({ withSchema: true });
3104            return this.find().done(() => {
3105                this.query.update({ withSchema: false });
3106            });
3107        }
3108        setPath(path) {
3109            this.path = path.replace(/\/+$/, "") + "/";
3110        }
3111        setSchema(schema) {
3112            this.schema = schema;
3113        }
3114        getSchema() {
3115            return this.schema;
3116        }
3117        loadDataFromResponse(response) {
3118            let data;
3119            data = this.decodeData(response);
3120            this.objects.clear();
3121            if (data[this.objectNameMany] && data[this.objectNameMany].length) {
3122                this.hasMoreRecords =
3123                    this.query.perpage && data[this.objectNameMany].length > this.query.perpage;
3124                if (this.hasMoreRecords) {
3125                    data[this.objectNameMany].pop();
3126                }
3127                data[this.objectNameMany].forEach((obj) => {
3128                    this.objects.push(obj);
3129                });
3130            }
3131            else {
3132                this.hasMoreRecords = false;
3133            }
3134            this.loaded = true;
3135            this.events.trigger("loaded");
3136        }
3137        reload() {
3138            return this.find();
3139        }
3140        create(object) {
3141            const defer = jQuery.Deferred();
3142            defer.promise();
3143            const data = {};
3144            data[this.objectNameSingle] = this.encodeData(object);
3145            this.server
3146                .post(this.path, data)
3147                .done((response) => {
3148                const data = this.decodeData(response);
3149                const object = data[this.objectNameSingle];
3150                this.objects.push(object);
3151                defer.resolve(object);
3152                this.events.trigger("created", this, [object]);
3153            })
3154                .fail((response) => {
3155                defer.reject(response);
3156            });
3157            return defer;
3158        }
3159        findById(id, nocache = false) {
3160            const defer = jQuery.Deferred();
3161            defer.promise();
3162            let object;
3163            if (!nocache) {
3164                object = this.objects.findById(id.toString());
3165            }
3166            if (!nocache && object) {
3167                defer.resolve(object);
3168            }
3169            else {
3170                this.server
3171                    .get(this.path + id)
3172                    .done((response) => {
3173                    const data = this.decodeData(response);
3174                    defer.resolve(data[this.objectNameSingle]);
3175                })
3176                    .fail((response) => {
3177                    defer.reject(response);
3178                });
3179            }
3180            return defer;
3181        }
3182        find(query) {
3183            this.events.trigger("load");
3184            const defer = jQuery.Deferred();
3185            defer.promise();
3186            if (typeof query !== "undefined") {
3187                this.query.update(query);
3188            }
3189            if (this.noFiltersNoLoad && !this.query.hasFilters()) {
3190                this.objects.clear();
3191                this.events.trigger("loaded");
3192                defer.resolve(this.getLoaded());
3193                return defer;
3194            }
3195            if (!this.schema) {
3196                this.query.update({ withSchema: true });
3197            }
3198            this.server
3199                .get(this.path, this.query)
3200                .done((response) => {
3201                if (!this.schema) {
3202                    this.query.update({ withSchema: false });
3203                }
3204                this.loadDataFromResponse(response);
3205                defer.resolve(this.getLoaded());
3206            })
3207                .fail((response) => {
3208                defer.reject(response);
3209            });
3210            return defer;
3211        }
3212        getLoaded() {
3213            return this.objects;
3214        }
3215        getLoadedObject(id) {
3216            return this.objects.findById(id.toString());
3217        }
3218        getLoadedAsArray() {
3219            return this.objects;
3220        }
3221        update(object) {
3222            const defer = jQuery.Deferred();
3223            defer.promise();
3224            const data = {};
3225            const objectUpdatedFields = "getDirtyFields" in object ? object.getDirtyFields() : object;
3226            data[this.objectNameSingle] = this.encodeData(objectUpdatedFields);
3227            this.server
3228                .put(this.path + objectUpdatedFields.id, data)
3229                .done((response) => {
3230                if ("clearDirtyFields" in object) {
3231                    object.clearDirtyFields();
3232                }
3233                defer.resolve(object);
3234                this.events.trigger("updated", this, object);
3235            })
3236                .fail((response, stat) => {
3237                defer.reject(response, stat);
3238            });
3239            return defer;
3240        }
3241        delete(id) {
3242            const defer = jQuery.Deferred();
3243            defer.promise();
3244            this.server
3245                .delete(this.path + id)
3246                .done((response) => {
3247                this.objects.delete(id.toString());
3248                this.events.trigger("deleted");
3249                defer.resolve();
3250            })
3251                .fail((response) => {
3252                defer.reject(response);
3253            });
3254            return defer;
3255        }
3256        clear() {
3257            const defer = jQuery.Deferred();
3258            defer.promise();
3259            this.server
3260                .delete(this.path)
3261                .done((response) => {
3262                this.objects.clear();
3263                this.events.trigger("loaded");
3264                this.events.trigger("cleared");
3265                defer.resolve();
3266            })
3267                .fail((response) => {
3268                defer.reject(response);
3269            });
3270            return defer;
3271        }
3272        onFirstPage() {
3273            return this.query.page === 1;
3274        }
3275        onLastPage() {
3276            return this.hasMoreRecords === false;
3277        }
3278        encodeData(params) {
3279            return params;
3280        }
3281        decodeData(dataJSON) {
3282            let data;
3283            if (typeof dataJSON === "string") {
3284                data = JSON.parse(dataJSON);
3285            }
3286            else {
3287                data = dataJSON;
3288            }
3289            if ((data.object || data.region || data.regions || data.objects) && data.schema) {
3290                this.setSchema(new Schema(data.schema));
3291            }
3292            const dataFormatted = {};
3293            for (const key in data) {
3294                if (data[key]) {
3295                    switch (key) {
3296                        case "object":
3297                        case "region":
3298                            dataFormatted[key] = new CustomObject(data[key], this.schema);
3299                            break;
3300                        case "objects":
3301                        case "regions":
3302                            dataFormatted[key] = data[key].map((obj) => new CustomObject(obj, this.schema));
3303                            break;
3304                        case "schema":
3305                            dataFormatted[key] = this.schema || new Schema(data[key]);
3306                            break;
3307                        case "schemas":
3308                            dataFormatted[key] = data[key].map((obj) => new Schema(obj));
3309                            break;
3310                    }
3311                }
3312            }
3313            return dataFormatted;
3314        }
3315        import(data, convertLatlngToAddress, mapsvg) {
3316            const _this = this;
3317            const locationField = _this.schema.getFieldByType("location");
3318            let language = "en";
3319            if (locationField && locationField.language) {
3320                language = locationField.language;
3321            }
3322            data = this.formatCSV(data, mapsvg);
3323            return this.importByChunks(data, language, convertLatlngToAddress).done(function () {
3324                _this.find();
3325            });
3326        }
3327        importByChunks(data, language, convertLatlngToAddress) {
3328            const _this = this;
3329            let i, j, temparray, chunk = 50;
3330            const chunks = [];
3331            for (i = 0, j = data.length; i < j; i += chunk) {
3332                temparray = data.slice(i, i + chunk);
3333                chunks.push(temparray);
3334            }
3335            if (chunks.length > 0) {
3336                let delay = 0;
3337                const delayPlus = chunks[0][0] && chunks[0][0].location ? 1000 : 0;
3338                var defer = $$2.Deferred();
3339                defer.promise();
3340                _this.completeChunks = 0;
3341                chunks.forEach(function (chunk) {
3342                    delay += delayPlus;
3343                    setTimeout(function () {
3344                        const data = {
3345                            language: language,
3346                            convertLatlngToAddress: convertLatlngToAddress,
3347                        };
3348                        data[_this.objectNameMany] = JSON.stringify(chunk);
3349                        _this.server
3350                            .post(_this.path + "import", data)
3351                            .done(function (_data) {
3352                            _this.completeChunk(chunks, defer);
3353                        })
3354                            .fail((response) => {
3355                            console.error(response);
3356                        });
3357                    }, delay);
3358                });
3359            }
3360            return defer;
3361        }
3362        completeChunk(chunks, defer) {
3363            const _this = this;
3364            _this.completeChunks++;
3365            if (_this.completeChunks === chunks.length) {
3366                defer.resolve();
3367            }
3368        }
3369        formatCSV(data, mapsvg) {
3370            const _this = this;
3371            const latLngRegex = /^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/g;
3372            const regionsTable = mapsvg.regionsRepository.getSchema().name;
3373            data.forEach(function (object, index) {
3374                const newObject = {};
3375                for (const key in object) {
3376                    let field = _this.schema.getField(key);
3377                    if (key === "post") {
3378                        field = { type: "post" };
3379                    }
3380                    if (field !== undefined) {
3381                        switch (field.type) {
3382                            case "region":
3383                                newObject[key] = {};
3384                                newObject[key] = object[key]
3385                                    .split(",")
3386                                    .map(function (regionId) {
3387                                    return regionId.trim();
3388                                })
3389                                    .filter(function (rId) {
3390                                    return (mapsvg.getRegion(rId) !== undefined ||
3391                                        mapsvg.regions.find(function (item) {
3392                                            return item.title === rId;
3393                                        }) !== undefined);
3394                                })
3395                                    .map(function (rId) {
3396                                    let r = mapsvg.getRegion(rId);
3397                                    if (typeof r === "undefined") {
3398                                        r = mapsvg.regions.find(function (item) {
3399                                            return item.title === rId;
3400                                        });
3401                                    }
3402                                    return { id: r.id, title: r.title, tableName: regionsTable };
3403                                });
3404                                break;
3405                            case "location":
3406                                if (object[key].match(latLngRegex)) {
3407                                    const coords = object[key].split(",").map(function (n) {
3408                                        return parseFloat(n);
3409                                    });
3410                                    if (coords.length == 2 &&
3411                                        coords[0] > -90 &&
3412                                        coords[0] < 90 &&
3413                                        coords[1] > -180 &&
3414                                        coords[1] < 180) {
3415                                        newObject[key] = {
3416                                            geoPoint: { lat: coords[0], lng: coords[1] },
3417                                        };
3418                                    }
3419                                    else {
3420                                        newObject[key] = "";
3421                                    }
3422                                }
3423                                else if (object[key]) {
3424                                    newObject[key] = { address: object[key] };
3425                                }
3426                                if (typeof newObject[key] == "object") {
3427                                    newObject[key].img = mapsvg.options.defaultMarkerImage;
3428                                }
3429                                break;
3430                            case "select":
3431                                const field = _this.schema.getField(key);
3432                                if (field.multiselect) {
3433                                    const labels = _this.schema.getField(key).options.map(function (f) {
3434                                        return f.label;
3435                                    });
3436                                    newObject[key] = object[key]
3437                                        .split(",")
3438                                        .map(function (label) {
3439                                        return label.trim();
3440                                    })
3441                                        .filter(function (label) {
3442                                        return labels.indexOf(label) !== -1;
3443                                    })
3444                                        .map(function (label) {
3445                                        return _this.schema
3446                                            .getField(key)
3447                                            .options.filter(function (option) {
3448                                            return option.label == label;
3449                                        })[0];
3450                                    });
3451                                    if (newObject[key].length === 0) {
3452                                        const values = _this.schema
3453                                            .getField(key)
3454                                            .options.map(function (f) {
3455                                            return f.value + "";
3456                                        });
3457                                        newObject[key] = object[key]
3458                                            .split(",")
3459                                            .map(function (value) {
3460                                            return value.trim();
3461                                        })
3462                                            .filter(function (value) {
3463                                            return values.indexOf(value) !== -1;
3464                                        })
3465                                            .map(function (value) {
3466                                            return _this.schema
3467                                                .getField(key)
3468                                                .options.filter(function (option) {
3469                                                return option.value == value;
3470                                            })[0];
3471                                        });
3472                                    }
3473                                }
3474                                else {
3475                                    newObject[key] = object[key];
3476                                }
3477                                break;
3478                            case "radio":
3479                            case "text":
3480                            case "textarea":
3481                            case "status":
3482                            default:
3483                                newObject[key] = object[key];
3484                                break;
3485                        }
3486                    }
3487                }
3488                data[index] = newObject;
3489            });
3490            return data;
3491        }
3492    }
3493
3494    class MapsRepository extends Repository {
3495        constructor() {
3496            super("map", "maps");
3497            this.path = "maps/";
3498        }
3499        encodeData(params) {
3500            const data = {};
3501            if (typeof params.options !== "undefined") {
3502                data.options = JSON.stringify(params.options);
3503                data.options = data.options.replace(/select/g, "!mapsvg-encoded-slct");
3504                data.options = data.options.replace(/table/g, "!mapsvg-encoded-tbl");
3505                data.options = data.options.replace(/database/g, "!mapsvg-encoded-db");
3506                data.options = data.options.replace(/varchar/g, "!mapsvg-encoded-vc");
3507                data.options = data.options.replace(/int\(11\)/g, "!mapsvg-encoded-int");
3508            }
3509            if (typeof params.title !== "undefined") {
3510                data.title = params.title;
3511            }
3512            if (typeof params.id !== "undefined") {
3513                data.id = params.id;
3514            }
3515            if (typeof params.status !== "undefined") {
3516                data.status = params.status;
3517            }
3518            return data;
3519        }
3520        decodeData(dataJSON) {
3521            let data;
3522            if (typeof dataJSON === "string") {
3523                data = JSON.parse(dataJSON);
3524            }
3525            else {
3526                data = dataJSON;
3527            }
3528            return data;
3529        }
3530        copy(id, title) {
3531            const defer = jQuery.Deferred();
3532            defer.promise();
3533            const data = { options: { title: title } };
3534            this.server
3535                .post(this.path + id + "/copy", this.encodeData(data))
3536                .done((response) => {
3537                const data = this.decodeData(response);
3538                this.objects.clear();
3539                this.events.trigger("loaded");
3540                this.events.trigger("cleared");
3541                defer.resolve(data.map);
3542            })
3543                .fail(() => {
3544                defer.reject();
3545            });
3546            return defer;
3547        }
3548        createFromV2(object) {
3549            const defer = jQuery.Deferred();
3550            defer.promise();
3551            const data = {};
3552            data[this.objectNameSingle] = this.encodeData(object);
3553            this.server
3554                .post(this.path + "/createFromV2", data)
3555                .done((response) => {
3556                const data = this.decodeData(response);
3557                const object = data[this.objectNameSingle];
3558                this.objects.push(object);
3559                defer.resolve(object);
3560                this.events.trigger("created", this, [object]);
3561            })
3562                .fail(() => {
3563                defer.reject();
3564            });
3565            return defer;
3566        }
3567        delete(id) {
3568            const defer = jQuery.Deferred();
3569            defer.promise();
3570            this.server
3571                .delete(this.path + id)
3572                .done((response) => {
3573                this.objects.delete(id.toString());
3574                this.events.trigger("deleted");
3575                defer.resolve();
3576            })
3577                .fail(() => {
3578                defer.reject();
3579            });
3580            return defer;
3581        }
3582    }
3583
3584    class MapsV2Repository extends Repository {
3585        constructor() {
3586            super("map", "maps");
3587            this.path = "maps-v2/";
3588        }
3589        encodeData(params) {
3590            const data = {};
3591            data.options = JSON.stringify(params.options);
3592            data.options = data.options.replace(/select/g, "!mapsvg-encoded-slct");
3593            data.options = data.options.replace(/table/g, "!mapsvg-encoded-tbl");
3594            data.options = data.options.replace(/database/g, "!mapsvg-encoded-db");
3595            data.options = data.options.replace(/varchar/g, "!mapsvg-encoded-vc");
3596            data.id = params.id;
3597            data.title = params.title;
3598            return data;
3599        }
3600        decodeData(dataJSON) {
3601            let data;
3602            if (typeof dataJSON === "string") {
3603                data = JSON.parse(dataJSON);
3604            }
3605            else {
3606                data = dataJSON;
3607            }
3608            return data;
3609        }
3610    }
3611
3612    class Converter {
3613        constructor(mapElement, defViewBox, viewBox, geoViewBox) {
3614            this.mapElement = mapElement;
3615            this.defViewBox = defViewBox;
3616            this.viewBox = viewBox;
3617            this.yShift = 0;
3618            if (geoViewBox) {
3619                this.setGeoViewBox(geoViewBox);
3620            }
3621        }
3622        setYShift() {
3623            if (this.defViewBox.width === 20426) {
3624                this.yShift = 0;
3625                return;
3626            }
3627            if (this.geoViewBox) {
3628                const topLeftPoint = this.convertGeoToSVG(this.geoViewBox.ne);
3629                this.yShift = topLeftPoint.y - this.defViewBox.y;
3630            }
3631        }
3632        setGeoViewBox(geoViewBox) {
3633            this.geoViewBox = geoViewBox;
3634            this.mapLonDelta = this.geoViewBox.ne.lng - this.geoViewBox.sw.lng;
3635            this.mapLatBottomDegree = (this.geoViewBox.sw.lat * Math.PI) / 180;
3636            this.worldMapWidth = (this.defViewBox.width / this.mapLonDelta) * 360;
3637            this.worldMapRadius = ((this.defViewBox.width / this.mapLonDelta) * 360) / (2 * Math.PI);
3638            this.setYShift();
3639        }
3640        setWorldShift(on) {
3641            this.worldShift = on;
3642        }
3643        getScale() {
3644            return this.mapElement.clientWidth / this.viewBox.width;
3645        }
3646        convertSVGToPixel(svgPoint) {
3647            const scale = this.getScale();
3648            let shiftXByGM = 0;
3649            const shiftYByGM = 0;
3650            if (this.worldShift) {
3651                if (this.viewBox.x - this.defViewBox.x > this.defViewBox.width) {
3652                    shiftXByGM =
3653                        this.worldMapWidth *
3654                            Math.floor((this.viewBox.x - this.defViewBox.x) / this.defViewBox.width);
3655                }
3656            }
3657            return new ScreenPoint((svgPoint.x - this.viewBox.x + shiftXByGM) * scale, (svgPoint.y - this.viewBox.y + shiftYByGM) * scale);
3658        }
3659        convertPixelToSVG(screenPoint) {
3660            const scale = this.getScale();
3661            return new SVGPoint(screenPoint.x / scale + this.viewBox.x, screenPoint.y / scale + this.viewBox.y);
3662        }
3663        convertGeoToSVG(geoPoint) {
3664            if (!this.geoViewBox) {
3665                throw new Error("Can't do convertGeoToSVG() - geoViewBox is not provided.");
3666            }
3667            let x = (geoPoint.lng - this.geoViewBox.sw.lng) * (this.defViewBox.width / this.mapLonDelta);
3668            const lat = (geoPoint.lat * Math.PI) / 180;
3669            const mapOffsetY = (this.worldMapRadius / 2) *
3670                Math.log((1 + Math.sin(this.mapLatBottomDegree)) / (1 - Math.sin(this.mapLatBottomDegree)));
3671            let y = this.defViewBox.height -
3672                ((this.worldMapRadius / 2) * Math.log((1 + Math.sin(lat)) / (1 - Math.sin(lat))) -
3673                    mapOffsetY);
3674            x += this.defViewBox.x;
3675            y += this.defViewBox.y;
3676            y -= this.yShift;
3677            return new SVGPoint(x, y);
3678        }
3679        convertSVGToGeo(svgPoint) {
3680            if (!this.geoViewBox) {
3681                throw new Error("Can't do convertSVGToGeo() - geoViewBox is not provided.");
3682            }
3683            const tx = svgPoint.x - this.defViewBox.x;
3684            const ty = svgPoint.y - this.defViewBox.y;
3685            const mapOffsetY = (this.worldMapRadius / 2) *
3686                Math.log((1 + Math.sin(this.mapLatBottomDegree)) / (1 - Math.sin(this.mapLatBottomDegree)));
3687            const equatorY = this.defViewBox.height + mapOffsetY;
3688            const a = (equatorY - ty) / this.worldMapRadius;
3689            let lat = (180 / Math.PI) * (2 * Math.atan(Math.exp(a)) - Math.PI / 2);
3690            let lng = this.geoViewBox.sw.lng + (tx / this.defViewBox.width) * this.mapLonDelta;
3691            lat = parseFloat(lat.toFixed(6));
3692            lng = parseFloat(lng.toFixed(6));
3693            return new GeoPoint(lat, lng);
3694        }
3695    }
3696
3697    const $$3 = jQuery;
3698    class ResizeSensor {
3699        constructor(element, callback) {
3700            const _this = this;
3701            _this.element = element;
3702            _this.callback = callback;
3703            const style = getComputedStyle(element);
3704            let zIndex = parseInt(style.zIndex);
3705            if (isNaN(zIndex)) {
3706                zIndex = 0;
3707            }
3708            zIndex--;
3709            _this.expand = document.createElement("div");
3710            _this.expand.style.position = "absolute";
3711            _this.expand.style.left = "0px";
3712            _this.expand.style.top = "0px";
3713            _this.expand.style.right = "0px";
3714            _this.expand.style.bottom = "0px";
3715            _this.expand.style.overflow = "hidden";
3716            _this.expand.style.zIndex = zIndex.toString();
3717            _this.expand.style.visibility = "hidden";
3718            const expandChild = document.createElement("div");
3719            expandChild.style.position = "absolute";
3720            expandChild.style.left = "0px";
3721            expandChild.style.top = "0px";
3722            expandChild.style.width = "10000000px";
3723            expandChild.style.height = "10000000px";
3724            _this.expand.appendChild(expandChild);
3725            _this.shrink = document.createElement("div");
3726            _this.shrink.style.position = "absolute";
3727            _this.shrink.style.left = "0px";
3728            _this.shrink.style.top = "0px";
3729            _this.shrink.style.right = "0px";
3730            _this.shrink.style.bottom = "0px";
3731            _this.shrink.style.overflow = "hidden";
3732            _this.shrink.style.zIndex = zIndex.toString();
3733            _this.shrink.style.visibility = "hidden";
3734            const shrinkChild = document.createElement("div");
3735            shrinkChild.style.position = "absolute";
3736            shrinkChild.style.left = "0px";
3737            shrinkChild.style.top = "0px";
3738            shrinkChild.style.width = "200%";
3739            shrinkChild.style.height = "200%";
3740            _this.shrink.appendChild(shrinkChild);
3741            _this.element.appendChild(_this.expand);
3742            _this.element.appendChild(_this.shrink);
3743            const size = element.getBoundingClientRect();
3744            _this.currentWidth = size.width;
3745            _this.currentHeight = size.height;
3746            _this.setScroll();
3747            _this.expand.addEventListener("scroll", function () {
3748                _this.onScroll();
3749            });
3750            _this.shrink.addEventListener("scroll", function () {
3751                _this.onScroll();
3752            });
3753        }
3754        onScroll() {
3755            const _this = this;
3756            const size = _this.element.getBoundingClientRect();
3757            const newWidth = size.width;
3758            const newHeight = size.height;
3759            if (newWidth != _this.currentWidth || newHeight != _this.currentHeight) {
3760                _this.currentWidth = newWidth;
3761                _this.currentHeight = newHeight;
3762                _this.callback();
3763            }
3764            this.setScroll();
3765        }
3766        setScroll() {
3767            this.expand.scrollLeft = 10000000;
3768            this.expand.scrollTop = 10000000;
3769            this.shrink.scrollLeft = 10000000;
3770            this.shrink.scrollTop = 10000000;
3771        }
3772        destroy() {
3773            this.expand.remove();
3774            this.shrink.remove();
3775        }
3776    }
3777
3778    class ViewBox {
3779        constructor(x, y, width, height) {
3780            if (typeof x === "object") {
3781                if (x.hasOwnProperty("x") &&
3782                    x.hasOwnProperty("y") &&
3783                    x.hasOwnProperty("width") &&
3784                    x.hasOwnProperty("height")) {
3785                    this.x = typeof x.x === "string" ? parseFloat(x.x) : x.x;
3786                    this.y = typeof x.y === "string" ? parseFloat(x.y) : x.y;
3787                    this.width = typeof x.width === "string" ? parseFloat(x.width) : x.width;
3788                    this.height = typeof x.height === "string" ? parseFloat(x.height) : x.height;
3789                }
3790                else if (typeof x === "object" && x.length && x.length === 4) {
3791                    this.x = typeof x[0] === "string" ? parseFloat(x[0]) : x[0];
3792                    this.y = typeof x[1] === "string" ? parseFloat(x[1]) : x[1];
3793                    this.width = typeof x[2] === "string" ? parseFloat(x[2]) : x[2];
3794                    this.height = typeof x[3] === "string" ? parseFloat(x[3]) : x[3];
3795                }
3796            }
3797            else {
3798                this.x = typeof x === "string" ? parseFloat(x) : x;
3799                this.y = typeof y === "string" ? parseFloat(y) : y;
3800                this.width = typeof width === "string" ? parseFloat(width) : width;
3801                this.height = typeof height === "string" ? parseFloat(height) : height;
3802            }
3803        }
3804        update(newViewBox) {
3805            this.x = newViewBox.x;
3806            this.y = newViewBox.y;
3807            this.width = newViewBox.width;
3808            this.height = newViewBox.height;
3809        }
3810        toString() {
3811            return this.x + " " + this.y + " " + this.width + " " + this.height;
3812        }
3813        toArray() {
3814            return [this.x, this.y, this.width, this.height];
3815        }
3816        clone() {
3817            return new ViewBox({ x: this.x, y: this.y, width: this.width, height: this.height });
3818        }
3819        fitsInViewBox(viewBox, atLeastByOneDimension) {
3820            if (atLeastByOneDimension === true) {
3821                return viewBox.width >
3821 this.width || viewBox.height > this.height;
3822            }
3823            else {
3824                return viewBox.width > this.width && viewBox.height > this.height;
3825            }
3826        }
3827        addPadding(padding) {
3828            if (padding.top) {
3829                this.y -= padding.top;
3830                this.height += padding.top;
3831            }
3832            if (padding.right) {
3833                this.width += padding.right;
3834            }
3835            if (padding.bottom) {
3836                this.height += padding.bottom;
3837            }
3838            if (padding.left) {
3839                this.x -= padding.left;
3840                this.width += padding.left;
3841            }
3842        }
3843    }
3844    class GeoViewBox {
3845        constructor(sw, ne) {
3846            this.sw = sw;
3847            this.ne = ne;
3848        }
3849    }
3850
3851    const $$4 = jQuery;
3852    class MapObject {
3853        constructor(element, mapsvg) {
3854            this.id = "";
3855            this.objects = [];
3856            this.events = new Events(this);
3857            this.element = element;
3858            this.mapsvg = mapsvg;
3859        }
3860        getBBox() {
3861            return new ViewBox(1, 2, 3, 4);
3862        }
3863        getGeoBounds() {
3864            const bbox = this.getBBox();
3865            const pointSW = new SVGPoint(bbox.x, bbox.y + bbox.height);
3866            const pointNE = new SVGPoint(bbox.x + bbox.width, bbox.y);
3867            const sw = this.mapsvg.converter.convertSVGToGeo(pointSW);
3868            const ne = this.mapsvg.converter.convertSVGToGeo(pointNE);
3869            return { sw: sw, ne: ne };
3870        }
3871        getComputedStyle(prop, elem) {
3872            elem = elem || this.element;
3873            return MapObject.getComputedStyle(prop, elem);
3874        }
3875        static getComputedStyle(prop, elem) {
3876            const _p1 = elem.getAttribute(prop);
3877            if (_p1) {
3878                return _p1;
3879            }
3880            const _p2 = elem.getAttribute("style");
3881            if (_p2) {
3882                const s = _p2.split(";");
3883                const z = s.filter(function (e) {
3884                    e = e.trim();
3885                    const attr = e.split(":");
3886                    if (attr[0] == prop)
3887                        return true;
3888                });
3889                if (z.length) {
3890                    return z[0].split(":").pop().trim();
3891                }
3892            }
3893            const parent = elem.parentElement;
3894            const elemType = parent ? parent.tagName : null;
3895            if (elemType && elemType != "svg")
3896                return MapObject.getComputedStyle(prop, parent);
3897            else
3898                return undefined;
3899        }
3900        getStyle(prop) {
3901            const _p1 = this.attr(prop);
3902            if (_p1) {
3903                return _p1;
3904            }
3905            const _p2 = this.attr("style");
3906            if (_p2) {
3907                const s = _p2.split(";");
3908                const z = s.filter(function (e) {
3909                    var e = e.trim();
3910                    if (e.indexOf(prop) === 0)
3911                        return e;
3912                });
3913                return z.length ? z[0].split(":").pop().trim() : undefined;
3914            }
3915            return "";
3916        }
3917        getCenter() {
3918            const x = this.element.getBoundingClientRect().left;
3919            const y = this.element.getBoundingClientRect().top;
3920            const w = this.element.getBoundingClientRect().width;
3921            const h = this.element.getBoundingClientRect().height;
3922            const point = new ScreenPoint(x + w / 2, y + h / 2);
3923            return point;
3924        }
3925        getCenterSVG() {
3926            const bbox = this.getBBox();
3927            const point = new SVGPoint(bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
3928            return point;
3929        }
3930        getCenterLatLng(yShift) {
3931            yShift = yShift ? yShift : 0;
3932            const bbox = this.getBBox();
3933            const x = bbox.x + bbox.width / 2;
3934            const y = bbox.y + bbox.height / 2 - yShift;
3935            const point = new SVGPoint(x, y);
3936            return this.mapsvg.converter.convertSVGToGeo(point);
3937        }
3938        attr(v1, v2 = null) {
3939            const svgDom = this.element;
3940            if (typeof v1 == "object") {
3941                for (const key in v1) {
3942                    const item = v1[key];
3943                    if (typeof item === "string" || typeof item === "number") {
3944                        svgDom.setAttribute(key, "" + item);
3945                    }
3946                }
3947            }
3948            else if (typeof v1 == "string" && (typeof v2 == "string" || typeof v2 == "number")) {
3949                svgDom.setAttribute(v1, "" + v2);
3950            }
3951            else if (v2 == undefined) {
3952                return svgDom.getAttribute(v1);
3953            }
3954        }
3955        setId(id) {
3956            if (id !== undefined) {
3957                this.id = id;
3958                this.element.setAttribute("id", id);
3959            }
3960        }
3961    }
3962
3963    const $$5 = jQuery;
3964    class Marker extends MapObject {
3965        constructor(params) {
3966            super(null, params.mapsvg);
3967            this.element = $$5("<div />").addClass("mapsvg-marker")[0];
3968            this.image = $$5('<img src="" />').addClass("mapsvg-marker-image")[0];
3969            if (params.object) {
3970                this.setObject(params.object);
3971            }
3972            if (!(params.location instanceof Location)) {
3973                throw new Error("MapSVG.Marker: no Location provided for Marker initializaton");
3974            }
3975            else {
3976                this.location = params.location;
3977                this.location.marker = this;
3978            }
3979            this.setImage(this.location.imagePath);
3980            $$5(this.element).append(this.image);
3981            if (params.width && params.height) {
3982                this.setSize(params.width, params.height);
3983            }
3984            else {
3985                this.setSize(15, 24);
3986            }
3987            this.setId(this.mapsvg.markerId());
3988            this.setSvgPointFromLocation();
3989            this.setAltAttr();
3990        }
3991        reload() {
3992            this.setImage();
3993            this.setSvgPointFromLocation();
3994        }
3995        getImagePath() {
3996            return (this.object && this.object.getMarkerImage()) || this.location.getMarkerImage();
3997        }
3998        setSize(width, height) {
3999            this.width = width;
4000            this.height = height;
4001            this.setCentered(this.width === this.height);
4002        }
4003        setSvgPointFromLocation() {
4004            const svgPoint = this.location.geoPoint &&
4005                this.location.geoPoint.lat !== 0 &&
4006                this.location.geoPoint.lng !== 0
4007                ? this.mapsvg.converter.convertGeoToSVG(this.location.geoPoint)
4008                : this.location.svgPoint;
4009            if (svgPoint) {
4010                this.setSvgPoint(svgPoint);
4011            }
4012        }
4013        setId(id) {
4014            MapObject.prototype.setId.call(this, id);
4015            this.mapsvg.markers.reindex();
4016        }
4017        getBBox() {
4018            if (this.centered) {
4019                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);
4020            }
4021            else {
4022                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);
4023            }
4024        }
4025        getOptions() {
4026            const o = {
4027                id: this.id,
4028                src: this.src,
4029                svgPoint: this.svgPoint,
4030                geoPoint: this.geoPoint,
4031            };
4032            $$5.each(o, function (key, val) {
4033                if (val == undefined) {
4034                    delete o[key];
4035                }
4036            });
4037            return o;
4038        }
4039        update(data) {
4040            for (const key in data) {
4041                const setter = "set" + MapSVG.ucfirst(key);
4042                if (setter in this)
4043                    this[setter](data[key]);
4044            }
4045        }
4046        setImage(src, skipChangingLocationImage = false) {
4047            if (!src) {
4048                src = this.getImagePath();
4049            }
4050            this.src = MapSVG.safeURL(src);
4051            const img = new Image();
4052            const marker = this;
4053            img.onload = function () {
4054                if (marker.image.getAttribute("src") !== "src") {
4055                    marker.image.setAttribute("src", marker.src);
4056                }
4057                marker.setSize(this.width, this.height);
4058                marker.adjustScreenPosition();
4059            };
4060            img.src = this.src;
4061            this.events.trigger("change");
4062        }
4063        setAltAttr() {
4064            const marker = this;
4065            marker.altAttr =
4066                typeof marker.object != "undefined" &&
4067                    typeof marker.object.title != "undefined" &&
4068                    marker.object.title !== ""
4069                    ? marker.object.title
4070                    : marker.id;
4071            marker.element.setAttribute("alt", marker.altAttr);
4072        }
4073        setSvgPoint(svgPoint) {
4074            this.svgPoint = svgPoint;
4075            this.adjustScreenPosition();
4076            this.events.trigger("change");
4077        }
4078        adjustScreenPosition() {
4079            const pos = this.mapsvg.converter.convertSVGToPixel(this.svgPoint);
4080            pos.x -= this.width / 2;
4081            pos.y -= !this.centered ? this.height : this.height / 2;
4082            this.setScreenPosition(pos.x, pos.y);
4083        }
4084        moveSrceenPositionBy(deltaX, deltaY) {
4085            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
4086            this.setScreenPosition(x, y);
4087        }
4088        setScreenPosition(x, y) {
4089            if (this.screenPoint instanceof ScreenPoint) {
4090                this.screenPoint.x = x;
4091                this.screenPoint.y = y;
4092            }
4093            else {
4094                this.screenPoint = new ScreenPoint(x, y);
4095            }
4096            this.updateVisibility();
4097            if (this.visible === true) {
4098                this.element.style.transform = "translate(" + x + "px," + y + "px)";
4099                this.adjustLabelScreenPosition();
4100            }
4101        }
4102        adjustLabelScreenPosition() {
4103            if (this.label) {
4104                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());
4105            }
4106        }
4107        inViewBox() {
4108            const x = this.screenPoint.x, y = this.screenPoint.y, mapFullWidth = this.mapsvg.containers.map.offsetWidth, mapFullHeight = this.mapsvg.containers.map.offsetHeight;
4109            return (x - this.width / 2 < 2 * mapFullWidth &&
4110                x + this.width / 2 > -mapFullWidth &&
4111                y - this.height / 2 < 2 * mapFullHeight &&
4112                y + this.height / 2 > -mapFullHeight);
4113        }
4114        updateVisibility() {
4115            if (this.inViewBox() === true) {
4116                this.visible = true;
4117                this.element.classList.remove("mapsvg-out-of-sight");
4118                if (this.label) {
4119                    this.label.classList.remove("mapsvg-out-of-sight");
4120                }
4121            }
4122            else {
4123                this.visible = false;
4124                this.element.classList.add("mapsvg-out-of-sight");
4125                if (this.label) {
4126                    this.label.classList.add("mapsvg-out-of-sight");
4127                }
4128            }
4129            return this.visible;
4130        }
4131        isMoving() {
4132            return this.moving;
4133        }
4134        setMoving(value) {
4135            this.moving = value;
4136        }
4137        drag(startCoords, scale, endCallback, clickCallback) {
4138            const _this = this;
4139            this.svgPointBeforeDrag = new SVGPoint(this.svgPoint.x, this.svgPoint.y);
4140            this.setMoving(true);
4141            $$5("body").on("mousemove.drag.mapsvg", function (e) {
4142                e.preventDefault();
4143                $$5(_this.mapsvg.containers.map).addClass("no-transitions");
4144                const mouseNew = MapSVG.mouseCoords(e);
4145                const dx = mouseNew.x - startCoords.x;
4146                const dy = mouseNew.y - startCoords.y;
4147                const newSvgPoint = new SVGPoint(_this.svgPointBeforeDrag.x + dx / scale, _this.svgPointBeforeDrag.y + dy / scale);
4148                _this.setSvgPoint(newSvgPoint);
4149            });
4150            $$5("body").on("mouseup.drag.mapsvg", function (e) {
4151                e.preventDefault();
4152                _this.undrag();
4153                const mouseNew = MapSVG.mouseCoords(e);
4154                const dx = mouseNew.x - startCoords.x;
4155                const dy = mouseNew.y - startCoords.y;
4156                const newSvgPoint = new SVGPoint(_this.svgPointBeforeDrag.x + dx / scale, _this.svgPointBeforeDrag.y + dy / scale);
4157                _this.setSvgPoint(newSvgPoint);
4158                if (_this.mapsvg.isGeo()) {
4159                    _this.geoPoint = _this.mapsvg.converter.convertSVGToGeo(newSvgPoint);
4160                }
4161                endCallback && endCallback.call(_this);
4162                if (_this.svgPointBeforeDrag.x == _this.svgPoint.x &&
4163                    _this.svgPointBeforeDrag.y == _this.svgPoint.y)
4164                    clickCallback && clickCallback.call(_this);
4165            });
4166        }
4167        undrag() {
4168            this.setMoving(false);
4169            $$5("body").off(".drag.mapsvg");
4170            $$5(this.mapsvg.containers.map).removeClass("no-transitions");
4171        }
4172        delete() {
4173            if (this.label) {
4174                this.label.remove();
4175                this.label = null;
4176            }
4177            $$5(this.element).empty().remove();
4178        }
4179        setObject(obj) {
4180            this.object = obj;
4181            $$5(this.element).attr("data-object-id", this.object.id);
4182        }
4183        hide() {
4184            $$5(this.element).addClass("mapsvg-marker-hidden");
4185            if (this.label) {
4186                $$5(this.label).hide();
4187            }
4188        }
4189        show() {
4190            $$5(this.element).removeClass("mapsvg-marker-hidden");
4191            if (this.label) {
4192                $$5(this.label).show();
4193            }
4194        }
4195        highlight() {
4196            $$5(this.element).addClass("mapsvg-marker-hover");
4197        }
4198        unhighlight() {
4199            $$5(this.element).removeClass("mapsvg-marker-hover");
4200        }
4201        select() {
4202            this.selected = true;
4203            $$5(this.element).addClass("mapsvg-marker-active");
4204        }
4205        deselect() {
4206            this.selected = false;
4207            $$5(this.element).removeClass("mapsvg-marker-active");
4208        }
4209        getData() {
4210            return this.object;
4211        }
4212        getChoroplethColor() {
4213            const markerValue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
4214            let color;
4215            if (!markerValue) {
4216                color = this.mapsvg.options.choropleth.coloring.noData.color;
4217            }
4218            else if (this.mapsvg.options.choropleth.coloring.mode === "gradient") {
4219                const gradient = this.mapsvg.options.choropleth.coloring.gradient, w = gradient.values.maxAdjusted === 0
4220                    ? 0
4221                    : (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);
4222                color = "rgba(" + r + "," + g + "," + b + "," + a + ")";
4223            }
4224            else {
4225                const paletteColors = this.mapsvg.options.choropleth.coloring.palette.colors;
4226                if (!paletteColors[0].valueFrom && markerValue < paletteColors[0].valueTo) {
4227                    color = paletteColors[0].color;
4228                }
4229                else if (!paletteColors[paletteColors.length - 1].valueTo &&
4230                    markerValue > paletteColors[paletteColors.length - 1].valueFrom) {
4231                    color = paletteColors[paletteColors.length - 1].color;
4232                }
4233                else {
4234                    paletteColors.forEach(function (paletteColor) {
4235                        if (markerValue >= paletteColor.valueFrom &&
4236                            markerValue < paletteColor.valueTo) {
4237                            color = paletteColor.color;
4238                        }
4239                    });
4240                    color = color
4241                        ? color
4242                        : this.mapsvg.options.choropleth.coloring.palette.outOfRange.color;
4243                }
4244            }
4245            return color;
4246        }
4247        getBubbleSize() {
4248            let bubbleSize;
4249            if (this.object[this.mapsvg.options.choropleth.sourceField]) {
4250                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]);
4251                bubbleSize =
4252                    ((sourceFieldvalue - minSourceFieldvalue) /
4253                        (maxSourceFieldvalue - minSourceFieldvalue)) *
4254                        (maxBubbleSize - minBubbleSize) +
4255                        Number(minBubbleSize);
4256            }
4257            else {
4258                bubbleSize = false;
4259            }
4260            return bubbleSize;
4261        }
4262        getBubbleScreenPosition() {
4263            const bubbleSize = Number(this.getBubbleSize());
4264            return {
4265                x: this.width / 2 - bubbleSize / 2,
4266                y: this.height - bubbleSize / 2,
4267            };
4268        }
4269        drawBubble() {
4270            const bubbleId = "mapsvg-bubble-" + this.object.id;
4271            const bubbleValue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
4272            if (bubbleValue) {
4273                if (!this.bubble) {
4274                    this.bubble = $$5('<div id="' +
4275                        bubbleId +
4276                        '" data-marker-id="' +
4277                        this.element.id +
4278                        '" class="mapsvg-bubble mapsvg-marker-bubble"></div>')[0];
4279                    $$5(this.element).append(this.bubble);
4280                }
4281                const color = this.getChoroplethColor(), bubbleSize = Number(this.getBubbleSize());
4282                $$5(this.bubble)
4283                    .css("background-color", color)
4284                    .css("width", bubbleSize + "px")
4285                    .css("height", bubbleSize + "px")
4286                    .css("lineHeight", bubbleSize - 2 + "px");
4287            }
4288            else {
4289                $$5("#" + bubbleId).remove();
4290                delete this.bubble;
4291            }
4292        }
4293        setBubbleMode(bubbleMode) {
4294            this.bubbleMode = bubbleMode;
4295            if (bubbleMode) {
4296                this.setCentered(true);
4297                this.drawBubble();
4298                if (this.bubble) {
4299                    this.width = this.bubble.offsetWidth;
4300                    this.height = this.bubble.offsetHeight;
4301                    this.adjustScreenPosition();
4302                }
4303            }
4304            else {
4305                this.setImage(this.src);
4306            }
4307        }
4308        setLabel(html) {
4309            if (html) {
4310                if (!this.label) {
4311                    this.label = $$5("<div />").addClass("mapsvg-marker-label")[0];
4312                    $$5(this.element).append(this.label);
4313                }
4314                $$5(this.label).html(html);
4315            }
4316            else {
4317                if (this.label) {
4318                    $$5(this.label).remove();
4319                    delete this.label;
4320                }
4321            }
4322        }
4323        setCentered(on) {
4324            this.centered = on;
4325        }
4326    }
4327
4328    const $$6 = jQuery;
4329    class MarkerCluster extends MapObject {
4330        constructor(options, mapsvg) {
4331            super(null, mapsvg);
4332            this.svgPoint = options.svgPoint;
4333            this.cellX = options.cellX;
4334            this.cellY = options.cellY;
4335            this.markers = options.markers || [];
4336            this.cellSize = 50;
4337            this.width = 30;
4338            this.elem = $$6('<div class="mapsvg-marker-cluster">' + this.markers.length + "</div>")[0];
4339            $$6(this.elem).data("cluster", this);
4340            if (this.markers.length < 2) {
4341                $$6(this.elem).hide();
4342            }
4343            this.adjustScreenPosition();
4344        }
4345        addMarker(marker) {
4346            this.markers.push(marker);
4347            if (this.markers.length > 1) {
4348                if (this.markers.length === 2) {
4349                    $$6(this.elem).show();
4350                }
4351                if (this.markers.length === 2) {
4352                    const x = this.markers.map(function (m) {
4353                        return m.svgPoint.x;
4354                    });
4355                    this.min_x = Math.min.apply(null, x);
4356                    this.max_x = Math.max.apply(null, x);
4357                    const y = this.markers.map(function (m) {
4358                        return m.svgPoint.y;
4359                    });
4360                    this.min_y = Math.min.apply(null, y);
4361                    this.max_y = Math.max.apply(null, y);
4362                    this.svgPoint.x = this.min_x + (this.max_x - this.min_x) / 2;
4363                    this.svgPoint.y = this.min_y + (this.max_y - this.min_y) / 2;
4364                }
4365                if (this.markers.length > 2) {
4366                    if (marker.svgPoint.x < this.min_x) {
4367                        this.min_x = marker.svgPoint.x;
4368                    }
4369                    else if (marker.svgPoint.x > this.max_x) {
4370                        this.max_x = marker.svgPoint.x;
4371                    }
4372                    if (marker.svgPoint.y < this.min_y) {
4373                        this.min_y = marker.svgPoint.y;
4374                    }
4375                    else if (marker.svgPoint.x > this.max_x) {
4376                        this.max_y = marker.svgPoint.y;
4377                    }
4378                    this.svgPoint.x = this.min_x + (this.max_x - this.min_x) / 2;
4379                    this.svgPoint.y = this.min_y + (this.max_y - this.min_y) / 2;
4380                }
4381            }
4382            else {
4383                this.svgPoint.x = marker.svgPoint.x;
4384                this.svgPoint.y = marker.svgPoint.y;
4385            }
4386            $$6(this.elem).text(this.markers.length);
4387            this.adjustScreenPosition();
4388        }
4389        canTakeMarker(marker) {
4390            const _this = this;
4391            const screenPoint = _this.mapsvg.converter.convertSVGToPixel(marker.svgPoint);
4392            return (this.cellX === Math.ceil(screenPoint.x / this.cellSize) &&
4393                this.cellY === Math.ceil(screenPoint.y / this.cellSize));
4394        }
4395        destroy() {
4396            this.markers = null;
4397            $$6(this.elem).remove();
4398        }
4399        adjustScreenPosition() {
4400            const pos = this.mapsvg.converter.convertSVGToPixel(this.svgPoint);
4401            pos.x -= this.width / 2;
4402            pos.y -= this.width / 2;
4403            this.setScreenPosition(pos.x, pos.y);
4404        }
4405        moveSrceenPositionBy(deltaX, deltaY) {
4406            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
4407            this.setScreenPosition(x, y);
4408        }
4409        setScreenPosition(x, y) {
4410            if (this.screenPoint instanceof ScreenPoint) {
4411                this.screenPoint.x = x;
4412                this.screenPoint.y = y;
4413            }
4414            else {
4415                this.screenPoint = new ScreenPoint(x, y);
4416            }
4417            this.updateVisibility();
4418            if (this.visible === true) {
4419                this.elem.style.transform = "translate(" + x + "px," + y + "px)";
4420            }
4421        }
4422        inViewBox() {
4423            const x = this.screenPoint.x, y = this.screenPoint.y, mapFullWidth = this.mapsvg.containers.map.offsetWidth, mapFullHeight = this.mapsvg.containers.map.offsetHeight;
4424            return (x - this.width / 2 < mapFullWidth &&
4425                x + this.width / 2 > 0 &&
4426                y - this.width / 2 < mapFullHeight &&
4427                y + this.width / 2 > 0);
4428        }
4429        updateVisibility() {
4430            if (this.inViewBox() === true) {
4431                this.visible = true;
4432                this.elem.classList.remove("mapsvg-out-of-sight");
4433            }
4434            else {
4435                this.visible = false;
4436                this.elem.classList.add("mapsvg-out-of-sight");
4437            }
4438            return this.visible;
4439        }
4440        getBBox() {
4441            let bbox = {
4442                x: this.svgPoint.x,
4443                y: this.svgPoint.y,
4444                width: this.cellSize / this.mapsvg.getScale(),
4445                height: this.cellSize / this.mapsvg.getScale(),
4446            };
4447            bbox = $$6.extend(true, {}, bbox);
4448            return new ViewBox(bbox.x, bbox.y, bbox.width, bbox.height);
4449        }
4450        getData() {
4451            return this.markers.map((m) => m.object);
4452        }
4453    }
4454
4455    const $$7 = jQuery;
4456    class Region extends MapObject {
4457        constructor(element, mapsvg) {
4458            super(element, mapsvg);
4459            this.id = this.element.getAttribute("id");
4460            if (this.id && this.mapsvg.options.regionPrefix) {
4461                this.setId(this.id.replace(this.mapsvg.options.regionPrefix, ""));
4462            }
4463            this.id_no_spaces = this.id.replace(/\s/g, "_");
4464            this.element.setAttribute("class", (this.element.className || "") + " mapsvg-region");
4465            this.setStyleInitial();
4466            const regionOptions = this.mapsvg.options.regions && this.mapsvg.options.regions[this.id]
4467                ? this.mapsvg.options.regions[this.id]
4468                : null;
4469            this.disabled = this.getDisabledState();
4470            this.disabled && this.attr("class", this.attr("class") + " mapsvg-disabled");
4471            this.default_attr = {};
4472            this.selected_attr = {};
4473            this.hover_attr = {};
4474            let selected = false;
4475            if (regionOptions && regionOptions.selected) {
4476                selected = true;
4477                delete regionOptions.selected;
4478            }
4479            regionOptions && this.update(regionOptions);
4480            this.setFill();
4481            if (selected) {
4482                this.setSelected();
4483            }
4484            this.saveState();
4485        }
4486        adjustStroke(scale) {
4487            $$7(this.element).css({ "stroke-width": this.style["stroke-width"] / scale });
4488        }
4489        setStyleInitial() {
4490            this.style = { fill: this.getComputedStyle("fill") };
4491            this.style.stroke = this.getComputedStyle("stroke") || "";
4492            let w;
4493            w = this.getComputedStyle("stroke-width");
4494            w = w ? w.replace("px", "") : "1";
4495            w = parseFloat(w);
4496            this.style["stroke-width"] = w;
4497            $$7(this.element).attr("data-stroke-width", w);
4498        }
4499        saveState() {
4500            this.initialState = JSON.stringify(this.getOptions());
4501        }
4502        getBBox() {
4503            const _bbox = this.element.getBBox();
4504            const bbox = new ViewBox(_bbox.x, _bbox.y, _bbox.width, _bbox.height);
4505            const matrix = this.element.getTransformToElement(this.mapsvg.containers.svg);
4506            if (!matrix) {
4507                return _bbox;
4508            }
4509            const x2 = bbox.x + bbox.width;
4510            const y2 = bbox.y + bbox.height;
4511            let position = this.mapsvg.containers.svg.createSVGPoint();
4512            position.x = bbox.x;
4513            position.y = bbox.y;
4514            position = position.matrixTransform(matrix);
4515            bbox.x = position.x;
4516            bbox.y = position.y;
4517            position.x = x2;
4518            position.y = y2;
4519            position = position.matrixTransform(matrix);
4520            bbox.width = position.x - bbox.x;
4521            bbox.height = position.y - bbox.y;
4522            return bbox;
4523        }
4524        changed() {
4525            return JSON.stringify(this.getOptions()) != this.initialState;
4526        }
4527        edit() {
4528            this.elemOriginal = $$7(this.element).clone()[0];
4529        }
4530        editCommit() {
4531            this.elemOriginal = null;
4532        }
4533        editCancel() {
4534            this.mapsvg.containers.svg.appendChild(this.elemOriginal);
4535            this.element = this.elemOriginal;
4536            this.elemOriginal = null;
4537        }
4538        getOptions(forTemplate) {
4539            let o;
4540            o = {
4541                id: this.id,
4542                id_no_spaces: this.id_no_spaces,
4543                title: this.title,
4544                fill: this.mapsvg.options.regions[this.id] && this.mapsvg.options.regions[this.id].fill,
4545                data: this.data,
4546                choroplethValue: this.choroplethValue,
4547            };
4548            if (forTemplate) {
4549                o.disabled = this.disabled;
4550            }
4551            for (const key in o) {
4552                if (typeof o[key] === "undefined") {
4553                    delete o[key];
4554                }
4555            }
4556            if (this.customAttrs) {
4557                const that = this;
4558                this.customAttrs.forEach(function (attr) {
4559                    o[attr] = that[attr];
4560                });
4561            }
4562            return o;
4563        }
4564        forTemplate() {
4565            const data = {
4566                id: this.id,
4567                title: this.title,
4568                objects: this.objects,
4569                data: this.data,
4570            };
4571            if (this.data) {
4572                for (const key in this.data) {
4573                    if (key != "title" && key != "id")
4574                        data[key] = this.data[key];
4575                }
4576            }
4577            return data;
4578        }
4579        getData() {
4580            return this.forTemplate();
4581        }
4582        update(options) {
4583            for (const key in options) {
4584                const setter = "set" + MapSVG.ucfirst(key);
4585                if (setter in this)
4586                    this[setter](options[key]);
4587                else {
4588                    this[key] = options[key];
4589                    this.customAttrs = this.customAttrs || [];
4590                    this.customAttrs.push(key);
4591                }
4592            }
4593        }
4594        setTitle(title) {
4595            if (title) {
4596                this.title = title;
4597            }
4598            this.element.setAttribute("title", this.title);
4599        }
4600        setStyle(style) {
4601            $$7.extend(true, this.style, style);
4602            this.setFill();
4603        }
4604        getChoroplethColor() {
4605            const o = this.mapsvg.options.choropleth;
4606            let color = "";
4607            if (this.data &&
4608                (this.data[this.mapsvg.options.regionChoroplethField] ||
4609                    this.data[this.mapsvg.options.regionChoroplethField] === 0)) {
4610                const w = o.maxAdjusted === 0
4611                    ? 0
4612                    : (parseFloat(this.data[this.mapsvg.options.regionChoroplethField]) - o.min) /
4613                        o.maxAdjusted;
4614                const c = {
4615                    r: Math.round(o.colors.diffRGB.r * w + o.colors.lowRGB.r),
4616                    g: Math.round(o.colors.diffRGB.g * w + o.colors.lowRGB.g),
4617                    b: Math.round(o.colors.diffRGB.b * w + o.colors.lowRGB.b),
4618                    a: (o.colors.diffRGB.a * w + o.colors.lowRGB.a).toFixed(2),
4619                };
4620                color = "rgba(" + c.r + "," + c.g + "," + c.b + "," + c.a + ")";
4621            }
4622            else {
4623                color = o.colors.noData;
4624            }
4625            return color;
4626        }
4627        _new_getChoroplethColor() {
4628            let regionValue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]), color;
4629            if (!regionValue) {
4630                color = this.mapsvg.options.choropleth.coloring.noData.color;
4631            }
4632            else if (this.mapsvg.options.choropleth.coloring.mode === "gradient") {
4633                const gradient = this.mapsvg.options.choropleth.coloring.gradient, w = gradient.values.maxAdjusted === 0
4634                    ? 0
4635                    : (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);
4636                color = "rgba(" + r + "," + g + "," + b + "," + a + ")";
4637            }
4638            else {
4639                const paletteColors = this.mapsvg.options.choropleth.coloring.palette.colors;
4640                if (!paletteColors[0].valueFrom && regionValue < paletteColors[0].valueTo) {
4641                    color = paletteColors[0].color;
4642                }
4643                else if (!paletteColors[paletteColors.length - 1].valueTo &&
4644                    regionValue > paletteColors[paletteColors.length - 1].valueFrom) {
4645                    color = paletteColors[paletteColors.length - 1].color;
4646                }
4647                else {
4648                    paletteColors.forEach(function (paletteColor) {
4649                        if (regionValue >= paletteColor.valueFrom &&
4650                            regionValue < paletteColor.valueTo) {
4651                            color = paletteColor.color;
4652                        }
4653                    });
4654                    color = color
4655                        ? color
4656                        : this.mapsvg.options.choropleth.coloring.palette.outOfRange.color;
4657                }
4658            }
4659            return color;
4660        }
4661        getBubbleSize() {
4662            let bubbleSize;
4663            if (this.data[this.mapsvg.options.choropleth.sourceField]) {
4664                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]);
4665                bubbleSize =
4666                    ((sourceFieldvalue - minSourceFieldvalue) /
4667                        (maxSourceFieldvalue - minSourceFieldvalue)) *
4668                        (maxBubbleSize - minBubbleSize) +
4669                        minBubbleSize;
4670            }
4671            else {
4672                bubbleSize = false;
4673            }
4674            return bubbleSize;
4675        }
4676        setFill(fill) {
4677            if (this.mapsvg.options.colorsIgnore) {
4678                $$7(this.element).css(this.style);
4679                return;
4680            }
4681            if (fill) {
4682                const regions = {};
4683                regions[this.id] = { fill: fill };
4684                $$7.extend(true, this.mapsvg.options, { regions: regions });
4685            }
4686            else if (!fill &&
4687                fill !== undefined &&
4688                this.mapsvg.options.regions &&
4689                this.mapsvg.options.regions[this.id] &&
4690                this.mapsvg.options.regions[this.id].fill) {
4691                delete this.mapsvg.options.regions[this.id].fill;
4692            }
4693            if (this.mapsvg.options.choropleth.on) {
4694                this.default_attr["fill"] = this.getChoroplethColor();
4695            }
4696            else if (this.status !== undefined &&
4697                this.mapsvg.regions &&
4698                this.mapsvg.regionsRepository.getSchema().getFieldByType("status") &&
4699                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict &&
4700                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict[this.status] &&
4701                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict[this.status].color) {
4702                this.default_attr["fill"] = this.mapsvg.regionsRepository
4703                    .getSchema()
4704                    .getFieldByType("status").optionsDict[this.status].color;
4705            }
4706            else if (this.mapsvg.options.regions[this.id] &&
4707                this.mapsvg.options.regions[this.id].fill) {
4708                this.default_attr["fill"] = this.mapsvg.options.regions[this.id].fill;
4709            }
4710            else if (this.mapsvg.options.colors.base) {
4711                this.default_attr["fill"] = this.mapsvg.options.colors.base;
4712            }
4713            else if (this.style.fill != "none") {
4714                this.default_attr["fill"] = this.style.fill
4715                    ? this.style.fill
4716                    : this.mapsvg.options.colors.baseDefault;
4717            }
4718            else {
4719                this.default_attr["fill"] = "none";
4720            }
4721            if (MapSVG.isNumber(this.mapsvg.options.colors.selected))
4722                this.selected_attr["fill"] = tinycolor(this.default_attr.fill)
4723                    .lighten(parseFloat("" + this.mapsvg.options.colors.selected))
4724                    .toRgbString();
4725            else
4726                this.selected_attr["fill"] = this.mapsvg.options.colors.selected;
4727            if (MapSVG.isNumber(this.mapsvg.options.colors.hover))
4728                this.hover_attr["fill"] = tinycolor(this.default_attr.fill)
4729                    .lighten(parseFloat("" + this.mapsvg.options.colors.hover))
4730                    .toRgbString();
4731            else
4732                this.hover_attr["fill"] = this.mapsvg.options.colors.hover;
4733            $$7(this.element).css("fill", this.default_attr["fill"]);
4734            this.fill = this.default_attr["fill"];
4735            if (this.style.stroke != "none" && this.mapsvg.options.colors.stroke != undefined) {
4736                $$7(this.element).css("stroke", this.mapsvg.options.colors.stroke);
4737            }
4738            else {
4739                const s = this.style.stroke == undefined ? "" : this.style.stroke;
4740                $$7(this.element).css("stroke", s);
4741            }
4742            if (this.selected)
4743                this.setSelected();
4744        }
4745        setDisabled(on, skipSetFill) {
4746            on = on !== undefined ? MapSVG.parseBoolean(on) : this.getDisabledState();
4747            const prevDisabled = this.disabled;
4748            this.disabled = on;
4749            this.attr("class", this.attr("class").replace("mapsvg-disabled", ""));
4750            if (on) {
4751                this.attr("class", this.attr("class") + " mapsvg-disabled");
4752            }
4753            if (this.disabled != prevDisabled)
4754                this.mapsvg.deselectRegion(this);
4755            !skipSetFill && this.setFill();
4756        }
4757        setStatus(status) {
4758            const statusOptions = this.mapsvg.options.regionStatuses && this.mapsvg.options.regionStatuses[status];
4759            if (statusOptions) {
4760                this.status = status;
4761                if (this.data) {
4762                    this.data.status = status;
4763                    this.data.status_text = statusOptions.label;
4764                }
4765                this.setDisabled(statusOptions.disabled, true);
4766            }
4767            else {
4768                this.status = undefined;
4769                if (this.data) {
4770                    this.data.status = undefined;
4771                    this.data.status_text = undefined;
4772                }
4773                this.setDisabled(false, true);
4774            }
4775            this.setFill();
4776        }
4777        setSelected() {
4778            this.mapsvg.selectRegion(this);
4779        }
4780        setchoroplethValue(val) {
4781            if ($$7.isNumeric(val)) {
4782                if (typeof val === "string") {
4783                    val = parseFloat(val);
4784                }
4785                this.choroplethValue = val;
4786            }
4787            else {
4788                this.choroplethValue = undefined;
4789            }
4790        }
4791        getDisabledState(asDefault) {
4792            const opts = this.mapsvg.options.regions[this.id];
4793            if (!asDefault && opts && opts.disabled !== undefined) {
4794                return opts.disabled;
4795            }
4796            else {
4797                return (this.mapsvg.options.disableAll ||
4798                    this.style.fill === "none" ||
4799                    this.id == "labels" ||
4800                    this.id == "Labels");
4801            }
4802        }
4803        highlight() {
4804            $$7(this.element).css({ fill: this.hover_attr.fill });
4805            $$7(this.element).addClass("mapsvg-region-hover");
4806        }
4807        unhighlight() {
4808            $$7(this.element).css({ fill: this.default_attr.fill });
4809            $$7(this.element).removeClass("mapsvg-region-hover");
4810        }
4811        select() {
4812            $$7(this.element).css({ fill: this.selected_attr.fill });
4813            this.selected = true;
4814            $$7(this.element).addClass("mapsvg-region-active");
4815        }
4816        deselect() {
4817            $$7(this.element).css({ fill: this.default_attr.fill });
4818            this.selected = false;
4819            $$7(this.element).removeClass("mapsvg-region-active");
4820        }
4821        setData(data) {
4822            this.data = data;
4823            if (typeof data.title !== "undefined") {
4824                this.setTitle(data.title);
4825            }
4826        }
4827        drawBubble() {
4828            if (this.data) {
4829                const bubbleId = "mapsvg-bubble-" + this.id;
4830                const bubbleValue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]);
4831                if (bubbleValue) {
4832                    if (!this.center) {
4833                        this.center = this.getCenterSVG();
4834                    }
4835                    const pos = this.mapsvg.converter.convertSVGToPixel(this.center);
4836                    if (!this.bubble) {
4837                        this.bubble = $$7('<div id="' +
4838                            bubbleId +
4839                            '" class="mapsvg-bubble mapsvg-region-bubble"></div>')[0];
4840                        $$7(this.mapsvg.layers.bubbles).append(this.bubble);
4841                    }
4842                    const color = this.getChoroplethColor();
4843                    const bubbleSize = Number(this.getBubbleSize());
4844                    $$7(this.bubble)
4845                        .css("transform", "translate(-50%,-50%) translate(" + pos.x + "px," + pos.y + "px)")
4846                        .css("background-color", color)
4847                        .css("width", bubbleSize + "px")
4848                        .css("height", bubbleSize + "px")
4849                        .css("lineHeight", bubbleSize - 2 + "px");
4850                }
4851                else {
4852                    delete this.bubble;
4853                }
4854            }
4855        }
4856        adjustLabelScreenPosition() {
4857            if (this.label) {
4858                if (!this.center) {
4859                    this.center = this.getCenterSVG();
4860                }
4861                const pos = this.mapsvg.converter.convertSVGToPixel(this.center), x = pos.x - this.label.offsetWidth / 2, y = pos.y - this.label.offsetHeight / 2;
4862                this.setLabelScreenPosition(x, y);
4863            }
4864        }
4865        adjustBubbleScreenPosition() {
4866            if (this.bubble) {
4867                if (!this.center) {
4868                    this.center = this.getCenterSVG();
4869                }
4870                const pos = this.mapsvg.converter.convertSVGToPixel(this.center), x = pos.x - this.bubble.offsetWidth / 2, y = pos.y - this.bubble.offsetHeight / 2;
4871                this.setBubbleScreenPosition(x, y);
4872            }
4873        }
4874        moveLabelScreenPositionBy(deltaX, deltaY) {
4875            if (this.label) {
4876                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;
4877                this.setLabelScreenPosition(x, y);
4878            }
4879        }
4880        moveBubbleScreenPositionBy(deltaX, deltaY) {
4881            if (this.bubble) {
4882                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;
4883                this.setBubbleScreenPosition(x, y);
4884            }
4885        }
4886        setLabelScreenPosition(x, y) {
4887            if (this.label) {
4888                this.label.style.transform = "translate(" + x + "px," + y + "px)";
4889            }
4890        }
4891        setBubbleScreenPosition(x, y) {
4892            if (this.bubble) {
4893                this.bubble.style.transform = "translate(" + x + "px," + y + "px)";
4894            }
4895        }
4896    }
4897
4898    class SchemaRepository extends Repository {
4899        constructor() {
4900            const objectName = "schema";
4901            super(objectName, +objectName + "s");
4902            this.className = "Schema";
4903            this.objectNameSingle = objectName;
4904            this.objectNameMany = objectName + "s";
4905            this.path = objectName + "s/";
4906            this.events = new Events(this);
4907        }
4908        create(schema) {
4909            const defer = jQuery.Deferred();
4910            defer.promise();
4911            const data = {};
4912            data[this.objectNameSingle] = this.encodeData(schema);
4913            this.server
4914                .post(this.path, data)
4915                .done((response) => {
4916                const data = this.decodeData(response);
4917                schema.id = data[this.objectNameSingle].id;
4918                this.objects.push(schema);
4919                this.events.trigger("created");
4920                schema.events.trigger("created");
4921                defer.resolve(schema);
4922            })
4923                .fail(() => {
4924                defer.reject();
4925            });
4926            return defer;
4927        }
4928        update(schema) {
4929            const defer = jQuery.Deferred();
4930            defer.promise();
4931            const data = {};
4932            data[this.objectNameSingle] = this.encodeData(schema);
4933            this.server
4934                .put(this.path + schema.id, data)
4935                .done((response) => {
4936                const data = this.decodeData(response);
4937                this.objects.push(schema);
4938                defer.resolve(schema);
4939                this.events.trigger("changed");
4940                schema.events.trigger("changed");
4941            })
4942                .fail(() => {
4943                defer.reject();
4944            });
4945            return defer;
4946        }
4947        encodeData(schema) {
4948            const _schema = schema.getData();
4949            let fieldsJsonString = JSON.stringify(_schema);
4950            fieldsJsonString = fieldsJsonString.replace(/select/g, "!mapsvg-encoded-slct");
4951            fieldsJsonString = fieldsJsonString.replace(/table/g, "!mapsvg-encoded-tbl");
4952            fieldsJsonString = fieldsJsonString.replace(/database/g, "!mapsvg-encoded-db");
4953            fieldsJsonString = fieldsJsonString.replace(/varchar/g, "!mapsvg-encoded-vc");
4954            fieldsJsonString = fieldsJsonString.replace(/int\(11\)/g, "!mapsvg-encoded-int");
4955            const back = JSON.parse(fieldsJsonString);
4956            back.fields = JSON.stringify(_schema.fields);
4957            return back;
4958        }
4959    }
4960
4961    const $$8 = jQuery;
4962    class Controller {
4963        constructor(options) {
4964            this.containers = {
4965                main: options.container,
4966            };
4967            this.mapsvg = options.mapsvg;
4968            this.template = options.template || "";
4969            this.scrollable = options.scrollable === undefined ? true : options.scrollable;
4970            this.withToolbar = options.withToolbar === undefined ? true : options.withToolbar;
4971            this.autoresize = MapSVG.parseBoolean(options.autoresize);
4972            this.templates = {
4973                toolbar: Handlebars.compile(this.getToolbarTemplate()),
4974                main: Handlebars.compile(this.getMainTemplate()),
4975            };
4976            this.data = options.data;
4977            this.width = options.width;
4978            this.color = options.color;
4979            this.events = new Events(this);
4980            if (options.events) {
4981                for (const eventName in options.events) {
4982                    if (typeof options.events[eventName] === "function") {
4983                        this.events.on(eventName, options.events[eventName]);
4984                    }
4985                }
4986            }
4987        }
4988        viewDidLoad() {
4989            const _this = this;
4990            _this.updateScroll();
4991            if (this.autoresize) {
4992                _this.adjustHeight();
4993                this.resizeSensor.setScroll();
4994            }
4995        }
4996        _viewDidLoad() {
4997            this.updateScroll();
4998        }
4999        viewDidAppear() { }
5000        viewDidDisappear() { }
5001        updateScroll() {
5002            if (!this.scrollable)
5003                return;
5004            const _this = this;
5005            $$8(this.containers.contentWrap).nanoScroller({
5006                preventPageScrolling: true,
5007            });
5008            setTimeout(function () {
5009                $$8(_this.containers.contentWrap).nanoScroller({
5010                    preventPageScrolling: true,
5011                });
5012            }, 300);
5013        }
5014        adjustHeight() {
5015            const _this = this;
5016            $$8(_this.containers.main).height($$8(_this.containers.main).find(".mapsvg-auto-height").outerHeight() +
5017                (_this.containers.toolbar ? $$8(_this.containers.toolbar).outerHeight() : 0));
5018        }
5019        _init() {
5020            const _this = this;
5021            _this.render();
5022            _this.init();
5023        }
5024        init() { }
5025        getToolbarTemplate() {
5026            return "";
5027        }
5028        setMainTemplate(template) {
5029            return (this.templates.main = Handlebars.compile(template));
5030        }
5031        getMainTemplate() {
5032            return this.template;
5033        }
5034        render() {
5035            const _this = this;
5036            this.containers.view = $$8("<div />")
5037                .attr("id", "mapsvg-controller-" + this.name)
5038                .addClass("mapsvg-controller-view")[0];
5039            this.containers.contentWrap = $$8("<div />").addClass("mapsvg-controller-view-wrap")[0];
5040            this.containers.contentWrap2 = $$8("<div />")[0];
5041            this.containers.sizer = $$8("<div />").addClass("mapsvg-auto-height")[0];
5042            this.containers.contentView = $$8("<div />").addClass("mapsvg-controller-view-content")[0];
5043            this.containers.sizer.appendChild(this.containers.contentView);
5044            if (this.scrollable) {
5045                $$8(this.containers.contentWrap).addClass("nano");
5046                $$8(this.containers.contentWrap2).addClass("nano-content");
5047            }
5048            this.containers.contentWrap.appendChild(this.containers.contentWrap2);
5049            this.containers.contentWrap2.appendChild(this.containers.sizer);
5050            if (this.withToolbar && this.templates.toolbar) {
5051                this.containers.toolbar = $$8("<div />").addClass("mapsvg-controller-view-toolbar")[0];
5052                this.containers.view.appendChild(this.containers.toolbar);
5053            }
5054            this.containers.view.append(this.containers.contentWrap);
5055            this.containers.main.appendChild(this.containers.view);
5056            $$8(this.containers.main).data("controller", this);
5057            if (this.width)
5058                this.containers.view.style.width = this.width;
5059            if (this.color)
5060                this.containers.view.style["background-color"] = this.color;
5061            _this.viewReadyToFill();
5062            this.redraw();
5063            setTimeout(function () {
5064                _this._viewDidLoad();
5065                _this.viewDidLoad();
5066                _this.setEventHandlersCommon();
5067                _this.setEventHandlers();
5068            }, 1);
5069        }
5070        viewReadyToFill() {
5071            const _this = this;
5072            if (_this.autoresize) {
5073                _this.resizeSensor = new ResizeSensor(this.containers.sizer, () => {
5074                    _this.adjustHeight();
5075                    _this.updateScroll();
5076                    _this.events.trigger("resize", this, [this]);
5077                });
5078            }
5079        }
5080        redraw(data) {
5081            if (data !== undefined) {
5082                this.data = data;
5083            }
5084            try {
5085                $$8(this.containers.contentView).html(this.templates.main(this.data));
5086            }
5087            catch (err) {
5088                console.error(err);
5089                $$8(this.containers.contentView).html("");
5090            }
5091            if (this.withToolbar && this.templates.toolbar)
5092                $$8(this.containers.toolbar).html(this.templates.toolbar(this.data));
5093            this.updateTopShift();
5094            if (this.noPadding)
5095                this.containers.contentView.style.padding = "0";
5096            this.updateScroll();
5097        }
5098        updateTopShift() {
5099            const _this = this;
5100            if (!this.withToolbar)
5101                return;
5102            $$8(_this.containers.contentWrap).css({
5103                top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5104            });
5105            setTimeout(function () {
5106                $$8(_this.containers.contentWrap).css({
5107                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5108                });
5109            }, 100);
5110            setTimeout(function () {
5111                $$8(_this.containers.contentWrap).css({
5112                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5113                });
5114            }, 200);
5115            setTimeout(function () {
5116                $$8(_this.containers.contentWrap).css({
5117                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
5118                });
5119                _this.updateScroll();
5120            }, 500);
5121        }
5122        setEventHandlersCommon() { }
5123        setEventHandlers() { }
5124        destroy() {
5125            delete this.resizeSensor;
5126            $$8(this.containers.view).empty().remove();
5127        }
5128    }
5129
5130    const $$9 = jQuery;
5131    class DirectoryController extends Controller {
5132        constructor(options) {
5133            super(options);
5134            this.repository = options.repository;
5135            this.noPadding = true;
5136            this.position = options.position;
5137            this.search = options.search;
5138        }
5139        getToolbarTemplate() {
5140            let t = '<div class="mapsvg-directory-search-wrap">';
5141            t += '<div class="mapsvg-directory-filter-wrap filter-wrap"></div>';
5142            t += "</div>";
5143            t += "</div>";
5144            return t;
5145        }
5146        viewDidLoad() {
5147            const _this = this;
5148            this.menuBtn = $$9('<div class="mapsvg-button-menu"><i class="mapsvg-icon-menu"></i> ' +
5149                this.mapsvg.options.mobileView.labelList +
5150                "</div>")[0];
5151            this.mapBtn = $$9('<div class="mapsvg-button-map"><i class="mapsvg-icon-map"></i> ' +
5152                this.mapsvg.options.mobileView.labelMap +
5153                "</div>")[0];
5154            if (MapSVG.isPhone && _this.mapsvg.options.menu.hideOnMobile) {
5155                if (this.mapsvg.options.menu.showFirst == "map") {
5156                    this.toggle(false);
5157                }
5158                else {
5159                    this.toggle(true);
5160                }
5161            }
5162            this.mobileButtons = $$9('<div class="mapsvg-mobile-buttons"></div>')[0];
5163            this.mobileButtons.append(this.menuBtn, this.mapBtn);
5164            if (this.mapsvg.options.menu.on !== false) {
5165                this.mapsvg.containers.wrapAll.appendChild(this.mobileButtons);
5166            }
5167            this.events.trigger("shown", this.containers.view);
5168        }
5169        setEventHandlers() {
5170            const _this = this;
5171            $$9(window).on("resize", function () {
5172                _this.updateTopShift();
5173            });
5174            $$9(this.menuBtn).on("click", function () {
5175                _this.toggle(true);
5176            });
5177            $$9(this.mapBtn).on("click", function () {
5178                _this.toggle(false);
5179                _this.mapsvg.redraw();
5180            });
5181            $$9(this.containers.view)
5182                .on("click.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5183                if (e.target.nodeName == "A") {
5184                    return;
5185                }
5186                const objID = $$9(this).data("object-id");
5187                let regions;
5188                let marker;
5189                let detailsViewObject;
5190                let eventObject;
5191                _this.deselectItems();
5192                _this.selectItems(objID, false);
5193                if (MapSVG.isPhone && _this.mapsvg.options.menu.showMapOnClick) {
5194                    _this.toggle(false);
5195                }
5196                if (_this.mapsvg.options.menu.source == "regions") {
5197                    regions = [_this.mapsvg.getRegion(objID)];
5198                    eventObject = regions[0];
5199                    detailsViewObject = regions[0];
5200                }
5201                else {
5202                    detailsViewObject = _this.repository.getLoadedObject(objID);
5203                    eventObject = detailsViewObject;
5204                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5205                    if (_regions) {
5206                        regions = _regions
5207                            .map(function (region) {
5208                            return _this.mapsvg.getRegion(region.id);
5209                        })
5210                            .filter(function (r) {
5211                            return r !== undefined;
5212                        });
5213                    }
5214                }
5215                if (detailsViewObject.location && detailsViewObject.location.marker)
5216                    marker = detailsViewObject.location.marker;
5217                if (_this.mapsvg.options.actions.directoryItem.click.showDetail
5217s) {
5218                    _this.mapsvg.loadDetailsView(detailsViewObject);
5219                }
5220                if (regions && regions.length > 0) {
5221                    if (_this.mapsvg.options.actions.directoryItem.click.zoom) {
5222                        _this.mapsvg.zoomTo(regions, _this.mapsvg.options.actions.directoryItem.click.zoomToLevel);
5223                    }
5224                    if (regions.length > 1) {
5225                        _this.mapsvg.setMultiSelect(true);
5226                    }
5227                    regions.forEach(function (region) {
5228                        const center = region.getCenter();
5229                        e.clientX = center[0];
5230                        e.clientY = center[1];
5231                        if (_this.mapsvg.options.actions.directoryItem.click.selectRegion) {
5232                            _this.mapsvg.selectRegion(region, true);
5233                        }
5234                        if (_this.mapsvg.options.actions.directoryItem.click.showRegionPopover) {
5235                            if (_this.mapsvg.options.actions.directoryItem.click.zoom) {
5236                                setTimeout(function () {
5237                                    _this.mapsvg.showPopover(region);
5238                                }, 500);
5239                            }
5240                            else {
5241                                _this.mapsvg.showPopover(region);
5242                            }
5243                        }
5244                        if (_this.mapsvg.options.actions.directoryItem.click.fireRegionOnClick) {
5245                            _this.mapsvg.events.trigger("click.region", region, [region]);
5246                        }
5247                    });
5248                    if (regions.length > 1) {
5249                        _this.mapsvg.setMultiSelect(false, false);
5250                    }
5251                }
5252                if (marker) {
5253                    if (_this.mapsvg.options.actions.directoryItem.click.zoomToMarker) {
5254                        _this.mapsvg.zoomTo(marker, _this.mapsvg.options.actions.directoryItem.click.zoomToMarkerLevel);
5255                    }
5256                    if (_this.mapsvg.options.actions.directoryItem.click.showMarkerPopover) {
5257                        if (_this.mapsvg.options.actions.directoryItem.click.zoomToMarker) {
5258                            setTimeout(function () {
5259                                _this.mapsvg.showPopover(detailsViewObject);
5260                            }, 500);
5261                        }
5262                        else {
5263                            _this.mapsvg.showPopover(detailsViewObject);
5264                        }
5265                    }
5266                    if (_this.mapsvg.options.actions.directoryItem.click.fireMarkerOnClick) {
5267                        _this.mapsvg.events.trigger("click.marker", marker, [e, _this.mapsvg]);
5268                    }
5269                    _this.mapsvg.selectMarker(marker);
5270                }
5271                _this.events.trigger("click", this, [e, eventObject, _this.mapsvg]);
5272                const actions = _this.mapsvg.options.actions;
5273                if (actions.directoryItem.click.goToLink) {
5274                    const linkParts = actions.directoryItem.click.linkField.split(".");
5275                    let url;
5276                    if (linkParts.length > 1) {
5277                        const obj = linkParts.shift();
5278                        const attr = "." + linkParts.join(".");
5279                        if (obj == "Region") {
5280                            if (regions[0] && regions[0].data)
5281                                url = eval("regions[0].data" + attr);
5282                        }
5283                        else {
5284                            if (detailsViewObject)
5285                                url = eval("detailsViewObject" + attr);
5286                        }
5287                        if (url) {
5288                            if (actions.directoryItem.click.newTab) {
5289                                const win = window.open(url, "_blank");
5290                                win.focus();
5291                            }
5292                            else {
5293                                window.location.href = url;
5294                            }
5295                        }
5296                    }
5297                }
5298                if (actions.directoryItem.click.showAnotherMap) {
5299                    if (_this.mapsvg.editMode) {
5300                        alert('"Show another map" action is disabled in the preview');
5301                        return true;
5302                    }
5303                    const linkParts2 = actions.directoryItem.click.showAnotherMapField.split(".");
5304                    if (linkParts2.length > 1) {
5305                        const obj2 = linkParts2.shift();
5306                        const attr2 = "." + linkParts2.join(".");
5307                        let map_id;
5308                        if (obj2 == "Region") {
5309                            if (regions[0] && regions[0].data)
5310                                map_id = eval("regions[0].data" + attr2);
5311                        }
5312                        else {
5313                            if (detailsViewObject)
5314                                map_id = eval("detailsViewObject" + attr2);
5315                        }
5316                        if (map_id) {
5317                            const container = actions.directoryItem.click.showAnotherMapContainerId
5318                                ? $$9("#" + actions.directoryItem.click.showAnotherMapContainerId)[0]
5319                                : $$9(_this.mapsvg.containers.wrapAll)[0];
5320                            _this.mapsvg.loadMap(map_id, container);
5321                        }
5322                    }
5323                }
5324            })
5325                .on("mouseover.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5326                const objID = $$9(this).data("object-id");
5327                let regions;
5328                let detailsViewObject;
5329                let eventObject;
5330                let marker;
5331                if (_this.mapsvg.options.menu.source == "regions") {
5332                    regions = [_this.mapsvg.getRegion(objID)];
5333                    eventObject = regions[0];
5334                    detailsViewObject = regions[0];
5335                }
5336                else {
5337                    detailsViewObject = _this.repository.getLoadedObject(objID);
5338                    eventObject = detailsViewObject;
5339                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5340                    if (_regions) {
5341                        regions = _regions.map(function (region) {
5342                            return _this.mapsvg.getRegion(region.id);
5343                        });
5344                    }
5345                    if (detailsViewObject.location) {
5346                        marker = detailsViewObject.location.marker;
5347                    }
5348                }
5349                if (regions && regions.length) {
5350                    _this.mapsvg.highlightRegions(regions);
5351                }
5352                if (marker) {
5353                    _this.mapsvg.highlightMarker(marker);
5354                    if (_this.mapsvg.options.actions.directoryItem.hover.centerOnMarker) {
5355                        _this.mapsvg.centerOn(marker);
5356                    }
5357                }
5358                _this.events.trigger("mouseover", $$9(this), [e, eventObject, _this.mapsvg]);
5359            })
5360                .on("mouseout.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5361                const objID = $$9(this).data("object-id");
5362                let regions;
5363                let detailsViewObject;
5364                let eventObject;
5365                let marker;
5366                if (_this.mapsvg.options.menu.source == "regions") {
5367                    regions = [_this.mapsvg.getRegion(objID)];
5368                    eventObject = regions[0];
5369                    detailsViewObject = regions[0];
5370                }
5371                else {
5372                    detailsViewObject = _this.repository.getLoadedObject(objID);
5373                    eventObject = detailsViewObject;
5374                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5375                    if (_regions) {
5376                        regions = _regions.map(function (region) {
5377                            return _this.mapsvg.getRegion(region.id);
5378                        });
5379                    }
5380                    if (detailsViewObject.location) {
5381                        marker = detailsViewObject.location.marker;
5382                    }
5383                }
5384                if (regions && regions.length) {
5385                    _this.mapsvg.unhighlightRegions();
5386                }
5387                if (marker) {
5388                    _this.mapsvg.unhighlightMarker();
5389                }
5390                _this.events.trigger("mouseout", $$9(this), [e, eventObject, _this.mapsvg]);
5391            });
5392            $$9(this.containers.contentView).on("click", ".mapsvg-category-item", function () {
5393                const panel = $$9(this).next(".mapsvg-category-block");
5394                if (panel[0].style.maxHeight || panel.hasClass("active")) {
5395                    panel[0].style.maxHeight = null;
5396                }
5397                else {
5398                    panel[0].style.maxHeight = panel[0].scrollHeight + "px";
5399                }
5400                if ($$9(this).hasClass("active")) {
5401                    $$9(this).toggleClass("active", false);
5402                    $$9(this).next(".mapsvg-category-block").addClass("collapsed").removeClass("active");
5403                }
5404                else {
5405                    if (_this.mapsvg.options.menu.categories.collapseOther) {
5406                        $$9(this).parent().find(".mapsvg-category-item.active").removeClass("active");
5407                        $$9(this)
5408                            .parent()
5409                            .find(".mapsvg-category-block.active")
5410                            .removeClass("active")
5411                            .addClass("collapsed");
5412                    }
5413                    $$9(this).toggleClass("active", true);
5414                    $$9(this).next(".mapsvg-category-block").removeClass("collapsed").addClass("active");
5415                }
5416                const panels = $$9(".mapsvg-category-block.collapsed");
5417                panels.each(function (i, panel) {
5418                    panel.style.maxHeight = null;
5419                });
5420            });
5421        }
5422        highlightItems(ids) {
5423            const _this = this;
5424            if (typeof ids != "object")
5425                ids = [ids];
5426            ids.forEach(function (id) {
5427                $$9(_this.containers.view)
5428                    .find("#mapsvg-directory-item-" + _this.convertId(id)
5428)
5429                    .addClass("hover");
5430            });
5431        }
5432        unhighlightItems() {
5433            $$9(this.containers.view).find(".mapsvg-directory-item").removeClass("hover");
5434        }
5435        selectItems(ids, scrollTo = true) {
5436            if (typeof ids != "object")
5437                ids = [ids];
5438            ids.forEach((id) => {
5439                $$9(this.containers.view)
5440                    .find("#mapsvg-directory-item-" + this.convertId(id))
5441                    .addClass("selected");
5442            });
5443            if (scrollTo && $$9("#mapsvg-directory-item-" + ids[0]).length > 0) {
5444                this.scrollable &&
5445                    $$9(this.containers.contentWrap).nanoScroller({
5446                        scrollTo: $$9(this.containers.view).find("#mapsvg-directory-item-" + this.convertId(ids[0])),
5447                    });
5448            }
5449        }
5450        deselectItems() {
5451            $$9(this.containers.view).find(".mapsvg-directory-item").removeClass("selected");
5452        }
5453        removeItems(ids) {
5454            $$9(this.containers.view)
5455                .find("#mapsvg-directory-item-" + this.convertId(ids))
5456                .remove();
5457        }
5458        filterOut(items) {
5459            return items;
5460        }
5461        loadItemsToDirectory() {
5462            let items = [];
5463            const _this = this;
5464            if (!_this.repository.loaded)
5465                return false;
5466            if (_this.mapsvg.options.menu.categories &&
5467                _this.mapsvg.options.menu.categories.on &&
5468                _this.mapsvg.options.menu.categories.groupBy) {
5469                const categoryField = _this.mapsvg.options.menu.categories.groupBy;
5470                if (_this.repository.getSchema().getField(categoryField) === undefined ||
5471                    _this.repository.getSchema().getField(categoryField).options === undefined) {
5472                    return false;
5473                }
5474                const categories = _this.repository.getSchema().getField(categoryField).options;
5475                categories.forEach(function (category) {
5476                    let dbItems = _this.repository.getLoaded();
5477                    dbItems = _this.filterOut(dbItems);
5478                    const itemArr = [];
5479                    dbItems.forEach((item) => {
5480                        itemArr.push(item);
5481                    });
5482                    const catItems = itemArr.filter(function (object) {
5483                        if (categoryField === "regions") {
5484                            const objectRegions = typeof object[categoryField] !== "undefined" &&
5485                                object[categoryField].length
5486                                ? object[categoryField]
5487                                : [];
5488                            const objectRegionIDs = objectRegions.map(function (region) {
5489                                return region.id;
5490                            });
5491                            return objectRegionIDs.indexOf(category.id) !== -1;
5492                        }
5493                        else {
5494                            return object[categoryField] == category.value;
5495                        }
5496                    });
5497                    category.counter = catItems.length;
5498                    if (categoryField === "regions") {
5499                        category.label = category.title;
5500                        category.value = category.id;
5501                    }
5502                    items.push({ category: category, items: catItems });
5503                });
5504                if (_this.mapsvg.options.menu.categories.hideEmpty) {
5505                    items = items.filter(function (item) {
5506                        return item.category.counter > 0;
5507                    });
5508                }
5509            }
5510            else {
5511                if (_this.mapsvg.options.menu.source === "regions") {
5512                    items = _this.repository.getLoaded().map((r) => {
5513                        const data = r.getData();
5514                        data.objects = _this.mapsvg.getRegion(data.id).objects;
5515                        data.id_no_spaces = data.id.split(" ").join("_");
5516                        return data;
5517                    });
5518                }
5519                else {
5520                    items = _this.repository
5521                        .getLoaded()
5522                        .map((r) => r.getData(_this.mapsvg.regionsRepository.schema.name));
5523                }
5524            }
5525            try {
5526                $$9(this.containers.contentView).html(this.templates.main({ items: items }));
5527            }
5528            catch (err) {
5529                console.error('MapSVG: Error in the "Directory item" template');
5530                console.error(err);
5531            }
5532            if (items.length === 0) {
5533                $$9(this.containers.contentView).html('<div class="mapsvg-no-results">' +
5534                    this.mapsvg.options.menu.noResultsText +
5535                    "</div>");
5536            }
5537            if (_this.mapsvg.options.menu.categories.on) {
5538                if (_this.mapsvg.options.menu.categories.collapse && items.length > 1) {
5539                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("collapsed");
5540                }
5541                else if (_this.mapsvg.options.menu.categories.collapse && items.length === 1) {
5542                    $$9(this.containers.contentView).find(".mapsvg-category-item").addClass("active");
5543                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("active");
5544                    const panel = $$9(this.containers.contentView).find(".mapsvg-category-block")[0];
5545                    if (panel)
5546                        panel.style.maxHeight = panel.scrollHeight + "px";
5547                }
5548                else if (!_this.mapsvg.options.menu.categories.collapse) {
5549                    $$9(this.containers.contentView).find(".mapsvg-category-item").addClass("active");
5550                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("active");
5551                    const panels = $$9(this.containers.contentView).find(".mapsvg-category-block");
5552                    if (panels.length)
5553                        panels.each(function (i, panel) {
5554                            panel.style.maxHeight = panel.scrollHeight + "px";
5555                        });
5556                }
5557            }
5558            this.updateTopShift();
5559            this.updateScroll();
5560        }
5561        toggle(on) {
5562            const _this = this;
5563            if (on) {
5564                $$9(this.containers.main).parent().show();
5565                $$9(_this.mapsvg.containers.mapContainer).hide();
5566                $$9(this.menuBtn).addClass("active");
5567                $$9(this.mapBtn).removeClass("active");
5568            }
5569            else {
5570                $$9(this.containers.main).parent().hide();
5571                $$9(_this.mapsvg.containers.mapContainer).show();
5572                $$9(this.menuBtn).removeClass("active");
5573                $$9(this.mapBtn).addClass("active");
5574            }
5575            if (!$$9(this.containers.main).parent().is(":visible")) {
5576                if (MapSVG.isPhone) {
5577                    $$9(_this.mapsvg.containers.wrap).css("height", "auto");
5578                    _this.updateScroll();
5579                }
5580            }
5581            else {
5582                if (MapSVG.isPhone &&
5583                    $$9(this.containers.main).height() < parseInt(this.mapsvg.options.menu.minHeight)) {
5584                    $$9(_this.mapsvg.containers.wrap).css("height", parseInt(this.mapsvg.options.menu.minHeight) + "px");
5585                    _this.updateScroll();
5586                }
5587            }
5588            this.updateTopShift();
5589        }
5590        addPagination(pager) {
5591            $$9(this.containers.contentView).append('<div class="mapsvg-pagination-container"></div>');
5592            $$9(this.containers.contentView).find(".mapsvg-pagination-container").html(pager);
5593        }
5594        convertId(id) {
5595            return (id + "")
5596                .split(" ")
5597                .join("_")
5598                .replace(/(:|\(|\)|\.|\[|\]|,|=|@)/g, "\\$1");
5599        }
5600    }
5601
5602    const $$a = jQuery;
5603    class DetailsController extends Controller {
5604        constructor(options) {
5605            super(options);
5606            this.modal = options.modal;
5607        }
5608        getToolbarTemplate() {
5609            if (this.withToolbar)
5610                return '<div class="mapsvg-popover-close mapsvg-details-close"></div>';
5611            else
5612                return "";
5613        }
5614        viewDidLoad() {
5615            const _this = this;
5616            this.events.trigger("shown", _this, [_this]);
5617            if (this.modal &&
5618                MapSVG.isPhone &&
5619                this.mapsvg.options.detailsView.mobileFullscreen &&
5620                !this.mobileCloseBtn) {
5621                this.mobileCloseBtn = $$a('<button class="mapsvg-mobile-modal-close">' +
5622                    _this.mapsvg.options.mobileView.labelClose +
5623                    "</button>")[0];
5624                this.containers.view.appendChild(this.mobileCloseBtn);
5625            }
5626        }
5627        setEventHandlers() {
5628            const _this = this;
5629            $$a(this.containers.toolbar).on("click touchend", ".mapsvg-popover-close", function (e) {
5630                e.stopPropagation();
5631                _this.destroy();
5632                _this.events.trigger("closed", _this, [_this]);
5633            });
5634            $$a(this.containers.view).on("click touchend", ".mapsvg-mobile-modal-close", function (e) {
5635                e.stopPropagation();
5636                _this.destroy();
5637                _this.events.trigger("closed", _this, [_this]);
5638            });
5639        }
5640    }
5641
5642    const $$b = jQuery;
5643    class FormElement {
5644        constructor(options, formBuilder, external) {
5645            this.readonly = typeof options.readonly !== "undefined" ? options.readonly : false;
5646            this.protected = typeof options.protected !== "undefined" ? options.protected : false;
5647            this.auto_increment =
5648                typeof options.auto_increment !== "undefined" ? options.auto_increment : false;
5649            this.not_null = typeof options.not_null !== "undefined" ? options.not_null : false;
5650            this.searchable = typeof options.searchable !== "undefined" ? options.searchable : false;
5651            this.visible = typeof options.visible !== "undefined" ? options.visible : true;
5652            this.formBuilder = formBuilder;
5653            this.events = new Events(this);
5654            this.type = options.type;
5655            this.value = options.value;
5656            this.db_type = options.db_type || "varchar(255)";
5657            this.label = this.label || (options.label === undefined ? "Label" : options.label);
5658            this.name = this.name || options.name || "label";
5659            this.help = options.help || "";
5660            this.placeholder = options.placeholder;
5661            this.setExternal(external);
5662            let t = this.type;
5663            if (t === "marker" && this.mapIsGeo) {
5664                t = "marker-geo";
5665            }
5666            if (t === "location" && this.mapIsGeo) {
5667                t = "location-geo";
5668            }
5669            if (this.filtersMode) {
5670                this.parameterName = options.parameterName || "";
5671                this.parameterNameShort = this.parameterName.split(".")[1];
5672                this.name = this.parameterNameShort;
5673                this.placeholder = options.placeholder || "";
5674                this.templates = {
5675                    main: Handlebars.compile($$b("#mapsvg-filters-tmpl-" + t + "-view").html()),
5676                };
5677            }
5678            else {
5679                this.templates = {
5680                    main: Handlebars.compile($$b("#mapsvg-data-tmpl-" + t + "-view").html()),
5681                };
5682            }
5683            this.inputs = {};
5684        }
5685        init() {
5686            this.setDomElements();
5687            this.setEventHandlers();
5688        }
5689        setDomElements() {
5690            this.domElements = {
5691                main: $$b(this.templates.main(this.getDataForTemplate()))[0],
5692            };
5693            $$b(this.domElements.main).data("formElement", this);
5694            this.addSelect2();
5695        }
5696        setEventHandlers() {
5697            const _this = this;
5698            if (this.formBuilder.editMode) {
5699                $$b(this.domElements.main).on("click", function () {
5700                    _this.events.trigger("click", _this, [_this]);
5701                });
5702            }
5703        }
5704        addSelect2() {
5705            if ($$b().mselect2) {
5706                $$b(this.domElements.main)
5707                    .find("select")
5708                    .css({ width: "100%", display: "block" })
5709                    .mselect2()
5710                    .on("select2:focus", function () {
5711                    $$b(this).mselect2("open");
5712                });
5713                $$b(this.domElements.main)
5714                    .find(".select2-selection--multiple .select2-search__field")
5715                    .css("width", "100%");
5716            }
5717        }
5718        setEditorEventHandlers() {
5719            const _this = this;
5720            $$b(this.domElements.edit).on("click", "button.mapsvg-remove", function () {
5721                $$b(_this.domElements.main).empty().remove();
5722                $$b(_this.domElements.edit).empty().remove();
5723                _this.events.trigger("delete", _this, [_this]);
5724            });
5725            $$b(this.domElements.edit).on("click", ".mapsvg-filter-insert-options", function () {
5726                const objType = _this.parameterName.split(".")[0];
5727                const fieldName = _this.parameterName.split(".")[1];
5728                let field;
5729                if (objType == "Object") {
5730                    field = _this.formBuilder.mapsvg.objectsRepository.getSchema().getField(fieldName);
5731                }
5732                else {
5733                    if (fieldName == "id") {
5734                        const options = [];
5735                        _this.formBuilder.mapsvg.regions.forEach(function (r) {
5736                            options.push({ label: r.id, value: r.id });
5737                        });
5738                        field = {
5739                            options: options,
5740                        };
5741                    }
5742                    else if (fieldName === "title") {
5743                        const options = [];
5744                        _this.formBuilder.mapsvg.regions.forEach(function (r) {
5745                            options.push({ label: r.title, value: r.title });
5746                        });
5747                        field = { options: options };
5748                    }
5749                    else {
5750                        field = _this.formBuilder.mapsvg.regionsRepository
5751                            .getSchema()
5752                            .getField(fieldName);
5753                    }
5754                }
5755                if ((field && field.options) || fieldName === "regions") {
5756                    let options;
5757                    if (fieldName == "regions") {
5758                        const _options = _this.formBuilder.mapsvg.regions.map((r) => {
5759                            return { id: r.id, title: r.title };
5760                        });
5761                        _options.sort(function (a, b) {
5762                            if (a.title < b.title)
5763                                return -1;
5764                            if (a.title > b.title)
5765                                return 1;
5766                            return 0;
5767                        });
5768                        options = _options.map(function (o) {
5769                            return (o.title || o.id) + ":" + o.id;
5770                        });
5771                    }
5772                    else {
5773                        options = field.options.map(function (o) {
5774                            return o.label + ":" + o.value;
5775                        });
5776                    }
5777                    $$b(this)
5778                        .closest(".form-group")
5779                        .find("textarea")
5780                        .val(options.join("\n"))
5781                        .trigger("change");
5782                }
5783            });
5784            $$b(this.domElements.edit).on("keyup change paste", "input, textarea, select", function () {
5785                const prop = $$b(this).attr("name");
5786                const array = $$b(this).data("array");
5787                if (_this.type === "status" && array) {
5788                    const param = $$b(this).data("param");
5789                    const index = $$b(this).closest("tr").index();
5790                    _this.options[index] = _this.options[index] || {
5791                        label: "",
5792                        value: "",
5793                        color: "",
5794                        disabled: false,
5795                    };
5796                    _this.options[index][param] = $$b(this).is(":checkbox")
5797                        ? $$b(this).prop("checked")
5798                        : $$b(this).val();
5799                    _this.redraw();
5800                }
5801                else if (_this.type === "distance" && array) {
5802                    const param = $$b(this).data("param");
5803                    const index = $$b(this).closest("tr").index();
5804                    if (!_this.options[index]) {
5805                        _this.options[index] = { value: "", default: false };
5806                    }
5807                    if (param === "default") {
5808                        _this.options.forEach(function (option) {
5809                            option.default = false;
5810                        });
5811                        _this.options[index].default = $$b(this).prop("checked");
5812                    }
5813                    else {
5814                        _this.options[index].value = $$b(this).val();
5815                    }
5816                    _this.redraw();
5817                }
5818                else if (prop == "label" || prop == "name") {
5819                    return false;
5820                }
5821                else {
5822                    let value;
5823                    value =
5824                        $$b(this).attr("type") == "checkbox" ? $$b(this).prop("checked") : $$b(this).val();
5825                    if ($$b(this).attr("type") == "radio") {
5826                        const name = $$b(this).attr("name");
5827                        value = $$b('input[name="' + name + '"]:checked').val();
5828                    }
5829                    _this.update(prop, value);
5830                }
5831            });
5832            $$b(this.domElements.edit).on("keyup change paste", 'input[name="label"]', function () {
5833                if (!_this.nameChanged) {
5834                    _this.label = $$b(this).val() + "";
5835                    if (_this.type != "region" && _this.type != "location" && _this.type != "title") {
5836                        let str = $$b(this).val() + "";
5837                        str = str.toLowerCase().replace(/ /g, "_").replace(/\W/g, "");
5838                        if (str.length < 64) {
5839                            $$b(_this.domElements.edit).find('input[name="name"]').val(str);
5840                        }
5841                        _this.name = str + "";
5842                    }
5843                    $$b(_this.domElements.main).find("label").first().html(_this.label);
5844                    if (!_this.filtersMode) {
5845                        $$b(_this.domElements.main)
5846                            .find("label")
5847                            .first()
5848                            .append('<div class="field-name">' + _this.name + "</div>");
5849                    }
5850                }
5851            });
5852            $$b(this.domElements.edit).on("keyup change paste", 'input[name="name"]', function (e) {
5853                if (e.target.value) {
5854                    if (e.target.value.match(/[^a-zA-Z0-9_]/g)) {
5855                        e.target.value = e.target.value.replace(/[^a-zA-Z0-9_]/g, "");
5856                        $$b(e.target).trigger("change");
5857                    }
5858                    if (e.target.value[0].match(/[^a-zA-Z_]/g)) {
5859                        e.target.value =
5860                            e.target.value[0].replace(/[^a-zA-Z_]/g, "") + e.target.value.slice(1);
5861                        $$b(e.target).trigger("change");
5862                    }
5863                }
5864                if (_this.type != "region")
5865                    _this.name = e.target.value;
5866                $$b(_this.domElements.main)
5867                    .find("label")
5868                    .html(_this.label + '<div class="field-name">' + _this.name + "</div>");
5869                _this.nameChanged = true;
5870            });
5871            $$b(this.domElements.edit).on("keyup change paste", 'textarea[name="help"]', function (e) {
5872                $$b(_this.domElements.main).find(".form-text").text(e.target.value);
5873            });
5874        }
5875        getEditor() {
5876            if (!this.filtersMode) {
5877                this.templates.edit =
5878                    this.templates.edit ||
5879                        Handlebars.compile($$b("#mapsvg-data-tmpl-" + this.type + "-control").html());
5880            }
5881            else {
5882                this.templates.edit =
5883                    this.templates.edit ||
5884                        Handlebars.compile($$b("#mapsvg-filters-tmpl-" + this.type + "-control").html());
5885            }
5886            this.domElements.edit = $$b("<div>" + this.templates.edit(this.getDataForTemplate()) + "</div>")[0];
5887            return this.domElements.edit;
5888        }
5889        destroyEditor() {
5890            $$b(this.domElements.edit).empty().remove();
5891        }
5892        initEditor() {
5893            $$b(this.domElements.edit).find("input").first().select();
5894            if ($$b().colorpicker) {
5895                $$b(this.domElements.edit)
5896                    .find(".cpicker")
5897                    .colorpicker()
5898                    .on("changeColor.colorpicker", function (event) {
5899                    const input = $$b(this).find("input");
5900                    if (input.val() == "")
5901                        $$b(this).find("i").css({ "background-color": "" });
5902                });
5903            }
5904            if ($$b().mselect2) {
5905                if (this.type !== "distance") {
5906                    $$b(this.domElements.edit)
5907                        .find("select")
5908                        .css({ width: "100%", display: "block" })
5909                        .mselect2();
5910                }
5911            }
5912            this.setEditorEventHandlers();
5913        }
5914        getSchema() {
5915            let data;
5916            data = {
5917                type: this.type,
5918                db_type: this.db_type,
5919                label: this.label,
5920                name: this.name,
5921                value: this.value,
5922                searchable: this.searchable,
5923                help: this.help,
5924                visible: this.visible === undefined ? true : this.visible,
5925                readonly: this.readonly,
5926                placeholder: this.placeholder,
5927                protected: this.protected,
5928                auto_increment: this.auto_increment,
5929                not_null: this.not_null,
5930            };
5931            if (this.options) {
5932                data.options = this.getSchemaFieldOptionsList();
5933            }
5934            if (this.filtersMode) {
5935                data.parameterName = this.parameterName;
5936                data.parameterNameShort = this.parameterName.split(".")[1];
5937            }
5938            return data;
5939        }
5940        getSchemaFieldOptionsList() {
5941            const options = [];
5942            this.options.forEach((option, index) => {
5943                if (this.options[index].value !== "") {
5944                    options.push(this.options[index]);
5945                }
5946            });
5947            return options;
5948        }
5949        getDataForTemplate() {
5950            const data = this.getSchema();
5951            data._name = data.name;
5952            if (this.namespace) {
5953                data.name = this.name.split("[")[0];
5954                let suffix = this.name.split("[")[1] || "";
5955                if (suffix)
5956                    suffix = "[" + suffix;
5957                data.name = this.namespace + "[" + data.name + "]" + suffix;
5958            }
5959            data.external = this.external;
5960            return data;
5961        }
5962        update(prop, value) {
5963            const _this = this;
5964            if (prop == "options") {
5965                const options = [];
5966                value = value.split("\n").forEach(function (row) {
5967                    row = row.trim().split(":");
5968                    if (_this.type == "checkbox" && row.length == 3) {
5969                        options.push({
5970                            label: row[0],
5971                            name: row[1],
5972                            value: row[2],
5973                        });
5974                    }
5975                    else if ((_this.type == "radio" ||
5976                        _this.type == "select" ||
5977                        _this.type == "checkboxes") &&
5978                        row.length == 2) {
5979                        options.push({
5980                            label: row[0],
5981                            value: row[1],
5982                        });
5983                    }
5984                });
5985                this.options = options;
5986            }
5987            else {
5988                this[prop] = value;
5989            }
5990            if (prop == "parameterName") {
5991                $$b(this.domElements.edit).find(".mapsvg-filter-param-name").text(value);
5992            }
5993        }
5994        redraw() {
5995            const newView = $$b(this.templates.main(this.getDataForTemplate()));
5996            $$b(this.domElements.main).html(newView.html());
5997            if ($$b().mselect2) {
5998                if (this.type !== "distance") {
5999                    $$b(this.domElements.main)
6000                        .find("select")
6001                        .css({ width: "100%", display: "block" })
6002                        .mselect2()
6003                        .on("select2:focus", function () {
6004                        $$b(this).mselect2("open");
6005                    });
6006                }
6007                else {
6008                    $$b(this.domElements.main)
6009                        .find("select")
6010                        .mselect2()
6011                        .on("select2:focus", function () {
6012                        $$b(this).mselect2("open");
6013                    });
6014                }
6015            }
6016        }
6017        redrawEditor() {
6018            if (this.domElements.edit) {
6019                $$b(this.domElements.edit).empty();
6020                $$b(this.domElements.edit).html("<div>" + this.templates.edit(this.getDataForTemplate()) + "</div>");
6021                this.initEditor();
6022            }
6023        }
6024        setOptions(options) {
6025            if (options) {
6026                this.options = [];
6027                this.optionsDict = {};
6028                options.forEach((value, key) => {
6029                    this.options.push(value);
6030                    this.optionsDict[key] = value;
6031                });
6032                return this.options;
6033            }
6034            else {
6035                return this.setOptions([
6036                    { label: "Option one", name: "option_one", value: 1 },
6037                    { label: "Option two", name: "option_two", value: 2 },
6038                ]);
6039            }
6040        }
6041        getData() {
6042            return { name: this.name, value: this.getValue() };
6043        }
6044        destroy() {
6045            if ($$b().mselect2) {
6046                const sel = $$b(this.domElements.main).find(".mapsvg-select2");
6047                if (sel.length) {
6048                    sel.mselect2("destroy");
6049                }
6050            }
6051        }
6052        show() {
6053            $$b(this.domElements.main).show();
6054        }
6055        hide() {
6056            $$b(this.domElements.main).hide();
6057        }
6058        setExternal(params) {
6059            this.external = params;
6060            if (typeof this.external.mapIsGeo !== "undefined") {
6061                this.mapIsGeo = this.external.mapIsGeo;
6062            }
6063            if (typeof this.external.editMode !== "undefined") {
6064                this.editMode = this.external.editMode;
6065            }
6066            if (typeof this.external.filtersMode !== "undefined") {
6067                this.filtersMode = this.external.filtersMode;
6068            }
6069            if (typeof this.external.namespace !== "undefined") {
6070                this.namespace = this.external.namespace;
6071            }
6072        }
6073        getValue() {
6074            return this.value;
6075        }
6076        setValue(value, updateInput = true) {
6077            this.value = value;
6078            if (updateInput) {
6079                this.setInputValue(value);
6080            }
6081        }
6082        setInputValue(value) {
6083            return;
6084        }
6085        triggerChanged() {
6086            this.events.trigger("changed", this, [this]);
6087        }
6088    }
6089
6090    const $$c = jQuery;
6091    class CheckboxFormElement extends FormElement {
6092        constructor(options, formBuilder, external) {
6093            super(options, formBuilder, external);
6094            if (typeof options.showAsSwitch === "undefined") {
6095                this.showAsSwitch = true;
6096            }
6097            else {
6098                this.showAsSwitch = options.showAsSwitch;
6099            }
6100            this.db_type = "tinyint(1)";
6101            this.checkboxLabel = options.checkboxLabel;
6102            this.checkboxValue = options.checkboxValue;
6103        }
6104        setDomElements() {
6105            super.setDomElements();
6106            this.inputs.checkbox = $$c(this.domElements.main).find("input")[0];
6107            this.inputs.switch = $$c(this.domElements.main).find("input")[0];
6108        }
6109        setEventHandlers() {
6110            super.setEventHandlers();
6111            $$c(this.inputs.checkbox).on("change", (e) => {
6112                this.setValue(e.target.checked, false);
6113                this.triggerChanged();
6114            });
6115        }
6116        setEditorEventHandlers() {
6117            super.setEditorEventHandlers();
6118            $$c(this.domElements.edit).on("change", "[name='showAsSwitch']", (e) => {
6119                if (this.showAsSwitch) {
6120                    $$c(this.domElements.main)
6121                        .find("[name='checkboxToSwitch']")
6122                        .addClass("form-switch form-switch-md");
6123                }
6124                if (!this.showAsSwitch) {
6125                    $$c(this.domElements.main)
6126                        .find("[name='checkboxToSwitch']")
6127                        .removeClass("form-switch form-switch-md");
6128                }
6129            });
6130            $$c(this.domElements.edit).on("keyup change paste", '[name="checkboxLabel"]', 
6130(e) => {
6131                $$c(this.domElements.main).find(".form-check-label").text(e.target.value);
6132            });
6133        }
6134        getSchema() {
6135            const schema = super.getSchema();
6136            if (this.checkboxLabel) {
6137                schema.checkboxLabel = this.checkboxLabel;
6138            }
6139            if (this.checkboxValue) {
6140                schema.checkboxValue = this.checkboxValue;
6141            }
6142            schema.showAsSwitch = this.showAsSwitch;
6143            return schema;
6144        }
6145        setInputValue(value) {
6146            this.inputs.checkbox.checked = value === true;
6147        }
6148    }
6149
6150    const $$d = jQuery;
6151    class CheckboxesFormElement extends FormElement {
6152        constructor(options, formBuilder, external) {
6153            super(options, formBuilder, external);
6154            this.db_type = "text";
6155            this.checkboxLabel = options.checkboxLabel;
6156            this.setOptions(options.options);
6157        }
6158        setDomElements() {
6159            super.setDomElements();
6160            this.$checkboxes = $$d(this.domElements.main).find('input[type="checkbox"]');
6161            this.setInputValue(this.value || []);
6162        }
6163        setEventHandlers() {
6164            super.setEventHandlers();
6165            this.$checkboxes.on("change", (e) => {
6166                const values = [];
6167                $$d(this.domElements.main)
6168                    .find("input:checked")
6169                    .each((i, el) => {
6170                    values.push(jQuery(el).attr("value"));
6171                });
6172                this.setValue(values, false);
6173                this.triggerChanged();
6174            });
6175        }
6176        setInputValue(values) {
6177            if (values === null) {
6178                $$d(this.domElements.main).find(`input`).prop("checked", false);
6179            }
6180            else {
6181                values.forEach((value) => {
6182                    $$d(this.domElements.main).find(`input[value="${value}"]`).prop("checked", true);
6183                });
6184            }
6185        }
6186    }
6187
6188    const $$e = jQuery;
6189    class DateFormElement extends FormElement {
6190        constructor(options, formBuilder, external) {
6191            super(options, formBuilder, external);
6192            if (this.formBuilder.admin) {
6193                this.languages = [
6194                    "en-GB",
6195                    "ar",
6196                    "az",
6197                    "bg",
6198                    "bs",
6199                    "ca",
6200                    "cs",
6201                    "cy",
6202                    "da",
6203                    "de",
6204                    "el",
6205                    "es",
6206                    "et",
6207                    "eu",
6208                    "fa",
6209                    "fi",
6210                    "fo",
6211                    "fr",
6212                    "gl",
6213                    "he",
6214                    "hr",
6215                    "hu",
6216                    "hy",
6217                    "id",
6218                    "is",
6219                    "it",
6220                    "ja",
6221                    "ka",
6222                    "kh",
6223                    "kk",
6224                    "kr",
6225                    "lt",
6226                    "lv",
6227                    "mk",
6228                    "ms",
6229                    "nb",
6230                    "nl",
6231                    "nl-BE",
6232                    "no",
6233                    "pl",
6234                    "pt-BR",
6235                    "pt",
6236                    "ro",
6237                    "rs",
6238                    "rs-latin",
6239                    "ru",
6240                    "sk",
6241                    "sl",
6242                    "sq",
6243                    "sr",
6244                    "sr-latin",
6245                    "sv",
6246                    "sw",
6247                    "th",
6248                    "tr",
6249                    "uk",
6250                    "vi",
6251                    "zh-CN",
6252                    "zh-TW",
6253                ];
6254            }
6255            this.db_type = "varchar(50)";
6256            this.language = options.language;
6257        }
6258        setDomElements() {
6259            super.setDomElements();
6260            this.inputs.date = $$e(this.domElements.main).find("input")[0];
6261        }
6262        setEventHandlers() {
6263            super.setEventHandlers();
6264            $$e(this.inputs.date).on("change", (e) => {
6265                this.setValue(e.target.value, false);
6266                this.triggerChanged();
6267            });
6268        }
6269        getSchema() {
6270            const schema = super.getSchema();
6271            schema.language = this.language;
6272            return schema;
6273        }
6274        getDataForTemplate() {
6275            const data = super.getDataForTemplate();
6276            if (this.formBuilder.admin)
6277                data.languages = this.languages;
6278            data.language = this.language;
6279            return data;
6280        }
6281    }
6282
6283    const $$f = jQuery;
6284    class DistanceFormElement extends FormElement {
6285        constructor(options, formBuilder, external) {
6286            super(options, formBuilder, external);
6287            this.name = "distance";
6288            this.label = this.label || (options.label === undefined ? "Search radius" : options.label);
6289            this.distanceControl = options.distanceControl || "select";
6290            this.distanceUnits = options.distanceUnits || "km";
6291            this.distanceUnitsLabel = options.distanceUnitsLabel || "km";
6292            this.fromLabel = options.fromLabel || "from";
6293            this.placeholder = options.placeholder;
6294            this.userLocationButton = options.userLocationButton || false;
6295            this.type = options.type;
6296            this.addressField = options.addressField || true;
6297            this.addressFieldPlaceholder = options.addressFieldPlaceholder || "Address";
6298            this.languages = [
6299                { value: "sq", label: "Albanian" },
6300                { value: "ar", label: "Arabic" },
6301                {
6302                    value: "eu",
6303                    label: "Basque",
6304                },
6305                { value: "be", label: "Belarusian" },
6306                { value: "bg", label: "Bulgarian" },
6307                {
6308                    value: "my",
6309                    label: "Burmese",
6310                },
6311                { value: "bn", label: "Bengali" },
6312                { value: "ca", label: "Catalan" },
6313                {
6314                    value: "zh-cn",
6315                    label: "Chinese (simplified)",
6316                },
6317                { value: "zh-tw", label: "Chinese (traditional)" },
6318                {
6319                    value: "hr",
6320                    label: "Croatian",
6321                },
6322                { value: "cs", label: "Czech" },
6323                { value: "da", label: "Danish" },
6324                {
6325                    value: "nl",
6326                    label: "Dutch",
6327                },
6328                { value: "en", label: "English" },
6329                {
6330                    value: "en-au",
6331                    label: "English (australian)",
6332                },
6333                { value: "en-gb", label: "English (great Britain)" },
6334                {
6335                    value: "fa",
6336                    label: "Farsi",
6337                },
6338                { value: "fi", label: "Finnish" },
6339                { value: "fil", label: "Filipino" },
6340                {
6341                    value: "fr",
6342                    label: "French",
6343                },
6344                { value: "gl", label: "Galician" },
6345                { value: "de", label: "German" },
6346                {
6347                    value: "el",
6348                    label: "Greek",
6349                },
6350                { value: "gu", label: "Gujarati" },
6351                { value: "iw", label: "Hebrew" },
6352                {
6353                    value: "hi",
6354                    label: "Hindi",
6355                },
6356                { value: "hu", label: "Hungarian" },
6357                { value: "id", label: "Indonesian" },
6358                {
6359                    value: "it",
6360                    label: "Italian",
6361                },
6362                { value: "ja", label: "Japanese" },
6363                { value: "kn", label: "Kannada" },
6364                {
6365                    value: "kk",
6366                    label: "Kazakh",
6367                },
6368                { value: "ko", label: "Korean" },
6369                { value: "ky", label: "Kyrgyz" },
6370                {
6371                    value: "lt",
6372                    label: "Lithuanian",
6373                },
6374                { value: "lv", label: "Latvian" },
6375                { value: "mk", label: "Macedonian" },
6376                {
6377                    value: "ml",
6378                    label: "Malayalam",
6379                },
6380                { value: "mr", label: "Marathi" },
6381                { value: "no", label: "Norwegian" },
6382                {
6383                    value: "pl",
6384                    label: "Polish",
6385                },
6386                { value: "pt", label: "Portuguese" },
6387                {
6388                    value: "pt-br",
6389                    label: "Portuguese (brazil)",
6390                },
6391                { value: "pt-pt", label: "Portuguese (portugal)" },
6392                {
6393                    value: "pa",
6394                    label: "Punjabi",
6395                },
6396                { value: "ro", label: "Romanian" },
6397                { value: "ru", label: "Russian" },
6398                {
6399                    value: "sr",
6400                    label: "Serbian",
6401                },
6402                { value: "sk", label: "Slovak" },
6403                { value: "sl", label: "Slovenian" },
6404                {
6405                    value: "es",
6406                    label: "Spanish",
6407                },
6408                { value: "sv", label: "Swedish" },
6409                { value: "tl", label: "Tagalog" },
6410                {
6411                    value: "ta",
6412                    label: "Tamil",
6413                },
6414                { value: "te", label: "Telugu" },
6415                { value: "th", label: "Thai" },
6416                {
6417                    value: "tr",
6418                    label: "Turkish",
6419                },
6420                { value: "uk", label: "Ukrainian" },
6421                { value: "uz", label: "Uzbek" },
6422                {
6423                    value: "vi",
6424                    label: "Vietnamese",
6425                },
6426            ];
6427            this.countries = MapSVG.countries;
6428            this.country = options.country;
6429            this.language = options.language;
6430            this.searchByZip = options.searchByZip;
6431            this.zipLength = parseInt(options.zipLength) || 5;
6432            this.userLocationButton = MapSVG.parseBoolean(options.userLocationButton);
6433            this.options = options.options || [
6434                { value: "10", default: true },
6435                { value: "30", default: false },
6436                { value: "50", default: false },
6437                { value: "100", default: false },
6438            ];
6439            let defOption;
6440            if (this.value) {
6441                this.options.forEach((option) => {
6442                    if (option.value === this.value.length) {
6443                        defOption = option;
6444                    }
6445                });
6446            }
6447            if (!defOption) {
6448                defOption = this.options.find(function (option) {
6449                    return option.default === true;
6450                });
6451            }
6452            if (!defOption) {
6453                defOption = this.options[0];
6454            }
6455            const defLengthOption = this.options.find((opt) => opt.selected === true);
6456            this.defaultLength = defOption.value;
6457            this.setDefaultValue();
6458        }
6459        setDefaultValue() {
6460            this.value = {
6461                units: this.distanceUnits,
6462                geoPoint: { lat: null, lng: null },
6463                length: this.defaultLength,
6464                address: "",
6465                country: this.country,
6466            };
6467        }
6468        setDomElements() {
6469            super.setDomElements();
6470            this.inputs.units = ($$f(this.domElements.main).find('[name="distanceUnits"]')[0]);
6471            this.inputs.geoPoint = ($$f(this.domElements.main).find('[name="distanceGeoPoint"]')[0]);
6472            this.inputs.length = ($$f(this.domElements.main).find('[name="distanceLength"]')[0]);
6473            this.inputs.address = ($$f(this.domElements.main).find('[name="distance"]')[0]);
6474        }
6475        getSchema() {
6476            const schema = super.getSchema();
6477            schema.distanceControl = this.distanceControl;
6478            schema.distanceUnits = this.distanceUnits;
6479            schema.distanceUnitsLabel = this.distanceUnitsLabel;
6480            schema.fromLabel = this.fromLabel;
6481            schema.addressField = this.addressField;
6482            schema.addressFieldPlaceholder = this.addressFieldPlaceholder;
6483            schema.userLocationButton = this.userLocationButton;
6484            schema.placeholder = this.placeholder;
6485            schema.language = this.language;
6486            schema.country = this.country;
6487            schema.searchByZip = this.searchByZip;
6488            schema.zipLength = parseInt(this.zipLength + "");
6489            schema.userLocationButton = MapSVG.parseBoolean(this.userLocationButton);
6490            if (schema.distanceControl === "none") {
6491                schema.distanceDefault = schema.options.filter(function (o) {
6492                    return o.default;
6493                })[0].value;
6494            }
6495            schema.options.forEach(function (option, index) {
6496                if (schema.options[index].value === "") {
6497                    schema.options.splice(index, 1);
6498                }
6499                else {
6500                    schema.options[index].default = MapSVG.parseBoolean(schema.options[index].default);
6501                }
6502            });
6503            return schema;
6504        }
6505        getDataForTemplate() {
6506            const data = super.getDataForTemplate();
6507            if (this.formBuilder.admin) {
6508                data.languages = this.languages;
6509                data.countries = this.countries;
6510            }
6511            data.language = this.language;
6512            data.country = this.country;
6513            data.searchByZip = this.searchByZip;
6514            data.zipLength = this.zipLength;
6515            data.userLocationButton = MapSVG.parseBoolean(this.userLocationButton);
6516            return data;
6517        }
6518        destroy() {
6519            if ($$f().mselect2) {
6520                const sel = $$f(this.domElements.main).find(".mapsvg-select2");
6521                if (sel.length) {
6522                    sel.mselect2("destroy");
6523                }
6524            }
6525        }
6526        initEditor() {
6527            super.initEditor();
6528            this.mayBeAddDistanceRow();
6529            if ($$f().mselect2) {
6530                $$f(this.domElements.edit).find("select").mselect2();
6531            }
6532        }
6533        setEventHandlers() {
6534            super.setEventHandlers();
6535            const _this = this;
6536            $$f(this.domElements.edit).on("keyup change paste", ".mapsvg-edit-distance-row input", function () {
6537                _this.mayBeAddDistanceRow();
6538            });
6539            const server = new Server();
6540            const locations = new Bloodhound({
6541                datumTokenizer: Bloodhound.tokenizers.obj.whitespace("formatted_address"),
6542                queryTokenizer: Bloodhound.tokenizers.whitespace,
6543                remote: {
6544                    url: server.getUrl("geocoding") +
6545                        "?address=" +
6546                        (this.searchByZip === true ? "zip%20" : "") +
6547                        "%QUERY%&language=" +
6548                        this.language +
6549                        (this.country ? "&country=" + this.country : ""),
6550                    wildcard: "%QUERY%",
6551                    transform: function (response) {
6552                        if (response.error_message) {
6553                            alert(response.error_message);
6554                        }
6555                        return response.results;
6556                    },
6557                    rateLimitWait: 600,
6558                },
6559            });
6560            const thContainer = $$f(this.domElements.main).find(".typeahead");
6561            this.spinner = $$f("<span class='spinner-border spinner-border-sm'></span>")[0];
6562            if (this.searchByZip) {
6563                $$f(this.domElements.main).find(".mapsvg-distance-fields").addClass("search-by-zip");
6564                thContainer.on("change keyup", (e) => {
6565                    const zip = $$f(e.target).val().toString();
6566                    if (zip.length === _this.zipLength) {
6567                        $$f(this.spinner).appendTo($$f(e.target).closest(".distance-search-wrap"));
6568                        locations.search($$f(e.target).val(), (data) => this.handleAddressFieldChange(zip, data), (data) => this.handleAddressFieldChange(zip, data, true));
6569                    }
6570                });
6571            }
6572            else {
6573                const tH = thContainer
6574                    .typeahead({ minLength: 3 }, {
6575                    name: "mapsvg-addresses",
6576                    display: "formatted_address",
6577                    limit: 5,
6578                    async: true,
6579                    source: (query, sync, async) => {
6580                        const request = { address: query };
6581                        if (this.country) {
6582                            request.componentRestrictions = { country: this.country };
6583                        }
6584                        MapSVG.geocode(request, async);
6585                    },
6586                })
6587                    .on("typeahead:asyncrequest", (e) => {
6588                    $$f(this.spinner).appendTo($$f(e.target).closest(".twitter-typeahead"));
6589                })
6590                    .on("typeahead:asynccancel typeahead:asyncreceive", (e) => {
6591                    $$f(this.spinner).remove();
6592                });
6593                $$f(this.domElements.main).find(".mapsvg-distance-fields").removeClass("search-by-zip");
6594            }
6595            if (_this.userLocationButton) {
6596                const userLocationButton = $$f(this.domElements.main).find(".user-location-button");
6597                userLocationButton.on("click", () => {
6598                    _this.formBuilder.mapsvg.showUserLocation((location) => {
6599                        locations.search(location.geoPoint.lat + "," + location.geoPoint.lng, (data) => this.setAddressByUserLocation(data, location), (data) => this.setAddressByUserLocation(data, location));
6600                        this.setValue({ geoPoint: location.geoPoint });
6601                        this.triggerChanged();
6602                    });
6603                });
6604            }
6605            thContainer.on("change keyup", (e) => {
6606                const input = e.target;
6607                if (input.value === "" && this.getValue() !== null) {
6608                    this.setValue(null);
6609                    this.triggerChanged();
6610                }
6611            });
6612            thContainer.on("typeahead:select", (ev, item) => {
6613                this.setValue({
6614                    address: item.formatted_address,
6615                    geoPoint: item.geometry.location.toJSON(),
6616                });
6617                this.triggerChanged();
6618                thContainer.blur();
6619            });
6620            $$f(this.inputs.geoPoint).on("change", (e) => {
6621                const geoPoint = e.target.value.split(",").map((value) => parseFloat(value));
6622                this.setValue({ geoPoint: { lat: geoPoint[0], lng: geoPoint[1] } }, false);
6623                this.triggerChanged();
6624            });
6625            $$f(this.inputs.length).on("change", (e) => {
6626                this.setLength(parseInt(e.target.value), false);
6627                this.triggerChanged();
6628            });
6629        }
6630        setAddressByUserLocation(data, location) {
6631            if (data && data[0]) {
6632                this.setAddress(data[0].formatted_address);
6633            }
6634            else {
6635                this.setAddress(location.geoPoint.lat + "," + location.geoPoint.lng);
6636            }
6637        }
6638        handleAddressFieldChange(zip, data, removeSpinner = false) {
6639            if (removeSpinner) {
6640                $$f(this.spinner).remove();
6641            }
6642            if (data && data[0]) {
6643                this.setValue({ address: zip, geoPoint: data[0].geometry.location }, false);
6644                this.triggerChanged();
6645            }
6646        }
6647        addSelect2() {
6648            if ($$f().mselect2) {
6649                $$f(this.domElements.main)
6650                    .find("select")
6651                    .mselect2()
6652                    .on("select2:focus", function () {
6653                    $$f(this).mselect2("open");
6654                });
6655            }
6656        }
6657        mayBeAddDistanceRow() {
6658            const _this = this;
6659            const editDistanceRow = $$f($$f("#mapsvg-edit-distance-row").html());
6660            const z = $$f(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child input");
6661            if (z && z.last() && z.last().val() && z.last().val().toString().trim().length) {
6662                const newRow = editDistanceRow.clone();
6663                newRow.insertAfter($$f(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child"));
6664            }
6665            const rows = $$f(_this.domElements.edit).find(".mapsvg-edit-distance-row");
6666            const row1 = rows.eq(rows.length - 2);
6667            const row2 = rows.eq(rows.length - 1);
6668            if (row1.length &&
6669                row2.length &&
6670                !row1.find("input:eq(0)").val().toString().trim() &&
6671                !row2.find("input:eq(0)").val().toString().trim()) {
6672                row2.remove();
6673            }
6674        }
6675        setValue(value, updateInput = true) {
6676            if (value === null) {
6677                this.setGeoPoint(null);
6678                this.setAddress("");
6679            }
6680            else {
6681                for (const key in value) {
6682                    if (typeof this.value[key] !== undefined) {
6683                        const method = "set" + MapSVG.ucfirst(key);
6684                        if (typeof this[method] === "function") {
6685                            this[method](value[key], updateInput);
6686                        }
6687                    }
6688                }
6689            }
6690        }
6691        setGeoPoint(geoPoint, updateInput = true) {
6692            this.value.geoPoint = geoPoint === null ? { lat: null, lng: null } : geoPoint;
6693            if (updateInput) {
6694                this.setInputGeoPointValue(geoPoint);
6695            }
6696        }
6697        setInputGeoPointValue(geoPoint) {
6698            this.inputs.geoPoint.value = geoPoint ? geoPoint.lat + "," + geoPoint.lng : "";
6699        }
6700        setLength(length, updateInput = true) {
6701            this.value.length = parseInt(length.toString());
6702            this.defaultLength = this.value.length;
6703            if (updateInput) {
6704                this.setInputLengthValue(this.value.length);
6705            }
6706        }
6707        setInputLengthValue(length) {
6708            this.inputs.length.value = length.toString();
6709        }
6710        setAddress(address, updateInput = true) {
6711            this.value.address = address !== null ? address : "";
6712            if (updateInput) {
6713                this.setInputAddressValue(this.value.address);
6714            }
6715        }
6716        setInputAddressValue(address) {
6717            this.inputs.address.value = address;
6718        }
6719        getValue() {
6720            return this.value.geoPoint.lat === null ? null : this.value;
6721        }
6722    }
6723
6724    const $$g = jQuery;
6725    class EmptyFormElement extends FormElement {
6726        constructor(options, formBuilder, external) {
6727            super(options, formBuilder, external);
6728            this.readonly = true;
6729        }
6730    }
6731
6732    class IdFormElement extends FormElement {
6733        constructor(options, formBuilder, external) {
6734            super(options, formBuilder, external);
6735        }
6736        getData() {
6737            return { name: "id", value: this.value };
6738        }
6739    }
6740
6741    function createCommonjsModule(fn, module) {
6742    	return module = { exports: {} }, fn(module, module.exports), module.exports;
6743    }
6744
6745    var sortable_min = createCommonjsModule(function (module) {
6746    /**!
6747     * Sortable
6748     * @author	RubaXa   <[email protected]>
6749     * @license MIT
6750     */
6751
6752    (function sortableModule(factory) {
6753
6754        {
6755            module.exports = factory();
6756        }
6757    })(function sortableFactory() {
6758
6759        if (typeof window == "undefined" || !window.document) {
6760            return function sortableError() {
6761                throw new Error("Sortable.js requires a window with a document");
6762            };
6763        }
6764
6765        var dragEl,
6766            parentEl,
6767            ghostEl,
6768            cloneEl,
6769            rootEl,
6770            nextEl,
6771            scrollEl,
6772            scrollParentEl,
6773            scrollCustomFn,
6774            lastEl,
6775            lastCSS,
6776            lastParentCSS,
6777            oldIndex,
6778            newIndex,
6779            activeGroup,
6780            putSortable,
6781            autoScroll = {},
6782            tapEvt,
6783            touchEvt,
6784            moved,
6785            /** @const */
6786            RSPACE = /\s+/g,
6787            expando = "Sor
6787table" + new Date().getTime(),
6788            win = window,
6789            document = win.document,
6790            parseInt = win.parseInt,
6791            $ = win.jQuery || win.Zepto,
6792            Polymer = win.Polymer,
6793            supportDraggable = !!("draggable" in document.createElement("div")),
6794            supportCssPointerEvents = (function (el) {
6795                // false when IE11
6796                if (navigator.userAgent.match(/Trident.*rv[ :]?11\./)) {
6797                    return false;
6798                }
6799                el = document.createElement("x");
6800                el.style.cssText = "pointer-events:auto";
6801                return el.style.pointerEvents === "auto";
6802            })(),
6803            _silent = false,
6804            abs = Math.abs,
6805            min = Math.min,
6806            touchDragOverListeners = [],
6807            _autoScroll = _throttle(function (
6808                /**Event*/ evt,
6809                /**Object*/ options,
6810                /**HTMLElement*/ rootEl
6811            ) {
6812                // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
6813                if (rootEl && options.scroll) {
6814                    var el,
6815                        rect,
6816                        sens = options.scrollSensitivity,
6817                        speed = options.scrollSpeed,
6818                        x = evt.clientX,
6819                        y = evt.clientY,
6820                        winWidth = window.innerWidth,
6821                        winHeight = window.innerHeight,
6822                        vx,
6823                        vy,
6824                        scrollOffsetX,
6825                        scrollOffsetY;
6826
6827                    // Delect scrollEl
6828                    if (scrollParentEl !== rootEl) {
6829                        scrollEl = options.scroll;
6830                        scrollParentEl = rootEl;
6831                        scrollCustomFn = options.scrollFn;
6832
6833                        if (scrollEl === true) {
6834                            scrollEl = rootEl;
6835
6836                            do {
6837                                if (
6838                                    scrollEl.offsetWidth < scrollEl.scrollWidth ||
6839                                    scrollEl.offsetHeight < scrollEl.scrollHeight
6840                                ) {
6841                                    break;
6842                                }
6843                                /* jshint boss:true */
6844                            } while ((scrollEl = scrollEl.parentNode));
6845                        }
6846                    }
6847
6848                    if (scrollEl) {
6849                        el = scrollEl;
6850                        rect = scrollEl.getBoundingClientRect();
6851                        vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
6852                        vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
6853                    }
6854
6855                    if (!(vx || vy)) {
6856                        vx = (winWidth - x <= sens) - (x <= sens);
6857                        vy = (winHeight - y <= sens) - (y <= sens);
6858
6859                        /* jshint expr:true */
6860                        (vx || vy) && (el = win);
6861                    }
6862
6863                    if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
6864                        autoScroll.el = el;
6865                        autoScroll.vx = vx;
6866                        autoScroll.vy = vy;
6867
6868                        clearInterval(autoScroll.pid);
6869
6870                        if (el) {
6871                            autoScroll.pid = setInterval(function () {
6872                                scrollOffsetY = vy ? vy * speed : 0;
6873                                scrollOffsetX = vx ? vx * speed : 0;
6874
6875                                if ("function" === typeof scrollCustomFn) {
6876                                    return scrollCustomFn.call(
6877                                        _this,
6878                                        scrollOffsetX,
6879                                        scrollOffsetY,
6880                                        evt
6881                                    );
6882                                }
6883
6884                                if (el === win) {
6885                                    win.scrollTo(
6886                                        win.pageXOffset + scrollOffsetX,
6887                                        win.pageYOffset + scrollOffsetY
6888                                    );
6889                                } else {
6890                                    el.scrollTop += scrollOffsetY;
6891                                    el.scrollLeft += scrollOffsetX;
6892                                }
6893                            }, 24);
6894                        }
6895                    }
6896                }
6897            },
6898            30),
6899            _prepareGroup = function (options) {
6900                function toFn(value, pull) {
6901                    if (value === void 0 || value === true) {
6902                        value = group.name;
6903                    }
6904
6905                    if (typeof value === "function") {
6906                        return value;
6907                    } else {
6908                        return function (to, from) {
6909                            var fromGroup = from.options.group.name;
6910
6911                            return pull
6912                                ? value
6913                                : value &&
6914                                      (value.join ? value.indexOf(fromGroup) > -1 : fromGroup == value);
6915                        };
6916                    }
6917                }
6918
6919                var group = {};
6920                var originalGroup = options.group;
6921
6922                if (!originalGroup || typeof originalGroup != "object") {
6923                    originalGroup = { name: originalGroup };
6924                }
6925
6926                group.name = originalGroup.name;
6927                group.checkPull = toFn(originalGroup.pull, true);
6928                group.checkPut = toFn(originalGroup.put);
6929
6930                options.group = group;
6931            };
6932        /**
6933         * @class  Sortable
6934         * @param  {HTMLElement}  el
6935         * @param  {Object}       [options]
6936         */
6937        function Sortable(el, options) {
6938            if (!(el && el.nodeType && el.nodeType === 1)) {
6939                throw "Sortable: `el` must be HTMLElement, and not " + {}.toString.call(el);
6940            }
6941
6942            this.el = el; // root element
6943            this.options = options = _extend({}, options);
6944
6945            // Export instance
6946            el[expando] = this;
6947
6948            // Default options
6949            var defaults = {
6950                group: Math.random(),
6951                sort: true,
6952                disabled: false,
6953                store: null,
6954                handle: null,
6955                scroll: true,
6956                scrollSensitivity: 30,
6957                scrollSpeed: 10,
6958                draggable: /[uo]l/i.test(el.nodeName) ? "li" : ">*",
6959                ghostClass: "sortable-ghost",
6960                chosenClass: "sortable-chosen",
6961                dragClass: "sortable-drag",
6962                ignore: "a, img",
6963                filter: null,
6964                animation: 0,
6965                setData: function (dataTransfer, dragEl) {
6966                    dataTransfer.setData("Text", dragEl.textContent);
6967                },
6968                dropBubble: false,
6969                dragoverBubble: false,
6970                dataIdAttr: "data-id",
6971                delay: 0,
6972                forceFallback: false,
6973                fallbackClass: "sortable-fallback",
6974                fallbackOnBody: false,
6975                fallbackTolerance: 0,
6976                fallbackOffset: { x: 0, y: 0 },
6977            };
6978
6979            // Set default options
6980            for (var name in defaults) {
6981                !(name in options) && (options[name] = defaults[name]);
6982            }
6983
6984            _prepareGroup(options);
6985
6986            // Bind all private methods
6987            for (var fn in this) {
6988                if (fn.charAt(0) === "_" && typeof this[fn] === "function") {
6989                    this[fn] = this[fn].bind(this);
6990                }
6991            }
6992
6993            // Setup drag mode
6994            this.nativeDraggable = options.forceFallback ? false : supportDraggable;
6995
6996            // Bind events
6997            _on(el, "mousedown", this._onTapStart);
6998            _on(el, "touchstart", this._onTapStart);
6999
7000            if (this.nativeDraggable) {
7001                _on(el, "dragover", this);
7002                _on(el, "dragenter", this);
7003            }
7004
7005            touchDragOverListeners.push(this._onDragOver);
7006
7007            // Restore sorting
7008            options.store && this.sort(options.store.get(this));
7009        }
7010
7011        Sortable.prototype = /** @lends Sortable.prototype */ {
7012            constructor: Sortable,
7013
7014            _onTapStart: function (/** Event|TouchEvent */ evt) {
7015                if (evt.target.tagName == "i" || evt.target.tagName == "I") {
7016                    evt.target.click();
7017                    return;
7018                }
7019                var _this = this,
7020                    el = this.el,
7021                    options = this.options,
7022                    type = evt.type,
7023                    touch = evt.touches && evt.touches[0],
7024                    target = (touch || evt).target,
7025                    originalTarget = (evt.target.shadowRoot && evt.path[0]) || target,
7026                    filter = options.filter,
7027                    startIndex;
7028
7029                // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
7030                if (dragEl) {
7031                    return;
7032                }
7033
7034                if ((type === "mousedown" && evt.button !== 0) || options.disabled) {
7035                    return; // only left button or enabled
7036                }
7037
7038                if (options.handle && !_closest(originalTarget, options.handle, el)) {
7039                    return;
7040                }
7041
7042                target = _closest(target, options.draggable, el);
7043
7044                if (!target) {
7045                    return;
7046                }
7047
7048                // Get the index of the dragged element within its parent
7049                startIndex = _index(target, options.draggable);
7050
7051                // Check filter
7052                if (typeof filter === "function") {
7053                    if (filter.call(this, evt, target, this)) {
7054                        _dispatchEvent(_this, originalTarget, "filter", target, el, startIndex);
7055                        evt.preventDefault();
7056                        return; // cancel dnd
7057                    }
7058                } else if (filter) {
7059                    filter = filter.split(",").some(function (criteria) {
7060                        criteria = _closest(originalTarget, criteria.trim(), el);
7061
7062                        if (criteria) {
7063                            _dispatchEvent(_this, criteria, "filter", target, el, startIndex);
7064                            return true;
7065                        }
7066                    });
7067
7068                    if (filter) {
7069                        evt.preventDefault();
7070                        return; // cancel dnd
7071                    }
7072                }
7073
7074                // Prepare `dragstart`
7075                this._prepareDragStart(evt, touch, target, startIndex);
7076            },
7077
7078            _prepareDragStart: function (
7079                /** Event */ evt,
7080                /** Touch */ touch,
7081                /** HTMLElement */ target,
7082                /** Number */ startIndex
7083            ) {
7084                var _this = this,
7085                    el = _this.el,
7086                    options = _this.options,
7087                    ownerDocument = el.ownerDocument,
7088                    dragStartFn;
7089
7090                if (target && !dragEl && target.parentNode === el) {
7091                    tapEvt = evt;
7092
7093                    rootEl = el;
7094                    dragEl = target;
7095                    parentEl = dragEl.parentNode;
7096                    nextEl = dragEl.nextSibling;
7097                    activeGroup = options.group;
7098                    oldIndex = startIndex;
7099
7100                    this._lastX = (touch || evt).clientX;
7101                    this._lastY = (touch || evt).clientY;
7102
7103                    dragEl.style["will-change"] = "transform";
7104
7105                    dragStartFn = function () {
7106                        // Delayed drag has been triggered
7107                        // we can re-enable the events: touchmove/mousemove
7108                        _this._disableDelayedDrag();
7109
7110                        // Make the element draggable
7111                        dragEl.draggable = _this.nativeDraggable;
7112
7113                        // Chosen item
7114                        _toggleClass(dragEl, options.chosenClass, true);
7115
7116                        // Bind the events: dragstart/dragend
7117                        _this._triggerDragStart(touch);
7118
7119                        // Drag start event
7120                        _dispatchEvent(_this, rootEl, "choose", dragEl, rootEl, oldIndex);
7121                    };
7122
7123                    // Disable "draggable"
7124                    options.ignore.split(",").forEach(function (criteria) {
7125                        _find(dragEl, criteria.trim(), _disableDraggable);
7126                    });
7127
7128                    _on(ownerDocument, "mouseup", _this._onDrop);
7129                    _on(ownerDocument, "touchend", _this._onDrop);
7130                    _on(ownerDocument, "touchcancel", _this._onDrop);
7131
7132                    if (options.delay) {
7133                        // If the user moves the pointer or let go the click or touch
7134                        // before the delay has been reached:
7135                        // disable the delayed drag
7136                        _on(ownerDocument, "mouseup", _this._disableDelayedDrag);
7137                        _on(ownerDocument, "touchend", _this._disableDelayedDrag);
7138                        _on(ownerDocument, "touchcancel", _this._disableDelayedDrag);
7139                        _on(ownerDocument, "mousemove", _this._disableDelayedDrag);
7140                        _on(ownerDocument, "touchmove", _this._disableDelayedDrag);
7141
7142                        _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
7143                    } else {
7144                        dragStartFn();
7145                    }
7146                }
7147            },
7148
7149            _disableDelayedDrag: function () {
7150                var ownerDocument = this.el.ownerDocument;
7151
7152                clearTimeout(this._dragStartTimer);
7153                _off(ownerDocument, "mouseup", this._disableDelayedDrag);
7154                _off(ownerDocument, "touchend", this._disableDelayedDrag);
7155                _off(ownerDocument, "touchcancel", this._disableDelayedDrag);
7156                _off(ownerDocument, "mousemove", this._disableDelayedDrag);
7157                _off(ownerDocument, "touchmove", this._disableDelayedDrag);
7158            },
7159
7160            _triggerDragStart: function (/** Touch */ touch) {
7161                if (touch) {
7162                    // Touch device support
7163                    tapEvt = {
7164                        target: dragEl,
7165                        clientX: touch.clientX,
7166                        clientY: touch.clientY,
7167                    };
7168
7169                    this._onDragStart(tapEvt, "touch");
7170                } else if (!this.nativeDraggable) {
7171                    this._onDragStart(tapEvt, true);
7172                } else {
7173                    _on(dragEl, "dragend", this);
7174                    _on(rootEl, "dragstart", this._onDragStart);
7175                }
7176
7177                try {
7178                    if (document.selection) {
7179                        // Timeout neccessary for IE9
7180                        setTimeout(function () {
7181                            document.selection.empty();
7182                        });
7183                    } else {
7184                        window.getSelection().removeAllRanges();
7185                    }
7186                } catch (err) {}
7187            },
7188
7189            _dragStarted: function () {
7190                if (rootEl && dragEl) {
7191                    var options = this.options;
7192
7193                    // Apply effect
7194                    _toggleClass(dragEl, options.ghostClass, true);
7195                    _toggleClass(dragEl, options.dragClass, false);
7196
7197                    Sortable.active = this;
7198
7199                    // Drag start event
7200                    _dispatchEvent(this, rootEl, "start", dragEl, rootEl, oldIndex);
7201                }
7202            },
7203
7204            _emulateDragOver: function () {
7205                if (touchEvt) {
7206                    if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
7207                        return;
7208                    }
7209
7210                    this._lastX = touchEvt.clientX;
7211                    this._lastY = touchEvt.clientY;
7212
7213                    if (!supportCssPointerEvents) {
7214                        _css(ghostEl, "display", "none");
7215                    }
7216
7217                    var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
7218                        parent = target,
7219                        i = touchDragOverListeners.length;
7220
7221                    if (parent) {
7222                        do {
7223                            if (parent[expando]) {
7224                                while (i--) {
7225                                    touchDragOverListeners[i]({
7226                                        clientX: touchEvt.clientX,
7227                                        clientY: touchEvt.clientY,
7228                                        target: target,
7229                                        rootEl: parent,
7230                                    });
7231                                }
7232
7233                                break;
7234                            }
7235
7236                            target = parent; // store last element
7237                        } while (
7238                            /* jshint boss:true */
7239                            (parent = parent.parentNode)
7240                        );
7241                    }
7242
7243                    if (!supportCssPointerEvents) {
7244                        _css(ghostEl, "display", "");
7245                    }
7246                }
7247            },
7248
7249            _onTouchMove: function (/**TouchEvent*/ evt) {
7250                if (tapEvt) {
7251                    var options = this.options,
7252                        fallbackTolerance = options.fallbackTolerance,
7253                        fallbackOffset = options.fallbackOffset,
7254                        touch = evt.touches ? evt.touches[0] : evt,
7255                        dx = touch.clientX - tapEvt.clientX + fallbackOffset.x,
7256                        dy = touch.clientY - tapEvt.clientY + fallbackOffset.
7256y,
7257                        translate3d = evt.touches
7258                            ? "translate3d(" + dx + "px," + dy + "px,0)"
7259                            : "translate(" + dx + "px," + dy + "px)";
7260
7261                    // only set the status to dragging, when we are actually dragging
7262                    if (!Sortable.active) {
7263                        if (
7264                            fallbackTolerance &&
7265                            min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) <
7266                                fallbackTolerance
7267                        ) {
7268                            return;
7269                        }
7270
7271                        this._dragStarted();
7272                    }
7273
7274                    // as well as creating the ghost element on the document body
7275                    this._appendGhost();
7276
7277                    moved = true;
7278                    touchEvt = touch;
7279
7280                    _css(ghostEl, "webkitTransform", translate3d);
7281                    _css(ghostEl, "mozTransform", translate3d);
7282                    _css(ghostEl, "msTransform", translate3d);
7283                    _css(ghostEl, "transform", translate3d);
7284
7285                    evt.preventDefault();
7286                }
7287            },
7288
7289            _appendGhost: function () {
7290                if (!ghostEl) {
7291                    var rect = dragEl.getBoundingClientRect(),
7292                        css = _css(dragEl),
7293                        options = this.options,
7294                        ghostRect;
7295
7296                    ghostEl = dragEl.cloneNode(true);
7297
7298                    _toggleClass(ghostEl, options.ghostClass, false);
7299                    _toggleClass(ghostEl, options.fallbackClass, true);
7300                    _toggleClass(ghostEl, options.dragClass, true);
7301
7302                    _css(ghostEl, "top", rect.top - parseInt(css.marginTop, 10));
7303                    _css(ghostEl, "left", rect.left - parseInt(css.marginLeft, 10));
7304                    _css(ghostEl, "width", rect.width);
7305                    _css(ghostEl, "height", rect.height);
7306                    _css(ghostEl, "opacity", "0.8");
7307                    _css(ghostEl, "position", "fixed");
7308                    _css(ghostEl, "zIndex", "100000");
7309                    _css(ghostEl, "pointerEvents", "none");
7310
7311                    (options.fallbackOnBody && document.body.appendChild(ghostEl)) ||
7312                        rootEl.appendChild(ghostEl);
7313
7314                    // Fixing dimensions.
7315                    ghostRect = ghostEl.getBoundingClientRect();
7316                    _css(ghostEl, "width", rect.width * 2 - ghostRect.width);
7317                    _css(ghostEl, "height", rect.height * 2 - ghostRect.height);
7318                }
7319            },
7320
7321            _onDragStart: function (/**Event*/ evt, /**boolean*/ useFallback) {
7322                var dataTransfer = evt.dataTransfer,
7323                    options = this.options;
7324
7325                this._offUpEvents();
7326
7327                if (activeGroup.checkPull(this, this, dragEl, evt) == "clone") {
7328                    cloneEl = _clone(dragEl);
7329                    _css(cloneEl, "display", "none");
7330                    rootEl.insertBefore(cloneEl, dragEl);
7331                    _dispatchEvent(this, rootEl, "clone", dragEl);
7332                }
7333
7334                _toggleClass(dragEl, options.dragClass, true);
7335
7336                if (useFallback) {
7337                    if (useFallback === "touch") {
7338                        // Bind touch events
7339                        _on(document, "touchmove", this._onTouchMove);
7340                        _on(document, "touchend", this._onDrop);
7341                        _on(document, "touchcancel", this._onDrop);
7342                    } else {
7343                        // Old brwoser
7344                        _on(document, "mousemove", this._onTouchMove);
7345                        _on(document, "mouseup", this._onDrop);
7346                    }
7347
7348                    this._loopId = setInterval(this._emulateDragOver, 50);
7349                } else {
7350                    if (dataTransfer) {
7351                        dataTransfer.effectAllowed = "move";
7352                        options.setData && options.setData.call(this, dataTransfer, dragEl);
7353                    }
7354
7355                    _on(document, "drop", this);
7356                    setTimeout(this._dragStarted, 0);
7357                }
7358            },
7359
7360            _onDragOver: function (/**Event*/ evt) {
7361                var el = this.el,
7362                    target,
7363                    dragRect,
7364                    targetRect,
7365                    revert,
7366                    options = this.options,
7367                    group = options.group,
7368                    activeSortable = Sortable.active,
7369                    isOwner = activeGroup === group,
7370                    canSort = options.sort;
7371
7372                if (evt.preventDefault !== void 0) {
7373                    evt.preventDefault();
7374                    !options.dragoverBubble && evt.stopPropagation();
7375                }
7376
7377                moved = true;
7378
7379                if (
7380                    activeGroup &&
7381                    !options.disabled &&
7382                    (isOwner
7383                        ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
7384                        : putSortable === this ||
7385                          (activeGroup.checkPull(this, activeSortable, dragEl, evt) &&
7386                              group.checkPut(this, activeSortable, dragEl, evt))) &&
7387                    (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
7388                ) {
7389                    // Smart auto-scrolling
7390                    _autoScroll(evt, options, this.el);
7391
7392                    if (_silent) {
7393                        return;
7394                    }
7395
7396                    target = _closest(evt.target, options.draggable, el);
7397                    dragRect = dragEl.getBoundingClientRect();
7398                    putSortable = this;
7399
7400                    if (revert) {
7401                        _cloneHide(true);
7402                        parentEl = rootEl; // actualization
7403
7404                        if (cloneEl || nextEl) {
7405                            rootEl.insertBefore(dragEl, cloneEl || nextEl);
7406                        } else if (!canSort) {
7407                            rootEl.appendChild(dragEl);
7408                        }
7409
7410                        return;
7411                    }
7412
7413                    if (
7414                        el.children.length === 0 ||
7415                        el.children[0] === ghostEl ||
7416                        (el === evt.target && (target = _ghostIsLast(el, evt)))
7417                    ) {
7418                        if (target) {
7419                            if (target.animated) {
7420                                return;
7421                            }
7422
7423                            targetRect = target.getBoundingClientRect();
7424                        }
7425
7426                        _cloneHide(isOwner);
7427
7428                        if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
7429                            if (!dragEl.contains(el)) {
7430                                el.appendChild(dragEl);
7431                                parentEl = el; // actualization
7432                            }
7433
7434                            this._animate(dragRect, dragEl);
7435                            target && this._animate(targetRect, target);
7436                        }
7437                    } else if (
7438                        target &&
7439                        !target.animated &&
7440                        target !== dragEl &&
7441                        target.parentNode[expando] !== void 0
7442                    ) {
7443                        if (lastEl !== target) {
7444                            lastEl = target;
7445                            lastCSS = _css(target);
7446                            lastParentCSS = _css(target.parentNode);
7447                        }
7448
7449                        targetRect = target.getBoundingClientRect();
7450
7451                        var width = targetRect.right - targetRect.left,
7452                            height = targetRect.bottom - targetRect.top,
7453                            floating =
7454                                /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display) ||
7455                                (lastParentCSS.display == "flex" &&
7456                                    lastParentCSS["flex-direction"].indexOf("row") === 0),
7457                            isWide = target.offsetWidth > dragEl.offsetWidth,
7458                            isLong = target.offsetHeight > dragEl.offsetHeight,
7459                            halfway =
7460                                (floating
7461                                    ? (evt.clientX - targetRect.left) / width
7462                                    : (evt.clientY - targetRect.top) / height) > 0.5,
7463                            nextSibling = target.nextElementSibling,
7464                            moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt),
7465                            after;
7466
7467                        if (moveVector !== false) {
7468                            _silent = true;
7469                            setTimeout(_unsilent, 30);
7470
7471                            _cloneHide(isOwner);
7472
7473                            if (moveVector === 1 || moveVector === -1) {
7474                                after = moveVector === 1;
7475                            } else if (floating) {
7476                                var elTop = dragEl.offsetTop,
7477                                    tgTop = target.offsetTop;
7478
7479                                if (elTop === tgTop) {
7480                                    after =
7481                                        (target.previousElementSibling === dragEl && !isWide) ||
7482                                        (halfway && isWide);
7483                                } else if (
7484                                    target.previousElementSibling === dragEl ||
7485                                    dragEl.previousElementSibling === target
7486                                ) {
7487                                    after = (evt.clientY - targetRect.top) / height > 0.5;
7488                                } else {
7489                                    after = tgTop > elTop;
7490                                }
7491                            } else {
7492                                after = (nextSibling !== dragEl && !isLong) || (halfway && isLong);
7493                            }
7494
7495                            if (!dragEl.contains(el)) {
7496                                if (after && !nextSibling) {
7497                                    el.appendChild(dragEl);
7498                                } else {
7499                                    target.parentNode.insertBefore(
7500                                        dragEl,
7501                                        after ? nextSibling : target
7502                                    );
7503                                }
7504                            }
7505
7506                            parentEl = dragEl.parentNode; // actualization
7507
7508                            this._animate(dragRect, dragEl);
7509                            this._animate(targetRect, target);
7510                        }
7511                    }
7512                }
7513            },
7514
7515            _animate: function (prevRect, target) {
7516                var ms = this.options.animation;
7517
7518                if (ms) {
7519                    var currentRect = target.getBoundingClientRect();
7520
7521                    _css(target, "transition", "none");
7522                    _css(
7523                        target,
7524                        "transform",
7525                        "translate3d(" +
7526                            (prevRect.left - currentRect.left) +
7527                            "px," +
7528                            (prevRect.top - currentRect.top) +
7529                            "px,0)"
7530                    );
7531
7532                    target.offsetWidth; // repaint
7533
7534                    _css(target, "transition", "all " + ms + "ms");
7535                    _css(target, "transform", "translate3d(0,0,0)");
7536
7537                    clearTimeout(target.animated);
7538                    target.animated = setTimeout(function () {
7539                        _css(target, "transition", "");
7540                        _css(target, "transform", "");
7541                        target.animated = false;
7542                    }, ms);
7543                }
7544            },
7545
7546            _offUpEvents: function () {
7547                var ownerDocument = this.el.ownerDocument;
7548
7549                _off(document, "touchmove", this._onTouchMove);
7550                _off(ownerDocument, "mouseup", this._onDrop);
7551                _off(ownerDocument, "touchend", this._onDrop);
7552                _off(ownerDocument, "touchcancel", this._onDrop);
7553            },
7554
7555            _onDrop: function (/**Event*/ evt) {
7556                var el = this.el,
7557                    options = this.options;
7558
7559                clearInterval(this._loopId);
7560                clearInterval(autoScroll.pid);
7561                clearTimeout(this._dragStartTimer);
7562
7563                // Unbind events
7564                _off(document, "mousemove", this._onTouchMove);
7565
7566                if (this.nativeDraggable) {
7567                    _off(document, "drop", this);
7568                    _off(el, "dragstart", this._onDragStart);
7569                }
7570
7571                this._offUpEvents();
7572
7573                if (evt) {
7574                    if (moved) {
7575                        evt.preventDefault();
7576                        !options.dropBubble && evt.stopPropagation();
7577                    }
7578
7579                    ghostEl && ghostEl.parentNode.removeChild(ghostEl);
7580
7581                    if (dragEl) {
7582                        if (this.nativeDraggable) {
7583                            _off(dragEl, "dragend", this);
7584                        }
7585
7586                        _disableDraggable(dragEl);
7587                        dragEl.style["will-change"] = "";
7588
7589                        // Remove class's
7590                        _toggleClass(dragEl, this.options.ghostClass, false);
7591                        _toggleClass(dragEl, this.options.chosenClass, false);
7592
7593                        if (rootEl !== parentEl) {
7594                            newIndex = _index(dragEl, options.draggable);
7595
7596                            if (newIndex >= 0) {
7597                                // Add event
7598                                _dispatchEvent(
7599                                    null,
7600                                    parentEl,
7601                                    "add",
7602                                    dragEl,
7603                                    rootEl,
7604                                    oldIndex,
7605                                    newIndex
7606                                );
7607
7608                                // Remove event
7609                                _dispatchEvent(
7610                                    this,
7611                                    rootEl,
7612                                    "remove",
7613                                    dragEl,
7614                                    rootEl,
7615                                    oldIndex,
7616                                    newIndex
7617                                );
7618
7619                                // drag from one list and drop into another
7620                                _dispatchEvent(
7621                                    null,
7622                                    parentEl,
7623                                    "sort",
7624                                    dragEl,
7625                                    rootEl,
7626                                    oldIndex,
7627                                    newIndex
7628                                );
7629                                _dispatchEvent(
7630                                    this,
7631                                    rootEl,
7632                                    "sort",
7633                                    dragEl,
7634                                    rootEl,
7635                                    oldIndex,
7636                                    newIndex
7637                                );
7638                            }
7639                        } else {
7640                            // Remove clone
7641                            cloneEl && cloneEl.parentNode.removeChild(cloneEl);
7642
7643                            if (dragEl.nextSibling !== nextEl) {
7644                                // Get the index of the dragged element within its parent
7645                                newIndex = _index(dragEl, options.draggable);
7646
7647                                if (newIndex >= 0) {
7648                                    // drag & drop within the same list
7649                                    _dispatchEvent(
7650                                        this,
7651                                        rootEl,
7652                                        "update",
7653                                        dragEl,
7654                                        rootEl,
7655                                        oldIndex,
7656                                        newIndex
7657                                    );
7658                                    _dispatchEvent(
7659                                        this,
7660                                        rootEl,
7661                                        "sort",
7662                                        dragEl,
7663                                        rootEl,
7664                                        oldIndex,
7665                                        newIndex
7666                                    );
7667                                }
7668                            }
7669                        }
7670
7671                        if (Sortable.active) {
7672                            /* jshint eqnull:true */
7673                            if (newIndex == null || newIndex === -1) {
7674                                newIndex = oldIndex;
7675                            }
7676
7677                            _dispatchEvent(this, rootEl, "end", dragEl, rootEl, oldIndex, newIndex);
7678
7679                            // Save sorting
7680                            this.save();
7681                        }
7682                    }
7683                }
7684
7685                this._nulling();
7686            },
7687
7688            _nulling: function () {
7689                rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = scrollEl = scrollParentEl = tapEvt = touchEvt = moved = newIndex = lastEl = lastCSS = putSortable = activeGroup = Sortable.active = null;
7690            },
7691
7692            handleEvent: function (/**Event*/ evt) {
7693                var type = evt.type;
7694
7695                if (type === "dragover" || type === "dragenter") {
7696                    if (dragEl) {
7697                        this._onDragOver(evt);
7698                        _globalDragOver(evt);
7699                    }
7700                } else if (type === "drop" || type === "dragend") {
7701                    this._onDrop(evt);
7702                }
7703            },
7704
7705            /**
7706             * Serializes the item into an array of string.
7707             * @returns {String[]}
7708             */
7709            toArray: function () {
7710                var order = [],
7711                    el,
7712                    children = this.el.children,
7713                    i = 0,
7714                    n = children.length,
7715                    options = this.options;
7716
7717                for (; i < n; i++) {
7718                    el = children[i];
7719                    if (_closest(el, options.draggable, this.el)) {
7720                        order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
7721                    }
7722                }
7723
7724                return order;
7725            },
7726
7727            /**
7728             * Sorts the elements according to the array.
7729             * @param  {String[]}  order  order of the items
7730             */
7731            sort: function (order) {
7732                var items = {},
7733                    rootEl = this.el;
7734
7735                this.toArray().forEach(function (id, i) {
7736                    var el = rootEl.children[i];
7737
7738                    if (_closest(el, this.options.draggable, rootEl)) {
7739                        items[id] = el;
7740                    }
7741                }, this);
7742
7743                order.forEach(function (id) {
7744                    if (items[id]) {
7745                        rootEl.removeChild(items[id]);
7746                        rootEl.appendChild(items[id]);
7747                    }
7748                });
7749            },
7750
7751            /**
7752             * Save the current sorting
7753             */
7754            save: function () {
7755                var store = this.options.store;
7756                store && store.set(this);
7757            },
7758
7759            /**
7760             * 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.
7761             * @param   {HTMLElement}  el
7762             * @param   {String}       [selector]  default: `options.draggable`
7763             * @returns {HTMLElement|null}
7764             */
7765            closest: function (el, selector) {
7766                return _closest(el, selector || this.options.draggable, this.el);
7767            },
7768
7769            /**
7770             * Set/get option
7771             * @param   {string} name
7772             * @param   {*}      [value]
7773             * @returns {*}
7774             */
7775            option: function (name, value) {
7776                var options = this.options;
7777
7778                if (value === void 0) {
7779                    return options[name];
7780                } else {
7781                    options[name] = value;
7782
7783                    if (name === "group") {
7784                        _prepareGroup(options);
7785                    }
7786                }
7787            },
7788
7789            /**
7790             * Destroy
7791             */
7792            destroy: function () {
7793                var el = this.el;
7794
7795                el[expando] = null;
7796
7797                _off(el, "mousedown", this._onTapStart);
7798                _off(el, "touchstart", this._onTapStart);
7799
7800                if (this.nativeDraggable) {
7801                    _off(el, "dragover", this);
7802                    _off(el, "dragenter", this);
7803                }
7804
7805                // Remove draggable attributes
7806                Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function (el) {
7807                    el.removeAttribute("draggable");
7808                });
7809
7810                touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
7811
7812                this._onDrop();
7813
7814                this.el = el = null;
7815            },
7816        };
7817
7818        function _cloneHide(state) {
7819            if (cloneEl && cloneEl.state !== state) {
7820                _css(cloneEl, "display", state ? "none" : "");
7821                !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl);
7822                cloneEl.state = state;
7823            }
7824        }
7825
7826        function _closest(/**HTMLElement*/ el, /**String*/ selector, /**HTMLElement*/ ctx) {
7827            if (el) {
7828                ctx = ctx || document;
7829
7830                do {
7831                    if ((selector === ">*" && el.parentNode === ctx) || _matches(el, selector)) {
7832                        return el;
7833                    }
7834                    /* jshint boss:true */
7835                } while ((el = _getParentOrHost(el)));
7836            }
7837
7838            return null;
7839        }
7840
7841        function _getParentOrHost(el) {
7842            var parent = el.host;
7843
7844            return parent && parent.nodeType ? parent : el.parentNode;
7845        }
7846
7847        function _globalDragOver(/**Event*/ evt) {
7848            if (evt.dataTransfer) {
7849                evt.dataTransfer.dropEffect = "move";
7850            }
7851            evt.preventDefault();
7852        }
7853
7854        function _on(el, event, fn) {
7855            el.addEventListener(event, fn, false);
7856        }
7857
7858        function _off(el, event, fn) {
7859            el.removeEventListener(event, fn, false);
7860        }
7861
7862        function _toggleClass(el, name, state) {
7863            if (el) {
7864                if (el.classList) {
7865                    el.classList[state ? "add" : "remove"](name);
7866                } else {
7867                    var className = (" " + el.className + " ")
7868                        .replace(RSPACE, " ")
7869                        .replace(" " + name + " ", " ");
7870                    el.className = (className + (state ? " " + name : "")).replace(RSPACE, " ");
7871                }
7872            }
7873        }
7874
7875        function _css(el, prop, val) {
7876            var style = el && el.style;
7877
7878            if (style) {
7879                if (val === void 0) {
7880                    if (document.defaultView && document.defaultView.getComputedStyle) {
7881                        val = document.defaultView.getComputedStyle(el, "");
7882                    } else if (el.currentStyle) {
7883                        val = el.currentStyle;
7884                    }
7885
7886                    return prop === void 0 ? val : val[prop];
7887                } else {
7888                    if (!(prop in style)) {
7889                        prop = "-webkit-" + prop;
7890                    }
7891
7892                    style[prop] = val + (typeof val === "string" ? "" : "px");
7893                }
7894            }
7895        }
7896
7897        function _find(ctx, tagName, iterator) {
7898            if (ctx) {
7899                var list = ctx.getElementsByTagName(tagName),
7900                    i = 0,
7901                    n = list.length;
7902
7903                if (iterator) {
7904                    for (; i < n; i++) {
7905                        iterator(list[i], i);
7906                    }
7907                }
7908
7909                return list;
7910            }
7911
7912            return [];
7913        }
7914
7915        function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) {
7916            sortable = sortable || rootEl[expando];
7917
7918            var evt = document.createEvent("Event"),
7919                options = sortable.options,
7920                onName = "on" + name.charAt(0).toUpperCase() + name.substr(1);
7921
7922            evt.initEvent(name, true, true);
7923
7924            evt.to = rootEl;
7925            evt.from = fromEl || rootEl;
7926            evt.item = targetEl || rootEl;
7927            evt.clone = cloneEl;
7928
7929            evt.oldIndex = startIndex;
7930            evt.newIndex = newIndex;
7931
7932            rootEl.dispatchEvent(evt);
7933
7934            if (options[onName]) {
7935                options[onName].call(sortable, evt);
7936            }
7937        }
7938
7939        function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt) {
7940            var evt,
7941                sortable = fromEl[expando],
7942                onMoveFn = sortable.options.onMove,
7943                retVal;
7944
7945            evt = document.createEvent("Event");
7946            evt.initEvent("move", true, true);
7947
7948            evt.to = toEl;
7949            evt.from = fromEl;
7950            evt.dragged = dragEl;
7951            evt.draggedRect = dragRect;
7952            evt.related = targetEl || toEl;
7953            evt.relatedRect = targetRect || toEl.getBoundingClientRect();
7954
7955            fromEl.dispatchEvent(evt);
7956
7957            if (onMoveFn) {
7958                retVal = onMoveFn.call(sortable, evt, originalEvt);
7959            }
7960
7961            return retVal;
7962        }
7963
7964        function _disableDraggable(el) {
7965            el.draggable = false;
7966        }
7967
7968        function _unsilent() {
7969            _silent = false;
7970        }
7971
7972        /** @returns {HTMLElement|false} */
7973        function _ghostIsLast(el, evt) {
7974            var lastEl = el.lastElementChild,
7975                rect = lastEl.getBoundingClientRect();
7976
7977            // 5 — min delta
7978            // abs — нельзя добавлять, а то глюки при наведении сверху
7979            return (
7980                (evt.clientY - (rect.top + rect.height) > 5 ||
7981                    evt.clientX - (rect.right + rect.width) > 5) &&
7982                lastEl
7983            );
7984        }
7985
7986        /**
7987         * Generate id
7988         * @param   {HTMLElement} el
7989         * @returns {String}
7990         * @private
7991         */
7992        function _generateId(el) {
7993            var str = el.tagName + el.className + el.src + el.href + el.textContent,
7994                i = str.length,
7995                sum = 0;
7996
7997            while (i--) {
7998                sum += str.charCodeAt(i);
7999            }
8000
8001            return sum.toString(36);
8002        }
8003
8004        /**
8005         * Returns the index of an element within its parent for a selected set of
8006         * elements
8007         * @param  {HTMLElement} el
8008         * @param  {selector} selector
8009         * @return {number}
8010         */
8011        function _index(el, selector) {
8012            var index = 0;
8013
8014            if (!el || !el.parentNode) {
8015                return -1;
8016            }
8017
8018            while (el && (el = el.previousElementSibling)) {
8019                if (
8020                    el.nodeName.toUpperCase() !== "TEMPLATE" &&
8021                    (selector === ">*" || _matches(el, selector))
8022                ) {
8023                    index++;
8024                }
8025            }
8026
8027            return index;
8028        }
8029
8030        function _matches(/**HTMLElement*/ el, /**String*/ selector) {
8031            if (el) {
8032                selector = selector.split(".");
8033
8034                var tag = selector.shift().toUpperCase(),
8035                    re = new RegExp("\\s(" + selector.join("|") + ")(?=\\s)", "g");
8036
8037                return (
8038                    (tag === "" || el.nodeName.toUpperCase() == tag) &&
8039                    (!selector.length ||
8040                        ((" " + el.className + " ").match(re) || []).length == selector.length)
8041                );
8042            }
8043
8044            return false;
8045        }
8046
8047        function _throttle(callback, ms) {
8048            var args, _this;
8049
8050            return function () {
8051                if (args === void 0) {
8052                    args = arguments;
8053                    _this = this;
8054
8055                    setTimeout(function () {
8056                        if (args.length === 1) {
8057                            callback.call(_this, args[0]);
8058                        } else {
8059                            callback.apply(_this, args);
8060                        }
8061
8062                        args = void 0;
8063                    }, ms);
8064                }
8065            };
8066        }
8067
8068        function _extend(dst, src) {
8069            if (dst && src) {
8070                for (var key in src) {
8071                    if (src.hasOwnProperty(key)) {
8072                        dst[key] = src[key];
8073                    }
8074                }
8075            }
8076
8077            return dst;
8078        }
8079
8080        function _clone(el) {
8081            return $
8082                ? $(el).clone(true)[0]
8083                : Polymer && Polymer.dom
8084                ? Polymer.dom(el).cloneNode(true)
8085                : el.cloneNode(true);
8086        }
8087
8088        // Export utils
8089        Sortable.utils = {
8090            on: _on,
8091            off: _off,
8092            css: _css,
8093            find: _find,
8094            is: function (el, selector) {
8095                return !!_closest(el, selector, el);
8096            },
8097            extend: _extend,
8098            throttle: _throttle,
8099            closest: _closest,
8100            toggleClass: _toggleClass,
8101            clone: _clone,
8102            index: _index,
8103        };
8104
8105        /**
8106         * Create sortable instance
8107         * @param {HTMLElement}  el
8108         * @param {Object}      [options]
8109         */
8110        Sortable.create = function (el, options) {
8111            return new Sortable(el, options);
8112        };
8113
8114        // Export
8115        Sortable.version = "1.4.2";
8116        return Sortable;
8117    });
8118    });
8119
8120    const $$h = jQuery;
8121    class ImagesFormElement extends FormElement {
8122        constructor(options, formBuilder, external) {
8123            super(options, formBuilder, external);
8124            this.searchType = options.searchType || "fulltext";
8125            this.mediaUploader = external.mediaUploader;
8126            this.button_text = options.button_text || "Browse...";
8127            this.db_type = "text";
8128            this.label = options.label || "Images";
8129            this.name = options.name || "images";
8130            this.images = this.value || [];
8131            this.value = JSON.stringify(this.value);
8132        }
8133        init() {
8134            super.init();
8135            this.redrawImages();
8136        }
8137        setDomElements() {
8138            super.setDomElements();
8139        }
8140        getData() {
8141            this.updateData();
8142            return { name: this.name, value: this.images };
8143        }
8144        getSchema() {
8145            const schema = super.getSchema();
8146            schema.button_text = this.button_text;
8147            return schema;
8148        }
8149        updateData() {
8150            const newListOfImages = [];
8151            $$h(this.domElements.main)
8152                .find(".mapsvg-thumbnail-wrap")
8153                .each(function (index, el) {
8154                const imageData = $$h(el).data("image");
8155                newListOfImages.push(imageData);
8156            });
8157            this.images = newListOfImages;
8158            this.value = JSON.stringify(this.images);
8159            $$h(this.domElements.main).find("input").val(this.value);
8160        }
8161        setEventHandlers() {
8162            super.setEventHandlers();
8163            if (this.formBuilder.editMode) {
8164                return;
8165            }
8166            const _this = this;
8167            const imageDOM = $$h(this.domElements.main).find(".mapsvg-data-images");
8168            this.external.mediaUploader.on("select", () => {
8169                if (_this.formBuilder.mediaUploaderisOpenedFor !== _this)
8170                    return false;
8171                const attachments = _this.external.mediaUploader.state().get("selection").toJSON();
8172                attachments.forEach(function (img) {
8173                    const image = { sizes: {} };
8174                    for (const type in img.sizes) {
8175                        image[type] = img.sizes[type].url
8176                            .replace("http://", "//")
8177                            .replace("https://", "//");
8178                        image.sizes[type] = {
8179                            width: img.sizes[type].width,
8180                            height: img.sizes[type].height,
8181                        };
8182                    }
8183                    if (!image.thumbnail) {
8184                        image.thumbnail = image.full;
8185                        image.sizes.thumbnail = {
8186                            width: img.sizes.full.width,
8187                            height: img.sizes.full.height,
8188                        };
8189                    }
8190                    if (!image.medium) {
8191                        image.medium = image.full;
8192                        image.sizes.medium = {
8193                            width: img.sizes.full.width,
8194                            height: img.sizes.full.height,
8195                        };
8196                    }
8197                    image.caption = img.caption;
8198                    image.description = img.description;
8199                    _this.images.push(image);
8200                });
8201                this.setValue(this.images);
8202                _this.redrawImages();
8203            });
8204            $$h(_this.domElements.main).on("click", ".mapsvg-upload-image", function (e) {
8205                e.preventDefault();
8206                _this.formBuilder.mediaUploaderisOpenedFor = _this;
8207                _this.external.mediaUploader.open();
8208            });
8209            $$h(_this.domElements.main).on("click", ".mapsvg-image-delete", function (e) {
8210                e.preventDefault();
8211                $$h(this).closest(".mapsvg-thumbnail-wrap").remove();
8212                _this.updateData();
8213            });
8214            _this.sortable = new sortable_min(imageDOM[0], {
8215                animation: 150,
8216                onStart: function () {
8217                    $$h(_this.domElements.main).addClass("sorting");
8218                },
8219                onEnd: function (evt) {
8220                    _this.images = [];
8221                    $$h(_this.domElements.main)
8222                        .find("img")
8223                        .each(function (i, image) {
8224                        _this.images.push($$h(image).data("image"));
8225                    });
8226                    this.value = JSON.stringify(_this.images);
8227                    $$h(_this.domElements.main).find("input").val(this.value);
8228                    $$h(_this.domElements.main).removeClass("sorting");
8229                },
8230            });
8231        }
8232        redrawImages() {
8233            const imageDOM = $$h(this.domElements.main).find(".mapsvg-data-images");
8234            imageDOM.empty();
8235            this.images &&
8236                this.images.forEach(function (image) {
8237                    const img = $$h('<img class="mapsvg-data-thumbnail" />')
8238                        .attr("src", image.thumbnail)
8239                        .data("image", image);
8240                    const imgContainer = $$h('<div class="mapsvg-thumbnail-wrap"></div>').data("image", image);
8241                    imgContainer.append(img);
8242                    imgContainer.append('<i class="mfa mfa-times  mapsvg-image-delete"></i>');
8243                    imageDOM.append(imgContainer);
8244                });
8245            $$h(this.domElements.main).find("input").val(this.value);
8246        }
8247        destroy() {
8248            super.destroy();
8249            this.external.mediaUploader.off("select");
8250        }
8251    }
8252
8253    const $$i = jQuery;
8254    class LocationFormElement extends FormElement {
8255        constructor(options, formBuilder, external) {
8256            super(options, formBuilder, external);
8257            this.label = this.label || (options.label === undefined ? "Location" : options.label);
8258            this.name = "location";
8259            this.db_type = "text";
8260            this.languages = [
8261                { value: "sq", label: "Albanian" },
8262                { value: "ar", label: "Arabic" },
8263                {
8264                    value: "eu",
8265                    label: "Basque",
8266                },
8267                { value: "be", label: "Belarusian" },
8268                { value: "bg", label: "Bulgarian" },
8269                {
8270                    value: "my",
8271                    label: "Burmese",
8272                },
8273                { value: "bn", label: "Bengali" },
8274                { value: "ca", label: "Catalan" },
8275                {
8276                    value: "zh-cn",
8277                    label: "Chinese (simplified)",
8278                },
8279                { value: "zh-tw", label: "Chinese (traditional)" },
8280                {
8281                    value: "hr",
8282                    label: "Croatian",
8283                },
8284                { value: "cs", label: "Czech" },
8285                { value: "da", label: "Danish" },
8286                {
8287                    value: "nl",
8288                    label: "Dutch",
8289                },
8290                { value: "en", label: "English" },
8291                {
8292                    value: "en-au",
8293                    label: "English (australian)",
8294                },
8295                { value: "en-gb", label: "English (great Britain)" },
8296                {
8297                    value: "fa",
8298                    label: "Farsi",
8299                },
8300                { value: "fi", label: "Finnish" },
8301                { value: "fil", label: "Filipino" },
8302                {
8303                    value: "fr",
8304                    label: "French",
8305                },
8306                { value: "gl", label: "Galician" },
8307                { value: "de", label: "German" },
8308                {
8309                    value: "el",
8310                    label: "Greek",
8311                },
8312                { value: "gu", label: "Gujarati" },
8313                { value: "iw", label: "Hebrew" },
8314                {
8315                    value: "hi",
8316                    label: "Hindi",
8317                },
8318                { value: "hu", label: "Hungarian" },
8319                { value: "id", label: "Indonesian" },
8320                {
8321                    value: "it",
8322                    label: "Italian",
8323                },
8324                { value: "ja", label: "Japanese" },
8325                { value: "kn", label: "Kannada" },
8326                {
8327                    value: "kk",
8328                    label: "Kazakh",
8329                },
8330                { value: "ko", label: "Korean" },
8331                { value: "ky", label: "Kyrgyz" },
8332                {
8333                    value: "lt",
8334                    label: "Lithuanian",
8335                },
8336                { value: "lv", label: "Latvian" },
8337                { value: "mk", label: "Macedonian" },
8338                {
8339                    value: "ml",
8340                    label: "Malayalam",
8341                },
8342                { value: "mr", label: "Marathi" },
8343                { value: "no", label: "Norwegian" },
8344                {
8345                    value: "pl",
8346                    label: "Polish",
8347                },
8348                { value: "pt", label: "Portuguese" },
8349                {
8350                    value: "pt-br",
8351                    label: "Portuguese (brazil)",
8352                },
8353                { value: "pt-pt", label: "Portuguese (portugal)" },
8354                {
8355                    value: "pa",
8356                    label: "Punjabi",
8357                },
8358                { value: "ro", label: "Romanian" },
8359                { value: "ru", label: "Russian" },
8360                {
8361                    value: "sr",
8362                    label: "Serbian",
8363                },
8364                { value: "sk", label: "Slovak" },
8365                { value: "sl", label: "Slovenian" },
8366                {
8367                    value: "es",
8368                    label: "Spanish",
8369                },
8370                { value: "sv", label: "Swedish" },
8371                { value: "tl", label: "Tagalog" },
8372                {
8373                    value: "ta",
8374                    label: "Tamil",
8375                },
8376                { value: "te", label: "Telugu" },
8377                { value: "th", label: "Thai" },
8378                {
8379                    value: "tr",
8380                    label: "Turkish",
8381                },
8382                { value: "uk", label: "Ukrainian" },
8383                { value: "uz", label: "Uzbek" },
8384                {
8385                    value: "vi",
8386                    label: "Vietnamese",
8387                },
8388            ];
8389            this.language = options.language;
8390            this.markerImages = MapSVG.markerImages;
8391            this.markersByField = options.markersByField;
8392            this.markerField = options.markerField;
8393            this.markersByFieldEnabled = MapSVG.parseBoolean(options.markersByFieldEnabled);
8394            this.defaultMarkerPath =
8395                options.defaultMarkerPath ||
8396                    this.formBuilder.mapsvg.getData().options.defaultMarkerImage;
8397            this.templates.marker = Handlebars.compile($$i("#mapsvg-data-tmpl-marker").html());
8398        }
8399        init() {
8400            super.init();
8401            if (this.value) {
8402                this.renderMarker();
8403            }
8404            this.renderMarkerSelector();
8405        }
8406        getSchema() {
8407            const schema = super.getSchema();
8408            schema.language = this.language;
8409            schema.defaultMarkerPath = this.defaultMarkerPath;
8410            schema.markersByField = this.markersByField;
8411            schema.markerField = this.markerField;
8412            schema.markersByFieldEnabled = MapSVG.parseBoolean(this.markersByFieldEnabled);
8413            return schema;
8414        }
8415        getData() {
8416            return { name: this.name, value: this.value };
8417        }
8418        getDataForTemplate() {
8419            const data = super.getDataForTemplate();
8420            if (this.formBuilder.admin) {
8421                data.languages = this.languages;
8422                data.markerImages = MapSVG.markerImages;
8423                data.markersByField = this.markersByField;
8424                data.markerField = this.markerField;
8425                data.markersByFieldEnabled = MapSVG.parseBoolean(this.markersByFieldEnabled);
8426                const _this = this;
8427                data.markerImages.forEach(function (m) {
8428                    if (m.relativeUrl === _this.defaultMarkerPath) {
8429                        m.default = true;
8430                    }
8431                    else {
8432                        m.default = false;
8433                    }
8434                });
8435            }
8436            data.language = this.language;
8437            if (this.value) {
8438                data.location = this.value;
8439                if (data.location.marker) {
8440                    data.location.img =
8441                        (this.value.marker.src.indexOf(MapSVG.urls.uploads) === 0 ? "uploads/" : "") +
8442                            this.value.marker.src.split("/").pop();
8443                }
8444            }
8445            data.showUploadBtn = data.external.filtersMode;
8446            return data;
8447        }
8448        initEditor() {
8449            super.initEditor();
8450            this.renderMarkerSelector();
8451            this.fillMarkersByFieldOptions(this.markerField);
8452        }
8453        setDomElements() {
8454            super.setDomElements();
8455            this.domElements.markerImageButton = $$i(this.domElements.main).find("img")[0];
8456        }
8457        setEventHandlers() {
8458            super.setEventHandlers();
8459            const _this = this;
8460            const server = new Server();
8461            if (_this.formBuilder.mapsvg.isGeo()) {
8462                const locations = new Bloodhound({
8463                    datumTokenizer: Bloodhound.tokenizers.obj.whitespace("formatted_address"),
8464                    queryTokenizer: Bloodhound.tokenizers.whitespace,
8465                    remote: {
8466                        url: server.getUrl("geocoding") + "?address=%QUERY%&language=" + this.language,
8467                        wildcard: "%QUERY%",
8468                        transform: function (response) {
8469                            if (response.error_message) {
8470                                alert(response.error_message);
8471                            }
8472                            return response.results;
8473                        },
8474                        rateLimitWait: 600,
8475                    },
8476                });
8477                const thContainer = $$i(this.domElements.main).find(".typeahead");
8478                const tH = thContainer
8479                    .typeahead({ minLength: 3 }, {
8480                    name: "mapsvg-addresses",
8481                    display: "formatted_address",
8482                    async: true,
8483                    source: (query, sync, async) => {
8484                        const preg = new RegExp(/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/);
8485                        if (preg.test(query)) {
8486                            const latlng = query.split(",").map((item) => item.trim());
8487                            const item = {
8488                                formatted_address: latlng.join(","),
8489                                address_components: [],
8490                                geometry: {
8491                                    location: {
8492                                        lat: () => latlng[0],
8493                                        lng: () => latlng[1],
8494                                    },
8495                                },
8496                            };
8497                            sync([item]);
8498                            return;
8499                        }
8500                        MapSVG.geocode({ address: query }, async);
8501                    },
8502                })
8503                    .on("typeahead:asyncrequest", function (e) {
8504                    $$i(e.target).addClass("tt-loading");
8505                })
8506                    .on("typeahead:asynccancel typeahead:asyncreceive", function (e) {
8507                    $$i(e.target).removeClass("tt-loading");
8508                });
8509                thContainer.on("typeahead:select", (ev, item) => {
8510                    this.setValue(null, false);
8511                    const address = {};
8512                    address.formatted = item.formatted_address;
8513                    item.address_components.forEach((addr_item) => {
8514                        const type = addr_item.types[0];
8515                        address[type] = addr_item.long_name;
8516                        if (addr_item.short_name != addr_item.long_name) {
8517                            address[type + "_short"] = addr_item.short_name;
8518                        }
8519                    });
8520                    const locationData = {
8521                        address: address,
8522                        geoPoint: new GeoPoint(item.geometry.location.lat(), item.geometry.location.lng()),
8523                        img: this.getMarkerImage(this.formBuilder.getData()),
8524                        imagePath: this.getMarkerImage(this.formBuilder.getData()),
8525                    };
8526                    this.setValue(locationData, false);
8527                    thContainer.typeahead("val", "");
8528                    this.triggerChanged();
8529                });
8530            }
8531            $$i(this.domElements.main).on("change", ".marker-file-uploader", function () {
8532                _this.markerIconUpload(this);
8533            });
8534            $$i(this.domElements.main).on("click", ".mapsvg-marker-image-btn-trigger", function (e) {
8535                e.preventDefault();
8536                $$i(this).toggleClass("active");
8537                _this.toggleMarkerSelector();
8538            });
8539            $$i(this.domElements.main).on("click", ".mapsvg-marker-delete", function (e) {
8540                e.preventDefault();
8541                _this.setValue(null);
8542                _this.triggerChanged();
8543            });
8544        }
8545        setEditorEventHandlers() {
8546            super.setEditorEventHandlers();
8547            const _this = this;
8548            $$i(this.domElements.edit).on("change", ".marker-file-uploader", function () {
8549                _this.markerIconUpload(this);
8550            });
8551            $$i(this.domElements.edit).on("change", 'select[name="markerField"]', function () {
8552                const fieldName = $$i(this).val();
8553                _this.resetMarkersByField();
8554                const newOptions = _this.fillMarkersByFieldOptions(fieldName);
8555                _this.setMarkersByField(newOptions);
8556            });
8557            $$i(this.domElements.edit).on("click", ".mapsvg-marker-image-selector button", function (e) {
8558                e.preventDefault();
8559                const src = $$i(this).find("img").attr("src");
8560                $$i(this).parent().find("button").removeClass("active");
8561                $$i(this).addClass("active");
8562                _this.setDefaultMarkerPath(src);
8563            });
8564            $$i(this.domElements.edit).on("click", ".mapsvg-marker-image-btn-trigger", function (e) {
8565                $$i(this).toggleClass("active");
8566                _this.toggleMarkerSelectorInLocationEditor.call(_this, $$i(this), e);
8567            });
8568        }
8569        markerIconUpload(input) {
8570            const uploadBtn = $$i(input).closest(".btn-file").buttonLoading(true);
8571            for (let i = 0; i < input.files.length; i++) {
8572                const data = new FormData();
8573                data.append("file", input.files[0]);
8574                const server = new Server();
8575                server
8576                    .ajax("markers", {
8577                    type: "POST",
8578                    data: data,
8579                    processData: false,
8580                    contentType: false,
8581                })
8582                    .done((resp) => {
8583                    if (resp.error) {
8584                        alert(resp.error);
8585                    }
8586                    else {
8587                        const marker = resp.marker;
8588                        const newMarker = `
8589                            <button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose active">
8590                                <img src="${marker.relativeUrl}" />
8591                            </button>
8592                            </button>
8593                        `;
8594                        $$i(this.domElements.markerSelector)
8595                            .find(".mapsvg-marker-image-btn.active")
8596                            .removeClass("active");
8597                        $$i(newMarker).appendTo(this.domElements.markerSelector);
8598                        this.setMarkerImage(marker.relativeUrl);
8599                        MapSVG.markerImages.push(marker);
8600                    }
8601                })
8602                    .always(function () {
8603                    uploadBtn.buttonLoading(false);
8604                });
8605            }
8606        }
8607        mayBeAddDistanceRow() {
8608            const _this = this;
8609            if (!this.domElements.editDistanceRow) {
8610                this.domElements.editDistanceRow = $$i($$i("#mapsvg-edit-distance-row").html())[0];
8611            }
8612            const z = $$i(this.domElements.edit).find(".mapsvg-edit-distance-row:last-child input");
8613            if (z && z.last() && z.last().val() && (z.last().val() + "").trim().length) {
8614                const newRow = $$i(this.templates.editDistanceRow).clone();
8615                newRow.insertAfter($$i(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child"));
8616            }
8617            const rows = $$i(_this.domElements.edit).find(".mapsvg-edit-distance-row");
8618            const row1 = rows.eq(rows.length - 2);
8619            const row2 = rows.eq(rows.length - 1);
8620            if (row1.length &&
8621                row2.length &&
8622                !row1.find("input:eq(0)").val().toString().trim() &&
8623                !row2.find("input:eq(0)").val().toString().trim()) {
8624                row2.remove();
8625            }
8626        }
8627        fillMarkersByFieldOptions(fieldName) {
8628            const _this = this;
8629            const field = _this.formBuilder.mapsvg.objectsRepository.getSchema().getField(fieldName);
8630            const options = {};
8631            if (field) {
8632                const markerImg = _this.formBuilder.mapsvg.options.defaultMarkerImage;
8633                const rows = [];
8634                field.options.forEach(function (option) {
8635                    const value = field.type === "region" ? option.id : option.value;
8636                    const label = field.type === "region" ? option.title || option.id : option.label;
8637                    const img = _this.markersByField && _this.markersByField[value]
8638                        ? _this.markersByField[value]
8639                        : markerImg;
8640                    rows.push('<tr data-option-id="' +
8641                        value +
8642                        '"><td>' +
8643                        label +
8644                        '</td><td><button class="btn dropdown-toggle btn-outline-secondary mapsvg-marker-image-btn-trigger mapsvg-marker-image-btn"><img src="' +
8645                        img +
8646                        '" class="new-marker-img" /><span class="caret"></span></button></td></tr>');
8647                    options[value] = img;
8648                });
8649                $$i("#markers-by-field").empty().append(rows);
8650            }
8651            return options;
8652        }
8653        renderMarker(marker) {
8654            if (marker && marker.location) {
8655                this.value = marker.location.getData();
8656            }
8657            this.renderMarkerHtml();
8658        }
8659        renderMarkerHtml() {
8660            if (!this.value) {
8661                $$i(this.domElements.main).find(".mapsvg-new-marker").hide();
8662            }
8663            else {
8664                $$i(this.domElements.main)
8665                    .find(".mapsvg-new-marker")
8666                    .show()
8667                    .html(this.templates.marker(this.value));
8668            }
8669        }
8670        toggleMarkerSelector() {
8671            if (this.domElements.markerSelectorWrap &&
8672                $$i(this.domElements.markerSelectorWrap).is(":visible")) {
8673                $$i(this.domElements.markerSelectorWrap).hide();
8674                return;
8675            }
8676            if (this.domElements.markerSelectorWrap &&
8677                $$i(this.domElements.markerSelectorWrap).not(":visible")) {
8678                $$i(this.domElements.markerSelector).find(".active").removeClass("active");
8679                if (this.value && this.value.markerImagePath) {
8680                    $$i(this.domElements.markerSelector)
8681                        .find('[src="' + this.value.markerImagePath + '"]')
8682                        .parent()
8683                        .addClass("active");
8684                }
8685                $$i(this.domElements.markerSelectorWrap).show();
8686                return;
8687            }
8688        }
8689        renderMarkerSelector() {
8690            const _this = this;
8691            const view = this.formBuilder.editMode ? this.domElements.edit : this.domElements.main;
8692            if (!view)
8693                return;
8694            const currentImage = this.value ? this.value.markerImagePath : null;
8695            const images = MapSVG.markerImages.map(function (image) {
8696                return ('<button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose ' +
8697                    (currentImage == image.relativeUrl ? "active" : "") +
8698                    '"><img src="' +
8699                    image.relativeUrl +
8700                    '" /></button>');
8701            });
8702            this.domElements.markerSelectorWrap = $$i(view).find(".mapsvg-marker-image-selector")[0];
8703            this.domElements.markerSelector = $$i(this.domElements.markerSelectorWrap).find(".mapsvg-marker-images")[0];
8704            if (this.domElements.markerSelector) {
8705                $$i(this.domElements.markerSelector).empty();
8706            }
8707            if (!this.formBuilder.editMode) {
8708                this.domElements.markerSelectorWrap.style.display = "none";
8709                $$i(this.domElements.markerSelector).on("click", ".mapsvg-marker-image-btn-choose", function (e) {
8710                    e.preventDefault();
8711                    const src = $$i(this).find("img").attr("src");
8712                    $$i(_this.domElements.markerSelectorWrap).hide();
8713                    $$i(_this.domElements.markerSelector).find(".active").removeClass("active");
8714                    $$i(this).addClass("active");
8715                    $$i(_this.domElements.main)
8716                        .find(".mapsvg-marker-image-btn-trigger")
8717                        .toggleClass("active", false);
8718                    $$i(_this.domElements.markerImageButton).attr("src", src);
8719                    _this.setMarkerImage(src);
8720                });
8721            }
8722            $$i(this.domElements.markerSelector).html(images.join(""));
8723        }
8724        setMarkerImage(src) {
8725            this.setDefaultMarkerPath(src);
8726            const value = this.value;
8727            if (value) {
8728                value.img = src;
8729                value.imagePath = src;
8730                this.setValue(value);
8731                this.triggerChanged();
8732                this.renderMarker();
8733            }
8734        }
8735        toggleMarkerSelectorInLocationEditor(jQueryObj, e) {
8736            e.preventDefault();
8737            const _this = this;
8738            if (jQueryObj.data("markerSelector") && jQueryObj.data("markerSelector").is(":visible")) {
8739                jQueryObj.data("markerSelector").hide();
8740                return;
8741            }
8742            if (jQueryObj.data("markerSelector") && jQueryObj.data("markerSelector").not(":visible")) {
8743                jQueryObj.data("markerSelector").show();
8744                return;
8745            }
8746            const markerBtn = $$i(this).closest("td").find(".mapsvg-marker-image-btn-trigger");
8747            const currentImage = markerBtn.attr("src");
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            if (!jQueryObj.data("markerSelector")) {
8756                const ms = $$i('<div class="mapsvg-marker-image-selector"></div>');
8757                jQueryObj.closest("td").append(ms);
8758                jQueryObj.data("markerSelector", ms);
8759            }
8760            else {
8761                jQueryObj.data("markerSelector").empty();
8762            }
8763            jQueryObj.data("markerSelector").html(images.join(""));
8764            jQueryObj
8765                .data("markerSelector")
8766                .on("click", ".mapsvg-marker-image-btn-choose", function (e) {
8767                e.preventDefault();
8768                const src = $$i(this).find("img").attr("src");
8769                jQueryObj.data("markerSelector").hide();
8770                const td = $$i(this).closest("td");
8771          
8771      const fieldId = $$i(this).closest("tr").data("option-id");
8772                const btn = td.find(".mapsvg-marker-image-btn-trigger");
8773                btn.toggleClass("active", false);
8774                btn.find("img").attr("src", src);
8775                _this.setMarkerByField(fieldId, src);
8776            });
8777        }
8778        setMarkersByField(options) {
8779            this.markersByField = options;
8780        }
8781        resetMarkersByField() {
8782            this.markersByField = {};
8783        }
8784        setMarkerByField(fieldId, markerImg) {
8785            this.markersByField = this.markersByField || {};
8786            this.markersByField[fieldId] = markerImg;
8787        }
8788        deleteMarker() {
8789            $$i(this.domElements.main).find(".mapsvg-new-marker").hide();
8790            $$i(this.domElements.main).find(".mapsvg-marker-id").attr("disabled", "disabled");
8791        }
8792        destroy() {
8793            if ($$i().mselect2) {
8794                const sel = $$i(this.domElements.main).find(".mapsvg-select2");
8795                if (sel.length) {
8796                    sel.mselect2("destroy");
8797                }
8798            }
8799            this.domElements.markerSelector && $$i(this.domElements.markerSelector).popover("dispose");
8800        }
8801        setDefaultMarkerPath(path) {
8802            this.defaultMarkerPath = path;
8803            this.formBuilder.mapsvg.setDefaultMarkerImage(path);
8804        }
8805        getMarkerImage(data) {
8806            let fieldValue;
8807            if (this.markersByFieldEnabled) {
8808                fieldValue = data[this.markerField];
8809                if (!fieldValue) {
8810                    return this.defaultMarkerPath || MapSVG.defaultMarkerImage;
8811                }
8812                else {
8813                    if (this.markerField === "regions") {
8814                        fieldValue = fieldValue[0] && fieldValue[0].id;
8815                    }
8816                    else if (typeof fieldValue === "object" && fieldValue.length) {
8817                        fieldValue = fieldValue[0].value;
8818                    }
8819                    if (this.markersByField[fieldValue]) {
8820                        return (this.markersByField[fieldValue] ||
8821                            this.defaultMarkerPath ||
8822                            MapSVG.defaultMarkerImage);
8823                    }
8824                }
8825            }
8826            else {
8827                return this.defaultMarkerPath || MapSVG.defaultMarkerImage;
8828            }
8829        }
8830        setValue(value, updateInput = true) {
8831            this.value = value;
8832            if (this.value) {
8833                if (!this.value.address) {
8834                    this.value.address = {};
8835                }
8836                if (Object.keys(this.value.address).length < 2 && this.value.geoPoint) {
8837                    this.value.address.formatted =
8838                        this.value.geoPoint.lat + "," + this.value.geoPoint.lng;
8839                }
8840            }
8841            this.renderMarker();
8842        }
8843    }
8844
8845    const $$j = jQuery;
8846    class ModalFormElement extends FormElement {
8847        constructor(options, formBuilder, external) {
8848            super(options, formBuilder, external);
8849            this.showButtonText = options.showButtonText;
8850        }
8851        getSchema() {
8852            const schema = super.getSchema();
8853            schema.showButtonText = this.showButtonText;
8854            return schema;
8855        }
8856    }
8857
8858    const $$k = jQuery;
8859    class PostFormElement extends FormElement {
8860        constructor(options, formBuilder, external) {
8861            super(options, formBuilder, external);
8862            if (this.formBuilder.admin)
8863                this.post_types = this.formBuilder.admin.getPostTypes();
8864            this.post_type = options.post_type || this.post_types[0];
8865            this.add_fields = MapSVG.parseBoolean(options.add_fields);
8866            this.db_type = "int(11)";
8867            this.name = "post";
8868            this.post = options.post;
8869        }
8870        setDomElements() {
8871            super.setDomElements();
8872            this.inputs.postSelect = ($$k(this.domElements.main).find(".mapsvg-find-post")[0]);
8873        }
8874        getSchema() {
8875            const schema = super.getSchema();
8876            schema.post_type = this.post_type;
8877            schema.add_fields = this.add_fields;
8878            return schema;
8879        }
8880        destroy() {
8881            if ($$k().mselect2) {
8882                const sel = $$k(this.domElements.main).find(".mapsvg-select2");
8883                if (sel.length) {
8884                    sel.mselect2("destroy");
8885                }
8886            }
8887        }
8888        getDataForTemplate() {
8889            const data = super.getDataForTemplate();
8890            if (this.formBuilder.admin)
8891                data.post_types = this.formBuilder.admin.getPostTypes();
8892            data.post_type = this.post_type;
8893            data.post = this.post;
8894            data.add_fields = this.add_fields || 0;
8895            return data;
8896        }
8897        setEventHandlers() {
8898            super.setEventHandlers();
8899            const server = new Server();
8900            $$k(this.inputs.postSelect)
8901                .mselect2({
8902                placeholder: "Search post by title",
8903                allowClear: true,
8904                disabled: this.readonly,
8905                ajax: {
8906                    url: server.getUrl("posts"),
8907                    dataType: "json",
8908                    delay: 250,
8909                    data: (params) => {
8910                        return {
8911                            filters: { post_type: this.post_type },
8912                            search: params.term,
8913                            page: params.page,
8914                        };
8915                    },
8916                    processResults: (data, params) => {
8917                        params.page = params.page || 1;
8918                        return {
8919                            results: data.posts ? data.posts : [],
8920                            pagination: {
8921                                more: false,
8922                            },
8923                        };
8924                    },
8925                    cache: true,
8926                },
8927                escapeMarkup: (markup) => {
8928                    return markup;
8929                },
8930                minimumInputLength: 1,
8931                templateResult: this.formatRepo,
8932                templateSelection: this.formatRepoSelection,
8933            })
8934                .on("select2:select", (e) => {
8935                const post = e.params.data;
8936                this.setValue(post);
8937                this.setInputValue(post);
8938                this.triggerChanged();
8939            })
8940                .on("change", (e) => {
8941                if (e.target.value === "") {
8942                    $$k(this.domElements.main).find(".mapsvg-post-id").text("");
8943                    $$k(this.domElements.main).find(".mapsvg-post-url").text("");
8944                    this.setValue(null, false);
8945                    this.triggerChanged();
8946                }
8947            });
8948        }
8949        formatRepo(repo) {
8950            if (repo.loading) {
8951                return repo.text;
8952            }
8953            else {
8954                return "<div class='select2-result-repository clearfix'>" + repo.post_title + "</div>";
8955            }
8956        }
8957        formatRepoSelection(repo) {
8958            return repo.post_title || repo.text;
8959        }
8960        setValue(post, updateInput = true) {
8961            this.value = post;
8962            if (updateInput) {
8963                this.setInputValue(post);
8964            }
8965        }
8966        setInputValue(post) {
8967            $$k(this.domElements.main).find(".mapsvg-post-id").text(post.id);
8968            $$k(this.domElements.main).find(".mapsvg-post-url").text(post.url).attr("href", post.url);
8969        }
8970    }
8971
8972    const $$l = jQuery;
8973    class RadioFormElement extends FormElement {
8974        constructor(options, formBuilder, external) {
8975            super(options, formBuilder, external);
8976            this.setOptions(options.options);
8977        }
8978        setDomElements() {
8979            super.setDomElements();
8980            this.inputs.radios = this.formBuilder.getForm().elements[this.name];
8981            this.$radios = $$l(this.domElements.main).find('input[type="radio"]');
8982        }
8983        setEventHandlers() {
8984            super.setEventHandlers();
8985            this.$radios.on("change", (e) => {
8986                this.setValue(e.target.value, false);
8987                this.triggerChanged();
8988            });
8989        }
8990        setInputValue(value) {
8991            if (value === null) {
8992                this.$radios.prop("checked", false);
8993            }
8994            else {
8995                this.inputs.radios.value = value;
8996            }
8997        }
8998    }
8999
9000    const $$m = jQuery;
9001    class RegionsFormElement extends FormElement {
9002        constructor(options, formBuilder, external) {
9003            super(options, formBuilder, external);
9004            this.searchable = MapSVG.parseBoolean(options.searchable);
9005            this.options = this.formBuilder.getRegionsList();
9006            this.label = options.label === undefined ? "Regions" : options.label;
9007            this.name = "regions";
9008            this.db_type = "text";
9009            if (typeof this.value === "undefined") {
9010                this.value = [];
9011            }
9012            this.regionsTableName = this.formBuilder.mapsvg.regionsRepository.getSchema().name;
9013        }
9014        setDomElements() {
9015            super.setDomElements();
9016            this.inputs.select = $$m(this.domElements.main).find("select")[0];
9017        }
9018        getData() {
9019            return { name: "regions", value: this.value };
9020        }
9021        getSchema() {
9022            const schema = super.getSchema();
9023            if (schema.multiselect)
9024                schema.db_type = "text";
9025            const opts = $$m.extend(true, {}, { options: this.options });
9026            schema.options = opts.options;
9027            schema.optionsDict = {};
9028            schema.options.forEach(function (option) {
9029                schema.optionsDict[option.id] = option.title || option.id;
9030            });
9031            return schema;
9032        }
9033        getDataForTemplate() {
9034            const data = super.getDataForTemplate();
9035            data.regionsTableName = this.regionsTableName;
9036            data.regionsFromCurrentTable = this.getRegionsForCurrentTable();
9037            return data;
9038        }
9039        getRegionsForCurrentTable() {
9040            return this.value
9041                ? this.value.filter((region) => region.tableName === this.regionsTableName)
9042                : [];
9043        }
9044        setEventHandlers() {
9045            super.setEventHandlers();
9046            $$m(this.inputs.select).on("change", (e) => {
9047                const selectedOptions = Array.from(this.inputs.select.selectedOptions);
9048                const selectedValues = selectedOptions.map((option) => option.value);
9049                this.setValue(selectedValues, false);
9050                this.triggerChanged();
9051            });
9052        }
9053        destroy() {
9054            if ($$m().mselect2) {
9055                const sel = $$m(this.domElements.main).find(".mapsvg-select2");
9056                if (sel.length) {
9057                    sel.mselect2("destroy");
9058                }
9059            }
9060        }
9061        setValue(regionIds, updateInput = true) {
9062            const regionsFromOtherTables = this.value.filter((region) => region.tableName !== this.regionsTableName);
9063            const regions = [];
9064            regionIds.forEach((regionId) => {
9065                const region = this.formBuilder.mapsvg.getRegion(regionId);
9066                regions.push({ id: region.id, title: region.title, tableName: this.regionsTableName });
9067            });
9068            this.value = regions.concat(regionsFromOtherTables);
9069            if (updateInput) {
9070                this.setInputValue(regionIds);
9071            }
9072        }
9073    }
9074
9075    const $$n = jQuery;
9076    class SaveFormElement extends FormElement {
9077        constructor(options, formBuilder, external) {
9078            super(options, formBuilder, external);
9079            this.readonly = true;
9080        }
9081        setDomElements() {
9082            super.setDomElements();
9083            this.inputs.btnSave = $$n(this.domElements.main).find(".btn-save")[0];
9084            this.inputs.btnClose = $$n(this.domElements.main).find(".mapsvg-close")[0];
9085        }
9086        setEventHandlers() {
9087            super.setEventHandlers();
9088            $$n(this.inputs.btnSave).on("click", (e) => {
9089                e.preventDefault();
9090                this.events.trigger("click.btn.save");
9091            });
9092            $$n(this.inputs.btnClose).on("click", (e) => {
9093                e.preventDefault();
9094                this.events.trigger("click.btn.close");
9095            });
9096        }
9097    }
9098
9099    const $$o = jQuery;
9100    class SearchFormElement extends FormElement {
9101        constructor(options, formBuilder, external) {
9102            super(options, formBuilder, external);
9103            this.searchFallback = MapSVG.parseBoolean(options.searchFallback) || false;
9104            this.width = options.width || "100%";
9105            this.name = "search";
9106        }
9107        setDomElements() {
9108            super.setDomElements();
9109            this.inputs.text = $$o(this.domElements.main).find("input")[0];
9110        }
9111        setEventHandlers() {
9112            super.setEventHandlers();
9113            $$o(this.inputs.text).on("change keyup paste", (e) => {
9114                this.setValue(e.target.value, false);
9115                this.triggerChanged();
9116            });
9117        }
9118        setInputValue(value) {
9119            this.inputs.text.value = value;
9120        }
9121        getSchema() {
9122            const schema = super.getSchema();
9123            schema.searchFallback = MapSVG.parseBoolean(this.searchFallback);
9124            schema.placeholder = this.placeholder;
9125            schema.width = this.width;
9126            return schema;
9127        }
9128    }
9129
9130    const $$p = jQuery;
9131    class SelectFormElement extends FormElement {
9132        constructor(options, formBuilder, external) {
9133            super(options, formBuilder, external);
9134            this.searchable = MapSVG.parseBoolean(options.searchable);
9135            this.multiselect = MapSVG.parseBoolean(options.multiselect);
9136            this.optionsGrouped = options.optionsGrouped;
9137            this.db_type = this.multiselect ? "text" : "varchar(255)";
9138            this.setOptions(options.options);
9139        }
9140        setDomElements() {
9141            super.setDomElements();
9142            this.inputs.select = $$p(this.domElements.main).find("select")[0];
9143        }
9144        getSchema() {
9145            const schema = super.getSchema();
9146            schema.multiselect = MapSVG.parseBoolean(this.multiselect);
9147            if (schema.multiselect)
9148                schema.db_type = "text";
9149            schema.optionsGrouped = this.optionsGrouped;
9150            const opts = $$p.extend(true, {}, { options: this.options });
9151            schema.options = opts.options || [];
9152            schema.optionsDict = {};
9153            schema.options.forEach(function (option) {
9154                schema.optionsDict[option.value] = option.label;
9155            });
9156            return schema;
9157        }
9158        setEventHandlers() {
9159            super.setEventHandlers();
9160            $$p(this.inputs.select).on("change", (e) => {
9161                if (this.multiselect) {
9162                    const selectedOptions = Array.from(this.inputs.select.selectedOptions);
9163                    const selectedValues = selectedOptions.map((option) => {
9164                        return { label: option.label, value: option.value };
9165                    });
9166                    this.setValue(selectedValues, false);
9167                    this.triggerChanged();
9168                }
9169                else {
9170                    this.setValue(this.inputs.select.value, false);
9171                    this.triggerChanged();
9172                }
9173            });
9174        }
9175        addSelect2() {
9176            if ($$p().mselect2) {
9177                const select2Options = {};
9178                if (this.formBuilder.filtersMode && this.type == "select") {
9179                    select2Options.placeholder = this.placeholder;
9180                    if (!this.multiselect) {
9181                        select2Options.allowClear = true;
9182                    }
9183                }
9184                $$p(this.domElements.main)
9185                    .find("select")
9186                    .css({ width: "100%", display: "block" })
9187                    .mselect2(select2Options)
9188                    .on("select2:focus", function () {
9189                    $$p(this).mselect2("open");
9190                });
9191                $$p(this.domElements.main)
9192                    .find(".select2-selection--multiple .select2-search__field")
9193                    .css("width", "100%");
9194            }
9195        }
9196        setOptions(options) {
9197            if (options) {
9198                this.options = [];
9199                this.optionsDict = {};
9200                options.forEach((value, key) => {
9201                    this.options.push(value);
9202                    if (this.optionsGrouped) {
9203                        value.options.forEach((value2, key2) => {
9204                            this.optionsDict[value2.value] = value2;
9205                        });
9206                    }
9207                    else {
9208                        this.optionsDict[key] = value;
9209                    }
9210                });
9211                return this.options;
9212            }
9213            else {
9214                return this.setOptions([
9215                    { label: "Option one", name: "option_one", value: 1 },
9216                    { label: "Option two", name: "option_two", value: 2 },
9217                ]);
9218            }
9219        }
9220        setInputValue(value) {
9221            if (this.multiselect) {
9222                if (this.value) {
9223                    $$p(this.inputs.select).val(this.value.map((el) => el.value));
9224                }
9225                else {
9226                    $$p(this.inputs.select).val([]);
9227                }
9228            }
9229            else {
9230                this.inputs.select.value = this.value;
9231            }
9232            $$p(this.inputs.select).trigger("change.select2");
9233        }
9234    }
9235
9236    const $$q = jQuery;
9237    class StatusFormElement extends FormElement {
9238        constructor(options, formBuilder, external) {
9239            super(options, formBuilder, external);
9240            this.label = options.label || "Status";
9241            this.name = "status";
9242            this.setOptions(options.options);
9243        }
9244        setDomElements() {
9245            super.setDomElements();
9246            this.inputs.select = $$q(this.domElements.main).find("select")[0];
9247            if ($$q().colorpicker) {
9248                $$q(this.domElements.main)
9249                    .find(".cpicker")
9250                    .colorpicker()
9251                    .on("changeColor.colorpicker", function (event) {
9252                    const input = $$q(this).find("input");
9253                    if (input.val() == "")
9254                        $$q(this).find("i").css({ "background-color": "" });
9255                });
9256                this.domElements.edit &&
9257                    $$q(this.domElements.edit)
9258                        .find(".cpicker")
9259                        .colorpicker()
9260                        .on("changeColor.colorpicker", function (event) {
9261                        const input = $$q(this).find("input");
9262                        if (input.val() == "")
9263                            $$q(this).find("i").css({ "background-color": "" });
9264                    });
9265            }
9266        }
9267        destroy() {
9268            if ($$q().mselect2) {
9269                const sel = $$q(this.domElements.main).find(".mapsvg-select2");
9270                if (sel.length) {
9271                    sel.mselect2("destroy");
9272                }
9273            }
9274        }
9275        setEditorEventHandlers() {
9276            super.setEditorEventHandlers();
9277            const _this = this;
9278            $$q(this.domElements.edit).on("keyup change paste", ".mapsvg-edit-status-row input", function () {
9279                _this.mayBeAddStatusRow();
9280            });
9281        }
9282        initEditor() {
9283            super.initEditor();
9284            const _this = this;
9285            $$q(_this.domElements.edit)
9286                .find(".cpicker")
9287                .colorpicker()
9288                .on("changeColor.colorpicker", function (event) {
9289                const input = $$q(this).find("input");
9290                const index = $$q(this).closest("tr").index();
9291                if (input.val() == "")
9292                    $$q(this).find("i").css({ "background-color": "" });
9293                _this.options[index] = _this.options[index] || {
9294                    label: "",
9295                    value: "",
9296                    color: "",
9297                    disabled: false,
9298                };
9299                _this.options[index]["color"] = input.val();
9300            });
9301            _this.mayBeAddStatusRow();
9302        }
9303        mayBeAddStatusRow() {
9304            const _this = this;
9305            const editStatusRow = $$q($$q("#mapsvg-edit-status-row").html());
9306            const z = $$q(_this.domElements.edit).find(".mapsvg-edit-status-label:last-child");
9307            if (z && z.last() && z.last().val() && (z.last().val() + "").trim().length) {
9308                const newRow = editStatusRow.clone();
9309                newRow.insertAfter($$q(_this.domElements.edit).find(".mapsvg-edit-status-row:last-child"));
9310                newRow
9311                    .find(".cpicker")
9312                    .colorpicker()
9313                    .on("changeColor.colorpicker", function (event) {
9314                    const input = $$q(this).find("input");
9315                    const index = $$q(this).closest("tr").index();
9316                    if (input.val() == "")
9317                        $$q(this).find("i").css({ "background-color": "" });
9318                    _this.options[index] = _this.options[index] || {
9319                        label: "",
9320                        value: "",
9321                        color: "",
9322                        disabled: false,
9323                    };
9324                    _this.options[index]["color"] = input.val();
9325                });
9326            }
9327            const rows = $$q(_this.domElements.edit).find(".mapsvg-edit-status-row");
9328            const row1 = rows.eq(rows.length - 2);
9329            const row2 = rows.eq(rows.length - 1);
9330            if (row1.length &&
9331                row2.length &&
9332                !(row1.find("input:eq(0)").val().toString().trim() ||
9333                    row1.find("input:eq(1)").val().toString().trim() ||
9334                    row1.find("input:eq(2)").val().toString().trim()) &&
9335                !(row2.find("input:eq(0)").val().toString().trim() ||
9336                    row2.find("input:eq(1)").val().toString().trim() ||
9337                    row2.find("input:eq(2)").val().toString().trim())) {
9338                row2.remove();
9339            }
9340        }
9341        setEventHandlers() {
9342            super.setEventHandlers();
9343            $$q(this.inputs.select).on("change keyup paste", (e) => {
9344                this.setValue(e.target.value, false);
9345                this.triggerChanged();
9346            });
9347        }
9348        getSchema() {
9349            const schema = super.getSchema();
9350            const opts = $$q.extend(true, {}, { options: this.options });
9351            schema.options = opts.options;
9352            schema.optionsDict = {};
9353            schema.options.forEach(function (option, index) {
9354                if (schema.options[index].value === "") {
9355                    schema.options.splice(index, 1);
9356                }
9357                else {
9358                    schema.options[index].disabled = MapSVG.parseBoolean(schema.options[index].disabled);
9359                    schema.optionsDict[option.value] = option;
9360                }
9361            });
9362            return schema;
9363        }
9364        setInputValue(value) {
9365            this.inputs.select.value = value;
9366        }
9367    }
9368
9369    const $$r = jQuery;
9370    class TextareaFormElement extends FormElement {
9371        constructor(options, formBuilder, external) {
9372            super(options, formBuilder, external);
9373            this.searchType = options.searchType || "fulltext";
9374            this.searchable = MapSVG.parseBoolean(options.searchable);
9375            this.autobr = options.autobr;
9376            this.html = options.html;
9377            this.db_type = "text";
9378        }
9379        setDomElements() {
9380            super.setDomElements();
9381            this.inputs.textarea = $$r(this.domElements.main).find("textarea")[0];
9382            if (this.html) {
9383                this.editor = CodeMirror.fromTextArea(this.inputs.textarea, {
9384                    mode: { name: "handlebars", base: "text/html" },
9385                    matchBrackets: true,
9386                    lineNumbers: true,
9387                });
9388                if (this.formBuilder.admin) {
9389                    this.editor.on("change", this.setTextareaValue);
9390                }
9391            }
9392        }
9393        setEventHandlers() {
9394            super.setEventHandlers();
9395            $$r(this.inputs.textarea).on("change keyup paste", (e) => {
9396                this.setValue(e.target.value, false);
9397                this.triggerChanged();
9398            });
9399        }
9400        getSchema() {
9401            const schema = super.getSchema();
9402            schema.autobr = this.autobr;
9403            schema.html = this.html;
9404            return schema;
9405        }
9406        getDataForTemplate() {
9407            const data = super.getDataForTemplate();
9408            data.html = this.html;
9409            return data;
9410        }
9411        setTextareaValue(codemir
9411ror, changeobj) {
9412            const handler = codemirror.getValue();
9413            const textarea = $$r(codemirror.getTextArea());
9414            textarea.val(handler).trigger("change");
9415        }
9416        destroy() {
9417            const cm = $$r(this.domElements.main).find(".CodeMirror");
9418            if (cm.length) {
9419                cm.empty().remove();
9420            }
9421        }
9422    }
9423
9424    const $$s = jQuery;
9425    class TextFormElement extends FormElement {
9426        constructor(options, formBuilder, external) {
9427            super(options, formBuilder, external);
9428            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9429            this.searchType = options.searchType;
9430            this.width =
9431                this.formBuilder.filtersHide && !this.formBuilder.modal
9432                    ? null
9433                    : options.width || "100%";
9434            this.db_type = "varchar(255)";
9435        }
9436        setDomElements() {
9437            super.setDomElements();
9438            this.inputs.text = $$s(this.domElements.main).find('input[type="text"]')[0];
9439        }
9440        getSchema() {
9441            const schema = super.getSchema();
9442            schema.searchType = this.searchType;
9443            return schema;
9444        }
9445        setEventHandlers() {
9446            super.setEventHandlers();
9447            $$s(this.inputs.text).on("change keyup paste", (e) => {
9448                this.setValue(e.target.value, false);
9449                this.triggerChanged();
9450            });
9451        }
9452        setInputValue(value) {
9453            this.inputs.text.value = value;
9454        }
9455    }
9456
9457    const $$t = jQuery;
9458    class TitleFormElement extends FormElement {
9459        constructor(options, formBuilder, external) {
9460            super(options, formBuilder, external);
9461            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9462            this.width =
9463                this.formBuilder.filtersHide && !this.formBuilder.modal
9464                    ? null
9465                    : options.width || "100%";
9466            this.db_type = "varchar(255)";
9467        }
9468        setDomElements() {
9469            super.setDomElements();
9470            this.inputs.text = $$t(this.domElements.main).find('input[type="text"]')[0];
9471        }
9472        getSchema() {
9473            const schema = super.getSchema();
9474            schema.searchType = this.searchType;
9475            return schema;
9476        }
9477        setEventHandlers() {
9478            super.setEventHandlers();
9479            $$t(this.inputs.text).on("change keyup paste", (e) => {
9480                this.setValue(e.target.value, false);
9481                this.triggerChanged();
9482            });
9483        }
9484        setInputValue(value) {
9485            this.inputs.text.value = value;
9486        }
9487    }
9488
9489    const $$u = jQuery;
9490    class ColorPickerFormElement extends FormElement {
9491        constructor(options, formBuilder, external) {
9492            super(options, formBuilder, external);
9493            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9494            this.width =
9495                this.formBuilder.filtersHide && !this.formBuilder.modal
9496                    ? null
9497                    : options.width || "100%";
9498            this.db_type = "varchar(255)";
9499        }
9500        setDomElements() {
9501            super.setDomElements();
9502            this.inputs.text = $$u(this.domElements.main).find("input.cpicker")[0];
9503            $$u(this.domElements.main).find(".colorpicker-element").colorpicker();
9504        }
9505        getSchema() {
9506            const schema = super.getSchema();
9507            schema.searchType = this.searchType;
9508            return schema;
9509        }
9510        setEventHandlers() {
9511            super.setEventHandlers();
9512            $$u(this.inputs.text).on("change keyup paste", (e) => {
9513                this.setValue(e.target.value, false);
9514                this.triggerChanged();
9515            });
9516            $$u(this.domElements.main).find(".colorpicker-element").colorpicker().on("changeColor.colorpicker", (e) => {
9517                this.setValue(this.inputs.text.value, false);
9518                this.triggerChanged();
9519            });
9520        }
9521        setInputValue(value) {
9522            this.inputs.text.value = value;
9523        }
9524    }
9525
9526    const $$v = jQuery;
9527    class FormElementFactory {
9528        constructor(options) {
9529            this.mapsvg = options.mapsvg;
9530            this.editMode = options.editMode;
9531            this.filtersMode = options.filtersMode;
9532            this.namespace = options.namespace;
9533            this.mediaUploader = options.mediaUploader;
9534            this.formBuilder = options.formBuilder;
9535            this.showNames = options.showNames !== false;
9536        }
9537        create(options) {
9538            const types = {
9539                checkbox: CheckboxFormElement,
9540                checkboxes: CheckboxesFormElement,
9541                date: DateFormElement,
9542                distance: DistanceFormElement,
9543                empty: EmptyFormElement,
9544                id: IdFormElement,
9545                image: ImagesFormElement,
9546                location: LocationFormElement,
9547                modal: ModalFormElement,
9548                post: PostFormElement,
9549                radio: RadioFormElement,
9550                region: RegionsFormElement,
9551                save: SaveFormElement,
9552                search: SearchFormElement,
9553                select: SelectFormElement,
9554                status: StatusFormElement,
9555                text: TextFormElement,
9556                textarea: TextareaFormElement,
9557                title: TitleFormElement,
9558                colorpicker: ColorPickerFormElement,
9559            };
9560            const formElement = new types[options.type](options, this.formBuilder, this.getExtraParams());
9561            formElement.init();
9562            return formElement;
9563        }
9564        getExtraParams() {
9565            const databaseFields = [];
9566            const databaseFieldsFilterable = [];
9567            const databaseFieldsFilterableShort = [];
9568            const regionFields = [];
9569            const regionFieldsFilterable = [];
9570            const regions = new ArrayIndexed("id");
9571            let mapIsGeo = false;
9572            if (this.mapsvg) {
9573                mapIsGeo = this.mapsvg.isGeo();
9574                const schemaObjects = this.mapsvg.objectsRepository.getSchema();
9575                if (schemaObjects) {
9576                    schemaObjects.getFields().forEach(function (obj) {
9577                        if (obj.type == "text" ||
9578                            obj.type == "region" ||
9579                            obj.type == "textarea" ||
9580                            obj.type == "post" ||
9581                            obj.type == "select" ||
9582                            obj.type == "radio" ||
9583                            obj.type == "checkbox") {
9584                            if (obj.type == "post") {
9585                                databaseFields.push("Object.post.post_title");
9586                            }
9587                            else {
9588                                databaseFields.push("Object." + obj.name);
9589                            }
9590                        }
9591                        if (obj.type == "region" || obj.type == "select" || obj.type == "radio") {
9592                            databaseFieldsFilterable.push("Object." + obj.name);
9593                            databaseFieldsFilterableShort.push(obj.name);
9594                        }
9595                    });
9596                }
9597                const schemaRegions = this.mapsvg.regionsRepository.getSchema();
9598                if (schemaRegions) {
9599                    schemaRegions.getFieldsAsArray().forEach(function (obj) {
9600                        if (obj.type == "status" ||
9601                            obj.type == "text" ||
9602                            obj.type == "textarea" ||
9603                            obj.type == "post" ||
9604                            obj.type == "select" ||
9605                            obj.type == "radio" ||
9606                            obj.type == "checkbox") {
9607                            if (obj.type == "post") {
9608                                regionFields.push("Region.post.post_title");
9609                            }
9610                            else {
9611                                regionFields.push("Region." + obj.name);
9612                            }
9613                        }
9614                        if (obj.type == "status" || obj.type == "select" || obj.type == "radio") {
9615                            regionFieldsFilterable.push("Region." + obj.name);
9616                        }
9617                    });
9618                }
9619                this.mapsvg.regions.forEach((region) => {
9620                    regions.push({ id: region.id, title: region.title });
9621                });
9622            }
9623            return {
9624                databaseFields: databaseFields,
9625                databaseFieldsFilterable: databaseFieldsFilterable,
9626                databaseFieldsFilterableShort: databaseFieldsFilterableShort,
9627                regionFields: regionFields,
9628                regionFieldsFilterable: regionFieldsFilterable,
9629                regions: regions,
9630                mapIsGeo: mapIsGeo,
9631                mediaUploader: this.mediaUploader,
9632                filtersMode: this.filtersMode,
9633                showNames: this.showNames,
9634            };
9635        }
9636    }
9637
9638    const $$w = jQuery;
9639    class FormBuilder {
9640        constructor(options) {
9641            const _this = this;
9642            this.events = new Events();
9643            this.container = options.container;
9644            this.namespace = options.namespace;
9645            this.mediaUploader = options.mediaUploader;
9646            this.schema = options.schema || [];
9647            this.editMode = options.editMode == undefined ? false : options.editMode;
9648            this.filtersMode = options.filtersMode == undefined ? false : options.filtersMode;
9649            this.filtersHide = options.filtersHide == undefined ? false : options.filtersHide;
9650            this.modal = options.modal == undefined ? false : options.modal;
9651            this.admin = options.admin;
9652            this.mapsvg = options.mapsvg;
9653            this.data = options.data || {};
9654            this.clearButton = options.clearButton || false;
9655            this.clearButtonText = options.clearButtonText || "";
9656            this.searchButton = options.searchButton || false;
9657            this.searchButtonText = options.searchButtonText || "";
9658            this.showButtonText = options.showButtonText || "";
9659            this.scrollable =
9660                typeof options.scrollable !== "undefined"
9661                    ? options.scrollable
9662                    : !_this.editMode && !_this.filtersMode;
9663            this.showNames = typeof options.showNames !== "undefined" ? options.showNames : true;
9664            this.formElementFactory = new FormElementFactory({
9665                mapsvg: this.mapsvg,
9666                formBuilder: this,
9667                mediaUploader: this.mediaUploader,
9668                editMode: this.editMode,
9669                filtersMode: this.filtersMode,
9670                namespace: this.namespace,
9671                showNames: this.showNames,
9672            });
9673            this.events = new Events(this);
9674            if (options.events && Object.keys(options.events).length > 0) {
9675                for (const eventName in options.events) {
9676                    this.events.on(eventName, options.events[eventName]);
9677                }
9678            }
9679            this.template = "form-builder";
9680            this.closeOnSave = options.closeOnSave === true;
9681            this.newRecord = options.newRecord === true;
9682            this.types = options.types || [
9683                "text",
9684                "textarea",
9685                "checkbox",
9686                "radio",
9687                "select",
9688                "image",
9689                "region",
9690                "location",
9691                "post",
9692                "date",
9693            ];
9694            this.templates = {};
9695            this.elements = {};
9696            this.view = $$w("<div />").addClass("mapsvg-form-builder")[0];
9697            if (this.editMode)
9698                $$w(this.view).addClass("full-flex");
9699            if (!this.showNames) {
9700                $$w(this.view).addClass("hide-names");
9701            }
9702            this.formElements = new ArrayIndexed("name");
9703            if (!MapSVG.templatesLoaded[this.template]) {
9704                this.loadTemplates(() => this.init());
9705            }
9706            else {
9707                this.init();
9708            }
9709        }
9710        loadTemplates(callback) {
9711            $$w.get(MapSVG.urls.root + "dist/" + this.template + ".html", (data) => {
9712                $$w(data).appendTo("body");
9713                MapSVG.templatesLoaded[this.template] = true;
9714                Handlebars.registerPartial("dataMarkerPartial", $$w("#mapsvg-data-tmpl-marker").html());
9715                if (this.editMode) {
9716                    Handlebars.registerPartial("markerByFieldPartial", $$w("#mapsvg-markers-by-field-tmpl-partial").html());
9717                }
9718                callback();
9719            });
9720        }
9721        init() {
9722            const _this = this;
9723            MapSVG.formBuilder = this;
9724            this.form = document.createElement("form");
9725            this.form.className = "mapsvg-data-form-view";
9726            if (!this.filtersMode) {
9727                this.form.classList.add("form-horizontal");
9728            }
9729            if (this.editMode) {
9730                const template = document.getElementById("mapsvg-form-editor-tmpl-ui").innerHTML;
9731                const templateCompiled = Handlebars.compile(template);
9732                this.view.innerHTML = templateCompiled({ types: this.types });
9733                this.view.classList.add("edit");
9734                this.form.classList.add("mapsvg-data-flex-full");
9735                this.form.classList.add("mapsvg-data-container");
9736                $$w(this.view).find(".mapsvg-data-preview").prepend(this.form);
9737                this.formEditor = $$w(this.view).find("#mapsvg-data-form-edit")[0];
9738            }
9739            else {
9740                this.view.appendChild(this.form);
9741            }
9742            _this.elements = {
9743                buttons: {
9744                    text: $$w(_this.view).find("#mapsvg-data-btn-text")[0],
9745                    textarea: $$w(_this.view).find("#mapsvg-data-btn-textarea")[0],
9746                    checkbox: $$w(_this.view).find("#mapsvg-data-btn-checkbox")[0],
9747                    radio: $$w(_this.view).find("#mapsvg-data-btn-radio")[0],
9748                    select: $$w(_this.view).find("#mapsvg-data-btn-select")[0],
9749                    image: $$w(_this.view).find("#mapsvg-data-btn-image")[0],
9750                    region: $$w(_this.view).find("#mapsvg-data-btn-region")[0],
9751                    marker: $$w(_this.view).find("#mapsvg-data-btn-marker")[0],
9752                    saveSchema: $$w(_this.view).find("#mapsvg-data-btn-save-schema")[0],
9753                },
9754                containers: {
9755                    buttons_add: $$w(_this.view).find("#mapsvg-data-buttons-add")[0],
9756                },
9757            };
9758            _this.redraw();
9759        }
9760        getForm() {
9761            return this.form;
9762        }
9763        getFormEditor() {
9764            return this.formEditor;
9765        }
9766        viewDidLoad() { }
9767        setEventHandlers() {
9768            const _this = this;
9769            $$w(this.getForm()).on("submit", (e) => {
9770                e.preventDefault();
9771            });
9772            if (this.filtersMode && this.clearButton) {
9773                $$w(this.elements.buttons.clearButton).on("click", (e) => {
9774                    e.preventDefault();
9775                    this.clearAllFields();
9776                });
9777            }
9778            $$w(window)
9779                .off("keydown.form.mapsvg")
9780                .on("keydown.form.mapsvg", function (e) {
9781                if (MapSVG.formBuilder) {
9782                    if ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
9783                        MapSVG.formBuilder.save();
9784                    else if (e.keyCode == 27)
9785                        MapSVG.formBuilder.close();
9786                }
9787            });
9788            if (this.editMode) {
9789                $$w(this.view).on("click", "#mapsvg-data-buttons-add button", function (e) {
9790                    e.preventDefault();
9791                    const type = $$w(this).data("create");
9792                    const formElement = _this.formElementFactory.create({ type: type });
9793                    _this.addField(formElement);
9794                });
9795                $$w(this.view).on("click", "#mapsvg-data-btn-save-schema", function (e) {
9796                    e.preventDefault();
9797                    const fields = _this.getSchema();
9798                    const counts = {};
9799                    _this.formElements.forEach(function (elem) {
9800                        counts[elem.name] = (counts[elem.name] || 0) + 1;
9801                    });
9802                    $$w(_this.getForm()).find(".form-group").removeClass("has-error");
9803                    const errors = [];
9804                    const reservedFields = [
9805                        "lat",
9806                        "lon",
9807                        "lng",
9808                        "location",
9809                        "location_lat",
9810                        "location_lon",
9811                        "location_lng",
9812                        "location_address",
9813                        "location_img",
9814                        "marker",
9815                        "marker_id",
9816                        "regions",
9817                        "region_id",
9818                        "post",
9819                        "post_title",
9820                        "post_url",
9821                        "keywords",
9822                        "status",
9823                    ];
9824                    const reservedFieldsToTypes = {
9825                        regions: "region",
9826                        status: "status",
9827                        post: "post",
9828                        marker: "marker",
9829                        location: "location",
9830                    };
9831                    let errUnique, errEmpty;
9832                    _this.formElements.forEach(function (formElement, index) {
9833                        let err = false;
9834                        if (!_this.filtersMode) {
9835                            if (counts[formElement.name] > 1) {
9836                                if (!errUnique) {
9837                                    errUnique = "Field names should be unique";
9838                                    errors.push(errUnique);
9839                                    err = true;
9840                                }
9841                            }
9842                            else if (formElement.name.length === 0) {
9843                                if (!errEmpty) {
9844                                    errEmpty = "Field name can't be empty";
9845                                    errors.push(errEmpty);
9846                                    err = true;
9847                                }
9848                            }
9849                            else if (reservedFields.indexOf(formElement.name) != -1) {
9850                                if (!reservedFieldsToTypes[formElement.name] ||
9851                                    (reservedFieldsToTypes[formElement.name] &&
9852                                        reservedFieldsToTypes[formElement.name] != formElement.type)) {
9853                                    const msg = 'Field name "' +
9854                                        formElement.name +
9855                                        '" is reserved, please set another name';
9856                                    errors.push(msg);
9857                                    err = true;
9858                                }
9859                            }
9860                        }
9861                        if (formElement.options &&
9862                            formElement.type != "region" &&
9863                            formElement.type != "marker") {
9864                            const vals = formElement.options.map(function (obj) {
9865                                return obj.value;
9866                            });
9867                            const uniq = [...Array.from(new Set(vals).values())];
9868                            if (vals.length != uniq.length) {
9869                                errors.push('Check "Options" list - values should not repeat');
9870                                err = true;
9871                            }
9872                        }
9873                        err && $$w(formElement.domElements.main).addClass("has-error");
9874                    });
9875                    if (errors.length === 0) {
9876                        _this.events.trigger("saveSchema", _this, [_this, fields]);
9877                    }
9878                    else {
9879                        jQuery.growl.error({ title: "Errors", message: errors.join("<br />") });
9880                    }
9881                });
9882                setTimeout(function () {
9883                    const el = _this.getForm();
9884                    _this.sortable = new Sortable(el, {
9885                        animation: 150,
9886                        onStart: function () {
9887                            $$w(_this.getForm()).addClass("sorting");
9888                        },
9889                        onEnd: function () {
9890                            setTimeout(function () {
9891                                $$w(_this.getForm()).removeClass("sorting");
9892                                _this.formElements.clear();
9893                                $$w(el)
9894                                    .find(".form-group")
9895                                    .each(function (index, elem) {
9896                                    _this.formElements.push($$w(elem).data("formElement"));
9897                                });
9898                            }, 500);
9899                        },
9900                    });
9901                }, 1000);
9902            }
9903            new ResizeSensor(this.view, function () {
9904                _this.scrollApi && _this.scrollApi.reinitialise();
9905            });
9906        }
9907        clearAllFields() {
9908            this.formElements.forEach((f) => f.setValue(null));
9909            this.events.trigger("cleared");
9910        }
9911        setFormElementEventHandlers(formElement) {
9912            if (this.editMode) {
9913                formElement.events.on("click", (elem) => {
9914                    this.edit(elem);
9915                });
9916                formElement.events.on("delete", (elem) => {
9917                    this.deleteField(elem);
9918                });
9919            }
9920            else {
9921                formElement.events.on("changed", (_formElement) => {
9922                    const name = _formElement.name;
9923                    const value = _formElement.getValue();
9924                    if (_formElement.type !== "search") {
9925                        this.events.trigger("changed.field", _formElement, [_formElement, name, value]);
9926                    }
9927                    else {
9928                        this.events.trigger("changed.search", _formElement, [_formElement, value]);
9929                    }
9930                });
9931            }
9932        }
9933        save() {
9934            const _this = this;
9935            if (_this.markerBackup) {
9936                const marker = _this.mapsvg.getEditingMarker();
9937                marker.events.off("change");
9938                _this.markerBackup = marker.getOptions();
9939                _this.mapsvg.unsetEditingMarker();
9940            }
9941            const data = _this.getData();
9942            _this.saved = true;
9943            this.events.trigger("save", _this, [_this, data]);
9944        }
9945        getFormElementByType(type) {
9946            return this.formElements.find((el) => el.type === type);
9947        }
9948        getData() {
9949            const data = {};
9950            this.formElements.forEach((formElement) => {
9951                if (formElement.readonly === false || formElement.type === "id") {
9952                    const _formElementData = formElement.getData();
9953                    data[_formElementData.name] = _formElementData.value;
9954                }
9955            });
9956            return data;
9957        }
9958        reset() {
9959            this.formElements.forEach((formElement) => {
9960                formElement.setValue(null);
9961            });
9962        }
9963        update(data) {
9964            this.schema.getFields().forEach((field) => {
9965                const formElement = this.formElements.get(field.name);
9966                if (formElement) {
9967                    if (typeof data[field.name] !== "undefined") {
9968                        if (formElement.getValue() !== data[field.name]) {
9969                            formElement.setValue(data[field.name]);
9970                        }
9971                    }
9972                    else {
9973                        formElement.setValue(null);
9974                    }
9975                }
9976            });
9977        }
9978        redraw() {
9979            const _this = this;
9980            delete _this.markerBackup;
9981            $$w(this.container).empty();
9982            $$w(this.getForm()).empty();
9983            this.formElements.clear();
9984            this.schema &&
9985                this.schema.fields.length > 0 &&
9986                this.schema.fields.forEach((fieldSettings) => {
9987                    if (this.filtersMode) {
9988                        if (fieldSettings.type == "distance") {
9989                            fieldSettings.value = this.data.distance
9990                                ? this.data.distance
9991                                : fieldSettings.value !== undefined
9992                                    ? fieldSettings.value
9993                                    : null;
9994                        }
9995                        else {
9996                            fieldSettings.value = this.data[fieldSettings.parameterNameShort];
9997                        }
9998                    }
9999                    else {
10000                        fieldSettings.value = this.data
10001                            ? this.data[fieldSettings.name]
10002                            : fieldSettings.value !== undefined
10003                                ? fieldSettings.value
10004                                : null;
10005                    }
10006                    if (fieldSettings.type == "location" && !this.editMode) {
10007                        if (fieldSettings.value &&
10008                            fieldSettings.value.marker &&
10009                            fieldSettings.value.marker.id) ;
10010                        this.admin && this.admin.setMode && this.admin.setMode("editMarkers");
10011                        this.admin && this.admin.enableMarkersMode(true);
10012                    }
10013                    else if (fieldSettings.type == "post") {
10014                        fieldSettings.post = this.data["post"];
10015                    }
10016                    else if (fieldSettings.type === "region") {
10017                        fieldSettings.options = new ArrayIndexed("id", this.getRegionsList());
10018                    }
10019                    const formElement = this.formElementFactory.create(fieldSettings);
10020                    if (this.filtersMode) {
10021                        if (!this.filtersHide ||
10022                            (this.filtersHide && this.modal && fieldSettings.type !== "search") ||
10023                            (!this.modal && fieldSettings.type === "search")) {
10024                            this.addField(formElement);
10025                        }
10026                    }
10027                    else {
10028                        this.addField(formElement);
10029                    }
10030                });
10031            if (!_this.editMode) {
10032                if (this.schema.fields.length === 0 && !this.filtersMode) {
10033                    const formElement = this.formElementFactory.create({ type: "empty" });
10034                    _this.addField(formElement);
10035                }
10036                else {
10037                    if (_this.admin && !_this.admin.isMetabox) {
10038                        const formElement = this.formElementFactory.create({ type: "save" });
10039                        formElement.events.on("click.btn.save", () => {
10040                            this.save();
10041                        });
10042                        formElement.events.on("click.btn.close", () => {
10043                            this.close();
10044                        });
10045                        _this.addField(formElement);
10046                    }
10047                }
10048            }
10049            if (_this.filtersMode && _this.filtersHide && !_this.modal) {
10050                const formElement = this.formElementFactory.create({
10051                    type: "modal",
10052                    showButtonText: _this.showButtonText,
10053                });
10054                this.showFiltersButton = _this.addField(formElement);
10055            }
10056            if (this.scrollable) {
10057                const nano = $$w('<div class="nano"></div>');
10058                const nanoContent = $$w('<div class="nano-content"></div>');
10059                nano.append(nanoContent);
10060                nanoContent.append(this.view);
10061                $$w(_this.container).append(nano);
10062                nano.jScrollPane({ contentWidth: "0px", mouseWheelSpeed: 30 });
10063                _this.scrollApi = nano.data("jsp");
10064            }
10065            else {
10066                $$w(_this.container).append(this.view);
10067            }
10068            if (_this.filtersMode && _this.clearButton) {
10069                _this.elements.buttons.clearButton = $$w('<div class="form-group mapsvg-filters-reset-container">' +
10070                    '<button type="button" class="btn btn-outline-secondary mapsvg-filters-reset">' +
10071                    _this.clearButtonText +
10072                    "</button></div>")[0];
10073                $$w(this.getForm()).append(_this.elements.buttons.clearButton);
10074            }
10075            if (_this.filtersMode && _this.searchButton) {
10076                _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">' +
10077                    _this.searchButtonText +
10078                    "</button></div>")[0];
10079                $$w(this.getForm()).append(_this.elements.buttons.searchButton);
10080            }
10081            if (!this.editMode && !_this.filtersMode)
10082                $$w(this.view).find("input:visible,textarea:visible").not(".tt-hint").first().focus();
10083            const cm = $$w(this.container).find(".CodeMirror");
10084            cm.each(function (index, el) {
10085                el && el.CodeMirror.refresh();
10086            });
10087            _this.setEventHandlers();
10088            this.events.trigger("init", this, [this, this.getData()]);
10089            this.events.trigger("loaded", this, [this]);
10090        }
10091        updateExtraParamsInFormElements() {
10092            this.formElements.forEach((formElement) => {
10093                formElement.setExternal(this.formElementFactory.getExtraParams());
10094                if (formElement.type === "location") {
10095                    formElement.redraw();
10096                }
10097            });
10098        }
10099        deleteField(formElement) {
10100            const _this = this;
10101            _this.formElements.delete(formElement.name);
10102        }
10103        getExtraParams() {
10104            const databaseFields = [];
10105            this.mapsvg.objectsRepository
10106                .getSchema()
10107                .getFields()
10108                .forEach(function (obj) {
10109                if (obj.type == "text" ||
10110                    obj.type == "region" ||
10111                    obj.type == "textarea" ||
10112                    obj.type == "post" ||
10113                    obj.type == "select" ||
10114                    obj.type == "radio" ||
10115                    obj.type == "checkbox") {
10116                    if (obj.type == "post") {
10117                        databaseFields.push("Object.post.post_title");
10118                    }
10119                    else {
10120                        databaseFields.push("Object." + obj.name);
10121                    }
10122                }
10123            });
10124            let databaseFieldsFilterableShort = [];
10125            databaseFieldsFilterableShort = this.mapsvg.objectsRepository
10126                .getSchema()
10127                .getFieldsAsArray()
10128                .filter(function (obj) {
10129                return obj.type == "select" || obj.type == "radio" || obj.type == "region";
10130            })
10131                .map(function (obj) {
10132                return obj.name;
10133            });
10134            let markerFieldsShort = [];
10135            markerFieldsShort = databaseFieldsFilterableShort.filter((o) => o.type === "select" || o.type === "radio");
10136            const regionFields = this.mapsvg.regionsRepository
10137                .getSchema()
10138                .getFieldsAsArray()
10139                .map(function (obj) {
10140                if (obj.type == "status" ||
10141                    obj.type == "text" ||
10142                    obj.type == "textarea" ||
10143                    obj.type == "post" ||
10144                    obj.type == "select" ||
10145                    obj.type == "radio" ||
10146                    obj.type == "checkbox") {
10147                    if (obj.type == "post") {
10148                        return "Region.post.post_title";
10149                    }
10150                    else {
10151                        return "Region." + obj.name;
10152                    }
10153                }
10154            });
10155            return {
10156                databaseFields: databaseFields,
10157                databaseFieldsFilterableShort: databaseFieldsFilterableShort,
10158                regionFields: regionFields,
10159                markerFieldsShort: markerFieldsShort,
10160            };
10161        }
10162        addField(formElement) {
10163            const _this = this;
10164            if (["region", "marker", "post", "status", "distance", "location", "search"].indexOf(formElement.type) != -1) {
10165                let repeat = false;
10166                _this.formElements.forEach(function (control) {
10167                    if (control.type == formElement.type)
10168                        repeat = true;
10169                });
10170                if (repeat) {
10171                    jQuery.growl.error({
10172                        title: "Error",
10173                        message: 'You can add only 1 "' + MapSVG.ucfirst(formElement.type) + '" field',
10174                    });
10175                    return;
10176                }
10177            }
10178            _this.formElements.push(formElement);
10179            _this.getForm().append(formElement.domElements.main);
10180            this.setFormElementEventHandlers(formElement);
10181            if (this.editMode) {
10182                if (formElement.protected) {
10183                    formElement.hide();
10184                }
10185                else {
10186                    this.edit(formElement);
10187                }
10188            }
10189            return formElement;
10190        }
10191        edit(formElement) {
10192            const _this = this;
10193            _this.currentlyEditing && _this.currentlyEditing.destroyEditor();
10194            this.getFormEditor().appendChild(formElement.getEditor());
10195            formElement.initEditor();
10196            _this.currentlyEditing = formElement;
10197            $$w(_this.getForm()).find(".form-group.active").removeClass("active");
10198            $$w(formElement.domElements.main).addClass("active");
10199        }
10200        get() {
10201        }
10202        getSchema() {
10203            return this.formElements.map(function (formElement) {
10204                return formElement.getSchema();
10205            });
10206        }
10207        close() {
10208            this.formElements.forEach((formElement) => formElement.destroy());
10209            this.mediaUploader && this.mediaUploader.off("select");
10210            MapSVG.formBuilder = null;
10211            this.events.trigger("close", this, [this]);
10212        }
10213        destroy() {
10214            $$w(this.view).empty().remove();
10215            this.sortable = null;
10216        }
10217        toJSON(addEmpty) {
10218            const obj = {};
10219            function add(obj, name, value) {
10220                if (!addEmpty && !value)
10221                    return false;
10222                if (name.length == 1) {
10223                    obj[name[0]] = value;
10224                }
10225                else {
10226                    if (obj[name[0]] == null) {
10227                        if (name[1] === "") {
10228                            obj[name[0]] = [];
10229                        }
10230                        else {
10231                            obj[name[0]] = {};
10232                        }
10233                    }
10234                    if (obj[name[0]].length !== undefined) {
10235                        obj[name[0]].push(value);
10236                    }
10237                    else {
10238                        add(obj[name[0]], name.slice(1), value);
10239                    }
10240                }
10241            }
10242            $$w(this.elements.containers.formView)
10243                .find("input, textarea, select")
10244                .each(function () {
10245                if (!$$w(this).data("skip") &&
10246                    !$$w(this).prop("disabled") &&
10247                    $$w(this).attr("name") &&
10248                    !(!addEmpty &&
10249                        $$w(this).attr("type") == "checkbox" &&
10250                        $$w(this).attr("checked") == undefined) &&
10251                    !($$w(this).attr("type") == "radio" && $$w(this).attr("checked") == undefined)) {
10252                    let value;
10253                    if ($$w(this).attr("type") == "checkbox") {
10254                        value = $$w(this).prop("checked");
10255                    }
10256                    else {
10257                        value = $$w(this).val();
10258                    }
10259                    add(obj, $$w(this).attr("name").replace(/]/g, "").split("["), value);
10260                }
10261            });
10262            return obj;
10263        }
10264        getRegionsList() {
10265            return this.mapsvg.regions.map(function (r) {
10266                return { id: r.id, title: r.title };
10267            });
10268        }
10269        getRegionsAsArray() {
10270            return this.mapsvg.regions;
10271        }
10272        setRegions(location) {
10273            const regionsFormElement = this.formElements.get("regions");
10274            if (this.mapsvg.options.source.indexOf("/geo-calibrated/us
10274a.svg") !== -1) {
10275                regionsFormElement.setValue(["US-" + location.address.state_short]);
10276            }
10277            else if (this.mapsvg.options.source.indexOf("/geo-calibrated/world.svg") !== -1) {
10278                if (location.address.country_short) {
10279                    regionsFormElement.setValue([location.address.country_short]);
10280                }
10281            }
10282            else {
10283                if (location.address.administrative_area_level_1) {
10284                    this.mapsvg.regions.forEach((_region) => {
10285                        if (_region.title === location.address.administrative_area_level_1 ||
10286                            _region.title === location.address.administrative_area_level_2 ||
10287                            _region.id ===
10288                                location.address.country_short +
10289                                    "-" +
10290                                    location.address.administrative_area_level_1_short) {
10291                            regionsFormElement.setValue([_region.id]);
10292                        }
10293                    });
10294                }
10295            }
10296        }
10297    }
10298
10299    const $$x = jQuery;
10300    class FiltersController extends DetailsController {
10301        constructor(options) {
10302            super(options);
10303            this.showButtonText = options.showButtonText;
10304            this.clearButton = options.clearButton;
10305            this.clearButtonText = options.clearButtonText;
10306            this.searchButton = options.searchButton;
10307            this.searchButtonText = options.searchButtonText;
10308            this.padding = options.padding;
10309            this.schema = options.schema;
10310            this.hideFilters = options.hide;
10311            this.query = options.query;
10312        }
10313        viewDidLoad() {
10314            super.viewDidLoad();
10315            const _this = this;
10316            this.formBuilder = new FormBuilder({
10317                container: this.containers.contentView,
10318                filtersMode: true,
10319                schema: this.schema,
10320                modal: this.modal,
10321                filtersHide: this.hideFilters,
10322                showButtonText: this.showButtonText,
10323                clearButton: this.clearButton,
10324                clearButtonText: this.clearButtonText,
10325                searchButton: this.searchButton,
10326                searchButtonText: this.searchButtonText,
10327                editMode: false,
10328                mapsvg: this.mapsvg,
10329                data: {},
10330                admin: false,
10331                events: {
10332                    "changed.field": (formElement, field, value) => {
10333                        const filters = {};
10334                        let _value = value;
10335                        if (field === "regions") {
10336                            _value = {};
10337                            _value.region_ids = value instanceof Array ? value : [value];
10338                            _value.table_name = this.mapsvg.options.database.regionsTableName;
10339                            if (_value.region_ids.length === 0 || _value.region_ids[0] === "") {
10340                                _value = null;
10341                            }
10342                        }
10343                        filters[field] = _value;
10344                        this.query.setFilters(filters);
10345                        _this.events.trigger("changed.field", _this, [field, value]);
10346                        _this.events.trigger("changed.fields", _this, [field, value]);
10347                    },
10348                    "changed.search": (formElement, value) => {
10349                        this.query.setSearch(value);
10350                        _this.events.trigger("changed.search", _this, [value]);
10351                    },
10352                    cleared: (formBuilder) => {
10353                        this.query.clearFilters();
10354                        this.events.trigger("cleared", _this, []);
10355                    },
10356                    loaded: (formBuilder) => {
10357                        $$x(formBuilder.container).find(".mapsvg-form-builder").css({
10358                            padding: _this.padding,
10359                        });
10360                        this.updateScroll();
10361                        this.events.trigger("loaded");
10362                    },
10363                },
10364            });
10365        }
10366        reset() {
10367            this.formBuilder && this.formBuilder.reset();
10368        }
10369        update(query) {
10370            const _query = Object.assign({}, query.filters);
10371            _query.search = query.search;
10372            this.formBuilder && this.formBuilder.update(_query);
10373        }
10374        setFiltersCounter() {
10375            if (this.hideFilters) {
10376                const filtersCounter = Object.keys(this.query.filters).length;
10377                const filtersCounterString = filtersCounter === 0 ? "" : f
10377iltersCounter.toString();
10378                this.formBuilder &&
10379                    this.formBuilder.showFiltersButton &&
10380                    $$x(this.formBuilder.showFiltersButton.domElements.main)
10381                        .find("button")
10382                        .html(this.showButtonText + " <b>" + filtersCounterString + "</b>");
10383            }
10384        }
10385        setEventHandlers() {
10386            super.setEventHandlers();
10387            const _this = this;
10388            $$x(this.containers.view).on("click", ".mapsvg-btn-show-filters", function () {
10389                _this.events.trigger("click.btn.showFilters");
10390            });
10391            $$x(this.containers.view).on("click", "#mapsvg-search-container", function () {
10392                _this.events.trigger("click.btn.searchButton");
10393            });
10394        }
10395    }
10396
10397    const $$y = jQuery;
10398    class PopoverController extends Controller {
10399        constructor(options) {
10400            super(options);
10401            this.autoresize = true;
10402            this.point = options.point;
10403            this.yShift = options.yShift;
10404            this.mapObject = options.mapObject;
10405            this.id = this.mapObject.id + "_" + Math.random();
10406            $$y(this.containers.main).data("popover-id", this.id);
10407        }
10408        setPoint(point) {
10409            this.point = point;
10410        }
10411        getToolbarTemplate() {
10412            if (this.withToolbar)
10413                return '<div class="mapsvg-popover-close"></div>';
10414            else
10415                return "";
10416        }
10417        viewDidLoad() {
10418            super.viewDidLoad.call(this);
10419            if (MapSVG.isPhone &&
10420                this.mapsvg.options.popovers.mobileFullscreen &&
10421                !this.mobileCloseBtn) {
10422                this.mobileCloseBtn = $$y('<button class="mapsvg-mobile-modal-close mapsvg-btn">' +
10423                    this.mapsvg.getData().options.mobileView.labelClose +
10424                    "</button>")[0];
10425                $$y(this.containers.view).append(this.mobileCloseBtn);
10426            }
10427            this.adjustScreenPosition();
10428            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", true);
10429            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", true);
10430            this.adjustHeight();
10431            this.updateScroll();
10432            this.autoresize && this.resizeSensor.setScroll();
10433            this.events.trigger("shown", this, [this]);
10434        }
10435        adjustHeight() {
10436            $$y(this.containers.main).height($$y(this.containers.main).find(".mapsvg-auto-height").outerHeight() +
10437                (this.containers.toolbar ? $$y(this.containers.toolbar).outerHeight() : 0));
10438        }
10439        adjustScreenPosition() {
10440            if (this.point) {
10441                const pos = this.mapsvg.converter.convertSVGToPixel(this.point);
10442                pos.y -= this.yShift;
10443                pos.x = Math.round(pos.x);
10444                pos.y = Math.round(pos.y);
10445                this.setScreenPosition(pos.x, pos.y);
10446            }
10447        }
10448        moveSrceenPositionBy(deltaX, deltaY) {
10449            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
10450            this.setScreenPosition(x, y);
10451        }
10452        setScreenPosition(x, y) {
10453            this.screenPoint = new ScreenPoint(x, y);
10454            $$y(this.containers.main).css({
10455                transform: "translateX(-50%) translate(" + x + "px," + y + "px)",
10456            });
10457        }
10458        setEventHandlers() {
10459            $$y("body").off(".popover.mapsvg");
10460            $$y(this.containers.view).on("click touchend", ".mapsvg-popover-close, .mapsvg-mobile-modal-close", (e) => {
10461                e.stopImmediatePropagation();
10462                this.close();
10463            });
10464            $$y("body").on("mouseup.popover.mapsvg touchend.popover.mapsvg", (e) => {
10465                if (this.mapsvg.isScrolling ||
10466                    $$y(e.target).closest(".mapsvg-directory").length ||
10467                    $$y(e.target).closest(".mapsvg-popover").length ||
10468                    $$y(e.target).hasClass("mapsvg-btn-map"))
10469                    return;
10470                this.close();
10471            });
10472        }
10473        close() {
10474            if ($$y(this.containers.main).data("popover-id") != this.id ||
10475                !$$y(this.containers.main).is(":visible"))
10476                return;
10477            this.destroy();
10478            if (this.mapObject instanceof Region) {
10479                this.mapsvg.deselectRegion(this.mapObject);
10480            }
10481            if (this.mapObject instanceof Marker) {
10482                this.mapsvg.deselectAllMarkers();
10483            }
10484            this.events.trigger("closed", this, [this]);
10485        }
10486        destroy() {
10487            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", false);
10488            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", false);
10489            super.destroy.call(this);
10490        }
10491        show() {
10492            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", true);
10493            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", true);
10494        }
10495    }
10496
10497    const $$z = jQuery;
10498    class Tooltip extends Controller {
10499        constructor(options) {
10500            super(options);
10501            this.scrollable = false;
10502            this.withToolbar = false;
10503            this.autoresize = false;
10504            this.screenPoint = new ScreenPoint(0, 0);
10505            this.posOriginal = {};
10506            this.posShifted = {};
10507            this.posShiftedPrev = {};
10508            this.mirror = {};
10509            this.noPadding = true;
10510            this.setPosition(options.position);
10511            this.setSize(options.minWidth, options.maxWidth);
10512        }
10513        setSize(minWidth, maxWidth) {
10514            this.minWidth = minWidth;
10515            this.maxWidth = maxWidth;
10516            this.containers.main.style["min-width"] = this.minWidth + "px";
10517            this.containers.main.style["max-width"] = this.maxWidth + "px";
10518        }
10519        setPosition(position) {
10520            const ex = position.split("-");
10521            if (ex[0].indexOf("top") != -1 || ex[0].indexOf("bottom") != -1) {
10522                this.posOriginal.topbottom = ex[0];
10523            }
10524            if (ex[0].indexOf("left") != -1 || ex[0].indexOf("right") != -1) {
10525                this.posOriginal.leftright = ex[0];
10526            }
10527            if (ex[1]) {
10528                this.posOriginal.leftright = ex[1];
10529            }
10530            this.containers.main.className = this.containers.main.className.replace(/(^|\s)mapsvg-tt-\S+/g, "");
10531            this.containers.main.classList.add("mapsvg-tt-" + position);
10532        }
10533        setScreenPoint(x, y) {
10534            this.screenPoint.x = x;
10535            this.screenPoint.y = y;
10536        }
10537        viewDidLoad() {
10538            super.viewDidLoad.call(this);
10539        }
10540        viewDidAppear() {
10541            super.viewDidAppear();
10542            this.events.trigger("shown", this, [this]);
10543        }
10544        setScreenPosition(x, y) {
10545            this.setScreenPoint(x, y);
10546            this.containers.main.style.transform =
10547                "translateX(-50%) translate(" + x + "px," + y + "px)";
10548        }
10549        setEventHandlers() {
10550            const event = "mousemove.tooltip.mapsvg-" + this.mapsvg.id;
10551            $$z("body")
10552                .off(event)
10553                .on(event, (e) => {
10554                MapSVG.mouse = MapSVG.mouseCoords(e);
10555                this.containers.main.style.left =
10556                    e.clientX +
10557                        $$z(window).scrollLeft() -
10558                        $$z(this.mapsvg.containers.map).offset().left +
10559                        "px";
10560                this.containers.main.style.top =
10561                    e.clientY +
10562                        $$z(window).scrollTop() -
10563                        $$z(this.mapsvg.containers.map).offset().top +
10564                        "px";
10565                const m = new ScreenPoint(e.clientX + $$z(window).scrollLeft(), e.clientY + $$z(window).scrollTop());
10566                const _tbbox = this.containers.main.getBoundingClientRect();
10567                const _mbbox = this.mapsvg.containers.wrap.getBoundingClientRect();
10568                const tbbox = {
10569                    top: _tbbox.top + $$z(window).scrollTop(),
10570                    bottom: _tbbox.bottom + $$z(window).scrollTop(),
10571                    left: _tbbox.left + $$z(window).scrollLeft(),
10572                    right: _tbbox.right + $$z(window).scrollLeft(),
10573                    width: _tbbox.width,
10574                    height: _tbbox.height,
10575                };
10576                const mbbox = {
10577                    top: _mbbox.top + $$z(window).scrollTop(),
10578                    bottom: _mbbox.bottom + $$z(window).scrollTop(),
10579                    left: _mbbox.left + $$z(window).scrollLeft(),
10580                    right: _mbbox.right + $$z(window).scrollLeft(),
10581                    width: _mbbox.width,
10582                    height: _mbbox.height,
10583                };
10584                if (m.x > mbbox.right ||
10585                    m.y > mbbox.bottom ||
10586                    m.x < mbbox.left ||
10587                    m.y < mbbox.top) {
10588                    return;
10589                }
10590                if (this.mirror.top || this.mirror.bottom) {
10591                    if (this.mirror.top && m.y > this.mirror.top) {
10592                        this.mirror.top = 0;
10593                        delete this.posShifted.topbottom;
10594                    }
10595                    else if (this.mirror.bottom && m.y < this.mirror.bottom) {
10596                        this.mirror.bottom = 0;
10597                        delete this.posShifted.topbottom;
10598                    }
10599                }
10600                else {
10601                    if (tbbox.bottom < mbbox.top + tbbox.height) {
10602                        this.posShifted.topbottom = "bottom";
10603                        this.mirror.top = m.y;
10604                    }
10605                    else if (tbbox.top > mbbox.bottom - tbbox.height) {
10606                        this.posShifted.topbottom = "top";
10607                        this.mirror.bottom = m.y;
10608                    }
10609                }
10610                if (this.mirror.right || this.mirror.left) {
10611                    if (this.mirror.left && m.x > this.mirror.left) {
10612                        this.mirror.left = 0;
10613                        delete this.posShifted.leftright;
10614                    }
10615                    else if (this.mirror.right && m.x < this.mirror.right) {
10616                        this.mirror.right = 0;
10617                        delete this.posShifted.leftright;
10618                    }
10619                }
10620                else {
10621                    if (tbbox.right < mbbox.left + tbbox.width) {
10622                        this.posShifted.leftright = "right";
10623                        this.mirror.left = m.x;
10624                    }
10625                    else if (tbbox.left > mbbox.right - tbbox.width) {
10626                        this.posShifted.leftright = "left";
10627                        this.mirror.right = m.x;
10628                    }
10629                }
10630                let pos = $$z.extend({}, this.posOriginal, this.posShifted);
10631                const _pos = [];
10632                pos.topbottom && _pos.push(pos.topbottom);
10633                pos.leftright && _pos.push(pos.leftright);
10634                pos = _pos.join("-");
10635                if (this.posShifted.topbottom != this.posOriginal.topbottom ||
10636                    this.posShifted.leftright != this.posOriginal.leftright) {
10637                    this.containers.main.className = this.containers.main.className.replace(/(^|\s)mapsvg-tt-\S+/g, "");
10638                    this.containers.main.classList.add("mapsvg-tt-" + pos);
10639                    this.posShiftedPrev = pos;
10640                }
10641            });
10642        }
10643        setContent(template, data) {
10644            this.containers.main.innerHTML = template(data);
10645            return this;
10646        }
10647        show() {
10648            this.containers.main.classList.add("mapsvg-tooltip-visible");
10649            return this;
10650        }
10651        hide() {
10652            this.containers.main.classList.remove("mapsvg-tooltip-visible");
10653            return this;
10654        }
10655    }
10656
10657    const $$A = jQuery;
10658    class MapSVGMap {
10659        constructor(containerId, mapParams, externalParams) {
10660            this.markerOptions = { src: MapSVG.urls.root + "markers/pin1_red.png" };
10661            const options = mapParams.options;
10662            this.updateOutdatedOptions(options);
10663            this.dirtyFields = [];
10664            this.containerId = containerId;
10665            this.options = $$A.extend(true, {}, DefaultOptions, options);
10666            this.options.source = this.urlToRelativePath(this.options.source);
10667            this.editMode = this.options.editMode;
10668            delete this.options.editMode;
10669            this.id = mapParams.id;
10670            this.svgFileLastChanged = mapParams.svgFileLastChanged;
10671            this.regions = new ArrayIndexed("id");
10672            this.objects = new ArrayIndexed("id");
10673            this.events = new Events(this);
10674            this.highlightedRegions = [];
10675            this.editRegions = { on: false };
10676            this.editMarkers = { on: false };
10677            this.editData = { on: false };
10678            this.controllers = {};
10679            this.containers = {
10680                map: document.getElementById(this.containerId),
10681                scrollpane: $$A('<div class="mapsvg-scrollpane"></div>')[0],
10682                scrollpaneWrap: $$A('<div class="mapsvg-scrollpane-wrap"></div>')[0],
10683                layers: $$A('<div class="mapsvg-layers-wrap"></div>')[0],
10684            };
10685            this.containers.map.appendChild(this.containers.layers);
10686            this.containers.map.appendChild(this.containers.scrollpaneWrap);
10687            this.containers.scrollpaneWrap.appendChild(this.containers.scrollpane);
10688            this.whRatio = 0;
10689            this.isScrolling = false;
10690            this.markerOptions = {};
10691            this.svgDefault = {};
10692            this.scale = 1;
10693            this._scale = 1;
10694            this.selected_id = [];
10695            this.regions = new ArrayIndexed("id");
10696            if (!this.options.database.regionsTableName) {
10697                this.options.database.regionsTableName = "regions_" + this.id;
10698            }
10699            if (!this.options.database.objectsTableName) {
10700                this.options.database.objectsTableName = "objects_" + this.id;
10701            }
10702            this.regionsRepository = new Repository("region", "regions/" + this.options.database.regionsTableName);
10703            this.regionsRepository.query.update({ perpage: 0 });
10704            this.objectsRepository = new Repository("object", "objects/" + this.options.database.objectsTableName);
10705            if (this.options.database.noFiltersNoLoad) {
10706                this.objectsRepository.setNoFiltersNoLoad(true);
10707            }
10708            this.objectsRepository.query.update({
10709                perpage: this.options.database.pagination.on
10710                    ? this.options.database.pagination.perpage
10711                    : 0,
10712            });
10713            this.schemaRepository = new SchemaRepository();
10714            this.markers = new ArrayIndexed("id");
10715            this.markersClusters = new ArrayIndexed("id");
10716            this._viewBox = new ViewBox(0, 0, 0, 0);
10717            this.viewBox = new ViewBox(0, 0, 0, 0);
10718            this.zoomLevel = 0;
10719            this.scroll = {
10720                tx: 0,
10721                ty: 0,
10722                vxi: 0,
10723                vyi: 0,
10724                x: 0,
10725                y: 0,
10726                dx: 0,
10727                dy: 0,
10728                vx: 0,
10729                vy: 0,
10730                gx: 0,
10731                gy: 0,
10732                touchScrollStart: 0,
10733            };
10734            this.layers = {};
10735            this.geoCoordinates = false;
10736            this.geoViewBox = new GeoViewBox(new GeoPoint(0, 0), new GeoPoint(0, 0));
10737            this.eventsPreventList = {};
10738            this.googleMaps = {
10739                loaded: false,
10740                initialized: false,
10741                map: null,
10742                zoomLimit: true,
10743                maxZoomService: null,
10744            };
10745            this.afterLoadBlockers = 1;
10746            this.loaded = false;
10747            if (this.id) {
10748                this.afterLoadBlockers += 2;
10749            }
10750            if (this.options.googleMaps.on) {
10751                this.afterLoadBlockers++;
10752            }
10753            if (this.filtersShouldBeShown()) {
10754                this.afterLoadBlockers++;
10755            }
10756            this.init();
10757        }
10758        urlToRelativePath(url) {
10759            if (url.indexOf("//") === 0)
10760                url = url.replace(/^\/\/[^/]+/, "").replace("//", "/");
10761            else
10762                url = url.replace(/^.*:\/\/[^/]+/, "").replace("//", "/");
10763            return url;
10764        }
10765        setGroups(groups) {
10766            const _this = this;
10767            if (!this.groups) {
10768                _this.groups = new ArrayIndexed("id", _this.options.groups, {
10769                    autoId: true,
10770                    unique: true,
10771                });
10772            }
10773            else {
10774                this.options.groups = this.groups;
10775            }
10776            _this.groups.forEach(function (g) {
10777                g.objects &&
10778                    g.objects.length &&
10779                    g.objects.forEach(function (obj) {
10780                        _this.containers.svg
10781                            .querySelector("#" + obj.value)
10782                            .classList.toggle("mapsvg-hidden", !g.visible);
10783                    });
10784            });
10785        }
10786        getGroupSelectOptions() {
10787            const _this = this;
10788            const optionGroups = [];
10789            const options = [];
10790            const options2 = [];
10791            $$A(_this.containers.svg)
10792                .find("g")
10793                .each(function (index) {
10794                const id = $$A(this)[0].getAttribute("id");
10795                if (id) {
10796                    const title = $$A(this)[0].getAttribute("title");
10797                    options.push({ label: title || id, value: id });
10798                }
10799            });
10800            optionGroups.push({ title: "SVG Layers / Groups", options: options });
10801            $$A(_this.containers.svg)
10802                .find("path,ellipse,circle,polyline,polygon,rectangle,img,text")
10803                .each(function (index) {
10804                const id = $$A(this)[0].getAttribute("id");
10805                if (id) {
10806                    const title = $$A(this)[0].getAttribute("title");
10807                    options2.push({ label: title || id, value: id });
10808                }
10809            });
10810            optionGroups.push({ title: "Other SVG objects", options: options2 });
10811            return optionGroups;
10812        }
10813        setLayersControl(options) {
10814            const _this = this;
10815            if (options)
10816                $$A.extend(true, this.options.layersControl, options);
10817            if (this.options.layersControl.on) {
10818                if (!this.containers.layersControl) {
10819                    this.containers.layersControl = document.createElement("div");
10820                    this.containers.layersControl.classList.add("mapsvg-layers-control");
10821                    this.containers.layersControlLabel = document.createElement("div");
10822                    this.containers.layersControlLabel.classList.add("mapsvg-layers-label");
10823                    this.containers.layersControl.appendChild(this.containers.layersControlLabel);
10824                    const layersControlWrap = document.createElement("div");
10825                    layersControlWrap.classList.add("mapsvg-layers-list-wrap");
10826                    this.containers.layersControl.appendChild(layersControlWrap);
10827                    this.containers.layersControlListNano = document.createElement("div");
10828                    this.containers.layersControlListNano.classList.add("nano");
10829                    layersControlWrap.appendChild(this.containers.layersControlListNano);
10830                    this.containers.layersControlList = document.createElement("div");
10831                    this.containers.layersControlList.classList.add("mapsvg-layers-list");
10832                    this.containers.layersControlList.classList.add("nano-content");
10833                    this.containers.layersControlListNano.appendChild(this.containers.layersControlList);
10834                    this.containers.mapContainer.appendChild(this.containers.layersControl);
10835                }
10836                this.containers.layersControl.style.display = "block";
10837                this.containers.layersControlLabel.innerHTML = this.options.layersControl.label;
10838                this.containers.layersControlLabel.style.display = "block";
10839                this.containers.layersControlList.innerHTML = "";
10840                while (this.containers.layersControlList.firstChild) {
10841                    this.containers.layersControlList.removeChild(this.containers.layersControlList.firstChild);
10842                }
10843                this.containers.layersControl.classList.remove("mapsvg-top-left", "mapsvg-top-right", "mapsvg-bottom-left", "mapsvg-bottom-right");
10844                this.containers.layersControl.classList.add("mapsvg-" + this.options.layersControl.position);
10845                if (this.options.menu.on &&
10846                    !this.options.menu.customContainer &&
10847                    this.options.layersControl.position.indexOf("left") !== -1) {
10848                    this.containers.layersControl.style.left = this.options.menu.width;
10849                }
10850                this.containers.layersControl.style.maxHeight = this.options.layersControl.maxHeight;
10851                this.options.groups.forEach((g) => {
10852                    const item = document.createElement("div");
10853                    item.classList.add("mapsvg-layers-item");
10854                    item.setAttribute("data-group-id", g.id);
10855                    item.innerHTML =
10856                        '<input type="checkbox" class="ios8-switch ios8-switch-sm" ' +
10857                            (g.visible ? "checked" : "") +
10858                            " /><label>" +
10859                            g.title +
10860                            "</label>";
10861                    this.containers.layersControlList.appendChild(item);
10862                });
10863                $$A(this.containers.layersControlListNano).nanoScroller({
10864                    preventPageScrolling: true,
10865                    iOSNativeScrolling: true,
10866                });
10867                $$A(this.containers.layersControl).off();
10868                $$A(this.containers.layersControl).on("click", ".mapsvg-layers-item", function () {
10869                    const id = $$A(this).data("group-id");
10870                    const input = $$A(this).find("input");
10871                    input.prop("checked", !input.prop("checked"));
10872                    _this.groups.forEach(function (g) {
10873                        if (g.id === id)
10874                            g.visible = !g.visible;
10875                    });
10876                    _this.setGroups();
10877                });
10878                $$A(this.containers.layersControlLabel).off();
10879                $$A(this.containers.layersControlLabel).on("click", () => {
10880                    $$A(_this.containers.layersControl).toggleClass("closed");
10881                });
10882                $$A(this.containers.layersControl).toggleClass("closed", !this.options.layersControl.expanded);
10883            }
10884            else {
10885                if (this.containers.layersControl) {
10886                    this.containers.layersControl.style.display = "none";
10887                }
10888            }
10889        }
10890        loadDataObjects(params) {
10891            return this.objectsRepository.find(params);
10892        }
10893        loadDirectory() {
10894            if (!this.editMode &&
10895                this.options.menu.source === "database" &&
10896                !this.objectsRepository.loaded) {
10897                return;
10898            }
10899            if (this.options.menu.on) {
10900                this.controllers.directory.loadItemsToDirectory();
10901            }
10902            this.setPagination();
10903        }
10904        setPagination() {
10905            const _this = this;
10906            this.containers.pagerMap && $$A(this.containers.pagerMap).empty().remove();
10907            this.containers.pagerDir && $$A(this.containers.pagerDir).empty().remove();
10908            if (_this.options.database.pagination.on &&
10909                _this.options.database.pagination.perpage !== 0) {
10910                this.containers.directory.classList.toggle("mapsvg-with-pagination", ["directory", "both"].indexOf(_this.options.database.pagination.showIn) !== -1);
10911                this.containers.map.classList.toggle("mapsvg-with-pagination", ["map", "both"].indexOf(_this.options.database.pagination.showIn) !== -1);
10912                if (_this.options.menu.on) {
10913                    this.containers.pagerDir = _this.getPagination();
10914                    _this.controllers.directory.addPagination(this.containers.pagerDir);
10915                }
10916                this.containers.pagerMap = _this.getPagination();
10917                this.containers.map.appendChild(this.containers.pagerMap);
10918            }
10919        }
10920        getPagination(callback) {
10921            const _this = this;
10922            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; ' +
10923                _this.options.database.pagination.prev +
10924                " " +
10925                _this.options.database.pagination.perpage +
10926                '</a></li><li class="mapsvg-next"><a href="#">' +
10927                _this.options.database.pagination.next +
10928                " " +
10929                _this.options.database.pagination.perpage +
10930                ' &rarr;</a></li><!--<li class="mapsvg-last"><a href="#">Last</a></li>--></ul></nav>');
10931            if (this.objectsRepository.onFirstPage() && this.objectsRepository.onLastPage()) {
10932                pager.hide();
10933            }
10934            else {
10935                pager.find(".mapsvg-prev").removeClass("disabled");
10936                pager.find(".mapsvg-first").removeClass("disabled");
10937                pager.find(".mapsvg-last").removeClass("disabled");
10938                pager.find(".mapsvg-next").removeClass("disabled");
10939                this.objectsRepository.onLastPage() &&
10940                    pager.find(".mapsvg-next").addClass("disabled") &&
10941                    pager.find(".mapsvg-last").addClass("disabled");
10942                this.objectsRepository.onFirstPage() &&
10943                    pager.find(".mapsvg-prev").addClass("disabled") &&
10944                    pager.find(".mapsvg-first").addClass("disabled");
10945            }
10946            pager
10947                .on("click", ".mapsvg-next:not(.disabled)", (e) => {
10948                e.preventDefault();
10949                if (this.objectsRepository.onLastPage())
10950                    return;
10951                const query = new Query({ page: this.objectsRepository.query.page + 1 });
10952                this.objectsRepository.find(query).done(function () {
10953                    callback && callback();
10954                });
10955            })
10956                .on("click", ".mapsvg-prev:not(.disabled)", function (e) {
10957                e.preventDefault();
10958                if (_this.objectsRepository.onFirstPage())
10959                    return;
10960                const query = new Query({ page: _this.objectsRepository.query.page - 1 });
10961                _this.objectsRepository.find(query).done(function () {
10962                    callback && callback();
10963                });
10964            })
10965                .on("click", ".mapsvg-first:not(.disabled)", function (e) {
10966                e.preventDefault();
10967                if (_this.objectsRepository.onFirstPage())
10968                    return;
10969                const query = new Query({ page: 1 });
10970                _this.objectsRepository.find(query).done(function () {
10971                    callback && callback();
10972                });
10973            })
10974                .on("click", ".mapsvg-last:not(.disabled)", function (e) {
10975                e.preventDefault();
10976                if (_this.objectsRepository.onLastPage())
10977                    return;
10978                const query = new Query({ lastpage: true });
10979                _this.objectsRepository.find(query).done(function () {
10980                    callback && callback();
10981                });
10982            });
10983            return pager[0];
10984        }
10985        deleteMarkers() {
10986            while (this.markers.length) {
10987                this.markerDelete(this.markers[0]);
10988            }
10989        }
10990        deleteClusters() {
10991            if (this.markersClusters) {
10992                this.markersClusters.forEach(function (markerCluster) {
10993                    markerCluster.destroy();
10994                });
10995                this.markersClusters.clear();
10996            }
10997        }
10998        addLocations() {
10999            const _this = this;
11000            this.firstDataLoad = this.firstDataLoad === undefined;
11001            let locationField = this.objectsRepository.getSchema().getFieldByType("location");
11002            if (!locationField) {
11003                return;
11004            }
11005            locationField = locationField.name;
11006            if (locationField) {
11007                if (this.firstDataLoad) {
11008                    this.setMarkerImagesDependency();
11009                }
11010                _this.deleteMarkers();
11011                _this.deleteClusters();
11012                _this.clusters = {};
11013                _this.clustersByZoom = [];
11014                if (this.objectsRepository.getLoaded().length > 0) {
11015                    this.objectsRepository.getLoaded().forEach(function (object) {
11016                        if (object[locationField]) {
11017                            if (object[locationField].img &&
11018                                (object[locationField].geoPoint || object[locationField].svgPoint)) {
11019                                new Marker({
11020                                    location: object[locationField],
11021                                    object: object,
11022                                    mapsvg: _this,
11023                                });
11024                            }
11025                        }
11026                    });
11027                    if (_this.options.clustering.on) {
11028                        _this.startClusterizer();
11029                    }
11030                    else {
11031                        this.objectsRepository.getLoaded().forEach(function (object) {
11032                            if (object.location && object.location.marker) {
11033                                _this.markerAdd(object.location.marker);
11034                            }
11035                        });
11036                        _this.mayBeFitMarkers();
11037                    }
11038                }
11039            }
11040        }
11041        addClustersFromWorker(zoomLevel, clusters) {
11042            const _this = this;
11043            _this.clustersByZoom[zoomLevel] = [];
11044            for (const cell in clusters) {
11045                const markers = clusters[cell].markers.map(function (marker) {
11046                    return _this.objectsRepository.objects.findById(marker.id).location.marker;
11047                });
11048                _this.clustersByZoom[zoomLevel].push(new MarkerCluster({
11049                    markers: markers,
11050                    svgPoint: new SVGPoint(clusters[cell].x, clusters[cell].y),
11051                    cellX: clusters[cell].cellX,
11052                    cellY: clusters[cell].cellY,
11053                }, _this));
11054            }
11055            if (_this.zoomLevel === zoomLevel) {
11056                _this.clusterizeMarkers();
11057            }
11058        }
11059        startClusterizer() {
11060            if (!this.objectsRepository || this.objectsRepository.getLoaded().length === 0) {
11061                return;
11062            }
11063            const locationField = this.objectsRepository.getSchema().getFieldByType("location");
11064            if (!locationField) {
11065                return false;
11066            }
11067            if (!this.clusterizerWorker) {
11068                this.clusterizerWorker = new Worker(MapSVG.urls.root + "js/mapsvg/Core/clustering.js");
11069                this.clusterizerWorker.onmessage = (evt) => {
11070                    if (evt.data.clusters) {
11071                        this.addClustersFromWorker(evt.data.zoomLevel, evt.data.clusters);
11072                    }
11073                };
11074            }
11075            const objectsData = [];
11076            this.objectsRepository
11077                .getLoaded()
11078                .filter((o) => {
11079                return o.location && o.location.marker;
11080            })
11081                .forEach((o) => {
11082                objectsData.push({
11083                    id: o.id,
11084                    x: o.location.marker.svgPoint.x,
11085                    y: o.location.marker.svgPoint.y,
11086                });
11087            });
11088            this.clusterizerWorker.postMessage({
11089                objects: objectsData,
11090                cellSize: 50,
11091                mapWidth: this.containers.map.clientWidth,
11092                zoomLevels: this.zoomLevels,
11093                zoomLevel: this.zoomLevel,
11094                zoomDelta: this.zoomDelta,
11095                svgViewBox: this.svgDefault.viewBox,
11096            });
11097            this.events.on("zoom", () => {
11098                this.clusterizerWorker.postMessage({
11099                    message: "zoom",
11100                    zoomLevel: this.zoomLevel,
11101                });
11102            });
11103        }
11104        clusterizeMarkers(skipFitMarkers) {
11105            $$A(this.layers.markers)
11106                .children()
11107                .each((i, obj) => {
11108                $$A(obj).detach();
11109            });
11110            this.markers.clear();
11111            this.markersClusters.clear();
11112            this.clustersByZoom &&
11113                this.clustersByZoom[this.zoomLevel] &&
11114                this.clustersByZoom[this.zoomLevel].forEach((cluster) => {
11115                    if (this.options.googleMaps.on &&
11116                        this.googleMaps.map &&
11117                        this.googleMaps.map.getZoom() >= 17) {
11118                        this.markerAdd(cluster.markers[0]);
11119                    }
11120                    else {
11121                        if (cluster.markers.length > 1) {
11122                            this.markersClusterAdd(cluster);
11123                        }
11124                        else {
11125                            this.markerAdd(cluster.markers[0]);
11126                        }
11127                    }
11128                });
11129            if (this.editingMarker) {
11130                this.markerAdd(this.editingMarker);
11131            }
11132            if (!skipFitMarkers) {
11133                this.mayBeFitMarkers();
11134            }
11135            if (this.options.labelsMarkers.on) {
11136                this.setLabelsMarkers();
11137            }
11138        }
11139        getCssUrl() {
11140            return MapSVG.urls.root + "css/mapsvg.css";
11141        }
11142        isGeo() {
11143            return this.mapIsGeo;
11144        }
11145        functionFromString(string) {
11146            let func;
11147            let error;
11148            const fn = string.trim();
11149            if (fn.indexOf("{") == -1 || fn.indexOf("function") !== 0 || fn.indexOf("(") == -1) {
11150                return new SyntaxError("MapSVG user function error: no function body.");
11151            }
11152            const fnBody = fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"));
11153            const params = fn.substring(fn.indexOf("(") + 1, fn.indexOf(")"));
11154            try {
11155                func = new Function(params, fnBody);
11156            }
11157            catch (err) {
11158                error = err;
11159            }
11160            if (!error)
11161                return func;
11162            else
11163                return error;
11164        }
11165        getOptions(forTemplate, forWeb) {
11166            const options = $$A.extend(true, {}, this.options);
11167            function clearEmpties(o) {
11168                for (const k in o) {
11169                    if (!o[k] || typeof o[k] !== "object") {
11170                        continue;
11171                    }
11172                    clearEmpties(o[k]);
11173                    if (Object.keys(o[k]).length === 0) {
11174                        delete o[k];
11175                    }
11176                }
11177            }
11178            clearEmpties(options.regions);
11179            $$A.extend(true, options, this.optionsDelta);
11180            options.viewBox = this._viewBox.toArray();
11181            options.filtersSchema = this.filtersSchema.getFieldsAsArray();
11182            if (options.filtersSchema.length > 0) {
11183                options.filtersSchema.forEach((field) => {
11184                    if (field.type === "distance") {
11185                        field.value = "";
11186                    }
11187                });
11188            }
11189            delete options.markers;
11190            if (forTemplate) {
11191                options.svgFilename = options.source.split("/").pop();
11192                options.svgFiles = MapSVG.svgFiles;
11193            }
11194            if (forWeb)
11195                $$A.each(options, (key, val) => {
11196                    if (JSON.stringify(val) == JSON.stringify(this.defaults[key]))
11197                        delete options[key];
11198                });
11199            delete options.backend;
11200            return options;
11201        }
11202        restoreDeltaOptions() {
11203            this.update(this.optionsDelta);
11204            this.optionsDelta = {};
11205        }
11206        setEvents(functions) {
11207            let compiledFunction;
11208            for (const eventName in functions) {
11209                if (typeof functions[eventName] === "string") {
11210                    compiledFunction =
11211                        functions[eventName] != ""
11212                            ? this.functionFromString(functions[eventName])
11213                            : null;
11214                    if (!compiledFunction ||
11215                        compiledFunction.error ||
11216                        compiledFunction instanceof TypeError ||
11217                        compiledFunction instanceof SyntaxError) {
11218                        continue;
11219                    }
11220                }
11221                else if (typeof functions[eventName] === "function") {
11222                    compiledFunction = functions[eventName];
11223                }
11224                this.events.off(eventName);
11225                this.events.on(eventName, compiledFunction);
11226                if (eventName.indexOf("directory") !== -1) {
11227                    const event = eventName.split(".")[0];
11228                    if (this.controllers && this.controllers.directory) {
11229                        this.controllers.directory.events.off(event);
11230                        this.controllers.directory.events.on(event, compiledFunction);
11231                    }
11232                }
11233            }
11234            $$A.extend(true, this.options.events, functions);
11235        }
11236        setActions(options) {
11237            $$A.extend(true, this.options.actions, options);
11238        }
11239        setDetailsView(options) {
11240            options = options || this.options.detailsView || {};
11241            $$A.extend(true, this.options.detailsView, options);
11242            if (this.options.detailsView.location === "top" && this.options.menu.position === "left") {
11243                this.options.detailsView.location = "leftSidebar";
11244            }
11245            else if (this.options.detailsView.location === "top" &&
11246                this.options.menu.position === "right") {
11247                this.options.detailsView.location = "rightSidebar";
11248            }
11249            if (this.options.detailsView.location === "near" ||
11250                this.options.detailsView.location === "mapContainer") {
11251                this.options.detailsView.location = "map";
11252            }
11253            if (!this.containers.detailsView) {
11254                this.containers.detailsView = $$A('<div class="mapsvg-details-container"></div>')[0];
11255            }
11256            $$A(this.containers.detailsView).toggleClass("mapsvg-details-container-relative", !(MapSVG.isPhone && this.options.detailsView.mobileFullscreen) &&
11257                !this.shouldBeScrollable(this.options.detailsView.location));
11258            if (this.options.detailsView.location === "custom") {
11259                $$A("#" + this.options.detailsView.containerId).append($$A(this.containers.detailsView));
11260            }
11261            else {
11262                if (MapSVG.isPhone && this.options.detailsView.mobileFullscreen) {
11263                    $$A("body").append($$A(this.containers.detailsView));
11264                    $$A(this.containers.detailsView).addClass("mapsvg-container-fullscreen");
11265                }
11266                else {
11267                    this.containers[this.options.detailsView.location].append(this.containers.detailsView);
11268                }
11269                if (this.options.detailsView.margin) {
11270                    $$A(this.containers.detailsView).css("margin", this.options.detailsView.margin);
11271                }
11272                $$A(this.containers.detailsView).css("width", this.options.detailsView.width);
11273            }
11274        }
11275        setMobileView(options) {
11276            $$A.extend(true, this.options.mobileView, options);
11277        }
11278        attachDataToRegions(object) {
11279            this.regions.forEach(function (region) {
11280                region.objects = [];
11281            });
11282            this.objectsRepository.getLoaded().forEach((obj, index) => {
11283                const regions = obj.getRegionsForTable(this.options.database.regionsTableName);
11284                if (regions && regions.length) {
11285                    regions.forEach((region) => {
11286                        const r = this.getRegion(region.id);
11287                        if (r)
11288                            r.objects.push(obj);
11289                    });
11290                }
11291            });
11292        }
11293        setTemplates(templates) {
11294            this.templates = this.templates || {};
11295            for (let name in templates) {
11296                if (name != undefined) {
11297                    this.options.templates[name] = templates[name];
11298                    let t = this.options.templates[name];
11299                    if (name == "directoryItem" || name == "directoryCategoryItem") {
11300                        const dirItemTemplate = this.options.templates.directoryItem;
11301                        t =
11302                            '{{#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}}">' +
11303                                dirItemTemplate +
11304                                "</div>{{/each}}";
11305                        if (this.options.menu.categories &&
11306                            this.options.menu.categories.on &&
11307                            this.options.menu.categories.groupBy) {
11308                            const t2 = this.options.templates["directoryCategoryItem"];
11309                            t =
11310                                '{{#each items}}{{#with category}}<div id="mapsvg-category-item-{{value}}" class="mapsvg-category-item" data-category-value="{{value}}">' +
11311                                    t2 +
11312                                    '</div><div class="mapsvg-category-block" data-category-id="{{value}}">{{/with}}' +
11313                                    t +
11314                                    "</div>{{/each}}";
11315                        }
11316                        name = "directory";
11317                    }
11318                    try {
11319                        this.options.templates[name] = t;
11320                        this.templates[name] = Handlebars.compile(t, { strict: false });
11321                    }
11322                    catch (err) {
11323                        console.error(err);
11324                        this.templates[name] = Handlebars.compile("", { strict: false });
11325                    }
11326                    if (this.editMode &&
11327                        (name == "directory" || name == "directoryCategoryItem") &&
11328                        this.controllers &&
11329                        this.controllers.directory) {
11330                        this.controllers.directory.templates.main = this.templates[name];
11331                        this.loadDirectory();
11332                    }
11333                }
11334            }
11335        }
11336        update(options) {
11337            for (const key in options) {
11338                if (key == "regions") {
11339                    for (const id in options.regions) {
11340                        const region = this.getRegion(id);
11341                        region && region.update(options.regions[id]);
11342                        if (options.regions[id].disabled != undefined) {
11343                            this.deselectRegion(region);
11344                            this.options.regions[id] = this.options.regions[id] || {};
11345                            this.options.regions[id].disabled = region.disabled;
11346                        }
11347                    }
11348                }
11349                else {
11350                    const setter = "set" + MapSVG.ucfirst(key);
11351                    if (typeof this[setter] == "function")
11352                        this[setter](options[key]);
11353                    else {
11354                        this.options[key] = options[key];
11355                    }
11356                }
11357            }
11358        }
11359        getDirtyFields() {
11360            return this.getData();
11361        }
11362        clearDirtyFields() {
11363            this.dirtyFields = [];
11364        }
11365        setTitle(title) {
11366            title && (this.options.title = title);
11367        }
11368        setExtension(extension) {
11369            if (extension) {
11370                this.options.extension = extension;
11371            }
11372            else {
11373                delete this.options.extension;
11374            }
11375        }
11376        setDisableLinks(on) {
11377            on = MapSVG.parseBoolean(on);
11378            if (on) {
11379                $$A(this.containers.map).on("click.a.mapsvg", "a", function (e) {
11380                    e.preventDefault();
11381                });
11382            }
11383            else {
11384                $$A(this.containers.map).off("click.a.mapsvg");
11385            }
11386            this.disableLinks = on;
11387        }
11388        setLoadingText(val) {
11389            this.options.loadingText = val;
11390        }
11391        setLockAspectRatio(onoff) {
11392            this.options.lockAspectRatio = MapSVG.parseBoolean(onoff);
11393        }
11394        setMarkerEditHandler(handler) {
11395            this.markerEditHandler = handler;
11396        }
11397        setChoroplethSourceField(field) {
11398            this.options.choropleth.sourceField = field;
11399            this.redrawChoropleth();
11400        }
11401        setRegionEditHandler(handler) {
11402            this.regionEditHandler = handler;
11403        }
11404        setDisableAll(on) {
11405            on = MapSVG.parseBoolean(on);
11406            $$A.extend(true, this.options, { disableAll: on });
11407            $$A(this.containers.map).toggleClass("mapsvg-disabled-regions", on);
11408        }
11409        setRegionStatuses(_statuses) {
11410            this.options.regionStatuses = {};
11411            const colors = {};
11412            _statuses.forEach((statusOptions) => {
11413                this.options.regionStatuses[statusOptions.value] = statusOptions;
11414                colors[statusOptions.value] = statusOptions.color.length
11415                    ? statusOptions.color
11416                    : undefined;
11417            });
11418            this.setColors({ status: colors });
11419        }
11420        setColorsIgnore(val) {
11421            this.options.colorsIgnore = MapSVG.parseBoolean(val);
11422            this.regionsRedrawColors();
11423        }
11424        setColors(colors) {
11425            for (const i in colors) {
11426                if (i === "status") {
11427                    for (const s in colors[i]) {
11428                        MapSVG.fixColorHash(colors[i][s]);
11429                    }
11430                }
11431                else {
11432                    if (typeof colors[i] == "string") {
11433                        MapSVG.fixColorHash(colors[i]);
11434                    }
11435                }
11436            }
11437            $$A.extend(true, this.options, { colors: colors });
11438            if (colors && colors.status)
11439                this.options.colors.status = colors.status;
11440            if (this.options.colors.markers) {
11441                for (const z in this.options.colors.markers) {
11442                    for (const x in this.options.colors.markers[z]) {
11443                        this.options.colors.markers[z][x] = parseInt(this.options.colors.markers[z][x]);
11444                    }
11445                }
11446            }
11447            if (this.options.colors.background)
11448                $$A(this.containers.map).css({ background: this.options.colors.background });
11449            if (this.options.colors.hover) {
11450                this.options.colors.hover = !isNaN(this.options.colors.hover)
11451                    ? parseInt(this.options.colors.hover + "")
11452                    : this.options.colors.hover;
11453            }
11454            if (this.options.colors.selected) {
11455                this.options.colors.selected = !isNaN(this.options.colors.selected)
11456                    ? parseInt(this.options.colors.selected + "")
11457                    : this.options.colors.selected;
11458            }
11459            $$A(this.containers.leftSidebar).css({
11460                "background-color": this.options.colors.leftSidebar,
11461            });
11462            $$A(this.containers.rightSidebar).css({
11463                "background-color": this.options.colors.rightSidebar,
11464            });
11465            $$A(this.containers.header).css({ "background-color": this.options.colors.header });
11466            $$A(this.containers.footer).css({ "background-color": this.options.colors.footer });
11467            if ($$A(this.containers.detailsView) && this.options.colors.detailsView !== undefined) {
11468                $$A(this.containers.detailsView).css({
11469                    "background-color": this.options.colors.detailsView,
11470                });
11471            }
11472            if ($$A(this.containers.directory) && this.options.colors.directory !== undefined) {
11473                $$A(this.containers.directory).css({
11474                    "background-color": this.options.colors.directory,
11475                });
11476            }
11477            if ($$A(this.containers.filtersModal) && this.options.colors.modalFilters !== undefined) {
11478                $$A(this.containers.filtersModal).css({
11479                    "background-color": this.options.colors.modalFilters,
11480                });
11481            }
11482            if ($$A(this.containers.filters) && this.options.colors.directorySearch) {
11483                $$A(this.containers.filters).css({
11484                    "background-color": this.options.colors.directorySearch,
11485                });
11486            }
11487            else if ($$A(this.containers.filters)) {
11488                $$A(this.containers.filters).css({
11489                    "background-color": "",
11490                });
11491            }
11492            if (!this.containers.clustersCss) {
11493                this.containers.clustersCss = ($$A("<style></style>").appendTo("body")[0]);
11494            }
11495            let css = "";
11496            if (this.options.colors.clusters) {
11497                css += "background-color: " + this.options.colors.clusters + ";";
11498            }
11499            if (this.options.colors.clustersBorders) {
11500                css += "border-color: " + this.options.colors.clustersBorders + ";";
11501            }
11502            if (this.options.colors.clustersText) {
11503                css += "color: " + this.options.colors.clustersText + ";";
11504            }
11505            $$A(this.containers.clustersCss).html(".mapsvg-marker-cluster {" + css + "}");
11506            if (!this.containers.clustersHoverCss) {
11507                this.containers.clustersHoverCss = ($$A("<style></style>").appendTo("body")[0]);
11508            }
11509            let cssHover = "";
11510            if (this.options.colors.clustersHover) {
11511                cssHover += "background-color: " + this.options.colors.clustersHover + ";";
11512            }
11513            if (this.options.colors.clustersHoverBorders) {
11514                cssHover += "border-color: " + this.options.colors.clustersHoverBorders + ";";
11515            }
11516            if (this.options.colors.clustersHoverText) {
11517                cssHover += "color: " + this.options.colors.clustersHoverText + ";";
11518            }
11519            $$A(this.containers.clustersHoverCss).html(".mapsvg-marker-cluster:hover {" + cssHover + "}");
11520            if (!this.containers.markersCss) {
11521                this.containers.markersCss = $$A("<style></style>").appendTo("head")[0];
11522            }
11523            const markerCssText = ".mapsvg-with-marker-active .mapsvg-marker {\n" +
11524                "  opacity: " +
11525                this.options.colors.markers.inactive.opacity / 100 +
11526                ";\n" +
11527                "  -webkit-filter: grayscale(" +
11528                (100 - this.options.colors.markers.inactive.saturation) +
11529                "%);\n" +
11530                "  filter: grayscale(" +
11531                (100 - this.options.colors.markers.inactive.saturation) +
11532                "%);\n" +
11533                "}\n" +
11534                ".mapsvg-with-marker-active .mapsvg-marker-active {\n" +
11535                "  opacity: " +
11536                this.options.colors.markers.active.opacity / 100 +
11537                ";\n" +
11538                "  -webkit-filter: grayscale(" +
11539                (100 - this.options.colors.markers.active.saturation) +
11540                "%);\n" +
11541                "  filter: grayscale(" +
11542                (100 - this.options.colors.markers.active.saturation) +
11543                "%);\n" +
11544                "}\n" +
11545                ".mapsvg-with-marker-hover .mapsvg-marker {\n" +
11546                "  opacity: " +
11547                this.options.colors.markers.unhovered.opacity / 100 +
11548                ";\n" +
11549                "  -webkit-filter: grayscale(" +
11550                (100 - this.options.colors.markers.unhovered.saturation) +
11551                "%);\n" +
11552                "  filter: grayscale(" +
11553                (100 - this.options.colors.markers.unhovered.saturation) +
11554                "%);\n" +
11555                "}\n" +
11556                ".mapsvg-with-marker-hover .mapsvg-marker-hover {\n" +
11557                "  opacity: " +
11558                this.options.colors.markers.hovered.opacity / 100 +
11559                ";\n" +
11560                "  -webkit-filter: grayscale(" +
11561                (100 - this.options.colors.markers.hovered.saturation) +
11562                "%);\n" +
11563                "  filter: grayscale(" +
11564                (100 - this.options.colors.markers.hovered.saturation) +
11565                "%);\n" +
11566                "}\n";
11567            $$A(this.containers.markersCss).html(markerCssText);
11568            $$A.each(this.options.colors, (key, color) => {
11569                if (color === null || color == "")
11570                    delete this.options.colors[key];
11571            });
11572            this.regionsRedrawColors();
11573        }
11574        setTooltips(options) {
11575            if (options.on !== undefined)
11576                options.on = MapSVG.parseBoolean(options.on);
11577            $$A.extend(true, this.options, { tooltips: options });
11578            if (!this.containers.tooltip) {
11579                this.containers.tooltip = $$A("<div />").addClass("mapsvg-tooltip")[0];
11580                $$A(this.containers.map).append(this.containers.tooltip);
11581                this.controllers.tooltip = new Tooltip({
11582                    mapsvg: this,
11583                    container: this.containers.tooltip,
11584                    position: this.options.tooltips.position,
11585                    maxWidth: this.options.tooltips.maxWidth,
11586                    minWidth: this.options.tooltips.minWidth,
11587                });
11588                this.controllers.tooltip._init();
11589            }
11590            if (typeof this.options.tooltips.position !== "undefined") {
11591                this.controllers.tooltip.setPosition(this.options.tooltips.position);
11592            }
11593            if (typeof this.options.tooltips.maxWidth !== "undefined" ||
11594                typeof this.options.tooltips.minWidth !== "undefined") {
11595                this.controllers.tooltip.setSize(this.options.tooltips.minWidth, this.options.tooltips.maxWidth);
11596            }
11597        }
11598        setPopovers(options) {
11599            if (options.on !== undefined)
11600                options.on = MapSVG.parseBoolean(options.on);
11601            $$A.extend(this.options.popovers, options);
11602            if (!this.containers.popover) {
11603                this.containers.popover = $$A("<div />").addClass("mapsvg-popover")[0];
11604                this.layers.popovers.append(this.containers.popover);
11605            }
11606            $$A(this.containers.popover).css({
11607                width: this.options.popovers.width + (this.options.popovers.width == "auto" ? "" : "px"),
11608                "max-width": this.options.popovers.maxWidth + "%",
11609                "max-height": (this.options.popovers.maxHeight * $$A(this.containers.wrap).outerHeight()) / 100 +
11610                    "px",
11611            });
11612            if (this.options.popovers.mobileFullscreen && MapSVG.
11612isPhone) {
11613                $$A("body").toggleClass("mapsvg-fullscreen-popovers", true);
11614                $$A(this.containers.popover).appendTo("body");
11615            }
11616        }
11617        setRegionPrefix(prefix) {
11618            this.options.regionPrefix = prefix;
11619        }
11620        setInitialViewBox(v) {
11621            if (typeof v == "string")
11622                v = v
11623                    .trim()
11624                    .split(" ")
11625                    .map(function (v) {
11626                    return parseFloat(v);
11627                });
11628            this._viewBox.update(new ViewBox(v));
11629            if (this.options.googleMaps.on) {
11630                this.options.googleMaps.center = this.googleMaps.map.getCenter().toJSON();
11631                this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
11632            }
11633            this.zoomLevel = 0;
11634            this.setZoomLevels();
11635        }
11636        setViewBoxOnStart() {
11637            this.viewBoxFull = this.svgDefault.viewBox;
11638            this.viewBoxFake = this.viewBox;
11639            this.whRatioFull = this.viewBoxFull.width / this.viewBox.width;
11640            this.containers.svg.setAttribute("viewBox", this.viewBoxFull.toString());
11641            if ((MapSVG.device.ios || MapSVG.device.android) && this.svgDefault.viewBox.width > 1500) {
11642                this.iosDownscaleFactor = this.svgDefault.viewBox.width > 9999 ? 100 : 10;
11643                this.containers.svg.style.width =
11644                    (this.svgDefault.viewBox.width / this.iosDownscaleFactor).toString() + "px";
11645            }
11646            else {
11647                this.containers.svg.style.width = this.svgDefault.viewBox.width + "px";
11648            }
11649            this.vbStart = true;
11650        }
11651        setViewBox(viewBox, adjustGoogleMap = true) {
11652            let initial = false;
11653            if (typeof viewBox === "undefined" || (viewBox.width === 0 && viewBox.height === 0)) {
11654                viewBox = this.svgDefault.viewBox;
11655                initial = true;
11656            }
11657            const isZooming = viewBox.width != this.viewBox.width || viewBox.height != this.viewBox.height;
11658            this.viewBox.update(viewBox);
11659            this.whRatio = this.viewBox.width / this.viewBox.height;
11660            !this.vbStart && this.setViewBoxOnStart();
11661            if (initial) {
11662                if (this._viewBox.width === 0 && this._viewBox.height === 0) {
11663                    this._viewBox.update(this.viewBox);
11664                }
11665                this._scale = 1;
11666            }
11667            this.scale = this.getScale();
11668            this.superScale = (this.whRatioFull * this.svgDefault.viewBox.width) / this.viewBox.width;
11669            const w = this.svgDefault.viewBox.width / this.containers.map.clientWidth;
11670            this.superScale = this.superScale / w;
11671            if ((MapSVG.device.ios || MapSVG.device.android) && this.svgDefault.viewBox.width > 1500) {
11672                this.superScale *= this.iosDownscaleFactor;
11673            }
11674            this.scroll.tx = Math.round((this.svgDefault.viewBox.x - this.viewBox.x) * this.scale);
11675            this.scroll.ty = Math.round((this.svgDefault.viewBox.y - this.viewBox.y) * this.scale);
11676            if (this.googleMaps.map && adjustGoogleMap !== false) {
11677                const googlePrevZoom = this.googleMaps.map.getZoom();
11678                this.googleMaps.map.setCenter(this.getCenterGeoPoint());
11679                this.googleMaps.map.setZoom(this.getZoomForGoogle());
11680            }
11681            else {
11682                this.containers.scrollpane.style.transform =
11683                    "translate(" + this.scroll.tx + "px," + this.scroll.ty + "px)";
11684                this.containers.svg.style.transform = "scale(" + this.superScale + ")";
11685                this.syncZoomLevelWithGoogle();
11686            }
11687            this.movingItemsAdjustScreenPosition();
11688            if (isZooming) {
11689                this.adjustStrokes();
11690                this.toggleSvgLayerOnZoom();
11691                if (this.options.clustering.on) {
11692                    this.throttle(this.clusterizeOnZoom, 400, this);
11693                }
11694                else {
11695                    this.events.trigger("zoom");
11696                }
11697            }
11698            return true;
11699        }
11700        syncZoomLevelWithGoogle() {
11701            if (this.googleMaps.map &&
11702                this.googleMaps.map.getZoom() !== this.getZoomForGoogle() &&
11703                typeof this.zoomDelta !== "undefined") {
11704                this.zoomLevel = this.googleMaps.map.getZoom() - this.zoomDelta;
11705            }
11706        }
11707        getCenterGeoPoint() {
11708            return this.converter.convertSVGToGeo(this.getCenterSvgPoint());
11709        }
11710        getCenterSvgPoint() {
11711            return new SVGPoint(this.viewBox.x + this.viewBox.width / 2, this.viewBox.y + this.viewBox.height / 2);
11712        }
11713        getZoomForGoogle() {
11714            if (typeof this.zoomLevel === "string") {
11715                this.zoomLevel = parseInt(this.zoomLevel);
11716            }
11717            return this.zoomLevel + this.zoomDelta;
11718        }
11719        getZoomRange() {
11720            const range = { min: 0, max: 0 };
11721            if (this.options.googleMaps.on) {
11722                range.min = Math.max(0, this.options.zoom.limit[0] + this.zoomDelta) - this.zoomDelta;
11723                range.max = Math.min(22, this.options.zoom.limit[1] + this.zoomDelta) - this.zoomDelta;
11724            }
11725            else {
11726                range.min = this.options.zoom.limit[0];
11727                range.max = this.options.zoom.limit[1];
11728            }
11729            return range;
11730        }
11731        enableMovingElementsAnimation() {
11732            $$A(this.containers.map).removeClass("no-transitions-markers no-transitions-labels no-transitions-bubbles");
11733        }
11734        disableMovingElementsAnimation() {
11735            $$A(this.containers.map).addClass("no-transitions-markers no-transitions-labels no-transitions-bubbles");
11736        }
11737        clusterizeOnZoom() {
11738            if (this.options.googleMaps.on && this.googleMaps.map && this.zoomDelta) {
11739                this.zoomLevel = this.googleMaps.map.getZoom() - this.zoomDelta;
11740            }
11741            this.events.trigger("zoom");
11742            this.clusterizeMarkers(true);
11743        }
11744        throttle(method, delay, scope, params) {
11745            clearTimeout(method._tId);
11746            method._tId = setTimeout(function () {
11747                method.apply(scope, params);
11748            }, delay);
11749        }
11750        setViewBoxByGoogleMapBounds() {
11751            const googleMapBounds = this.googleMaps.map.getBounds();
11752            if (!googleMapBounds)
11753                return;
11754            const googleMapBoundsJSON = googleMapBounds.toJSON();
11755            if (googleMapBoundsJSON.west == -180 && googleMapBoundsJSON.east == 180) {
11756                const center = this.googleMaps.map.getCenter().toJSON();
11757            }
11758            const ne = new GeoPoint(googleMapBounds.getNorthEast().lat(), googleMapBounds.getNorthEast().lng());
11759            const sw = new GeoPoint(googleMapBounds.getSouthWest().lat(), googleMapBounds.getSouthWest().lng());
11760            const xyNE = this.converter.convertGeoToSVG(ne);
11761            const xySW = this.converter.convertGeoToSVG(sw);
11762            if (xyNE.x < xySW.y) {
11763                const mapPointsWidth = (this.svgDefault.viewBox.width / this.converter.mapLonDelta) * 360;
11764                xySW.x = -(mapPointsWidth - xySW.y);
11765            }
11766            const width = xyNE.x - xySW.x;
11767            const height = xySW.y - xyNE.y;
11768            const viewBox = new ViewBox(xySW.x, xyNE.y, width, height);
11769            this.setViewBox(viewBox);
11770        }
11771        redraw() {
11772            this.disableAnimation();
11773            if (MapSVG.browser.ie) {
11774                $$A(this.containers.svg).css({ height: this.svgDefault.viewBox.height });
11775            }
11776            if (this.options.googleMaps.on && this.googleMaps.map) {
11777                google.maps.event.trigger(this.googleMaps.map, "resize");
11778            }
11779            else {
11780                this.setViewBox(this.viewBox);
11781            }
11782            $$A(this.containers.popover) &&
11783                $$A(this.containers.popover).css({
11784                    "max-height": (this.options.popovers.maxHeight * $$A(this.containers.wrap).outerHeight()) /
11785                        100 +
11786                        "px",
11787                });
11788            if (this.controllers && this.controllers.directory) {
11789                this.controllers.directory.updateTopShift();
11790                this.controllers.directory.updateScroll();
11791            }
11792            this.movingItemsAdjustScreenPosition();
11793            this.adjustStrokes();
11794            this.enableAnimation();
11795        }
11796        setSize(width, height, responsive) {
11797            this.options.width = width;
11798            this.options.height = height;
11799            this.options.responsive =
11800                responsive != null && responsive != undefined
11801                    ? MapSVG.parseBoolean(responsive)
11802                    : this.options.responsive;
11803            if (!this.options.width && !this.options.height) {
11804                this.options.width = this.svgDefault.width;
11805                this.options.height = this.svgDefault.height;
11806            }
11807            else if (!this.options.width && this.options.height) {
11808                this.options.width =
11809                    (this.options.height * this.svgDefault.width) / this.svgDefault.height;
11810            }
11811            else if (this.options.width && !this.options.height) {
11812                this.options.height =
11813                    (this.options.width * this.svgDefault.height) / this.svgDefault.width;
11814            }
11815            this.whRatio = this.options.width / this.options.height;
11816            this.scale = this.getScale();
11817            this.setResponsive(responsive);
11818            if (this.options.choropleth.on && this.options.choropleth.bubbleMode) {
11819                this.redrawBubbles();
11820            }
11821            this.movingItemsAdjustScreenPosition();
11822        }
11823        setResponsive(on) {
11824            on = on != undefined ? MapSVG.parseBoolean(on) : this.options.responsive;
11825            $$A(this.containers.map).css({
11826                width: "100%",
11827                height: "0",
11828                "padding-bottom": (this.viewBox.height * 100) / this.viewBox.width + "%",
11829            });
11830            if (on) {
11831                $$A(this.containers.wrap).css({
11832                    width: "100%",
11833                    height: "auto",
11834                });
11835            }
11836            else {
11837                $$A(this.containers.wrap).css({
11838                    width: this.options.width + "px",
11839                    height: this.options.height + "px",
11840                });
11841            }
11842            $$A.extend(true, this.options, { responsive: on });
11843            if (!this.resizeSensor) {
11844                this.resizeSensor = new ResizeSensor(this.containers.map, () => {
11845                    this.redraw();
11846                });
11847            }
11848            this.redraw();
11849        }
11850        setScroll(options, skipEvents) {
11851            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11852            options.limit != undefined && (options.limit = MapSVG.parseBoolean(options.limit));
11853            $$A.extend(true, this.options, { scroll: options });
11854            !skipEvents && this.setEventHandlers();
11855        }
11856        setZoom(options) {
11857            options = options || {};
11858            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11859            options.fingers != undefined && (options.fingers = MapSVG.parseBoolean(options.fingers));
11860            options.mousewheel != undefined &&
11861                (options.mousewheel = MapSVG.parseBoolean(options.mousewheel));
11862            options.delta = 2;
11863            if (options.limit) {
11864                if (typeof options.limit == "string")
11865                    options.limit = options.limit.split(";");
11866                options.limit = [parseInt(options.limit[0]), parseInt(options.limit[1])];
11867            }
11868            if (!this.zoomLevels) {
11869                this.setZoomLevels();
11870            }
11871            $$A.extend(true, this.options, { zoom: options });
11872            $$A(this.containers.scrollpaneWrap).off("wheel.mapsvg");
11873            if (this.options.zoom.mousewheel) {
11874                if (MapSVG.browser.firefox) {
11875                    this.firefoxScroll = { insideIframe: false, scrollX: 0, scrollY: 0 };
11876                    $$A(this.containers.scrollpaneWrap)
11877                        .on("mouseenter", () => {
11878                        this.firefoxScroll.insideIframe = true;
11879                        this.firefoxScroll.scrollX = window.scrollX;
11880                        this.firefoxScroll.scrollY = window.scrollY;
11881                    })
11882                        .on("mouseleave", () => {
11883                        this.firefoxScroll.insideIframe = false;
11884                    });
11885                    $$A(document).scroll(() => {
11886                        if (this.firefoxScroll.insideIframe)
11887                            window.scrollTo(this.firefoxScroll.scrollX, this.firefoxScroll.scrollY);
11888                    });
11889                }
11890                $$A(this.containers.scrollpaneWrap).on("wheel.mapsvg", (event) => {
11891                    event.preventDefault();
11892                    this.mouseWheelZoom(event);
11893                    return false;
11894                });
11895                $$A(this.layers.markers).on("wheel.mapsvg", (event) => {
11896                    event.preventDefault();
11897                    this.mouseWheelZoom(event);
11898                    return false;
11899                });
11900            }
11901            this.canZoom = true;
11902        }
11903        mouseWheelZoom(event) {
11904            event.preventDefault();
11905            const d = Math.sign(-event.originalEvent.deltaY);
11906            const center = this.getSvgPointAtClick(event.originalEvent);
11907            d > 0 ? this.zoomIn(center) : this.zoomOut(center);
11908        }
11909        setControls(options) {
11910            options = options || {};
11911            $$A.extend(true, this.options, { controls: options });
11912            this.options.controls.zoom = MapSVG.parseBoolean(this.options.controls.zoom);
11913            this.options.controls.zoomReset = MapSVG.parseBoolean(this.options.controls.zoomReset);
11914            this.options.controls.userLocation = MapSVG.parseBoolean(this.options.controls.userLocation);
11915            this.options.controls.previousMap = MapSVG.parseBoolean(this.options.controls.previousMap);
11916            const loc = this.options.controls.location || "right";
11917            if (!this.containers.controls) {
11918                const buttons = $$A("<div />").addClass("mapsvg-buttons");
11919                const zoomGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11920                const zoomIn = $$A("<div />").addClass("mapsvg-btn-map mapsvg-in");
11921                zoomIn.on("touchend click", (e) => {
11922                    if (e.cancelable) {
11923                        e.preventDefault();
11924                    }
11925                    e.stopPropagation();
11926                    this.zoomIn();
11927                });
11928                const zoomOut = $$A("<div />").addClass("mapsvg-btn-map mapsvg-out");
11929                zoomOut.on("touchend click", (e) => {
11930                    if (e.cancelable) {
11931                        e.preventDefault();
11932                    }
11933                    e.stopPropagation();
11934                    this.zoomOut();
11935                });
11936                zoomGroup.append(zoomIn).append(zoomOut);
11937                const location = $$A("<div />").addClass("mapsvg-btn-map mapsvg-btn-location");
11938                location.on("touchend click", (e) => {
11939                    if (e.cancelable) {
11940                        e.preventDefault();
11941                    }
11942                    e.stopPropagation();
11943                    this.showUserLocation((location) => {
11944                        if (this.options.scroll.on) {
11945                            this.centerOn(location.marker);
11946                        }
11947                    });
11948                });
11949                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>';
11950                location.html(userLocationIcon);
11951                const locationGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11952                locationGroup.append(location);
11953                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>';
11954                const zoomResetButton = $$A("<div />")
11955                    .html(zoomResetIcon)
11956                    .addClass("mapsvg-btn-map mapsvg-btn-zoom-reset");
11957                zoomResetButton.on("touchend click", (e) => {
11958                    if (e.cancelable) {
11959                        e.preventDefault();
11960                    }
11961                    e.stopPropagation();
11962                    this.viewBoxReset(true);
11963                });
11964                const zoomResetGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11965                zoomResetGroup.append(zoomResetButton);
11966                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="">' +
11967                    '<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)">' +
11968                    '<g id="g4">
11968<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" ' +
11969                    'id="path8" inkscape:connector-curvature="0" /></g></g></svg>';
11970                const previousMapButton = $$A("<div />")
11971                    .html(previousMapIcon)
11972                    .addClass("mapsvg-btn-map mapsvg-btn-previous-map");
11973                previousMapButton.on("touchend click", (e) => {
11974                    if (e.cancelable) {
11975                        e.preventDefault();
11976                    }
11977                    e.stopPropagation();
11978                    this.loadPreviousMap();
11979                });
11980                const previousMapGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11981                previousMapGroup.append(previousMapButton);
11982                this.containers.controls = buttons[0];
11983                this.controls = {
11984                    zoom: zoomGroup[0],
11985                    userLocation: locationGroup[0],
11986                    zoomReset: zoomResetGroup[0],
11987                    previousMap: previousMapGroup[0],
11988                };
11989                $$A(this.containers.map).append($$A(this.containers.controls));
11990            }
11991            $$A(this.controls.zoom).toggle(this.options.controls.zoom);
11992            $$A(this.controls.userLocation).toggle(this.options.controls.userLocation);
11993            $$A(this.controls.zoomReset).toggle(this.options.controls.zoomReset);
11994            $$A(this.controls.previousMap).toggle(this.options.controls.previousMap && this.options.previousMapsIds.length > 0);
11995            $$A(this.containers.controls).removeClass("left");
11996            $$A(this.containers.controls).removeClass("right");
11997            (loc == "right" && $$A(this.containers.controls).addClass("right")) ||
11998                (loc == "left" && $$A(this.containers.controls).addClass("left"));
11999        }
12000        setZoomLevels() {
12001            if (!this.zoomLevels) {
12002                this.zoomLevels = new ArrayIndexed("zoomLevel");
12003            }
12004            else {
12005                this.zoomLevels.clear();
12006            }
12007            for (let i = -20; i < 0; i++) {
12008                const _scale = 1 / Math.pow(this.options.zoom.delta, Math.abs(i));
12009                this.zoomLevels.push({
12010                    zoomLevel: i,
12011                    _scale: _scale,
12012                    viewBox: new ViewBox(0, 0, this._viewBox.width / _scale, this._viewBox.height / _scale),
12013                });
12014            }
12015            for (let z = 0; z <= 20; z++) {
12016                const _scale = Math.pow(this.options.zoom.delta, Math.abs(z));
12017                this.zoomLevels.push({
12018                    zoomLevel: z,
12019                    _scale: _scale,
12020                    viewBox: new ViewBox(0, 0, this._viewBox.width / _scale, this._viewBox.height / _scale),
12021                });
12022            }
12023        }
12024        setCursor(type) {
12025            type = type == "pointer" ? "pointer" : "default";
12026            this.options.cursor = type;
12027            if (type == "pointer")
12028                $$A(this.containers.map).addClass("mapsvg-cursor-pointer");
12029            else
12030                $$A(this.containers.map).removeClass("mapsvg-cursor-pointer");
12031        }
12032        setMultiSelect(on, deselect) {
12033            this.options.multiSelect = MapSVG.parseBoolean(on);
12034            if (deselect !== false)
12035                this.deselectAllRegions();
12036        }
12037        _new_setChoropleth(options) {
12038            options = options || this.options.choropleth;
12039            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12040            if (typeof options.coloring === "undefined" ||
12041                typeof options.coloring.palette === "undefined" ||
12042                typeof options.coloring.palette.colors === "undefined") {
12043                if (typeof options.sourceFieldSelect === "undefined" ||
12044                    typeof options.sourceFieldSelect.variants === "undefined") {
12045                    $$A.extend(true, this.options.choropleth, options);
12046                }
12047                else {
12048                    this.options.choropleth.sourceFieldSelect.variants =
12049                        options.sourceFieldSelect.variants;
12050                }
12051            }
12052            else {
12053                const paletteColorsIndexes = Object.keys(options.coloring.palette.colors);
12054                if (paletteColorsIndexes.length > 1 ||
12055                    (paletteColorsIndexes[0] == "0" &&
12056                        Object.keys(options.coloring.palette.colors[0]).length > 1)) {
12057                    this.options.choropleth.coloring.palette.colors = options.coloring.palette.colors;
12058                }
12059                else {
12060                    const paletteColorIndex = Object.keys(options.coloring.palette.colors)[0];
12061                    $$A.extend(true, this.options.choropleth.coloring.palette.colors[paletteColorIndex], options.coloring.palette.colors[paletteColorIndex]);
12062                }
12063            }
12064            this.updateChoroplethMinMax();
12065            if (this.options.choropleth.on &&
12066                this.options.choropleth.sourceFieldSelect.on &&
12067                this.options.choropleth.sourceFieldSelect.variants) {
12068                if (!this.containers.choroplethSourceSelect) {
12069                    const sourceSelectOptions = [];
12070                    this.options.choropleth.sourceFieldSelect.variants.forEac
12070h((variant) => {
12071                        sourceSelectOptions.push($$A('<option value="' +
12072                            variant +
12073                            '" ' +
12074                            (variant === this.options.choropleth.sourceField
12075                                ? "selected"
12076                                : "") +
12077                            ">" +
12078                            variant +
12079                            "</option>"));
12080                    });
12081                    this.containers.choroplethSourceSelect = {
12082                        container: $$A('<div class="mapsvg-choropleth-source-field"></div>')[0],
12083                        select: $$A('<select id="mapsvg-choropleth-source-field-select" class="mapsvg-select2"></select>')[0],
12084                        options: sourceSelectOptions,
12085                    };
12086                    $$A(this.containers.choroplethSourceSelect.select).append(this.containers.choroplethSourceSelect.options);
12087                    $$A(this.containers.choroplethSourceSelect.container).append($$A(this.containers.choroplethSourceSelect.select));
12088                    $$A(this.containers.map).append($$A(this.containers.choroplethSourceSelect.container));
12089                    $$A(this.containers.choroplethSourceSelect.select).mselect2();
12090                    $$A(this.containers.choroplethSourceSelect.select)
12091                        .mselect2()
12092                        .on("select2:select select2:unselecting", (e) => {
12093                        if (e.cancelable) {
12094                            e.preventDefault();
12095                        }
12096                        e.stopPropagation();
12097                        this.setChoropleth({ sourceField: $$A(e.target).mselect2().val() });
12098                    });
12099                }
12100                else {
12101                    $$A(this.containers.choroplethSourceSelect.select).mselect2("destroy");
12102                    $$A(this.containers.choroplethSourceSelect.select).find("option").remove();
12103                    this.containers.choroplethSourceSelect.options = [];
12104                    this.options.choropleth.sourceFieldSelect.variants.forEac
12104h((variant) => {
12105                        this.containers.choroplethSourceSelect.options.push($$A('<option value="' +
12106                            variant +
12107                            '" ' +
12108                            (variant === this.options.choropleth.sourceField
12109                                ? "selected"
12110                                : "") +
12111                            ">" +
12112                            variant +
12113                            "</option>")[0]);
12114                    });
12115                    $$A(this.containers.choroplethSourceSelect.select).append(this.containers.choroplethSourceSelect.options);
12116                    $$A(this.containers.choroplethSourceSelect.select).mselect2({ width: "100%" });
12117                }
12118            }
12119            if ((!this.options.choropleth.on || !this.options.choropleth.sourceFieldSelect.on) &&
12120                this.containers.choroplethSourceSelect &&
12121                $$A(this.containers.choroplethSourceSelect.container).is(":visible")) {
12122                $$A(this.containers.choroplethSourceSelect.container).hide();
12123            }
12124            else if (this.options.choropleth.on &&
12125                this.options.choropleth.sourceFieldSelect.on &&
12126                this.containers.choroplethSourceSelect &&
12127                !$$A(this.containers.choroplethSourceSelect.container).is(":visible")) {
12128                $$A(this.containers.choroplethSourceSelect.container).show();
12129            }
12130            $$A(this.containers.map).find(".mapsvg-choropleth-legend").remove();
12131            if (this.options.choropleth.on && this.options.choropleth.coloring.legend.on) {
12132                const legend = this.options.choropleth.coloring.legend;
12133                let coloring = "";
12134                if (this.options.choropleth.coloring.mode === "gradient") {
12135                    coloring +=
12136                        '<div class="mapsvg-choropleth-legend-gradient-no-data">' +
12137                            this.options.choropleth.coloring.noData.description +
12138                            "</div>";
12139                    let legendGradient = "";
12140                    for (let chunkIdx = 1; chunkIdx < 5; chunkIdx++) {
12141                        legendGradient +=
12142                            '<div class="mapsvg-choropleth-legend-gradient-chunk">' +
12143                                ((this.options.choropleth.coloring.gradient.values.maxAdjusted * chunkIdx) /
12144                                    5 +
12145                                    this.options.choropleth.coloring.gradient.values.min) +
12146                                "</div>";
12147                    }
12148                    coloring +=
12149                        '<div class="mapsvg-choropleth-legend-gradient-colors">' +
12150                            legendGradient +
12151                            "</div>";
12152                }
12153                else {
12154                    coloring +=
12155                        '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="no-data">' +
12156                            '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
12157                            '<div class="mapsvg-choropleth-legend-palette-color-description">' +
12158                            this.options.choropleth.coloring.noData.description +
12159                            "</div>" +
12160                            "</div>";
12161                    coloring +=
12162                        '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="out-of-range">' +
12163                            '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
12164                            '<div class="mapsvg-choropleth-legend-palette-color-description">' +
12165                            this.options.choropleth.coloring.palette.outOfRange.description +
12166                            "</div>" +
12167                            "</div>";
12168                    const paletteColors = this.options.choropleth.coloring.palette.colors;
12169                    paletteColors.forEach((paletteColor, idx) => {
12170                        let paletteColorElementText = "";
12171                        if (paletteColor.description) {
12172                            paletteColorElementText = paletteColor.description;
12173                        }
12174                        else {
12175                            if (idx === 0 && !paletteColor.valueFrom && paletteColor.valueFrom !== 0) {
12176                                if (legend.layout === "vertical") {
12177                                    paletteColorElementText = "Less then " + paletteColor.valueTo;
12178                                }
12179                                else {
12180                                    paletteColorElementText = "< " + paletteColor.valueTo;
12181                                }
12182                            }
12183                            else if (idx === paletteColors.length - 1 && !paletteColor.valueTo) {
12184                                if (legend.layout === "vertical") {
12185                                    paletteColorElementText = paletteColor.valueFrom + " or more";
12186                                }
12187                                else {
12188                                    paletteColorElementText = paletteColor.valueFrom + " <";
12189                                }
12190                            }
12191                            else {
12192                                paletteColorElementText =
12193                                    paletteColor.valueFrom + " &#8804; " + paletteColor.valueTo;
12194                            }
12195                        }
12196                        coloring +=
12197                            '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="' +
12198                                idx +
12199                                '">' +
12200                                '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
12201                                '<div class="mapsvg-choropleth-legend-palette-color-description">' +
12202                                paletteColorElementText +
12203                                "</div>" +
12204                                "</div>";
12205                    });
12206                }
12207                this.containers.legend = {
12208                    title: $$A('<div class="mapsvg-choropleth-legend-title">' + legend.title + "</div>")[0],
12209                    text: $$A('<div class="mapsvg-choropleth-legend-text">' + legend.text + "</div>")[0],
12210                    coloring: $$A('<div class="mapsvg-choropleth-legend-' +
12211                        this.options.choropleth.coloring.mode +
12212                        '">' +
12213                        coloring +
12214                        "</div>")[0],
12215                    description: $$A('<div class="mapsvg-choropleth-legend-description">' +
12216                        legend.description +
12217                        "</div>")[0],
12218                    container: $$A("<div />").addClass("mapsvg-choropleth-legend mapsvg-choropleth-legend-" +
12219                        legend.layout +
12220                        " mapsvg-choropleth-legend-container-" +
12221                        legend.container)[0],
12222                };
12223                $$A(this.containers.legend.container)
12224                    .append(this.containers.legend.title)
12225                    .append(this.containers.legend.text)
12226                    .append(this.containers.legend.coloring)
12227                    .append(this.containers.legend.description);
12228                $$A(this.containers.map).append(this.containers.legend.container);
12229                this.setChoroplethLegendCSS();
12230                this.regionsRepository.events.on("updated", () => {
12231                    this.redrawChoropleth();
12232                });
12233                this.objectsRepository.events.on("updated", () => {
12234                    this.redrawChoropleth();
12235                });
12236            }
12237            if (this.options.choropleth.on && this.options.choropleth.coloring.mode === "gradient") {
12238                const colors = this.options.choropleth.coloring.gradient.colors;
12239                if (colors) {
12240                    colors.lowRGB = tinycolor(colors.low).toRgb();
12241                    colors.highRGB = tinycolor(colors.high).toRgb();
12242                    colors.diffRGB = {
12243                        r: colors.highRGB.r - colors.lowRGB.r,
12244                        g: colors.highRGB.g - colors.lowRGB.g,
12245                        b: colors.highRGB.b - colors.lowRGB.b,
12246                        a: colors.highRGB.a - colors.lowRGB.a,
12247                    };
12248                    this.containers.legend && this.setChoroplethLegendCSS();
12249                }
12250            }
12251            this.redrawChoropleth();
12252        }
12253        redrawChoropleth() {
12254            this.updateChoroplethMinMax();
12255            this.redrawBubbles();
12256            this.regionsRedrawColors();
12257        }
12258        updateChoroplethMinMax() {
12259            if (this.options.choropleth.on) {
12260                const gradient = this.options.choropleth.coloring.gradient, values = [];
12261                gradient.values.min = 0;
12262                gradient.values.max = null;
12263                if (this.options.choropleth.source === "regions") {
12264                    this.regions.forEach((region) => {
12265                        const choropleth = region.data && region.data[this.options.choropleth.sourceField];
12266                        choropleth != undefined && choropleth !== "" && values.push(choropleth);
12267                    });
12268                }
12269                else {
12270                    this.objectsRepository.objects.forEach((object) => {
12271                        const choropleth = object[this.options.choropleth.sourceField];
12272                        choropleth != undefined && choropleth !== "" && values.push(choropleth);
12273                    });
12274                }
12275                if (values.length > 0) {
12276                    gradient.values.min = Math.min.apply(null, values);
12277                    gradient.values.max = Math.max.apply(null, values);
12278                    gradient.values.maxAdjusted = gradient.values.max - gradient.values.min;
12279                }
12280            }
12281        }
12282        setChoroplethLegendCSS() {
12283            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;
12284            $$A(".mapsvg-choropleth-legend").css({
12285                width: legend.width,
12286                height: legend.height,
12287            });
12288            if (this.options.choropleth.coloring.mode === "gradient") {
12289                if (legend.layout === "horizontal") {
12290                    $$A(".mapsvg-choropleth-legend-horizontal .mapsvg-choropleth-legend-gradient-colors").css({
12291                        background: "linear-gradient(to right," +
12292                            gradient.colors.low +
12293                            " 1%," +
12294                            gradient.colors.high +
12295                            " 100%)",
12296                    });
12297                }
12298                else {
12299                    $$A(".mapsvg-choropleth-legend-vertical .mapsvg-choropleth-legend-gradient-colors").css({
12300                        background: "linear-gradient(to bottom," +
12301                            gradient.colors.low +
12302                            " 1%," +
12303                            gradient.colors.high +
12304                            " 100%)",
12305                    });
12306                }
12307                $$A(".mapsvg-choropleth-legend-gradient-no-data").css({
12308                    "background-color": noData.color,
12309                });
12310            }
12311            else {
12312                const paletteColors = this.options.choropleth.coloring.palette.colors;
12313                paletteColors.forEach(function (paletteColor, idx) {
12314                    $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="' +
12315                        idx +
12316                        '"] .mapsvg-choropleth-legend-palette-color').css({
12317                        "background-color": paletteColor.color,
12318                    });
12319                });
12320                $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="no-data"] .mapsvg-choropleth-legend-palette-color').css({
12321                    "background-color": noData.color,
12322                });
12323                $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="out-of-range"] .mapsvg-choropleth-legend-palette-color').css({
12324                    "background-color": outOfRange.color,
12325                });
12326            }
12327        }
12328        setCss(css) {
12329            this.options.css =
12330                css || (this.options.css ? this.options.css.replace(/%id%/g, "" + this.id) : "");
12331            this.liveCss = this.liveCss || $$A("<style></style>").appendTo("head")[0];
12332            $$A(this.liveCss).html(this.options.css);
12333        }
12334        setFilters(options) {
12335            options = options || this.options.filters;
12336            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12337            options.hide != undefined && (options.hide = MapSVG.parseBoolean(options.hide));
12338            $$A.extend(true, this.options, { filters: options });
12339            if (!MapSVG.googleMapsApiLoaded &&
12340                this.options.filters.on &&
12341                this.filtersSchema.getField("distance")) {
12342                this.loadGoogleMapsAPI(() => {
12343                    return 1;
12344                }, () => {
12345                    return 1;
12346                });
12347            }
12348            if (["leftSidebar", "rightSidebar", "header", "footer", "custom", "map"].indexOf(this.options.filters.location) === -1) {
12349                this.options.filters.location = "leftSidebar";
12350            }
12351            if (this.options.filters.on) {
12352                if (this.formBuilder) {
12353                    this.formBuilder.destroy();
12354                }
12355                if (!this.containers.filters) {
12356                    this.containers.filters = $$A('<div class="mapsvg-filters-wrap"></div>')[0];
12357                }
12358                else {
12359                    $$A(this.containers.filters).empty();
12360                    $$A(this.containers.filters).show();
12361                }
12362                $$A(this.containers.filters).css({
12363                    "background-color": this.options.colors.directorySearch,
12364                });
12365                if ($$A(this.containers.filtersModal)) {
12366                    $$A(this.containers.filtersModal).css({ width: this.options.filters.width });
12367                }
12368                if (this.options.filters.location === "custom") {
12369                    $$A(this.containers.filters)
12370                        .removeClass("mapsvg-filter-container-custom")
12371                        .addClass("mapsvg-filter-container-custom");
12372                    if ($$A("#" + this.options.filters.containerId).length) {
12373                        $$A("#" + this.options.filters.containerId).append(this.containers.filters);
12374                    }
12375                    else {
12376                        $$A(this.containers.filters).hide();
12377                        console.error("MapSVG: filter container #" +
12378                            this.options.filters.containerId +
12379                            " does not exists");
12380                    }
12381                }
12382                else {
12383                    if (MapSVG.isPhone) {
12384                        $$A(this.containers.header).append($$A(this.containers.filters));
12385                        this.setContainers({ header: { on: true } });
12386                    }
12387                    else {
12388                        const location = MapSVG.isPhone ? "header" : this.options.filters.location;
12389                        if (this.options.menu.on &&
12390                            this.controllers.directory &&
12391                            this.options.menu.location === this.options.filters.location) {
12392                            $$A(this.controllers.directory.containers.view)
12393                                .find(".mapsvg-directory-filter-wrap")
12394                                .append($$A(this.containers.filters));
12395                            this.controllers.directory.updateTopShift();
12396                        }
12397                        else {
12398                            $$A(this.containers[location]).append($$A(this.containers.filters));
12399                            this.controllers.directory && this.controllers.directory.updateTopShift();
12400                        }
12401                    }
12402                }
12403                this.loadFiltersController(this.containers.filters, false);
12404                this.updateFiltersState();
12405            }
12406            else {
12407                if ($$A(this.containers.filters)) {
12408                    $$A(this.containers.filters).empty();
12409                    $$A(this.containers.filters).hide();
12410                }
12411            }
12412            if (this.options.menu.on &&
12413                this.controllers.directory &&
12414                this.options.menu.location === this.options.filters.location) {
12415                this.controllers.directory.updateTopShift();
12416            }
12417        }
12418        updateFiltersState() {
12419            if (this.options.filters && this.options.filters.on && this.controllers.filters) {
12420                this.controllers.filters.update(this.objectsRepository.query);
12421                this.updateFilterTags();
12422            }
12423        }
12424        setGlobalDistanceFilter() {
12425            if (this.objectsRepository &&
12426                this.objectsRepository.query.filters &&
12427                this.objectsRepository.query.filters.distance) {
12428                const dist = this.objectsRepository.query.filters.distance;
12429                MapSVG.distanceSearch = this.objectsRepository.query.filters.distance;
12430            }
12431            else {
12432                MapSVG.distanceSearch = null;
12433            }
12434        }
12435        updateFilterTags() {
12436            $$A(this.containers.filterTags) && $$A(this.containers.filterTags).empty();
12437            for (const field_name in this.objectsRepository.query.filters) {
12438                let field_value = this.objectsRepository.query.filters[field_name];
12439                let _field_name = field_name;
12440                const filterField = this.filtersSchema.getField(_field_name);
12441                if (field_name == "regions") {
12442                    _field_name = "";
12443                    field_value = field_value.region_ids.map((id) => this.getRegion(id).title);
12444                }
12445                else {
12446                    _field_name = filterField && filterField.label;
12447                }
12448                if (field_name !== "distance") {
12449                    if (!this.containers.filterTags) {
12450                        this.containers.filterTags = $$A('<div class="mapsvg-filter-tags"></div>')[0];
12451                        if ($$A(this.containers.filters)) ;
12452                        else {
12453                            if (this.options.menu.on && this.controllers.directory) {
12454                                $$A(this.controllers.directory.containers.toolbar).append(this.containers.filterTags);
12455                                this.controllers.directory.updateTopShift();
12456                            }
12457                            else {
12458                                $$A(this.containers.map).append(this.containers.filterTags);
12459                                if (this.options.zoom.buttons.on) {
12460                                    if (this.options.layersControl.on) {
12461                                        if (this.options.layersControl.position == "top-left") {
12462                                            $$A(this.containers.filterTags).css({
12463                                                right: 0,
12464                                                bottom: 0,
12465                                            });
12466                                        }
12467                                        else {
12468                                            $$A(this.containers.filterTags).css({
12469                                                bottom: 0,
12470                                            });
12471                                        }
12472                                    }
12473                                    else {
12474                                        if (this.options.zoom.buttons.location == "left") {
12475                                            $$A(this.containers.filterTags).css({
12476                                                right: 0,
12477                                            });
12478                                        }
12479                                    }
12480                                }
12481                            }
12482                        }
12483                        $$A(this.containers.filterTags).on("click", ".mapsvg-filter-delete", (e) => {
12484                            const filterField = $$A(e.target).data("filter");
12485                            $$A(e.target).parent().remove();
12486                            this.objectsRepository.query.removeFilter(filterField);
12487                            this.deselectAllRegions();
12488                            this.loadDataObjects();
12489                        });
12490                    }
12491                    $$A(this.containers.filterTags).append('<div class="mapsvg-filter-tag">' +
12492                        (_field_name ? _field_name + ": " : "") +
12493                        field_value +
12494                        ' <span class="mapsvg-filter-delete" data-filter="' +
12495                        field_name +
12496                        '">
12496×</span></div>');
12497                }
12498            }
12499        }
12500        setContainers(options) {
12501            const _this = this;
12502            if (!this.containersCreated) {
12503                this.containers.wrapAll = document.createElement("div");
12504                this.containers.wrapAll.classList.add("mapsvg-wrap-all");
12505                this.containers.wrapAll.id = "mapsvg-map-" + this.id;
12506                this.containers.wrapAll.setAttribute("data-map-id", this.id ? this.id.toString() : "");
12507                this.containers.wrap = document.createElement("div");
12508                this.containers.wrap.classList.add("mapsvg-wrap");
12509                this.containers.mapContainer = document.createElement("div");
12510                this.containers.mapContainer.classList.add("mapsvg-map-container");
12511                this.containers.leftSidebar = document.createElement("div");
12512                this.containers.leftSidebar.className =
12513                    "mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-left";
12514                this.containers.rightSidebar = document.createElement("div");
12515                this.containers.rightSidebar.className =
12516                    "mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-right";
12517                this.containers.header = document.createElement("div");
12518                this.containers.header.className = "mapsvg-header mapsvg-top-container";
12519                this.containers.footer = document.createElement("div");
12520                this.containers.footer.className = "mapsvg-footer mapsvg-top-container";
12521                _this.containers.wrapAll = $$A('<div class="mapsvg-wrap-all"></div>')
12522                    .attr("id", "mapsvg-map-" + this.id)
12523                    .attr("data-map-id", this.id)[0];
12524                _this.containers.wrap = $$A('<div class="mapsvg-wrap"></div>')[0];
12525                _this.containers.mapContainer = $$A('<div class="mapsvg-map-container"></div>')[0];
12526                _this.containers.leftSidebar = $$A('<div class="mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-left"></div>')[0];
12527                _this.containers.rightSidebar = $$A('<div class="mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-right"></div>')[0];
12528                _this.containers.header = $$A('<div class="mapsvg-header mapsvg-top-container"></div>')[0];
12529                _this.containers.footer = $$A('<div class="mapsvg-footer mapsvg-top-container"></div>')[0];
12530                $$A(_this.containers.wrapAll).insertBefore(_this.containers.map);
12531                $$A(_this.containers.wrapAll).append(_this.containers.header);
12532                $$A(_this.containers.wrapAll).append(_this.containers.wrap);
12533                $$A(_this.containers.wrapAll).append(_this.containers.footer);
12534                $$A(_this.containers.mapContainer).append(_this.containers.map);
12535                $$A(_this.containers.wrap).append(_this.containers.leftSidebar);
12536                $$A(_this.containers.wrap).append(_this.containers.mapContainer);
12537                $$A(_this.containers.wrap).append(_this.containers.rightSidebar);
12538                _this.containersCreated = true;
12539            }
12540            options = options || _this.options.containers || {};
12541            for (const contName in options) {
12542                if (options[contName].on !== undefined) {
12543                    options[contName].on = MapSVG.parseBoolean(options[contName].on);
12544                }
12545                if (options[contName].width) {
12546                    if (typeof options[contName].width != "string" ||
12547                        (options[contName].width.indexOf("px") === -1 &&
12548                            options[contName].width.indexOf("%") === -1 &&
12549                            options[contName].width !== "auto")) {
12550                        options[contName].width = options[contName].width + "px";
12551                    }
12552                    $$A(_this.containers[contName]).css({ "flex-basis": options[contName].width });
12553                }
12554                if (options[contName].height) {
12555                    if (typeof options[contName].height != "string" ||
12556                        (options[contName].height.indexOf("px") === -1 &&
12557                            options[contName].height.indexOf("%") === -1 &&
12558                            options[contName].height !== "auto")) {
12559                        options[contName].height = options[contName].height + "px";
12560                    }
12561                    $$A(_this.containers[contName]).css({
12562                        "flex-basis": options[contName].height,
12563                        height: options[contName].height,
12564                    });
12565                }
12566                $$A.extend(true, _this.options, { containers: options });
12567                let on = _this.options.containers[contName].on;
12568                if (MapSVG.isPhone &&
12569                    _this.options.menu.hideOnMobile &&
12570                    _this.options.menu.location === contName &&
12571                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12572                    on = false;
12573                }
12574                else if (MapSVG.isPhone &&
12575                    _this.options.menu.location === "custom" &&
12576                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12577                    on = false;
12578                    $$A(_this.containers.wrapAll).addClass("mapsvg-hide-map-list-buttons");
12579                }
12580                else if (MapSVG.isPhone &&
12581                    !_this.options.menu.hideOnMobile &&
12582                    _this.options.menu.location === contName &&
12583                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12584                    $$A(_this.containers.wrapAll).addClass("mapsvg-hide-map-list-buttons");
12585                    $$A(_this.containers.wrapAll).addClass("mapsvg-directory-visible");
12586                }
12587                $$A(_this.containers[contName]).toggle(on);
12588            }
12589            _this.setDetailsView();
12590        }
12591        shouldBeScrollable(container) {
12592            const _this = this;
12593            switch (container) {
12594                case "map":
12595                case "leftSidebar":
12596                case "rightSidebar":
12597                    return true;
12598                case "custom":
12599                    return false;
12600                case "header":
12601                case "footer":
12602                    if (_this.options.containers[container].height &&
12603                        _this.options.containers[container].height !== "auto" &&
12604                        _this.options.containers[container].height !== "100%") {
12605                        return true;
12606                    }
12607                    else {
12608                        return false;
12609                    }
12610                default:
12611                    return false;
12612            }
12613        }
12614        setDirectory(options) {
12615            return this.setMenu(options);
12616        }
12617        setMenu(options) {
12618            options = options || this.options.menu;
12619            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12620            options.search != undefined && (options.search = MapSVG.parseBoolean(options.search));
12621            options.showMapOnClick != undefined &&
12622                (options.showMapOnClick = MapSVG.parseBoolean(options.showMapOnClick));
12623            options.searchFallback != undefined &&
12624                (options.searchFallback = MapSVG.parseBoolean(options.searchFallback));
12625            options.customContainer != undefined &&
12626                (options.customContainer = MapSVG.parseBoolean(options.customContainer));
12627            $$A.extend(true, this.options, { menu: options });
12628            this.controllers = this.controllers || {};
12629            if (!this.containers.directory) {
12630                this.containers.directory = $$A('<div class="mapsvg-directory"></div>')[0];
12631            }
12632            $$A(this.containers.directory).toggleClass("flex", this.shouldBeScrollable(this.options.menu.location));
12633            if (this.options.menu.on) {
12634                if (!this.controllers.directory) {
12635                    this.controllers.directory = new DirectoryController({
12636                        container: this.containers.directory,
12637                        template: this.options.templates.directory,
12638                        mapsvg: this,
12639                        repository: this.options.menu.source === "regions"
12640                            ? this.regionsRepository
12641                            : this.objectsRepository,
12642                        scrollable: this.shouldBeScrollable(this.options.menu.location),
12643                        events: {
12644                            click: (e, regionOrObject, mapsvg) => {
12645                                this.events.trigger("click.directoryItem", this, [
12646                                    e,
12647                                    regionOrObject,
12648                                    mapsvg,
12649                                ]);
12650                            },
12651                            mouseover: (e, regionOrObject, mapsvg) => {
12652                                this.events.trigger("mouseover.directoryItem", this, [
12653                                    e,
12654                                    regionOrObject,
12655                                    mapsvg,
12656                                ]);
12657                            },
12658                            mouseout: (e, regionOrObject, mapsvg) => {
12659                                this.events.trigger("mouseout.directoryItem", this, [
12660                                    e,
12661                                    regionOrObject,
12662                                    mapsvg,
12663                                ]);
12664                            },
12665                        },
12666                    });
12667                    this.controllers.directory._init();
12668                }
12669                if (options.source) {
12670                    this.controllers.directory.repository =
12671                        this.options.menu.source === "regions"
12672                            ? this.regionsRepository
12673                            : this.objectsRepository;
12674                }
12675                if (options.sortBy || options.sortDirection) {
12676                    this.controllers.directory.repository.query.update({
12677                        sort: [
12678                            {
12679                                field: this.options.menu.sortBy,
12680                                order: this.options.menu.sortDirection,
12681                            },
12682                        ],
12683                    });
12684                }
12685                if (options.filterout) {
12686                    const f = {};
12687                    f[this.options.menu.filterout.field] = this.options.menu.filterout.val;
12688                    this.controllers.directory.repository.query.setFilterOut(f);
12689                }
12690                if (options.location) {
12691                    this.controllers.directory.scrollable = this.shouldBeScrollable(this.options.menu.location);
12692                }
12693                let $container;
12694                if (MapSVG.isPhone && this.options.menu.hideOnMobile) {
12695                    $container = $$A(this.containers.leftSidebar);
12696                }
12697                else {
12698                    $container =
12699                        this.options.menu.location !== "custom"
12700                            ? $$A(this.containers[this.options.menu.location])
12701                            : $$A("#" + this.options.menu.containerId);
12702                }
12703                $container.append(this.containers.directory);
12704                if (this.options.colors.directory) {
12705                    $$A(this.containers.directory).css({
12706                        "background-color": this.options.colors.directory,
12707                    });
12708                }
12709                this.setFilters();
12710                this.setTemplates({ directoryItem: this.options.templates.directoryItem });
12711                if ((this.options.menu.source === "regions" && this.regionsRepository.loaded) ||
12712                    (this.options.menu.source === "database" && this.objectsRepository.loaded)) {
12713                    if (this.editMode &&
12714                        (options.sortBy || options.sortDirection || options.filterout)) {
12715                        this.controllers.directory.repository.reload();
12716                    }
12717                    this.loadDirectory();
12718                }
12719            }
12720            else {
12721                this.controllers.directory && this.controllers.directory.destroy();
12722                this.controllers.directory = null;
12723            }
12724        }
12725        setDatabase(options) {
12726            options = options || this.options.database;
12727            if (options.pagination) {
12728                if (options.pagination.on != undefined) {
12729                    options.pagination.on = MapSVG.parseBoolean(options.pagination.on);
12730                }
12731                if (options.pagination.perpage != undefined) {
12732                    options.pagination.perpage = parseInt(options.pagination.perpage);
12733                }
12734            }
12735            $$A.extend(true, this.options, { database: options });
12736            if (options.pagination) {
12737                if (options.pagination.on !== undefined || options.pagination.perpage) {
12738                    const query = new Query({
12739                        perpage: this.options.database.pagination.on
12740                            ? this.options.database.pagination.perpage
12741                            : 0,
12742                    });
12743                    this.objectsRepository.find(query);
12744                }
12745                else {
12746                    this.setPagination();
12747                }
12748            }
12749        }
12750        updateGoogleMapsMaxZoom(geoPoint) {
12751            this.googleMaps.maxZoomService.getMaxZoomAtLatLng(geoPoint, (result) => {
12752                if (result.status === "OK") {
12753                    this.googleMaps.currentMaxZoom = result.zoom;
12754                }
12755            });
12756        }
12757        setGoogleMaps(options) {
12758            options = options || this.options.googleMaps;
12759            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12760            if (!this.googleMaps) {
12761                this.googleMaps = { loaded: false, initialized: false, map: null, overlay: null };
12762            }
12763            $$A.extend(true, this.options, { googleMaps: options });
12764            if (this.options.googleMaps.on) {
12765                $$A(this.containers.map).toggleClass("mapsvg-with-google-map", true);
12766                if (!MapSVG.googleMapsApiLoaded) {
12767                    this.loadGoogleMapsAPI(() => {
12768                        this.setGoogleMaps();
12769                    }, () => {
12770                        this.setGoogleMaps({ on: false });
12771                    });
12772                }
12773                else {
12774                    if (!this.googleMaps.map) {
12775                        this.containers.googleMaps = $$A('<div class="mapsvg-layer mapsvg-layer-gm" id="mapsvg-google-maps-' +
12776                            this.id +
12777                            '"></div>').prependTo(this.containers.map)[0];
12778                        $$A(this.containers.googleMaps).css({
12779                            position: "absolute",
12780                            top: 0,
12781                            left: 0,
12782                            bottom: 0,
12783                            right: 0,
12784                            "z-index": "0",
12785                        });
12786                        this.googleMaps.map = new google.maps.Map(this.containers.googleMaps, {
12787                            mapTypeId: options.type,
12788                            fullscreenControl: false,
12789                            keyboardShortcuts: false,
12790                            mapTypeControl: false,
12791                            scaleControl: false,
12792                            scrollwheel: false,
12793                            streetViewControl: false,
12794                            zoomControl: false,
12795                            styles: options.styleJSON,
12796                            tilt: 0,
12797                        });
12798                        const southWest = new google.maps.LatLng(this.geoViewBox.sw.lat, this.geoViewBox.sw.lng);
12799                        const northEast = new google.maps.LatLng(this.geoViewBox.ne.lat, this.geoViewBox.ne.lng);
12800                        const bounds = new google.maps.LatLngBounds(southWest, northEast);
12801                        this.googleMaps.overlay = this.createGoogleMapOverlay(bounds, this.googleMaps.map);
12802                        if (!this.options.googleMaps.center || !this.options.googleMaps.zoom) {
12803                            this.googleMaps.map.fitBounds(bounds, 0);
12804                        }
12805                        else {
12806                            this.googleMaps.map.setZoom(this.options.googleMaps.zoom);
12807                            this.googleMaps.map.setCenter(this.options.googleMaps.center);
12808                        }
12809                        this.googleMaps.initialized = true;
12810                        this.googleMaps.maxZoomService = new google.maps.MaxZoomService();
12811                        this.googleMaps.map.addListener("idle", () => {
12812                            this.isZooming = false;
12813                        });
12814                        google.maps.event.addListenerOnce(this.googleMaps.map, "idle", () => {
12815                            setTimeout(() => {
12816                                $$A(this.containers.map).addClass("mapsvg-fade-in");
12817                                setTimeout(() => {
12818                                    $$A(this.containers.map).removeClass("mapsvg-google-map-loading");
12819                                    $$A(this.containers.map).removeClass("mapsvg-fade-in");
12820                                    if (!this.options.googleMaps.center ||
12821                                        !this.options.googleMaps.zoom) {
12822                                        this.options.googleMaps.center = this.googleMaps.map
12823                                            .getCenter()
12824                                            .toJSON();
12825                                        this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
12826                                    }
12827                                    this.zoomDelta = this.options.googleMaps.zoom - this.zoomLevel;
12828                                    this.updateGoogleMapsMaxZoom(this.options.googleMaps.center);
12829                                    this.setInitialViewBox(this.viewBox);
12830                                    this.toggleSvgLayerOnZoom();
12831                                    this.events.trigger("googleMapsLoaded");
12832                                    this.afterLoadBlockers--;
12833                                    this.finalizeMapLoading();
12834                                }, 300);
12835                            }, 1);
12836                        });
12837                        this.events.on("googleMapsBoundsChanged", (bounds) => {
12838                            this.setViewBoxByGoogleMapsOverlay();
12839                        });
12840                    }
12841                    else {
12842                        $$A(this.containers.map).toggleClass("mapsvg-with-google-map", true);
12843                        $$A(this.containers.googleMaps) && $$A(this.containers.googleMaps).show();
12844                        if (options.type) {
12845                            this.googleMaps.map.setMapTypeId(options.type);
12846                        }
12847                        this.setViewBoxByGoogleMapsOverlay();
12848                    }
12849                }
12850            }
12851            else {
12852                $$A(this.containers.map).toggleClass("mapsvg-with-google-map", false);
12853                $$A(this.containers.googleMaps) && $$A(this.containers.googleMaps).hide();
12854                this.googleMaps.initialized = false;
12855            }
12856            if (this.converter) {
12857                this.converter.setWorldShift(this.options.googleMaps.on);
12858            }
12859        }
12860        createGoogleMapOverlay(bounds, map) {
12861            class GoogleMapsOverlay extends google.maps.OverlayView {
12862                constructor(bounds, googleMapInstance, mapsvg) {
12863                    super();
12864                    this.bounds_ = bounds;
12865                    this.map_ = googleMapInstance;
12866                    this.mapsvg = mapsvg;
12867                    this.setMap(googleMapInstance);
12868                    this.prevCoords = {
12869                        sw: { x: 0, y: 0 },
12870                        sw2: { x: 0, y: 0 },
12871                        ne: { x: 0, y: 0 },
12872                        ne2: { x: 0, y: 0 },
12873                    };
12874                }
12875                draw() {
12876                    this.mapsvg.events.trigger("googleMapsBoundsChanged", this.map_, [
12877                        this.getPixelBounds(),
12878                        this.map_,
12879                    ]);
12880                }
12881                onAdd() {
12882                    this.element = document.createElement("div");
12883                    this.element.style.borderStyle = "none";
12884                    this.element.style.borderWidth = "0px";
12885                    this.element.style.position = "absolute";
12886                    const panes = this.getPanes();
12887                    panes.overlayLayer.appendChild(this.element);
12888                }
12889                getPixelBounds() {
12890                    const overlayProjection = this.getProjection();
12891                    if (!overlayProjection)
12892                        return;
12893                    const geoSW = this.bounds_.getSouthWest();
12894                    const geoNE = this.bounds_.getNorthEast();
12895                    const coords = {
12896                        sw: overlayProjection.fromLatLngToDivPixel(geoSW),
12897                        ne: overlayProjection.fromLatLngToDivPixel(geoNE),
12898                        sw2: overlayProjection.fromLatLngToContainerPixel(geoSW),
12899                        ne2: overlayProjection.fromLatLngToContainerPixel(geoNE),
12900                    };
12901                    const ww = overlayProjection.getWorldWidth();
12902                    if (this.prevCoords.sw) {
12903                        if (coords.ne.x < coords.sw.x) {
12904                            if (Math.abs(this.prevCoords.sw.x - coords.sw.x) >
12905                                Math.abs(this.prevCoords.ne.x - coords.ne.x)) {
12906                                coords.sw.x = coords.sw.x - ww;
12907                            }
12908                            else {
12909                                coords.ne.x = coords.ne.x + ww;
12910                            }
12911                            if (Math.abs(this.prevCoords.sw2.x - coords.sw2.x) >
12912                                Math.abs(this.prevCoords.ne2.x - coords.ne2.x)) {
12913                                coords.sw2.x = coords.sw2.x - ww;
12914                            }
12915                            else {
12916                                coords.ne2.x = coords.ne2.x + ww;
12917                            }
12918                        }
12919                    }
12920                    this.prevCoords = coords;
12921                    return { sw: coords.sw2, ne: coords.ne2 };
12922                }
12923            }
12924            return new GoogleMapsOverlay(bounds, map, this);
12925        }
12926        loadGoogleMapsAPI(callback, fail) {
12927            if (window.google !== undefined && google.maps) {
12928                MapSVG.googleMapsApiLoaded = true;
12929            }
12930            if (MapSVG.googleMapsApiLoaded) {
12931                if (typeof callback == "function") {
12932                    callback();
12933                }
12934                return;
12935            }
12936            MapSVG.googleMapsLoadCallbacks = MapSVG.googleMapsLoadCallbacks || [];
12937            if (typeof callback == "function") {
12938                MapSVG.googleMapsLoadCallbacks.push(callback);
12939            }
12940            if (MapSVG.googleMapsApiIsLoading) {
12941                return;
12942            }
12943            MapSVG.googleMapsApiIsLoading = true;
12944            window.gm_authFailure = () => {
12945                if (MapSVG.GoogleMapBadApiKey) {
12946                    MapSVG.GoogleMapBadApiKey();
12947                }
12948                else {
12949                    if (this.editMode) {
12950                        alert("Google maps API key is incorrect.");
12951                    }
12952                    else {
12953                        console.error("MapSVG: Google maps API key is incorrect.");
12954                    }
12955                }
12956            };
12957            this.googleMapsScript = document.createElement("script");
12958            this.googleMapsScript.onload = () => {
12959                MapSVG.googleMapsApiLoaded = true;
12960                MapSVG.googleMapsLoadCallbacks.forEach((_callback) => {
12961                    if (typeof callback == "function")
12962                        _callback();
12963                });
12964            };
12965            const gmLibraries = [];
12966            if (this.options.googleMaps.drawingTools) {
12967                gmLibraries.push("drawing");
12968            }
12969            if (this.options.googleMaps.geometry) {
12970                gmLibraries.push("geometry");
12971            }
12972            let libraries = "";
12973            if (gmLibraries.length > 0) {
12974                libraries = "&libraries=" + gmLibraries.join(",");
12975            }
12976            this.googleMapsScript.src =
12977                "https://maps.googleapis.com/maps/api/js?language=" +
12978                    this.options.googleMaps.language +
12979                    "&key=" +
12980                    this.options.googleMaps.apiKey +
12981                    libraries;
12982            document.head.appendChild(this.googleMapsScript);
12983        }
12984        loadDetailsView(obj) {
12985            this.controllers.popover && this.controllers.popover.close();
12986            if (this.controllers.detailsView)
12987                this.controllers.detailsView.destroy();
12988            this.controllers.detailsView = new DetailsController({
12989                autoresize: MapSVG.isPhone &&
12990                    this.options.detailsView.mobileFullscreen &&
12991                    this.options.detailsView.location !== "custom"
12992                    ? false
12993                    : this.options.detailsView.autoresize,
12994                container: this.containers.detailsView,
12995                template: obj instanceof Region
12996                    ? this.options.templates.detailsViewRegion
12997                    : this.options.templates.detailsView,
12998                mapsvg: this,
12999                data: obj.getData(),
13000                modal: MapSVG.isPhone &&
13001                    this.options.detailsView.mobileFullscreen &&
13002                    this.options.detailsView.location !== "custom",
13003                scrollable: (MapSVG.isPhone &&
13004                    this.options.detailsView.mobileFullscreen &&
13005                    this.options.detailsView.location !== "custom") ||
13006                    this.shouldBeScrollable(this.options.detailsView.location),
13007                withToolbar: !(MapSVG.isPhone &&
13008                    this.options.detailsView.mobileFullscreen &&
13009                    this.options.detailsView.location !== "custom") && this.shouldBeScrollable(this.options.detailsView.location),
13010                events: {
13011                    shown: (detailsController) => {
13012                        this.events.trigger("shown.detailsView", this, [this, detailsController]);
13013                        $$A(window).trigger("shown.detailsView", [this, detailsController]);
13014                    },
13015                    closed: (detailsController) => {
13016                        this.deselectAllRegions();
13017                        this.deselectAllMarkers();
13018                        this.controllers &&
13019                            this.controllers.directory &&
13020                            this.controllers.directory.deselectItems();
13021                        this.events.trigger("closed.detailsView", [this, detailsController]);
13022                    },
13023                },
13024            });
13025            this.controllers.detailsView._init();
13026        }
13027        loadFiltersModal() {
13028            if (this.options.filters.modalLocation != "custom") {
13029                if (!this.containers.filtersModal) {
13030                    this.containers.filtersModal = $$A('<div class="mapsvg-details-container mapsvg-filters-wrap"></div>')[0];
13031                }
13032                this.setColors();
13033                $$A(this.containers.filtersModal).css({ width: this.options.filters.width });
13034                if (MapSVG.isPhone) {
13035                    $$A("body").append($$A(this.containers.filtersModal));
13036                    $$A(this.containers.filtersModal).css({ width: "" });
13037                }
13038                else {
13039                    $$A(this.containers[this.options.filters.modalLocation]).append($$A(this.containers.filtersModal));
13040                }
13041            }
13042            else {
13043                this.containers.filtersModal = $$A("#" + this.options.filters.containerId)[0];
13044                $$A(this.containers.filtersModal).css({ width: "" });
13045            }
13046            this.loadFiltersController(this.containers.filtersModal, true);
13047        }
13048        loadFiltersController(container, modal = false) {
13049            if (!this.filtersShouldBeShown()) {
13050                return;
13051            }
13052            let filtersInDirectory, filtersHide;
13053            if (MapSVG.isPhone) {
13054                filtersInDirectory = true;
13055                filtersHide = this.options.filters.hideOnMobile;
13056            }
13057            else {
13058                filtersInDirectory =
13059                    this.options.menu.on &&
13060                        this.controllers.directory &&
13061                        this.options.menu.location === this.options.filters.location;
13062                filtersHide = this.options.filters.hide;
13063            }
13064            const scrollable = modal ||
13065                (!filtersInDirectory &&
13066                    ["leftSidebar", "rightSidebar"].indexOf(this.options.filters.location) !== -1);
13067            this.filtersRepository =
13068                this.options.filters.source === "regions"
13069                    ? this.regionsRepository
13070                    : this.objectsRepository;
13071            if (this.options.filters.searchButton) {
13072                this.changedFields = null;
13073                this.changedSearch = null;
13074            }
13075            else {
13076                this.changedSearch = () => {
13077                    this.filtersRepository.query.searchFallback = this.filtersSchema.getFieldByType("search").searchFallback;
13078                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
13079                };
13080                this.changedFields = () => {
13081                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
13082                };
13083            }
13084            this.controllers.filters = new FiltersController({
13085                container: container,
13086                query: this.filtersRepository.query,
13087                mapsvg: this,
13088                schema: this.filtersSchema,
13089                template: '<div class="mapsvg-filters-container"></div>',
13090                scrollable: scrollable,
13091                modal: modal,
13092                withToolbar: MapSVG.isPhone ? false : modal,
13093                width: $$A(container).hasClass("mapsvg-map-container")
13094                    ? this.options.filters.width
13095                    : "100%",
13096                hide: this.options.filters.hide,
13097                hideOnMobile: this.options.filters.hideOnMobile,
13098                showButtonText: this.options.filters.showButtonText,
13099                clearButton: this.options.filters.clearButton,
13100                clearButtonText: this.options.filters.clearButtonText,
13101                searchButton: this.options.filters.searchButton,
13102                searchButtonText: this.options.filters.searchButtonText,
13103                padding: this.options.filters.padding,
13104                events: {
13105                    cleared: () => {
13106                        this.deselectAllRegions();
13107                        this.filtersRepository.reload();
13108                    },
13109                    "changed.fields": this.changedFields,
13110                    "changed.search": this.changedSearch,
13111                    "click.btn.searchButton": () => {
13112                        this.filtersRepository.reload();
13113                    },
13114                    loaded: () => {
13115                        this.controllers.directory && this.controllers.directory.updateTopShift();
13116                        this.afterLoadBlockers--;
13117                        this.finalizeMapLoading();
13118                    },
13119                    "click.btn.showFilters": () => {
13120                        this.loadFiltersModal();
13121                    },
13122                },
13123            });
13124            this.controllers.filters._init();
13125        }
13126        filtersShouldBeShown() {
13127            return (this.options.filters.on &&
13128                this.options.filtersSchema &&
13129                this.options.filtersSchema.length > 0);
13130        }
13131        textSearch(text, fallback = false) {
13132            const query = new Query({
13133                filters: { search: text },
13134                searchFallback: fallback,
13135            });
13136            this.filtersRepository.find(query);
13137        }
13138        getRegion(id) {
13139            return this.regions.findById(id);
13140        }
13141        getRegions() {
13142            return this.regions;
13143        }
13144        getMarker(id) {
13145            return this.markers.findById(id);
13146        }
13147        checkId(id) {
13148            if (this.getRegion(id))
13149                return { canUse: false, error: "This ID is already being used by a Region" };
13150            else if (this.getMarker(id))
13151                return { canUse: false, error: "This ID is already being used by another Marker" };
13152            else
13153                return { canUse: true, error: "" };
13154        }
13155        regionsRedrawColors() {
13156            this.regions.forEach((region) => {
13157                region.setFill();
13158            });
13159        }
13160        redrawBubbles() {
13161            $$A(this.containers.map).removeClass("bubbles-regions-on bubbles-database-on");
13162            if (this.options.choropleth.on && this.options.choropleth.bubbleMode) {
13163                $$A(this.containers.map).addClass("bubbles-" + this.options.choropleth.source + "-on");
13164            }
13165            this.regions.forEach(function (region) {
13166                region.drawBubble();
13167            });
13168            const markersBubbleMode = this.options.choropleth.on &&
13169                this.options.choropleth.source == "database" &&
13170                this.options.choropleth.bubbleMode;
13171            this.markers.forEach(function (marker) {
13172                marker.setBubbleMode(markersBubbleMode);
13173            });
13174        }
13175        destroy() {
13176            if (this.controllers && this.controllers.directory) {
13177                this.controllers.directory.mobileButtons.remove();
13178            }
13179            $$A(this.containers.map)
13180                .empty()
13181                .insertBefore($$A(this.containers.wrapAll))
13182                .attr("style", "")
13183                .removeClass("mapsvg mapsvg-responsive");
13184            this.controllers.popover && this.controllers.popover.close();
13185            if (this.controllers.detailsView)
13186                this.controllers.detailsView.destroy();
13187            $$A(this.containers.wrapAll).remove();
13188        }
13189        getData() {
13190            return {
13191                id: this.id,
13192                title: this.options.title,
13193                options: this.getOptions(false, false),
13194            };
13195        }
13196        mayBeFitMarkers() {
13197            if (!this.lastTimeFitWas) {
13198                this.lastTimeFitWas = Date.now() - 99999;
13199            }
13200            this.fitDelta = Date.now() - this.lastTimeFitWas;
13201            if (this.fitDelta > 1000 &&
13202                !this.firstDataLoad &&
13203                !this.fitOnDataLoadDone &&
13204                this.options.fitMarkers) {
13205                this.fitMarkers();
13206                this.fitOnDataLoadDone = true;
13207            }
13208            if (this.firstDataLoad &&
13209                (this.options.fitMarkersOnStart ||
13210                    (this.options.fitMarkers && this.options.database.loadOnStart === false))) {
13211                this.firstDataLoad = false;
13212                if (this.options.googleMaps.on && !this.googleMaps.map) {
13213                    this.events.on("googleMapsLoaded", () => {
13214                        this.fitMarkers();
13215                    });
13216                }
13217                else {
13218                    this.fitMarkers();
13219                }
13220            }
13221            this.lastTimeFitWas = Date.now();
13222        }
13223        fitMarkers() {
13224            const dbObjects = this.objectsRepository.getLoaded();
13225            if (!dbObjects || dbObjects.length === 0) {
13226                return;
13227            }
13228            if (this.options.googleMaps.on && typeof google !== "undefined") {
13229                const lats = [];
13230                const lngs = [];
13231                if (dbObjects.length > 1) {
13232                    dbObjects.forEach((object) => {
13233                        if (object.location && object.location.geoPoint) {
13234                            lats.push(object.location.geoPoint.lat);
13235                            lngs.push(object.location.geoPoint.lng);
13236                        }
13237                    });
13238                    const minlat = Math.min.apply(null, lats), maxlat = Math.max.apply(null, lats);
13239                    const minlng = Math.min.apply(null, lngs), maxlng = Math.max.apply(null, lngs);
13240                    const bbox = new google.maps.LatLngBounds({ lat: minlat, lng: minlng }, { lat: maxlat, lng: maxlng });
13241                    this.googleMaps.map.fitBounds(bbox, 0);
13242                }
13243                else {
13244                    if (dbObjects[0].location &&
13245                        dbObjects[0].location.geoPoint.lat &&
13246                        dbObjects[0].location.geoPoint.lng) {
13247                        const coords = {
13248                            lat: dbObjects[0].location.geoPoint.lat,
13249                            lng: dbObjects[0].location.geoPoint.lng,
13250                        };
13251                        if (this.googleMaps.map) {
13252                            this.googleMaps.map.setCenter(coords);
13253                            this.googleMaps.map.setZoom(this.options.fitSingleMarkerZoom);
13254                        }
13255                    }
13256                }
13257            }
13258            else {
13259                if (this.options.clustering.on) {
13260                    const arr = [];
13261                    this.markersClusters.forEach((c) => {
13262                        arr.push(c);
13263                    });
13264                    this.markers.forEach((m) => {
13265                        arr.push(m);
13266                    });
13267                    this.zoomTo(arr);
13268                    return;
13269                }
13270                else {
13271                    this.zoomTo(this.markers);
13272                    return;
13273                }
13274            }
13275        }
13276        setFitSingleMarkerZoom(zoom) {
13277            this.options.fitSingleMarkerZoom = parseInt(zoom);
13278        }
13279        showUserLocation(callback) {
13280            this.getUserLocation((geoPoint) => {
13281                this.userLocation = null;
13282                this.userLocation = new Location({
13283                    geoPoint: geoPoint,
13284                    img: MapSVG.urls.root + "/markers/user-location.svg",
13285                });
13286                this.userLocationMarker && this.userLocationMarker.delete();
13287                this.userLocationMarker = new Marker({
13288                    location: this.userLocation,
13289                    mapsvg: this,
13290                    width: 15,
13291                    height: 15,
13292                });
13293                $$A(this.userLocationMarker.element).addClass("mapsvg-user-location");
13294                this.userLocationMarker.centered = true;
13295                this.getLayer("markers").append(this.userLocationMarker.element);
13296                this.userLocationMarker.adjustScreenPosition();
13297                callback && callback(this.userLocation);
13298            });
13299        }
13300        getUserLocation(callback) {
13301            if (navigator.geolocation) {
13302                navigator.geolocation.getCurrentPosition(function (position) {
13303                    const pos = new GeoPoint(position.coords.latitude, position.coords.longitude);
13304                    callback && callback(pos);
13305                });
13306            }
13307            else {
13308                return false;
13309            }
13310        }
13311        getScale() {
13312            const scale2 = this.containers.map.clientWidth / this.viewBox.width;
13313            return scale2 || 1;
13314        }
13315        getViewBox() {
13316            return this.viewBox;
13317        }
13318        viewBoxSetBySize(width, height) {
13319            this.setSize(width, height);
13320            this._viewBox.update(this.viewBoxGetBySize(width, height));
13321            this.setViewBox(this._viewBox);
13322            $$A(window).trigger("resize");
13323            this.setSize(width, height);
13324            this.setZoomLevels();
13325            return this.viewBox;
13326        }
13327        viewBoxGetBySize(width, height) {
13328            const new_ratio = width / height;
13329            const old_ratio = this.svgDefault.viewBox.width / this.svgDefault.viewBox.height;
13330            const vb = this.svgDefault.viewBox.clone();
13331            if (new_ratio != old_ratio) {
13332                if (new_ratio > old_ratio) {
13333                    vb.width = this.svgDefault.viewBox.height * new_ratio;
13334                    vb.x = this.svgDefault.viewBox.x - (vb.width - this.svgDefault.viewBox.width) / 2;
13335                }
13336                else {
13337                    vb.height = this.svgDefault.viewBox.width / new_ratio;
13338                    vb.y = this.svgDefault.viewBox.y - (vb.height - this.svgDefault.viewBox.height) / 2;
13339                }
13340            }
13341            return vb;
13342        }
13343        viewBoxReset(toInitial) {
13344            if (this.options.googleMaps.on && this.googleMaps.map) {
13345                if (!toInitial) {
13346                    this.options.googleMaps.center = null;
13347                    this.options.googleMaps.zoom = null;
13348                }
13349                if (!this.options.googleMaps.center || !this.options.googleMaps.zoom) {
13350                    const southWest = new google.maps.LatLng(this.geoViewBox.sw.lat, this.geoViewBox.sw.lng);
13351                    const northEast = new google.maps.LatLng(this.geoViewBox.ne.lat, this.geoViewBox.ne.lng);
13352                    const bounds = new google.maps.LatLngBounds(southWest, northEast);
13353                    this.googleMaps.map.fitBounds(bounds, 0);
13354                    this.options.googleMaps.center = this.googleMaps.map.getCenter().toJSON();
13355                    this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
13356                }
13357                else {
13358                    this.googleMaps.map.setZoom(this.options.googleMaps.zoom);
13359                    this.googleMaps.map.setCenter(this.options.googleMaps.center);
13360                }
13361            }
13362            else {
13363                if (toInitial) {
13364                    const v = this._viewBox || this.svgDefault.viewBox;
13365                    this.zoomLevel = 0;
13366                    this._scale = 1;
13367                    this.setViewBox(v);
13368                }
13369                else {
13370                    this.setViewBox();
13371                }
13372            }
13373            return this.viewBox;
13374        }
13375        getGeoViewBox() {
13376            const v = this.viewBox;
13377            const p1 = new SVGPoint(v.x, v.y);
13378            const p2 = new SVGPoint(v.x + v.width, v.y);
13379            const p3 = new SVGPoint(v.x, v.y);
13380            const p4 = new SVGPoint(v.x, v.y + v.height);
13381            const leftLon = this.converter.convertSVGToGeo(p1).lng;
13382            const rightLon = this.converter.convertSVGToGeo(p2).lng;
13383            const topLat = this.converter.convertSVGToGeo(p3).lat;
13384            const bottomLat = this.converter.convertSVGToGeo(p4).lat;
13385            return [leftLon, topLat, rightLon, bottomLat];
13386        }
13387        setStrokes() {
13388            $$A(this.containers.svg)
13389                .find("path, polygon, circle, ellipse, rect, line, polyline")
13390                .each((index, elem) => {
13391                const width = MapObject.getComputedStyle("stroke-width", elem);
13392                if (width) {
13393                    $$A(elem).attr("data-stroke-width", width.replace("px", ""));
13394                }
13395            });
13396        }
13397        adjustStrokes() {
13398            $$A(this.containers.svg)
13399                .find("path, polygon, circle, ellipse, rect, line, polyline")
13400                .each((index, elem) => {
13401                const width = elem.getAttribute("data-stroke-width");
13402                if (width) {
13403                    $$A(elem).css("stroke-width", Number(width) / this.scale);
13404                }
13405            });
13406        }
13407        zoomIn(center) {
13408            if (this.canZoom) {
13409                this.isZooming = true;
13410                this.canZoom = false;
13411                setTimeout(() => {
13412                    this.isZooming = false;
13413                    this.canZoom = true;
13414                }, 700);
13415                this.zoom(1, center);
13416            }
13417        }
13418        zoomOut(center) {
13419            if (this.canZoom) {
13420                this.isZooming = true;
13421                this.canZoom = false;
13422                setTimeout(() => {
13423                    this.isZooming = false;
13424                    this.canZoom = true;
13425                }, 700);
13426                this.zoom(-1, center);
13427            }
13428        }
13429        zoomTo(mapObjects, zoomToLevel) {
13430            if (mapObjects instanceof Marker || mapObjects instanceof MarkerCluster) {
13431                return this.zoomToMarkerOrCluster(mapObjects, zoomToLevel);
13432            }
13433            else {
13434                const convertedObjects = !Array.isArray(mapObjects) ? [mapObjects] : mapObjects;
13435                const bbox = this.getGroupBBox(convertedObjects);
13436                return this.fitViewBox(bbox, zoomToLevel);
13437            }
13438        }
13439        zoomToMarkerOrCluster(mapObject, zoomToLevel) {
13440            this.zoomLevel = zoomToLevel || 1;
13441            const foundZoomLevel = this.zoomLevels.get(this.zoomLevel);
13442            if (!foundZoomLevel) {
13443                return false;
13444            }
13445            const vb = foundZoomLevel.viewBox;
13446            if (this.canZoom) {
13447                this.isZooming = true;
13448                this.canZoom = false;
13449                setTimeout(() => {
13450                    this.isZooming = false;
13451                    this.canZoom = true;
13452                }, 700);
13453                const vbNew = new ViewBox(mapObject.svgPoint.x - vb.width / 2, mapObject.svgPoint.y - vb.height / 2, vb.width, vb.height);
13454                this.setViewBox(vbNew);
13455                this._scale = foundZoomLevel._scale;
13456                return true;
13457            }
13458            return false;
13459        }
13460        getGroupBBox(mapObjects) {
13461            let _bbox;
13462            const xmax = [];
13463            const ymax = [];
13464            const xmin = [];
13465            const ymin = [];
13466            for (let i = 0; i < mapObjects.length; i++) {
13467                _bbox = mapObjects[i].getBBox();
13468                xmin.push(_bbox.x);
13469                ymin.push(_bbox.y);
13470                const _w = _bbox.x + _bbox.width;
13471                const _h = _bbox.y + _bbox.height;
13472                xmax.push(_w);
13473                ymax.push(_h);
13474            }
13475            const _xmin = Math.min(...xmin);
13476            const _ymin = Math.min(...ymin);
13477            const width = Math.max(...xmax) - _xmin;
13478            const height = Math.max(...ymax) - _ymin;
13479            let padding = 10;
13480            const point1 = new ScreenPoint(padding, 0);
13481            const point2 = new ScreenPoint(0, 0);
13482            padding =
13483                this.converter.convertPixelToSVG(point1).x - this.converter.convertPixelToSVG(point2).x;
13484            return new ViewBox(_xmin - padding, _ymin - padding, width + padding * 2, height + padding * 2);
13485        }
13486        fitViewBox(fitViewBox, forceZoomLevel) {
13487            let viewBoxPrev;
13488            let foundZoomLevelNumber = 0;
13489            let foundZoomLevel;
13490            let newViewBox;
13491            this.zoomLevels.forEach((zoomLevel) => {
13492                if (viewBoxPrev && viewBoxPrev.x !== undefined) {
13493                    if (fitViewBox.fitsInViewBox(viewBoxPrev) &&
13494                        zoomLevel.viewBox.fitsInViewBox(fitViewBox, true)) {
13495                        foundZoomLevelNumber = forceZoomLevel ? forceZoomLevel : zoomLevel.zoomLevel;
13496                        foundZoomLevel = this.zoomLevels.get(foundZoomLevelNumber);
13497                        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);
13498                    }
13499                }
13500                viewBoxPrev = zoomLevel && zoomLevel.viewBox;
13501            });
13502            if (foundZoomLevel) {
13503                if (this.canZoom) {
13504                    this.isZooming = true;
13505                    this.canZoom = false;
13506                    setTimeout(() => {
13507                        this.isZooming = false;
13508                        this.canZoom = true;
13509                    }, 700);
13510                    this.zoomLevel = foundZoomLevelNumber;
13511                    this._scale = foundZoomLevel._scale;
13512                    this.setViewBox(newViewBox);
13513                    return true;
13514                }
13515            }
13516            else {
13517                return false;
13518            }
13519        }
13520        zoomToRegion(region, zoomToLevel) {
13521            this.fitViewBox(region.getBBox(), zoomToLevel);
13522            return true;
13523        }
13524        centerOn(region, yShift) {
13525            if (this.options.googleMaps.on) {
13526                yShift = yShift ? (yShift + 12) / this.getScale() : 0;
13527                $$A(this.containers.map).addClass("scrolling");
13528                const latLng = region.getCenterLatLng(yShift);
13529                this.googleMaps.map.panTo(latLng);
13530                setTimeout(() => {
13531                    $$A(this.containers.map).removeClass("scrolling");
13532                }, 100);
13533            }
13534            else {
13535                yShift = yShift ? (yShift + 12) / this.getScale() : 0;
13536                const bbox = region.getBBox();
13537                const vb = this.viewBox;
13538                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);
13539                this.setViewBox(newViewBox);
13540            }
13541        }
13542        zoom(delta, center) {
13543            let newViewBox = new ViewBox(0, 0, 0, 0);
13544            const d = delta > 0 ? 1 : -1;
13545            if (!this.zoomLevels.get(this.zoomLevel + d))
13546                return;
13547            const newZoomLevel = this.zoomLevel + d;
13548            const zoomIn = d > 0;
13549            const zoomOut = d < 0;
13550            const zoomRange = this.getZoomRange();
13551            const isInZoomRange = this.zoomLevel >= zoomRange.min && this.zoomLevel <= zoomRange.max;
13552            const goingOutOfZoomRange = isInZoomRange && (newZoomLevel > zoomRange.max || newZoomLevel < zoomRange.min);
13553            const outOfRangeAndMovingAway = !isInZoomRange &&
13554                ((zoomIn && newZoomLevel > zoomRange.max) || (zoomOut && newZoomLevel < zoomRange.min));
13555            if (goingOutOfZoomRange || outOfRangeAndMovingAway) {
13556                return;
13557            }
13558            this.zoomLevel = newZoomLevel;
13559            const z = this.zoomLevels.get(this.zoomLevel);
13560            this._scale = z._scale;
13561            newViewBox = z.viewBox;
13562            let shift = [];
13563            if (center) {
13564                const koef = zoomIn ? 0.5 : -1;
13565                newViewBox.x = this.viewBox.x + (center.x - this.viewBox.x) * koef;
13566                newViewBox.y = this.viewBox.y + (center.y - this.viewBox.y) * koef;
13567            }
13568            else {
13569                shift = [
13570                    (this.viewBox.width - newViewBox.width) / 2,
13571                    (this.viewBox.height - newViewBox.height) / 2,
13572                ];
13573                newViewBox.x = this.viewBox.x + shift[0];
13574                newViewBox.y = this.viewBox.y + shift[1];
13575            }
13576            this.shiftViewBoxToScrollBoundaries(newViewBox);
13577            this.setViewBox(newViewBox);
13578        }
13579        toggleSvgLayerOnZoom() {
13580            if (this.options.googleMaps.on &&
13581                this.googleMaps.map &&
13582                this.options.zoom.hideSvg &&
13583                this.googleMaps.map.getZoom() >= this.options.zoom.hideSvgZoomLevel) {
13584                if (!$$A(this.containers.svg).hasClass("mapsvg-invisible")) {
13585                    $$A(this.containers.svg).animate({ opacity: 0 }, 400, "linear", () => {
13586                        $$A(this.containers.svg).addClass("mapsvg-invisible");
13587                    });
13588                }
13589            }
13590            else {
13591                if ($$A(this.containers.svg).hasClass("mapsvg-invisible")) {
13592                    $$A(this.containers.svg).animate({ opacity: 1 }, 400, "linear", () => {
13593                        $$A(this.containers.svg).removeClass("mapsvg-invisible");
13594                    });
13595                }
13596            }
13597        }
13598        shiftViewBoxToScrollBoundaries(newViewBox) {
13599            if (this.options.scroll.limit) {
13600                if (newViewBox.x < this.svgDefault.viewBox.x)
13601                    newViewBox.x = this.svgDefault.viewBox.x;
13602                else if (newViewBox.x + newViewBox.width >
13603                    this.svgDefault.viewBox.x + this.svgDefault.viewBox.width)
13604                    newViewBox.x =
13605                        this.svgDefault.viewBox.x + this.svgDefault.viewBox.width - newViewBox.width;
13606                if (newViewBox.y < this.svgDefault.viewBox.y)
13607                    newViewBox.y = this.svgDefault.viewBox.y;
13608                else if (newViewBox.y + newViewBox.height >
13609                    this.svgDefault.viewBox.y + this.svgDefault.viewBox.height)
13610                    newViewBox.y =
13611                        this.svgDefault.viewBox.y + this.svgDefault.viewBox.height - newViewBox.height;
13612            }
13613            return newViewBox;
13614        }
13615        markerDelete(marker) {
13616            if (this.editingMarker && this.editingMarker.id == marker.id) {
13617                this.unsetEditingMarker();
13618            }
13619            if (this.markers.findById(marker.id)) {
13620                this.markers.delete(marker.id);
13621            }
13622            marker.delete();
13623            marker = null;
13624            if (this.markers.length === 0)
13625                this.options.markerLastID = 0;
13626        }
13627        markersClusterAdd(markersCluster) {
13628            this.layers.markers.append(markersCluster.elem);
13629            this.markersClusters.push(markersCluster);
13630            markersCluster.adjustScreenPosition();
13631        }
13632        markerAdd(marker) {
13633            $$A(marker.element).hide();
13634            marker.adjustScreenPosition();
13635            this.layers.markers.append(marker.element);
13636            this.markers.push(marker);
13637            marker.mapped = true;
13638            setTimeout(function () {
13639                $$A(marker.element).show();
13640            }, 100);
13641        }
13642        markerRemove(marker) {
13643            if (this.editingMarker && this.editingMarker.id == marker.id) {
13644                this.editingMarker = null;
13645                delete this.editingMarker;
13646            }
13647            if (this.markers.findById(marker.id)) {
13648                this.markers.findById(marker.id).element.remove();
13649                this.markers.delete(marker.id);
13650                marker = null;
13651            }
13652            if (this.markers.length === 0)
13653                this.options.markerLastID = 0;
13654        }
13655        markerId() {
13656            this.options.markerLastID = this.options.markerLastID + 1;
13657            const id = "marker_" + this.options.markerLastID;
13658            if (this.getMarker(id))
13659                return this.markerId();
13660            else
13661                return id;
13662        }
13663        movingItemsAdjustScreenPosition() {
13664            this.markersAdjustScreenPosition();
13665            this.popoverAdjustScreenPosition();
13666            this.bubblesRegionsAdjustScreenPosition();
13667            this.labelsRegionsAdjustScreenPosition();
13668        }
13669        movingItemsMoveScreenPositionBy(deltaX, deltaY) {
13670            this.markersMoveScreenPositionBy(deltaX, deltaY);
13671            this.popoverMoveScreenPositionBy(deltaX, deltaY);
13672            this.bubblesRegionsMoveScreenPositionBy(deltaX, deltaY);
13673            this.labelsRegionsMoveScreenPositionBy(deltaX, deltaY);
13674        }
13675        labelsRegionsAdjustScreenPosition() {
13676            if ($$A(this.containers.map).is(":visible")) {
13677                this.regions.forEach(function (region) {
13678                    region.adjustLabelScreenPosition();
13679                });
13680            }
13681        }
13682        bubblesRegionsAdjustScreenPosition() {
13683            if ($$A(this.containers.map).is(":visible")) {
13684                this.regions.forEach(function (region) {
13685                    region.adjustBubbleScreenPosition();
13686                });
13687            }
13688        }
13689        labelsRegionsMoveScreenPositionBy(deltaX, deltaY) {
13690            if ($$A(this.containers.map).is(":visible")) {
13691                this.regions.forEach(function (region) {
13692                    region.moveLabelScreenPositionBy(deltaX, deltaY);
13693                });
13694            }
13695        }
13696        bubblesRegionsMoveScreenPositionBy(deltaX, deltaY) {
13697            if ($$A(this.containers.map).is(":visible")) {
13698                this.regions.forEach((region) => {
13699                    region.moveBubbleScreenPositionBy(deltaX, deltaY);
13700                });
13701            }
13702        }
13703        markersAdjustScreenPosition() {
13704            this.markers.forEach((marker) => {
13705                marker.adjustScreenPosition();
13706            });
13707            this.markersClusters.forEach((cluster) => {
13708                cluster.adjustScreenPosition();
13709            });
13710            if (this.userLocationMarker) {
13711                this.userLocationMarker.adjustScreenPosition();
13712            }
13713        }
13714        markersMoveScreenPositionBy(deltaX, deltaY) {
13715            this.markers.forEach((marker) => {
13716                marker.moveSrceenPositionBy(deltaX, deltaY);
13717            });
13718            this.markersClusters.forEach((cluster) => {
13719                cluster.moveSrceenPositionBy(deltaX, deltaY);
13720            });
13721            if (this.userLocationMarker) {
13722                this.userLocationMarker.moveSrceenPositionBy(deltaX, deltaY);
13723            }
13724        }
13725        setEditingMarker(marker) {
13726            this.editingMarker = marker;
13727            if (!this.editingMarker.mapped) {
13728                this.editingMarker.needToRemove = true;
13729                this.markerAdd(this.editingMarker);
13730            }
13731        }
13732        unsetEditingMarker() {
13733            if (this.editingMarker && this.editingMarker.needToRemove) {
13734                this.markerRemove(this.editingMarker);
13735            }
13736            this.editingMarker = null;
13737        }
13738        getEditingMarker() {
13739            return this.editingMarker;
13740        }
13741        scrollStart(e, mapsvg) {
13742            if ($$A(e.target).hasClass("mapsvg-btn-map") ||
13743                $$A(e.target).closest(".mapsvg-choropleth").length)
13744                return;
13745            if (this.editMarkers.on && $$A(e.target).hasClass("mapsvg-marker"))
13746                return;
13747            e.preventDefault();
13748            $$A(this.containers.map).addClass("no-transitions");
13749            const ce = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]
13750                ? e.originalEvent.touches[0]
13751                : e;
13752            this.scrollStarted = true;
13753            this.scroll = {
13754                tx: this.scroll.tx || 0,
13755                ty: this.scroll.ty || 0,
13756                vxi: this.viewBox.x,
13757                vyi: this.viewBox.y,
13758                x: ce.clientX,
13759                y: ce.clientY,
13760                dx: 0,
13761                dy: 0,
13762                vx: 0,
13763                vy: 0,
13764                gx: ce.clientX,
13765                gy: ce.clientY,
13766                touchScrollStart: 0,
13767            };
13768            if (e.type.indexOf("mouse") === 0) {
13769                $$A(document).on("mousemove.scroll.mapsvg", (e) => {
13770                    this.scrollMove(e);
13771                });
13772                if (this.options.scroll.spacebar) {
13773                    $$A(document).on("keyup.scroll.mapsvg", (e) => {
13774                        if (e.keyCode == 32) {
13775                            this.scrollEnd(e, mapsvg);
13776                        }
13777                    });
13778                }
13779                else {
13780                    $$A(document).on("mouseup.scroll.mapsvg", (e) => {
13781                        this.scrollEnd(e, mapsvg);
13782                    });
13783                }
13784            }
13785        }
13786        scrollMove(e) {
13787            e.preventDefault();
13788            if (!this.isScrolling) {
13789                this.isScrolling = true;
13790                $$A(this.containers.map).addClass("scrolling");
13791            }
13792            const ce = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]
13793                ? e.originalEvent.touches[0]
13794                : e;
13795            this.panBy(this.scroll.gx - ce.clientX, this.scroll.gy - ce.clientY);
13796            this.scroll.gx = ce.clientX;
13797            this.scroll.gy = ce.clientY;
13798            this.scroll.dx = this.scroll.x - ce.clientX;
13799            this.scroll.dy = this.scroll.y - ce.clientY;
13800            let vx = this.scroll.vxi + this.scroll.dx / this.scale;
13801            let vy = this.scroll.vyi + this.scroll.dy / this.scale;
13802            if (this.options.scroll.limit) {
13803                if (vx < this.svgDefault.viewBox.x)
13804                    vx = this.svgDefault.viewBox.x;
13805                else if (this.viewBox.width + vx >
13806                    this.svgDefault.viewBox.x + this.svgDefault.viewBox.width)
13807                    vx = this.svgDefault.viewBox.x + this.svgDefault.viewBox.width - this.viewBox.width;
13808                if (vy < this.svgDefault.viewBox.y)
13809                    vy = this.svgDefault.viewBox.y;
13810                else if (this.viewBox.height + vy >
13811                    this.svgDefault.viewBox.y + this.svgDefault.viewBox.height)
13812                    vy =
13813                        this.svgDefault.viewBox.y +
13814                            this.svgDefault.viewBox.height -
13815                            this.viewBox.height;
13816            }
13817            this.scroll.vx = vx;
13818            this.scroll.vy = vy;
13819        }
13820        scrollEnd(e, mapsvg, noClick) {
13821            setTimeout(() => {
13822                this.enableAnimation();
13823                this.scrollStarted = false;
13824                this.isScrolling = false;
13825            }, 100);
13826            if (this.googleMaps && this.googleMaps.overlay) {
13827                this.googleMaps.overlay.draw();
13828            }
13829            $$A(this.containers.map).removeClass("scrolling");
13830            $$A(document).off("keyup.scroll.mapsvg");
13831            $$A(document).off("mousemove.scroll.mapsvg");
13832            $$A(document).off("mouseup.scroll.mapsvg");
13833            if (noClick !== true && Math.abs(this.scroll.dx) < 5 && Math.abs(this.scroll.dy) < 5) {
13834                if (this.editMarkers.on)
13835                    this.clickAddsMarker && this.markerAddClickHandler(e);
13836                else if (this.objectClickedBeforeScroll)
13837                    if (this.objectClickedBeforeScroll instanceof Marker) {
13838                        this.markerClickHandler(e, this.objectClickedBeforeScroll);
13839                    }
13840                    else if (this.objectClickedBeforeScroll instanceof Region) {
13841                        this.regionClickHandler(e, this.objectClickedBeforeScroll);
13842                    }
13843                    else if (this.objectClickedBeforeScroll instanceof MarkerCluster) {
13844                        this.markerClusterClickHandler(e, this.objectClickedBeforeScroll);
13845                    }
13846            }
13847            this.viewBox.x = this.scroll.vx || this.viewBox.x;
13848            this.viewBox.y = this.scroll.vy || this.viewBox.y;
13849        }
13850        setViewBoxByGoogleMapsOverlay() {
13851            const bounds = this.googleMaps.overlay.getPixelBounds();
13852            const scale = (bounds.ne.x - bounds.sw.x) / this.svgDefault.viewBox.width;
13853            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);
13854            this.setViewBox(vb, false);
13855        }
13856        panBy(x, y) {
13857            let tx = this.scroll.tx - x;
13858            let ty = this.scroll.ty - y;
13859            const scrolled = { x: true, y: true };
13860            if (this.options.scroll.limit) {
13861                const svg = $$A(this.containers.svg)[0].getBoundingClientRect();
13862                const bounds = $$A(this.containers.map)[0].getBoundingClientRect();
13863                if ((svg.left - x > bounds.left && x < 0) || (svg.right - x < bounds.right && x > 0)) {
13864                    tx = this.scroll.tx;
13865                    scrolled.x = false;
13866                }
13867                if ((svg.top - y > bounds.top && y < 0) || (svg.bottom - y < bounds.bottom && y > 0)) {
13868                    ty = this.scroll.ty;
13869                    scrolled.y = false;
13870                }
13871            }
13872            $$A(this.containers.scrollpane).css({
13873                transform: "translate(" + tx + "px," + ty + "px)",
13874            });
13875            this.scroll.tx = tx;
13876            this.scroll.ty = ty;
13877            if (scrolled.x || scrolled.y) {
13878                const moveX = scrolled.x ? x : 0;
13879                const moveY = scrolled.y ? y : 0;
13880                this.movingItemsMoveScreenPositionBy(moveX, moveY);
13881                if (this.googleMaps.map) {
13882                    let point = this.googleMaps.map.getCenter();
13883                    const projection = this.googleMaps.overlay.getProjection();
13884                    const pixelpoint = projection.fromLatLngToDivPixel(point);
13885                    pixelpoint.x += moveX;
13886                    pixelpoint.y += moveY;
13887                    point = projection.fromDivPixelToLatLng(pixelpoint);
13888                    this.googleMaps.map.setCenter(point);
13889                }
13890            }
13891            return scrolled;
13892        }
13893        setObjectClickedBeforeScroll(object) {
13894            this.objectClickedBeforeScroll = object;
13895        }
13896        touchStart(_e, mapsvg) {
13897            _e.preventDefault();
13898            if (this.scrollStarted) {
13899                this.scrollEnd(_e, mapsvg, true);
13900            }
13901            const e = _e.originalEvent;
13902            if (this.options.zoom.fingers && e.touches && e.touches.length == 2) {
13903                this.touchZoomStart = true;
13904                this.scaleDistStart = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY);
13905            }
13906            else if (e.touches && e.touches.length == 1) {
13907                this.scrollStart(_e, mapsvg);
13908            }
13909            $$A(document)
13910                .on("touchmove.scroll.mapsvg", (e) => {
13911                e.preventDefault();
13912                this.touchMove(e, this);
13913            })
13914                .on("touchend.scroll.mapsvg", (e) => {
13915                e.preventDefault();
13916                this.touchEnd(e, this);
13917            });
13918        }
13919        touchMove(_e, mapsvg) {
13920            _e.preventDefault();
13921            const e = _e.originalEvent;
13922            if (this.options.zoom.fingers && e.touches && e.touches.length == 2) {
13923                if (!MapSVG.ios) {
13924                    e.scale =
13925                        Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY) / this.scaleDistStart;
13926                }
13927                if (e.scale != 1 && this.canZoom) {
13928                    const d = e.scale > 1 ? 1 : -1;
13929                    const cx = e.touches[0].pageX >= e.touches[1].pageX
13930                        ? e.touches[0].pageX -
13931                            (e.touches[0].pageX - e.touches[1].pageX) / 2 -
13932                            $$A(this.containers.map).offset().left
13933                        : e.touches[1].pageX -
13934                            (e.touches[1].pageX - e.touches[0].pageX) / 2 -
13935                            $$A(this.containers.map).offset().left;
13936                    const cy = e.touches[0].pageY >= e.touches[1].pageY
13937                        ? e.touches[0].pageY -
13938                            (e.touches[0].pageY - e.touches[1].pageY) -
13939                            $$A(this.containers.map).offset().top
13940                        : e.touches[1].pageY -
13941                            (e.touches[1].pageY - e.touches[0].pageY) -
13942                            $$A(this.containers.map).offset().top;
13943                    const center = this.converter.convertPixelToSVG(new ScreenPoint(cx, cy));
13944                    if (d > 0)
13945                        this.zoomIn(center);
13946                    else
13947                        this.zoomOut(center);
13948                }
13949            }
13950            else if (e.touches && e.touches.length == 1) {
13951                this.scrollMove(_e);
13952            }
13953        }
13954        touchEnd(_e, mapsvg) {
13955            _e.preventDefault();
13956            const e = _e.originalEvent;
13957            if (this.touchZoomStart) {
13958                this.touchZoomStart = false;
13959            }
13960            else if (this.scrollStarted) {
13961                this.scrollEnd(_e, mapsvg);
13962            }
13963            $$A(document).off("touchmove.scroll.mapsvg");
13964            $$A(document).off("touchend.scroll.mapsvg");
13965        }
13966        getSelected() {
13967            return this.selected_id;
13968        }
13969        selectRegion(id, skipDirectorySelection) {
13970            let region;
13971            if (typeof id == "string") {
13972                region = this.getRegion(id);
13973            }
13974            else {
13975                region = id;
13976            }
13977            if (!region)
13978                return;
13979            let ids;
13980            if (this.options.multiSelect && !this.editRegions.on) {
13981                if (region.selected) {
13982                    this.deselectRegion(region);
13983                    if (!skipDirectorySelection && this.options.menu.on) {
13984                        if (this.options.menu.source == "database") {
13985                            if (region.objects && region.objects.length) {
13986                                ids = region.objects.map((obj) => {
13987                                    return obj.id.toString();
13988                                });
13989                            }
13990                        }
13991                        else {
13992                            ids = [region.id];
13993                        }
13994                        this.controllers.directory.deselectItems();
13995                    }
13996                    return;
13997                }
13998            }
13999            else if (this.selected_id.length > 0) {
14000                this.deselectAllRegions();
14001                if (!skipDirectorySelection && this.options.menu.on) {
14002                    if (this.options.menu.source == "database") {
14003                        if (region.objects && region.objects.length) {
14004                            ids = region.objects.map((obj) => {
14005                                return obj.id.toString();
14006                            });
14007                        }
14008                    }
14009                    else {
14010                        ids = [region.id];
14011                    }
14012                    this.controllers.directory.deselectItems();
14013                }
14014            }
14015            this.selected_id.push(region.id);
14016            region.select();
14017            const skip = this.options.actions.region.click.filterDirectory;
14018            if (!skip &&
14019                !skipDirectorySelection &&
14020                this.options.menu.on &&
14021                this.controllers &&
14022                this.controllers.directory) {
14023                if (this.options.menu.source == "database") {
14024                    if (region.objects && region.objects.length) {
14025                        ids = region.objects.map((obj) => {
14026                            return obj.id.toString();
14027                        });
14028                    }
14029                    else {
14030                        ids = [region.id];
14031                    }
14032                }
14033                else {
14034                    ids = [region.id];
14035                }
14036                this.controllers.directory.selectItems(ids);
14037            }
14038            if (this.options.actions.region.click.addIdToUrl &&
14039                !this.options.actions.region.click.showAnotherMap) {
14040                window.location.hash = "/m/" + region.id;
14041            }
14042        }
14043        deselectAllRegions() {
14044            $$A.each(this.selected_id, (index, id) => {
14045                this.deselectRegion(this.getRegion(id));
14046            });
14047        }
14048        deselectRegion(region) {
14049            if (!region)
14050                region = this.getRegion(this.selected_id[0]);
14051            if (region) {
14052                region.deselect();
14053                const i = $$A.inArray(region.id, this.selected_id);
14054                this.selected_id.splice(i, 1);
14055            }
14056            if (this.options.actions.region.click.addIdToUrl) {
14057                if (window.location.hash.indexOf(region.id) !== -1) {
14058                    history.replaceState(null, null, " ");
14059                }
14060            }
14061        }
14062        highlightRegions(regions) {
14063            regions.forEach((region) => {
14064                if (region && !region.selected && !region.disabled) {
14065                    this.highlightedRegions.push(region);
14066                    region.highlight();
14067                }
14068            });
14069        }
14070        unhighlightRegions() {
14071            this.highlightedRegions.forEach((region) => {
14072                if (region && !region.selected && !region.disabled)
14073                    region.unhighlight();
14074            });
14075            this.highlightedRegions = [];
14076        }
14077        selectMarker(marker) {
14078            if (!(marker instanceof Marker))
14079                return;
14080            this.deselectAllMarkers();
14081            marker.select();
14082            this.selected_marker = marker;
14083            $$A(this.layers.markers).addClass("mapsvg-with-marker-active");
14084            if (this.options.menu.on && this.options.menu.source == "database") {
14085                this.controllers.directory.deselectItems();
14086                this.controllers.directory.selectItems(marker.object.id);
14087            }
14088        }
14089        deselectAllMarkers() {
14090            this.selected_marker && this.selected_marker.deselect();
14091            $$A(this.layers.markers).removeClass("mapsvg-with-marker-active");
14092        }
14093        deselectMarker(marker) {
14094            if (marker) {
14095                marker.deselect();
14096            }
14097        }
14098        highlightMarker(marker) {
14099            $$A(this.layers.markers).addClass("mapsvg-with-marker-hover");
14100            marker.highlight();
14101            this.highlighted_marker = marker;
14102        }
14103        unhighlightMarker() {
14104            $$A(this.layers.markers).removeClass("mapsvg-with-marker-hover");
14105            this.highlighted_marker && this.highlighted_marker.unhighlight();
14106        }
14107        convertMouseToSVG(e) {
14108            const mc = MapSVG.mouseCoords(e);
14109            const x = mc.x - $$A(this.containers.map).offset().left;
14110            const y = mc.y - $$A(this.containers.map).offset().top;
14111            const screenPoint = new ScreenPoint(x, y);
14112            return this.converter.convertPixelToSVG(screenPoint);
14113        }
14114        pickChoroplethColor(choroplethValue) {
14115            const w = (choroplethValue - this.options.choropleth.coloring.gradient.values.min) /
14116                this.options.choropleth.coloring.gradient.values.maxAdjusted;
14117            const rgba = {
14118                r: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.r * w +
14119                    this.options.choropleth.coloring.gradient.colors.lowRGB.r),
14120                g: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.g * w +
14121                    this.options.choropleth.coloring.gradient.colors.lowRGB.g),
14122                b: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.b * w +
14123                    this.options.choropleth.coloring.gradient.colors.lowRGB.b),
14124                a: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.a * w +
14125                    this.options.choropleth.coloring.gradient.colors.lowRGB.a),
14126            };
14127            return rgba;
14128        }
14129        isRegionDisabled(id, svgfill) {
14130            if (this.options.regions[id] && (this.options.regions[id].disabled || svgfill == "none")) {
14131                return true;
14132            }
14133            else if ((this.options.regions[id] == undefined ||
14134                MapSVG.parseBoolean(this.options.regions[id].disabled)) &&
14135                (this.options.disableAll || svgfill == "none" || id == "labels" || id == "Labels")) {
14136                return true;
14137            }
14138            else {
14139                return false;
14140            }
14141        }
14142        loadMap(id, container) {
14143            if (!(container instanceof HTMLElement)) {
14144                console.error("Can't load a new map: container was not provided.");
14145                return;
14146            }
14147            const previousMapsIds = [...this.options.previousMapsIds];
14148            const currentMapId = this.id;
14149            if (previousMapsIds[previousMapsIds.length - 1] !== id) {
14150                previousMapsIds.push(currentMapId);
14151            }
14152            else {
14153                previousMapsIds.pop();
14154            }
14155            let showPreviousMapButton;
14156            if (this.options.actions.region.click.showAnotherMapContainerId !== "undefined") {
14157                showPreviousMapButton = false;
14158            }
14159            else {
14160                showPreviousMapButton = this.options.controls.previousMap;
14161            }
14162            const mapsRepo = new MapsRepository();
14163            mapsRepo.findById(id).done((map) => {
14164                this.destroy();
14165                const newMap = new MapSVGMap(container.getAttribute("id"), map);
14166                newMap.events.on("afterLoad", function () {
14167                    this.options.previousMapsIds = previousMapsIds;
14168                    this.options.controls.previousMap = showPreviousMapButton;
14169                    this.setControls(this.options.controls);
14170                });
14171            });
14172        }
14173        loadPreviousMap() {
14174            const previousMapId = this.options.previousMapsIds[this.options.previousMapsIds.length - 1];
14175            const container = document.getElementById(this.containerId);
14176            this.loadMap(previousMapId, container);
14177        }
14178        markerClusterClickHandler(e, markerCluster) {
14179            this.objectClickedBeforeScroll = null;
14180            if (this.eventsPreventList["click"])
14181                return;
14182            this.zoomTo(markerCluster.markers);
14183            return;
14184        }
14185        regionClickHandler(e, region) {
14186            this.objectClickedBeforeScroll = null;
14187            if (this.eventsPreventList["click"])
14188                return;
14189            this.selectRegion(region.id);
14190            if (this.editRegions.on) {
14191                this.regionEditHandler.call(region);
14192                return;
14193            }
14194            const actions = this.options.actions;
14195            if (actions.region.click.zoom) {
14196                this.zoomTo(region, parseInt(actions.region.click.zoomToLevel));
14197            }
14198            if (actions.region.click.filterDirectory) {
14199                const query = new Query({
14200                    filters: {
14201                        regions: {
14202                            table_name: this.regionsRepository.getSchema().name,
14203                            region_ids: [region.id],
14204                        },
14205                    },
14206                });
14207                this.objectsRepository.find(query).done(() => {
14208                    if (this.controllers.popover) {
14209                        this.controllers.popover.redraw(region.forTemplate());
14210                    }
14211                    if (this.controllers.detailsView) {
14212                        this.controllers.detailsView.redraw(region.forTemplate());
14213                    }
14214                });
14215                this.updateFiltersState();
14216            }
14217            if (actions.region.click.showDetails) {
14218                this.loadDetailsView(region);
14219            }
14220            if (actions.region.click.showPopover) {
14221                if (actions.region.click.zoom) {
14222                    setTimeout(() => {
14223                        this.showPopover(region);
14224                    }, 400);
14225                }
14226                else {
14227                    this.showPopover(region);
14228                }
14229            }
14230            else if (e && e.type.indexOf("touch") !== -1 && actions.region.touch.showPopover) {
14231                if (actions.region.click.zoom) {
14232                    setTimeout(() => {
14233                        this.showPopover(region);
14234                    }, 400);
14235                }
14236                else {
14237                    this.showPopover(region);
14238                }
14239            }
14240            if (actions.region.click.goToLink) {
14241                const linkParts = actions.region.click.linkField.split(".");
14242                let url;
14243                if (linkParts.length > 1) {
14244                    const obj = linkParts.shift();
14245                    const attr = "." + linkParts.join(".");
14246                    if (obj == "Region") {
14247                        if (region.data) {
14248                            try {
14249                                url = eval("region.data" + attr);
14250                            }
14251                            catch (err) {
14252                                console.log("No such field as region.data" + attr);
14253                            }
14254                        }
14255                    }
14256                    else {
14257                        if (region.objects && region.objects[0]) {
14258                            try {
14259                                url = eval("region.objects[0]" + attr);
14260                            }
14261                            catch (err) {
14262                                console.log("No such field as region.objects[0]" + attr);
14263                            }
14264                        }
14265                    }
14266                    if (url && !this.disableLinks) {
14267                        if (this.editMode) {
14268                            alert("Redirect: " + url + "\nLinks are disabled in the preview.");
14269                            return;
14270                        }
14271                        if (actions.region.click.newTab) {
14272                            const win = window.open(url, "_blank");
14273                            win.focus();
14274                        }
14275                        else {
14276                            window.location.href = url;
14277                        }
14278                    }
14279                }
14280            }
14281            if (actions.region.click.showAnotherMap) {
14282                if (this.editMode) {
14283                    alert('"Show another map" action is disabled in the preview');
14284                    return;
14285                }
14286                const linkParts = actions.region.click.showAnotherMapField.split(".");
14287                if (linkParts.length > 1) {
14288                    const obj = linkParts.shift();
14289                    const attr = "." + linkParts.join(".");
14290                    let map_id;
14291                    if (obj == "Region") {
14292                        if (region.data)
14293                            map_id = eval("region.data" + attr);
14294                    }
14295                    else {
14296                        if (region.objects && region.objects[0])
14297                            map_id = eval("region.objects[0]" + attr);
14298                    }
14299                    if (map_id) {
14300                        const container = actions.region.click.showAnotherMapContainerId
14301                            ? $$A("#" + actions.region.click.showAnotherMapContainerId)[0]
14302                            : $$A(this.containers.wrapAll)[0];
14303                        this.loadMap(map_id, container);
14304                    }
14305                }
14306            }
14307            this.events.trigger("click.region", region, [e, region, this]);
14308        }
14309        markerClickHandler(e, marker) {
14310            this.objectClickedBeforeScroll = null;
14311            if (this.eventsPreventList["click"])
14312                return;
14313            const actions = this.options.actions;
14314            this.selectMarker(marker);
14315            const passingObject = marker.object;
14316            if (actions.marker.click.zoom) {
14317                this.zoomTo(marker, parseInt(actions.marker.click.zoomToLevel));
14318            }
14319            if (actions.marker.click.filterDirectory) {
14320                const query = new Query({ filters: { id: marker.object.id } });
14321                this.objectsRepository.find(query);
14322                this.updateFiltersState();
14323            }
14324            if (actions.marker.click.showDetails)
14325                this.loadDetailsView(passingObject);
14326            if (actions.marker.click.showPopover) {
14327                if (actions.marker.click.zoom) {
14328                    setTimeout(() => {
14329                        this.showPopover(passingObject);
14330                    }, 500);
14331                }
14332                else {
14333                    this.showPopover(passingObject);
14334                }
14335            }
14336            else if (e && e.type.indexOf("touch") !== -1 && actions.marker.touch.showPopover) {
14337                if (actions.marker.click.zoom) {
14338                    setTimeout(() => {
14339                        this.showPopover(passingObject);
14340                    }, 500);
14341                }
14342                else {
14343                    this.showPopover(passingObject);
14344                }
14345            }
14346            if (actions.marker.click.goToLink) {
14347                const linkParts = actions.marker.click.linkField.split(".");
14348                let url;
14349                if (linkParts.length > 1) {
14350                    const obj = linkParts.shift();
14351                    const attr = "." + linkParts.join(".");
14352                    try {
14353                        url = eval("passingObject" + attr);
14354                    }
14355                    catch (err) {
14356                        console.log("MapSVG: No such field as passingObject" + attr);
14357                    }
14358                    if (url && !this.disableLinks)
14359                        if (this.editMode) {
14360                            alert("Redirect: " + url + "\nLinks are disabled in the preview.");
14361                            return;
14362                        }
14363                    if (actions.marker.click.newTab) {
14364                        const win = window.open(url, "_blank");
14365                        win.focus();
14366                    }
14367                    else {
14368                        window.location.href = url;
14369                    }
14370                }
14371            }
14372            this.events.trigger("click.marker", marker, [e, marker, this]);
14373        }
14374        fileExists(url) {
14375            if (url.substr(0, 4) == "data")
14376                return true;
14377            const http = new XMLHttpRequest();
14378            http.open("HEAD", url, false);
14379            http.send();
14380            return http.status != 404;
14381        }
14382        hideMarkers() {
14383            this.markers.forEach(function (marker) {
14384                marker.hide();
14385            });
14386            $$A(this.containers.wrap).addClass("mapsvg-edit-marker-mode");
14387        }
14388        hideMarkersExceptOne(id) {
14389            this.markers.forEach(function (marker) {
14390                if (typeof id === "undefined" || (marker.object && id != marker.object.id)) {
14391                    marker.hide();
14392                }
14393            });
14394            $$A(this.containers.wrap).addClass("mapsvg-edit-marker-mode");
14395        }
14396        showMarkers() {
14397            this.markers.forEach(function (m) {
14398                m.show();
14399            });
14400            this.deselectAllMarkers();
14401            $$A(this.containers.wrap).removeClass("mapsvg-edit-marker-mode");
14402        }
14403        markerAddClickHandler(e) {
14404            if ($$A(e.target).hasClass("mapsvg-marker"))
14405                return;
14406            const svgPoint = this.getSvgPointAtClick(e);
14407            const geoPoint = this.isGeo() ? this.converter.convertSVGToGeo(svgPoint) : null;
14408            if (!$$A.isNumeric(svgPoint.x) || !$$A.isNumeric(svgPoint.y))
14409                return;
14410            if (this.editingMarker) {
14411                if (geoPoint) {
14412                    this.editingMarker.location.setGeoPoint(geoPoint);
14413                }
14414                else {
14415                    this.editingMarker.location.setSvgPoint(svgPoint);
14416                }
14417                return;
14418            }
14419            const location = new Location({
14420                svgPoint: svgPoint,
14421                geoPoint: geoPoint,
14422                img: this.options.defaultMarkerImage,
14423            });
14424            const marker = new Marker({
14425                location: location,
14426                mapsvg: this,
14427            });
14428            this.markerAdd(marker);
14429            this.markerEditHandler && this.markerEditHandler.call(location, location);
14430        }
14431        getSvgPointAtClick(e) {
14432            const mc = MapSVG.mouseCoords(e);
14433            const x = mc.x - $$A(this.containers.map).offset().left;
14434            const y = mc.y - $$A(this.containers.map).offset().top;
14435            const screenPoint = new ScreenPoint(x, y);
14436            return this.converter.convertPixelToSVG(screenPoint);
14437        }
14438        setDefaultMarkerImage(src) {
14439            this.options.defaultMarkerImage = src;
14440        }
14441        setMarkerImagesDependency() {
14442            this.locationField = this.objectsRepository.schema.getFieldByType("location");
14443            if (this.locationField &&
14444                this.locationField.markersByFieldEnabled &&
14445                this.locationField.markerField &&
14446                Object.values(this.locationField.markersByField).length > 0) {
14447                this.setMarkersByField = true;
14448            }
14449            else {
14450                this.setMarkersByField = false;
14451            }
14452        }
14453        getMarkerImage(fieldValueOrObject, location) {
14454            let fieldValue;
14455            if (this.setMarkersByField) {
14456                if (typeof fieldValueOrObject === "object") {
14457                    fieldValue = fieldValueOrObject[this.locationField.markerField];
14458                    if (this.locationField.markerField === "regions") {
14459                        fieldValue = fieldValue[0] && fieldValue[0].id;
14460                    }
14461                    else if (typeof fieldValue === "object" && fieldValue.length) {
14462                        fieldValue = fieldValue[0].value;
14463                    }
14464                }
14465                else {
14466                    fieldValue = fieldValueOrObject;
14467                }
14468                if (this.locationField.markersByField[fieldValue]) {
14469                    return this.locationField.markersByField[fieldValue];
14470                }
14471            }
14472            return location && location.imagePath
14473                ? location.imagePath
14474                : this.options.defaultMarkerImage
14475                    ? this.options.defaultMarkerImage
14476                    : MapSVG.urls.root + "markers/_pin_default.png";
14477        }
14478        setMarkersEditMode(on, clickAddsMarker) {
14479            this.editMarkers.on = MapSVG.parseBoolean(on);
14480            this.clickAddsMarker = this.editMarkers.on;
14481            this.setEventHandlers();
14482        }
14483        setRegionsEditMode(on) {
14484            this.editRegions.on = MapSVG.parseBoolean(on);
14485            this.deselectAllRegions();
14486            this.setEventHandlers();
14487        }
14488        setEditMode(on) {
14489            this.editMode = on;
14490        }
14491        setDataEditMode(on) {
14492            this.editData.on = MapSVG.parseBoolean(on);
14493            this.deselectAllRegions();
14494            this.setEventHandlers();
14495        }
14496        download() {
14497            window.location.href = window.location.origin + this.options.source;
14498        }
14499        popoverAdjustScreenPosition() {
14500            if (this.controllers.popover instanceof PopoverController) {
14501                this.controllers.popover.adjustScreenPosition();
14502            }
14503        }
14504        popoverMoveScreenPositionBy(deltaX, deltaY) {
14505            if (this.controllers.popover instanceof PopoverController) {
14506                this.controllers.popover.moveSrceenPositionBy(deltaX, deltaY);
14507            }
14508        }
14509        showPopover(object) {
14510            const mapObject = object instanceof Region
14511                ? object
14512                : object.location && object.location.marker
14513                    ? object.location.marker
14514                    : null;
14515            if (!mapObject)
14516                return;
14517            let point;
14518            if (mapObject instanceof Marker) {
14519                point = mapObject.svgPoint;
14520            }
14521            else {
14522                point = mapObject.getCenterSVG();
14523            }
14524            this.controllers.popover && this.controllers.popover.destroy();
14525            this.controllers.popover = new PopoverController({
14526                container: this.containers.popover,
14527                point: point,
14528                yShift: mapObject instanceof Marker ? mapObject.height : 0,
14529                template: object instanceof Region
14530                    ? this.options.templates.popoverRegion
14531                    : this.options.templates.popoverMarker,
14532                mapsvg: this,
14533                data: object.getData(),
14534                mapObject: mapObject,
14535                scrollable: true,
14536                withToolbar: !(MapSVG.isPhone && this.options.popovers.mobileFullscreen),
14537                events: {
14538                    shown: (popover) => {
14539                        if (this.options.popovers.centerOn) {
14540                            const shift = popover.containers.main.offsetHeight / 2;
14541                            if (this.options.popovers.centerOn &&
14542                                !(MapSVG.isPhone && this.options.popovers.mobileFullscreen)) {
14543                                this.centerOn(mapObject, shift);
14544                            }
14545                        }
14546                        this.popoverShowingFor = mapObject;
14547                        this.events.trigger("shown.popover", this, [this, popover]);
14548                        $$A(window).trigger("shown.popover", [this, popover]);
14549                    },
14550                    closed: (popover) => {
14551                        this.options.popovers.resetViewboxOnClose && this.viewBoxReset(true);
14552                        this.popoverShowingFor = null;
14553                        this.events.trigger("closed.popover", this, [this, popover]);
14554                    },
14555                    resize: (popover) => {
14556                        if (this.options.popovers.centerOn) {
14557                            const shift = popover.containers.main.offsetHeight / 2;
14558                            if (this.options.popovers.centerOn &&
14559                                !(MapSVG.isPhone && this.options.popovers.mobileFullscreen)) {
14560                                this.centerOn(mapObject, shift);
14561                            }
14562                        }
14563                    },
14564                },
14565            });
14566            this.controllers.popover._init();
14567        }
14568        hidePopover() {
14569            this.controllers.popover && this.controllers.popover.close();
14570        }
14571        popoverOffHandler(e) {
14572            if (this.isScrolling ||
14573                $$A(e.target).closest(".mapsvg-popover").length ||
14574                $$A(e.target).hasClass("mapsvg-btn-map"))
14575                return;
14576            this.controllers.popover && this.controllers.popover.close();
14577        }
14578        mouseOverHandler(e, object) {
14579            if (this.eventsPreventList["mouseover"]) {
14580                return;
14581            }
14582            if (object instanceof Marker) {
14583                if (this.options.actions.marker.mouseover.showTooltip) {
14584                    this.showTooltip(object);
14585                }
14586            }
14587            if (object instanceof Region) {
14588                if (this.options.actions.region.mouseover.showTooltip) {
14589                    this.showTooltip(object);
14590                }
14591            }
14592            let ids;
14593            if (this.options.menu.on) {
14594                if (this.options.menu.source == "database") {
14595                    if (object instanceof Region && object.objects.length) {
14596                        ids = object.objects.map((obj) => {
14597                            return obj.id;
14598                        });
14599                    }
14600                    if (object instanceof Marker) {
14601                        ids = object.object ? [object.object.id] : [];
14602                    }
14603                }
14604                else {
14605                    if (object instanceof Region) {
14606                        ids = [object.id];
14607                    }
14608                    if (this instanceof Marker &&
14609                        object.object.regions &&
14610                        object.object.regions.length) {
14611                        ids = object.object.regions.map((obj) => {
14612                            return obj.id;
14613                        });
14614                    }
14615                }
14616                this.controllers.directory.highlightItems(ids);
14617            }
14618            if (object instanceof Region) {
14619                if (!object.selected)
14620                    object.highlight();
14621                this.events.trigger("mouseover.region", object, [e, this]);
14622            }
14623            else {
14624                this.highlightMarker(object);
14625                this.events.trigger("mouseover.marker", object, [e, this]);
14626            }
14627        }
14628        showTooltip(object) {
14629            let name, _object;
14630            if (object instanceof Region) {
14631                name = "tooltipRegion";
14632                _object = object;
14633            }
14634            else if (object instanceof Marker) {
14635                name = "tooltipMarker";
14636                _object = object.object;
14637            }
14638            else {
14639                name = "tooltipMarker";
14640                _object = object;
14641            }
14642            if (_object != null && this.popoverShowingFor !== object) {
14643                this.controllers.tooltip.setMainTemplate(this.options.templates[name]);
14644                this.controllers.tooltip.redraw(_object.getData());
14645                this.controllers.tooltip.show();
14646            }
14647        }
14648        mouseOutHandler(e, object) {
14649            if (this.eventsPreventList["mouseout"]) {
14650                return;
14651            }
14652            if (this.controllers.tooltip)
14653                this.controllers.tooltip.hide();
14654            if (object instanceof Region) {
14655                if (!object.selected)
14656                    object.unhighlight();
14657                this.events.trigger("mouseout.region", object, [e, this]);
14658            }
14659            else {
14660                this.unhighlightMarker();
14661                this.events.trigger("mouseout.marker", object, [e, this]);
14662            }
14663            let ids;
14664            if (this.options.menu.on) {
14665                if (this.options.menu.source == "database") {
14666                    if (object instanceof Marker) {
14667                        const marker = object;
14668                        ids = marker.object ? [marker.object.id] : [];
14669                    }
14670                }
14671                this.controllers.directory.unhighlightItems();
14672            }
14673        }
14674        eventsPrevent(event) {
14675            this.eventsPreventList[event] = true;
14676        }
14677        eventsRestore(event) {
14678            if (event) {
14679                this.eventsPreventList[event] = false;
14680            }
14681            else {
14682                this.eventsPreventList = {};
14683            }
14684        }
14685        setEventHandlers() {
14686            const _this = this;
14687            $$A(_this.containers.map).off(".common.mapsvg");
14688            $$A(_this.containers.scrollpane).off(".common.mapsvg");
14689            $$A(document).off(".scroll.mapsvg");
14690            $$A(document).off(".scrollInit.mapsvg");
14691            if (_this.editMarkers.on) {
14692                $$A(_this.containers.map).on("touchstart.common.mapsvg mousedown.common.mapsvg", ".mapsvg-marker", function (e) {
14693                    e.originalEvent.preventDefault();
14694                    const marker = _this.getMarker($$A(this).attr("id"));
14695                    const startCoords = MapSVG.mouseCoords(e);
14696                    marker.drag(startCoords, _this.scale);
14697                });
14698            }
14699            if (!_this.editMarkers.on) {
14700                $$A(_this.containers.map)
14701                    .on("mouseover.common.mapsvg", ".mapsvg-region", function (e) {
14702                    const id = $$A(this).attr("id");
14703                    _this.mouseOverHandler.call(_this, e, _this.getRegion(id));
14704                })
14705                    .on("mouseleave.common.mapsvg", ".mapsvg-region", function (e) {
14706                    const id = $$A(this).attr("id");
14707                    _this.mouseOutHandler.call(_this, e, _this.getRegion(id));
14708                });
14709            }
14710            if (!_this.editRegions.on) {
14711                $$A(_this.containers.map)
14712                    .on("mouseover.common.mapsvg", ".mapsvg-marker", function (e) {
14713                    const id = $$A(this).attr("id");
14714                    _this.mouseOverHandler.call(_this, e, _this.getMarker(id));
14715                })
14716                    .on("mouseleave.common.mapsvg", ".mapsvg-marker", function (e) {
14717                    const id = $$A(this).attr("id");
14718                    _this.mouseOutHandler.call(_this, e, _this.getMarker(id));
14719                });
14720            }
14721            if (_this.options.scroll.spacebar) {
14722                $$A(document).on("keydown.scroll.mapsvg", function (e) {
14723                    if (!(document.activeElement.tagName === "INPUT" &&
14724                        $$A(document.activeElement).attr("type") === "text") &&
14725                        !_this.isScrolling &&
14726                        e.keyCode == 32) {
14727                        e.preventDefault();
14728                        $$A(_this.containers.map).addClass("mapsvg-scrollable");
14729                        $$A(document)
14730                            .on("mousemove.scrollInit.mapsvg", function (e) {
14731                            _this.isScrolling = true;
14732                            $$A(document).off("mousemove.scrollInit.mapsvg");
14733                            _this.scrollStart(e, _this);
14734                        })
14735                            .on("keyup.scroll.mapsvg", function (e) {
14736                            if (e.keyCode == 32) {
14737                                $$A(document).off("mousemove.scrollInit.mapsvg");
14738                                $$A(_this.containers.map).removeClass("mapsvg-scrollable");
14739                            }
14740                        });
14741                    }
14742                });
14743            }
14744            else if (!_this.options.scroll.on) {
14745                if (!_this.editMarkers.on) {
14746                    $$A(_this.containers.map).on("touchstart.common.mapsvg", ".mapsvg-region", function (e) {
14747                        _this.scroll.touchScrollStart = $$A(window).scrollTop();
14748                    });
14749                    $$A(_this.containers.map).on("touchstart.common.mapsvg", ".mapsvg-marker", function (e) {
14750                        _this.scroll.touchScrollStart = $$A(window).scrollTop();
14751                    });
14752                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-region", function (e) {
14753                        if (e.cancelable) {
14754                            e.preventDefault();
14755                        }
14756                        if (!_this.scroll.touchScrollStart ||
14757                            _this.scroll.touchScrollStart === $$A(window).scrollTop()) {
14758                            _this.regionClickHandler(e, _this.getRegion($$A(this).attr("id")));
14759                        }
14760                    });
14761                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-marker", function (e) {
14762                        if (e.cancelable) {
14763                            e.preventDefault();
14764                        }
14765                        if (!_this.scroll.touchScrollStart ||
14766                            _this.scroll.touchScrollStart === $$A(window).scrollTop()) {
14767                            _this.markerClickHandler.call(_this, e, _this.getMarker($$A(this).attr("id")));
14768                        }
14769                    });
14770                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-marker-cluster", function (e) {
14771                        if (e.cancelable) {
14772                            e.preventDefault();
14773                        }
14774                        if (!_this.scroll.touchScrollStart ||
14775                            _this.scroll.touchScrollStart == $$A(window).scrollTop()) {
14776                            const cluster = $$A(this).data("cluster");
14777                            _this.zoomTo(cluster.markers);
14778                        }
14779                    });
14780                }
14781                else {
14782                    if (_this.clickAddsMarker)
14783                        $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", function (e) {
14784                            if (e.cancelable) {
14785                                e.preventDefault();
14786                            }
14787                            _this.markerAddClickHandler(e);
14788                        });
14789                }
14790            }
14791            else {
14792                $$A(_this.containers.map).on("touchstart.common.mapsvg mousedown.common.mapsvg", function (e) {
14793                    if ($$A(e.target).hasClass("mapsvg-popover") ||
14794                        $$A(e.target).closest(".mapsvg-popover").length) {
14795                        if ($$A(e.target).hasClass("mapsvg-popover-close")) {
14796                            if (e.type == "touchstart") {
14797                                if (e.cancelable) {
14798                                    e.preventDefault();
14799                                }
14800                            }
14801                        }
14802                        return;
14803                    }
14804                    if (e.type == "touchstart") {
14805                        if (e.cancelable) {
14806                            e.preventDefault();
14807                        }
14808                    }
14809                    let obj;
14810                    if (e.target &&
14811                        $$A(e.target).attr("class") &&
14812                        $$A(e.target).attr("class").indexOf("mapsvg-region") != -1) {
14813                        obj = _this.getRegion($$A(e.target).attr("id"));
14814                        _this.setObjectClickedBeforeScroll(obj);
14815                    }
14816                    else if (e.target &&
14817                        $$A(e.target).attr("class") &&
14818                        $$A(e.target).attr("class").indexOf("mapsvg-marker") != -1 &&
14819                        $$A(e.target).attr("class").indexOf("mapsvg-marker-cluster") 
14819=== -1) {
14820                        if (_this.editMarkers.on) {
14821                            return;
14822                        }
14823                        obj = _this.getMarker($$A(e.target).attr("id"));
14824                        _this.setObjectClickedBeforeScroll(obj);
14825                    }
14826                    else if (e.target &&
14827                        $$A(e.target).attr("class") &&
14828                        $$A(e.target).attr("class").indexOf("mapsvg-marker-cluster") != -1) {
14829                        if (_this.editMarkers.on) {
14830                            return;
14831                        }
14832                        obj = $$A(e.target).data("cluster");
14833                        _this.setObjectClickedBeforeScroll(obj);
14834                    }
14835                    if (e.type == "mousedown") {
14836                        _this.scrollStart(e, _this);
14837                    }
14838                    else {
14839                        _this.touchStart(e, _this);
14840                    }
14841                });
14842            }
14843            $$A(_this.containers.map).on("mouseleave.common.mapsvg", ".mapsvg-choropleth-gradient-wrap", (e) => {
14844                this.controllers.tooltip.hide();
14845            });
14846        }
14847        setLabelsRegions(options) {
14848            options = options || this.options.labelsRegions;
14849            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14850            $$A.extend(true, this.options, { labelsRegions: options });
14851            if (this.options.labelsRegions.on) {
14852                this.regions.forEach((region) => {
14853                    if (!region.label) {
14854                        region.label = jQuery('<div class="mapsvg-region-label" />')[0];
14855                        $$A(this.layers.labels).append(region.label);
14856                    }
14857                    try {
14858                        $$A(region.label).html(this.templates.labelRegion(region.forTemplate()));
14859                    }
14860                    catch (err) {
14861                        console.error('MapSVG: Error in the "Region Label" template');
14862                    }
14863                });
14864                this.labelsRegionsAdjustScreenPosition();
14865            }
14866            else {
14867                this.regions.forEach((region) => {
14868                    if (region.label) {
14869                        $$A(region.label).remove();
14870                        region.label = null;
14871                        delete region.label;
14872                    }
14873                });
14874            }
14875        }
14876        setLabelsMarkers(options) {
14877            options = options || this.options.labelsMarkers;
14878            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14879            $$A.extend(true, this.options, { labelsMarkers: options });
14880            if (this.options.labelsMarkers.on) {
14881                this.markers.forEach((marker) => {
14882                    try {
14883                        marker.setLabel(this.templates.labelMarker(marker.object));
14884                    }
14885                    catch (err) {
14886                        console.error('MapSVG: Error in the "Marker Label" template');
14887                    }
14888                });
14889            }
14890            else {
14891                this.markers.forEach((marker) => {
14892                    marker.setLabel("");
14893                });
14894            }
14895        }
14896        addLayer(name) {
14897            this.layers[name] = $$A('<div class="mapsvg-layer mapsvg-layer-' + name + '"></div>')[0];
14898            this.containers.layers.appendChild(this.layers[name]);
14899            return this.layers[name];
14900        }
14901        getLayer(name) {
14902            return this.layers[name];
14903        }
14904        getDb() {
14905            return this.objectsRepository;
14906        }
14907        getDbRegions() {
14908            return this.regionsRepository;
14909        }
14910        regionAdd(svgObject) {
14911            const region = new Region(svgObject, this);
14912            region.setStatus(1);
14913            this.regions.push(region);
14914            this.regions.sort(function (a, b) {
14915                return a.id == b.id ? 0 : +(a.id > b.id) || -1;
14916            });
14917            return region;
14918        }
14919        regionDelete(id) {
14920            if (this.regions.findById(id)) {
14921                this.regions.findById(id).elem.remove();
14922                this.regions.delete(id);
14923            }
14924            else if ($$A("#" + id).length) {
14925                $$A("#" + id).remove();
14926            }
14927        }
14928        reloadRegions() {
14929            this.regions.clear();
14930            $$A(this.containers.svg).find(".mapsvg-region").removeClass("mapsvg-region");
14931            $$A(this.containers.svg)
14932                .find(".mapsvg-region-disabled")
14933                .removeClass("mapsvg-region-disabled");
14934            $$A(this.containers.svg)
14935                .find("path, polygon, circle, ellipse, rect")
14936                .each((index, element) => {
14937                const elem = element;
14938                if ($$A(elem).closest("defs").length)
14939                    return;
14940                if (elem.getAttribute("data-stroke-width")) {
14941                    elem.style["stroke-width"] = elem.getAttribute("data-stroke-width");
14942                }
14943                if (elem.getAttribute("id")) {
14944                    if (!this.options.regionPrefix ||
14945                        (this.options.regionPrefix &&
14946                            elem.getAttribute("id").indexOf(this.options.regionPrefix) === 0)) {
14947                        const region = new Region(elem, this);
14948                        this.regions.push(region);
14949                    }
14950                }
14951            });
14952        }
14953        reloadRegionsFull() {
14954            const statuses = this.regionsRepository.getSchema().getFieldByType("status");
14955            this.regions.forEach((region) => {
14956                const _region = this.regionsRepository.getLoaded().findById(region.id);
14957                if (_region) {
14958                    region.setData(_region);
14959                    if (statuses && _region.status !== undefined && _region.status !== null) {
14960                        region.setStatus(_region.status);
14961                    }
14962                }
14963                else {
14964                    if (this.options.filters.filteredRegionsStatus ||
14965                        this.options.filters.filteredRegionsStatus === 0 ||
14966                        (this.options.menu.source === "regions" &&
14967                            this.options.menu.filterout &&
14968                            this.options.menu.filterout.field === "status" &&
14969                            this.options.menu.filterout.val) ||
14970                        this.options.menu.filterout.val === 0) {
14971                        const status = this.options.filters.filteredRegionsStatus ||
14972                            this.options.filters.filteredRegionsStatus === 0
14973                            ? this.options.filters.filteredRegionsStatus
14974                            : this.options.menu.filterout.val;
14975                        region.setStatus(status);
14976                    }
14977                }
14978            });
14979            this.loadDirectory();
14980            this.setChoropleth();
14981            this.setLayersControl();
14982            this.setGroups();
14983            if (this.options.labelsRegions.on) {
14984                this.setLabelsRegions();
14985            }
14986        }
14987        fixMarkersWorldScreen() {
14988            if (this.googleMaps.map)
14989                setTimeout(() => {
14990                    const markers = { left: 0, right: 0, leftOut: 0, rightOut: 0 };
14991                    if (this.markers.length > 1) {
14992                        this.markers.forEach((m) => {
14993                            if ($$A(m.element).offset().left <
14994                                $$A(this.containers.map).offset().left +
14995                                    this.containers.map.clientWidth / 2) {
14996                                markers.left++;
14997                                if ($$A(m.element).offset().left < $$A(this.containers.map).offset().left) {
14998                                    markers.leftOut++;
14999                                }
15000                            }
15001                            else {
15002                                markers.right++;
15003                                if ($$A(m.element).offset().left >
15004                                    $$A(this.containers.map).offset().left +
15005                                        this.containers.map.clientWidth) {
15006                                    markers.rightOut++;
15007                                }
15008                            }
15009                        });
15010                        if ((markers.left === 0 && markers.rightOut) ||
15011                            (markers.right === 0 && markers.leftOut)) {
15012                            const k = markers.left === 0 ? 1 : -1;
15013                            const ww = (this.svgDefault.viewBox.width / this.converter.mapLonDelta) *
15014                                360 *
15015                                this.getScale();
15016                            this.googleMaps.map.panBy(k * ww, 0);
15017                        }
15018                    }
15019                }, 600);
15020        }
15021        updateOutdatedOptions(options) {
15022            if (options.menu && (options.menu.position || options.menu.customContainer)) {
15023                if (options.menu.customContainer) {
15024                    options.menu.location = "custom";
15025                }
15026                else {
15027                    options.menu.position = options.menu.position === "left" ? "left" : "right";
15028                    options.menu.location =
15029                        options.menu.position === "left" ? "leftSidebar" : "rightSidebar";
15030                    if (!options.containers || !options.containers[options.menu.location]) {
15031                        options.containers = options.containers || {};
15032                        options.containers[options.menu.location] = { on: false, width: "200px" };
15033                    }
15034                    options.containers[options.menu.location].width = options.menu.width;
15035                    if (MapSVG.parseBoolean(options.menu.on)) {
15036                        options.containers[options.menu.location].on = true;
15037                    }
15038                }
15039                delete options.menu.position;
15040                delete options.menu.width;
15041                delete options.menu.customContainer;
15042            }
15043            if (options.detailsView &&
15044                (options.detailsView.location === "mapContainer" ||
15045                    options.detailsView.location === "near" ||
15046                    options.detailsView.location === "top")) {
15047                options.detailsView.location = "map";
15048            }
15049            if (!options.controls) {
15050                options.controls = {};
15051                options.controls.zoom =
15052                    options.zoom &&
15053                        options.zoom.on &&
15054                        (!options.zoom.buttons || options.zoom.buttons.location !== "hide");
15055                options.controls.location =
15056                    options.zoom && options.zoom.buttons && options.zoom.buttons.location !== "hide"
15057                        ? options.zoom.buttons.location
15058                        : "right";
15059            }
15060            if (options.colors && !options.colors.markers) {
15061                options.colors.markers = {
15062                    base: { opacity: 100, saturation: 100 },
15063                    hovered: { opacity: 100, saturation: 100 },
15064                    unhovered: { opacity: 100, saturation: 100 },
15065                    active: { opacity: 100, saturation: 100 },
15066                    inactive: { opacity: 100, saturation: 100 },
15067                };
15068            }
15069            if (options.tooltipsMode) {
15070                options.tooltips.mode = options.tooltipsMode;
15071                delete options.tooltipsMode;
15072            }
15073            if (options.popover) {
15074                options.popovers = options.popover;
15075                delete options.popover;
15076            }
15077        }
15078        init() {
15079            MapSVG.addInstance(this);
15080            if (this.options.source === "") {
15081                throw new Error("MapSVG: please provide SVG file source.");
15082            }
15083            this.disableAnimation();
15084            this.setEvents(this.options.events);
15085            this.events.trigger("beforeLoad");
15086            if (this.options.googleMaps.on ||
15087                (this.options.filters.on &&
15088                    this.options.filtersSchema.find((f) => f.type === "distance"))) {
15089                this.loadGoogleMapsAPI(() => {
15090                    return 1;
15091                }, () => {
15092                    return 1;
15093                });
15094            }
15095            this.containers.map.classList.add("mapsvg");
15096            this.setCss();
15097            if (this.options.colors && this.options.colors.background) {
15098                this.containers.map.style.background = this.options.colors.background;
15099            }
15100            this.setContainers(this.options.containers);
15101            this.setColors();
15102            this.addLoadingMessage();
15103            this.addLayer("markers");
15104            this.addLayer("labels");
15105            this.addLayer("bubbles");
15106            this.addLayer("popovers");
15107            this.addLayer("scrollpane");
15108            this.loadExtensions();
15109            $$A.ajax({ url: this.options.source + "?v=" + this.svgFileLastChanged })
15110                .fail((resp) => {
15111                this.svgLoadingFailed(resp);
15112            })
15113                .done((xmlData) => {
15114                this.renderSvgData(xmlData);
15115            });
15116            return this;
15117        }
15118        getContainer(name) {
15119            return this.containers[name];
15120        }
15121        renderSvgData(xmlData) {
15122            const svgTag = $$A(xmlData).find("svg");
15123            this.containers.svg = svgTag[0];
15124            if (svgTag.attr("width") && svgTag.attr("height")) {
15125                this.svgDefault.width = parseFloat(svgTag.attr("width").replace(/px/g, ""));
15126                this.svgDefault.height = parseFloat(svgTag.attr("height").replace(/px/g, ""));
15127                this.svgDefault.viewBox = svgTag.attr("viewBox")
15128                    ? new ViewBox(svgTag.attr("viewBox").split(" "))
15129                    : new ViewBox(0, 0, this.svgDefault.width, this.svgDefault.height);
15130            }
15131            else if (svgTag.attr("viewBox")) {
15132                this.svgDefault.viewBox = new ViewBox(svgTag.attr("viewBox").split(" "));
15133                this.svgDefault.width = this.svgDefault.viewBox.width;
15134                this.svgDefault.height = this.svgDefault.viewBox.height;
15135            }
15136            else {
15137                const msg = "MapSVG: width/height and viewBox are missing in the SVG file. Can't parse the file because of that.";
15138                if (this.editMode) {
15139                    alert(msg);
15140                }
15141                else {
15142                    console.error(msg);
15143                }
15144                return false;
15145            }
15146            this.geoViewBox = this.getGeoViewBoxFromSvgTag(this.containers.svg);
15147            if (this.options.viewBox && this.options.viewBox.length == 4) {
15148                this._viewBox = new ViewBox(this.options.viewBox);
15149            }
15150            else {
15151                this._viewBox = new ViewBox(this.svgDefault.viewBox);
15152            }
15153            svgTag.attr("preserveAspectRatio", "xMidYMid meet");
15154            svgTag.removeAttr("width");
15155            svgTag.removeAttr("height");
15156            $$A(this.containers.scrollpane).append(svgTag);
15157            this.setStrokes();
15158            this.reloadRegions();
15159            this.setSize(this.options.width, this.options.height, this.options.responsive);
15160            if (this.options.disableAll) {
15161                this.setDisableAll(true);
15162            }
15163            this.setViewBox(this._viewBox);
15164            this.converter = new Converter(this.containers.map, this.svgDefault.viewBox, this.viewBox);
15165            if (this.geoViewBox) {
15166                this.converter.setGeoViewBox(this.geoViewBox);
15167            }
15168            this.setResponsive(this.options.responsive);
15169            this.setScroll(this.options.scroll, true);
15170            this.setZoom(this.options.zoom);
15171            this.setControls(this.options.controls);
15172            this.setGoogleMaps();
15173            this.setTooltips(this.options.tooltips);
15174            this.setPopovers(this.options.popovers);
15175            if (this.options.cursor)
15176                this.setCursor(this.options.cursor);
15177            this.setTemplates(this.options.templates);
15178            this.loadExtensions();
15179            this.filtersSchema = new Schema({ fields: this.options.filtersSchema });
15180            this.objectsRepository.events.on("load", () => {
15181                this.showLoadingMessage();
15182            });
15183            this.objectsRepository.events.on("loaded", () => {
15184                this.setGlobalDistanceFilter();
15185                this.fitOnDataLoadDone = false;
15186                this.addLocations();
15187                this.fixMarkersWorldScreen();
15188                this.attachDataToRegions();
15189                this.loadDirectory();
15190                if (this.options.labelsMarkers.on) {
15191                    this.setLabelsMarkers();
15192                }
15193                if (this.options.templates.labelRegion.indexOf("{{objects") !== -1) {
15194                    this.setLabelsRegions();
15195                }
15196                if (this.options.filters.on &&
15197                    this.options.filters.source === "database" &&
15198                    this.controllers.filters &&
15199                    this.controllers.filters.hideFilters) {
15200                    this.controllers.filters.setFiltersCounter();
15201                }
15202                this.hideLoadingMessage();
15203                this.events.trigger("databaseLoaded");
15204                this.updateFiltersState();
15205                this.setChoropleth();
15206            });
15207            this.objectsRepository.events.on("schemaChanged", () => {
15208                this.objectsRepository.reload();
15209            });
15210            this.objectsRepository.events.on("updated", (obj) => {
15211                this.attachDataToRegions(obj);
15212                this.reloadRegionsFull();
15213            });
15214            this.objectsRepository.events.on("created", (obj) => {
15215                this.attachDataToRegions(obj);
15216                this.reloadRegionsFull();
15217            });
15218            this.objectsRepository.events.on("deleted", (id) => {
15219                this.attachDataToRegions();
15220                this.reloadRegionsFull();
15221            });
15222            this.regionsRepository.events.on("load", () => {
15223                this.showLoadingMessage();
15224            });
15225            this.regionsRepository.events.on("loaded", () => {
15226                this.hideLoadingMessage();
15227                this.reloadRegionsFull();
15228                if (this.options.filters.on &&
15229                    this.options.filters.source === "regions" &&
15230                    this.controllers.filters &&
15231                    this.controllers.filters.hideFilters) {
15232                    this.controllers.filters.setFiltersCounter();
15233                }
15234                this.events.trigger("regionsLoaded");
15235            });
15236            this.regionsRepository.events.on("updated", (regionData) => {
15237                this.reloadRegionsFull();
15238            });
15239            this.regionsRepository.events.on("created", (regionData) => {
15240                this.reloadRegionsFull();
15241            });
15242            this.regionsRepository.events.on("deleted", (regionData) => {
15243                this.reloadRegionsFull();
15244            });
15245            this.setMenu();
15246            this.setFilters();
15247            if (this.options.menu.filterout.field) {
15248                const f = {};
15249                f[this.options.menu.filterout.field] = this.options.menu.filterout.val;
15250                if (this.options.menu.source == "regions") ;
15251                else {
15252                    this.objectsRepository.query.setFilterOut(f);
15253                }
15254            }
15255            this.setEventHandlers();
15256            this.afterLoadBlockers--;
15257            if (!this.id) {
15258                this.finalizeMapLoading();
15259                return;
15260            }
15261            if (!this.options.data_regions) {
15262                this.regionsRepository.find().done((data) => {
15263                    this.afterLoadBlockers--;
15264                    this.finalizeMapLoading();
15265                });
15266            }
15267            else {
15268                this.regionsRepository.loadDataFromResponse(this.options.data_regions);
15269                this.afterLoadBlockers--;
15270            }
15271            if (!this.options.data_objects) {
15272                if (this.options.database.loadOnStart || this.editMode) {
15273                    this.objectsRepository.find().done((data) => {
15274                        this.afterLoadBlockers--;
15275                        this.finalizeMapLoading();
15276                    });
15277                }
15278                else {
15279                    this.afterLoadBlockers--;
15280                    this.finalizeMapLoading();
15281                }
15282            }
15283            else {
15284                if (this.editMode || this.options.database.loadOnStart) {
15285                    this.objectsRepository.loadDataFromResponse(this.options.data_objects);
15286                    this.afterLoadBlockers--;
15287                }
15288                else {
15289                    this.afterLoadBlockers--;
15290                }
15291                delete this.options.data_regions;
15292                delete this.options.data_objects;
15293                this.finalizeMapLoading();
15294            }
15295        }
15296        getGeoViewBoxFromSvgTag(svgTag) {
15297            const geo = $$A(svgTag).attr("mapsvg:geoViewBox") || $$A(svgTag).attr("mapsvg:geoviewbox");
15298            if (geo) {
15299                const geoParts = geo.split(" ").map((p) => parseFloat(p));
15300                if (geoParts.length == 4) {
15301                    this.mapIsGeo = true;
15302                    this.geoCoordinates = true;
15303                    const sw = new GeoPoint(geoParts[3], geoParts[0]);
15304                    const ne = new GeoPoint(geoParts[1], geoParts[2]);
15305                    return new GeoViewBox(sw, ne);
15306                }
15307            }
15308            else {
15309                return null;
15310            }
15311        }
15312        svgLoadingFailed(resp) {
15313            if (resp.status == 404) {
15314                let msg = "MapSVG: file not found - " +
15315                    this.options.source +
15316                    "\n\nIf you moved MapSVG from another server please read the following docs page: https://mapsvg.com/docs/installation/moving";
15317                if (this.editMode) {
15318                    msg +=
15319                        "\n\nIf you know the correct path for the SVG file, please write it and press OK:";
15320                    const oldSvgPath = this.options.source;
15321                    const userSvgPath = prompt(msg, oldSvgPath);
15322                    if (userSvgPath !== null) {
15323                        $$A.ajax({ url: userSvgPath + "?v=" + this.svgFileLastChanged })
15324                            .fail(function () {
15325                            location.reload();
15326                        })
15327                            .done((xmlData) => {
15328                            this.options.source = userSvgPath;
15329                            this.renderSvgData(xmlData);
15330                            const mapsRepo = new MapsRepository();
15331                            mapsRepo.update(this);
15332                        });
15333                    }
15334                    else {
15335                        location.reload();
15336                    }
15337                }
15338                else {
15339                    console.error(msg);
15340                }
15341            }
15342            else {
15343                const msg = "MapSVG: can't load SVG file for unknown reason. Please contact support: https://mapsvg.ticksy.com";
15344                if (this.editMode) {
15345                    alert(msg);
15346                }
15347                else {
15348                    console.error(msg);
15349                }
15350            }
15351        }
15352        addLoadingMessage() {
15353            this.containers.loading = document.createElement("div");
15354            this.containers.loading.className = "mapsvg-loading";
15355            const loadingTextBlock = document.createElement("div");
15356            loadingTextBlock.className = "mapsvg-loading-text";
15357            loadingTextBlock.innerHTML = this.options.loadingText;
15358            const spinner = document.createElement("div");
15359            spinner.className = "spinner-border spinner-border-sm";
15360            this.containers.loading.appendChild(spinner);
15361            this.containers.loading.appendChild(loadingTextBlock);
15362            this.containers.map.appendChild(this.containers.loading);
15363            if (this.options.googleMaps.on) {
15364                $$A(this.containers.map).addClass("mapsvg-google-map-loading");
15365            }
15366        }
15367        hideLoadingMessage() {
15368            $$A(this.containers.loading).hide();
15369        }
15370        showLoadingMessage() {
15371            $$A(this.containers.loading).show();
15372        }
15373        disableAnimation() {
15374            this.containers.map.classList.add("no-transitions");
15375        }
15376        enableAnimation() {
15377            $$A(this.containers.map).removeClass("no-transitions");
15378        }
15379        loadExtensions() {
15380            if (this.options.extension &&
15381                $$A().mapSvg.extensions &&
15382                $$A().mapSvg.extensions[_this.options.extension]) {
15383                const ext = $$A().mapSvg.extensions[_this.options.extension];
15384                ext && ext.common(this);
15385            }
15386        }
15387        finalizeMapLoading() {
15388            if (this.afterLoadBlockers > 0 || this.loaded) {
15389                return;
15390            }
15391            this.selectRegionByIdFromUrl();
15392            setTimeout(() => {
15393                this.movingItemsAdjustScreenPosition();
15394                this.adjustStrokes();
15395                setTimeout(() => {
15396                    this.hideLoadingMessage();
15397                    $$A(this.containers.loading).find(".mapsvg-loading-text").hide();
15398                    this.enableAnimation();
15399                }, 200);
15400            }, 100);
15401            this.loaded = true;
15402            this.events.trigger("afterLoad");
15403        }
15404        selectRegionByIdFromUrl() {
15405            const match = RegExp("[?&]mapsvg_select=([^&]*)").exec(window.location.search);
15406            if (match) {
15407                const select = decodeURIComponent(match[1].replace(/\+/g, " "));
15408                this.selectRegion(select);
15409            }
15410            if (window.location.hash) {
15411                const query = window.location.hash.replace("#/m/", "");
15412                const region = this.getRegion(query);
15413                if (region && this.options.actions.map.afterLoad.selectRegion) {
15414                    this.regionClickHandler(null, region);
15415                }
15416            }
15417        }
15418        createForm(options) {
15419            return new FormBuilder(options);
15420        }
15421        getApiUrl(path) {
15422            const server = new Server();
15423            return server.getUrl(path);
15424        }
15425        getConverter() {
15426            return this.converter;
15427        }
15428        setChoropleth(options) {
15429            const _this = this;
15430            options = options || _this.options.choropleth;
15431            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
15432            $$A.extend(true, _this.options, { choropleth: options });
15433            let needsRedraw = false;
15434            if (!_this.$gauge) {
15435                _this.$gauge = {};
15436                _this.$gauge.gradient = $$A("<td>&nbsp;</td>").addClass("mapsvg-gauge-gradient");
15437                _this.setGaugeGradientCSS();
15438                _this.$gauge.container = $$A("<div />").addClass("mapsvg-gauge").hide();
15439                _this.$gauge.table = $$A("<table />");
15440                const tr = $$A("<tr />");
15441                _this.$gauge.labelLow = $$A("<td>" + _this.options.choropleth.labels.low + "</td>");
15442                _this.$gauge.labelHigh = $$A("<td>" + _this.options.choropleth.labels.high + "</td>");
15443                tr.append(_this.$gauge.labelLow);
15444                tr.append(_this.$gauge.gradient);
15445                tr.append(_this.$gauge.labelHigh);
15446                _this.$gauge.table.append(tr);
15447                _this.$gauge.container.append(_this.$gauge.table);
15448                $$A(_this.containers.map).append(_this.$gauge.container);
15449            }
15450            if (!_this.options.choropleth.on && _this.$gauge.container.is(":visible")) {
15451                _this.$gauge.container.hide();
15452                needsRedraw = true;
15453            }
15454            else if (_this.options.choropleth.on && !_this.$gauge.container.is(":visible")) {
15455                _this.$gauge.container.show();
15456                needsRedraw = true;
15457                _this.regionsRepository.events.on("change", function () {
15458                    _this.redrawGauge();
15459                });
15460            }
15461            if (options.colors) {
15462                _this.options.choropleth.colors.lowRGB = tinycolor(_this.options.choropleth.colors.low).toRgb();
15463                _this.options.choropleth.colors.highRGB = tinycolor(_this.options.choropleth.colors.high).toRgb();
15464                _this.options.choropleth.colors.diffRGB = {
15465                    r: _this.options.choropleth.colors.highRGB.r -
15466                        _this.options.choropleth.colors.lowRGB.r,
15467                    g: _this.options.choropleth.colors.highRGB.g -
15468                        _this.options.choropleth.colors.lowRGB.g,
15469                    b: _this.options.choropleth.colors.highRGB.b -
15470                        _this.options.choropleth.colors.lowRGB.b,
15471                    a: _this.options.choropleth.colors.highRGB.a -
15472                        _this.options.choropleth.colors.lowRGB.a,
15473                };
15474                needsRedraw = true;
15475                _this.$gauge && _this.setGaugeGradientCSS();
15476            }
15477            if (options.labels) {
15478                _this.$gauge.labelLow.html(_this.options.choropleth.labels.low);
15479                _this.$gauge.labelHigh.html(_this.options.choropleth.labels.high);
15480            }
15481            needsRedraw && _this.redrawGauge();
15482        }
15483        redrawGauge() {
15484            const _this = this;
15485            _this.updateGaugeMinMax();
15486            _this.regionsRedrawColors();
15487        }
15488        updateGaugeMinMax() {
15489            const _this = this;
15490            _this.options.choropleth.min = 0;
15491            _this.options.choropleth.max = false;
15492            const values = [];
15493            _this.regions.forEach(function (r) {
15494                const gauge = r.data && r.data[_this.options.regionChoroplethField];
15495                gauge != undefined && values.push(gauge);
15496            });
15497            if (values.length > 0) {
15498                _this.options.choropleth.min = values.length == 1 ? 0 : Math.min.apply(null, values);
15499                _this.options.choropleth.max = Math.max.apply(null, values);
15500                _this.options.choropleth.maxAdjusted =
15501                    _this.options.choropleth.max - _this.options.choropleth.min;
15502            }
15503        }
15504        setGaugeGradientCSS() {
15505            const _this = this;
15506            _this.$gauge.gradient.css({
15507                background: "linear-gradient(to right," +
15508                    _this.options.choropleth.colors.low +
15509                    " 1%," +
15510                    _this.options.choropleth.colors.high +
15511                    " 100%)",
15512                filter: 'progid:DXImageTransform.Microsoft.gradient( startColorstr="' +
15513                    _this.options.choropleth.colors.low +
15514                    '", endColorstr="' +
15515                    _this.options.choropleth.colors.high +
15516                    '",GradientType=1 )',
15517            });
15518        }
15519        get $map() {
15520            return $$A(this.getContainer("map"));
15521        }
15522        get $svg() {
15523            return $$A(this.getContainer("svg"));
15524        }
15525        get $popover() {
15526            return $$A(this.getContainer("popover"));
15527        }
15528        get $details() {
15529            return $$A(this.getContainer("detailsView"));
15530        }
15531        get $directory() {
15532            return $$A(this.getContainer("directory"));
15533        }
15534        get database() {
15535            return this.objectsRepository;
15536        }
15537        get regionsDatabase() {
15538            return this.regionsRepository;
15539        }
15540    }
15541
15542    exports.MapSVGMap = MapSVGMap;
15543    exports.arrayIndexed = ArrayIndexed;
15544    exports.customObject = CustomObject;
15545    exports.formBuilder = FormBuilder;
15546    exports.geoPoint = GeoPoint;
15547    exports.globals = MapSVG;
15548    exports.location = Location;
15549    exports.map = MapSVGMap;
15550    exports.mapsRepository = MapsRepository;
15551    exports.mapsV2Repository = MapsV2Repository;
15552    exports.marker = Marker;
15553    exports.query = Query;
15554    exports.repository = Repository;
15555    exports.schema = Schema;
15556    exports.schemaRepository = SchemaRepository;
15557    exports.screenPoint = ScreenPoint;
15558    exports.server = Server;
15559    exports.svgPoint = SVGPoint;
15560
15561    Object.defineProperty(exports, '__esModule', { value: true });
15562
15563})));
15564//# 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.