PageSourceSearch

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

js capridgepartners.com collected 2026-10-07 18:12:58 UTC 629,579 bytes, 15,041 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            return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
315        };
316
317    Map.prototype.toArray = function () {
318        return Array.from(this, ([name, value]) => value);
319    };
320
321    MapSVG.ResizeSensor = class ResizeSensor {
322        constructor(element, callback) {
323            var _this = this;
324            _this.element = element;
325            _this.callback = callback;
326            var style = getComputedStyle(element);
327            var zIndex = parseInt(style.zIndex);
328            if (isNaN(zIndex)) {
329                zIndex = 0;
330            }
331            zIndex--;
332            _this.expand = document.createElement("div");
333            _this.expand.style.position = "absolute";
334            _this.expand.style.left = "0px";
335            _this.expand.style.top = "0px";
336            _this.expand.style.right = "0px";
337            _this.expand.style.bottom = "0px";
338            _this.expand.style.overflow = "hidden";
339            _this.expand.style.zIndex = zIndex.toString();
340            _this.expand.style.visibility = "hidden";
341            var expandChild = document.createElement("div");
342            expandChild.style.position = "absolute";
343            expandChild.style.left = "0px";
344            expandChild.style.top = "0px";
345            expandChild.style.width = "10000000px";
346            expandChild.style.height = "10000000px";
347            _this.expand.appendChild(expandChild);
348            _this.shrink = document.createElement("div");
349            _this.shrink.style.position = "absolute";
350            _this.shrink.style.left = "0px";
351            _this.shrink.style.top = "0px";
352            _this.shrink.style.right = "0px";
353            _this.shrink.style.bottom = "0px";
354            _this.shrink.style.overflow = "hidden";
355            _this.shrink.style.zIndex = zIndex.toString();
356            _this.shrink.style.visibility = "hidden";
357            var shrinkChild = document.createElement("div");
358            shrinkChild.style.position = "absolute";
359            shrinkChild.style.left = "0px";
360            shrinkChild.style.top = "0px";
361            shrinkChild.style.width = "200%";
362            shrinkChild.style.height = "200%";
363            _this.shrink.appendChild(shrinkChild);
364            _this.element.appendChild(_this.expand);
365            _this.element.appendChild(_this.shrink);
366            var size = element.getBoundingClientRect();
367            _this.currentWidth = size.width;
368            _this.currentHeight = size.height;
369            _this.setScroll();
370            _this.expand.addEventListener("scroll", function () {
371                _this.onScroll();
372            });
373            _this.shrink.addEventListener("scroll", function () {
374                _this.onScroll();
375            });
376        }
377        onScroll() {
378            var _this = this;
379            var size = _this.element.getBoundingClientRect();
380            var newWidth = size.width;
381            var newHeight = size.height;
382            if (newWidth != _this.currentWidth || newHeight != _this.currentHeight) {
383                _this.currentWidth = newWidth;
384                _this.currentHeight = newHeight;
385                _this.callback();
386            }
387            this.setScroll();
388        }
389        setScroll() {
390            this.expand.scrollLeft = 10000000;
391            this.expand.scrollTop = 10000000;
392            this.shrink.scrollLeft = 10000000;
393            this.shrink.scrollTop = 10000000;
394        }
395        destroy() {
396            this.expand.remove();
397            this.shrink.remove();
398        }
399    };
400
401    MapSVG.nonce = function () {
402        return mapsvg_runtime_vars.nonce;
403    };
404
405    /**
406     * Adds # hash at the beginning of HEX color value
407     * @param {String} color
408     * @returns {String}
409     * @private
410     */
411    MapSVG.fixColorHash = (color) => {
412        const hexColorNoHash = new RegExp(/^([0-9a-f]{3}|[0-9a-f]{6})$/i);
413        if (color && color.match(hexColorNoHash) !== null) {
414            color = "#" + color;
415        }
416        return color;
417    };
418
419    if (!Object.values) {
420        Object.values = function (object) {
421            return Object.keys(object).map(function (k) {
422                return object[k];
423            });
424        };
425    }
426
427    window.MapSVG = MapSVG;
428
429    const defRegionTemplate = "<div>\n" +
430        "  <p>This is the demo content of the <strong>Region %templateType%</strong>.</p>\n" +
431        '  <p>Click on the following link to edit the content of this window: <a href="#" class="mapsvg-template-link" data-template="%templateTypeSnake%Region">Menu > Templates > Region %templateType%</a>.</p>\n' +
432        '  <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' +
433        "</div>\n" +
434        "<hr />\n\n" +
435        "<!-- Region fields are available in this template -->\n" +
436        "<h5>{{#if title}} {{title}} {{else}} {{id}} {{/if}}</h5>\n" +
437        "<p>Status: {{status_text}}</p>\n\n" +
438        "<!-- Show all linked Database Objects: -->\n" +
439        "{{#each objects}}\n\n" +
440        "  <!-- DB Object are available inside of this block -->\n\n" +
441        "  <h5>{{title}}</h5>\n" +
442        "  <!-- When you need to render a field as HTML, use 3 curly braces instead of 2:-->\n" +
443        "  <p>{{{description}}}</p>\n" +
444        "  <p><em>{{location.address.formatted}}</em></p>\n\n" +
445        "  <!-- Show all images: -->\n" +
446        "  {{#each images}}\n" +
447        '    <!-- Image fields "thumbnail", "medium", "full" -->\n' +
448        "    <!-- are available in this block                -->\n" +
449        '    <img src="{{thumbnail}}" />\n' +
450        "  {{/each}}\n\n" +
451        "{{/each}}";
452    const defDBTemplate = "<div>\n" +
453        "  <p>This is the demo content of the <strong>DB Object %templateType%</strong>.</p>\n" +
454        '  <p>Click on the following link to edit the content of this window: <a href="#" class="mapsvg-template-link" data-template="%templateTypeSnake%Region">Menu > Templates > Region %templateType%</a>.</p>\n' +
455        '  <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' +
456        "</div>\n" +
457        "<hr />\n\n" +
458        "<!-- DB Object fields are available in this template. -->\n" +
459        "<h5>{{title}}</h5>\n" +
460        "<!-- When you need to render a fields as HTML, use 3 curly braces instead of 2:-->\n" +
461        "<p>{{{description}}}</p>\n" +
462        "<p><em>{{location.address.formatted}}</em></p>\n\n" +
463        "<!-- Show all images: -->\n" +
464        "{{#each images}}\n" +
465        '  <!-- Image fields "thumbnail", "medium", "full" -->\n' +
466        "  <!-- are available in this block                -->\n" +
467        '  <img src="{{thumbnail}}" />\n' +
468        "{{/each}}\n\n" +
469        "<!-- Show all linked Regions, comma-separated: -->\n" +
470        "<p> Regions: \n" +
471        "  {{#each regions}}\n" +
472        "    <!-- Region fields are available in this block -->\n" +
473        "    {{#if title}}\n" +
474        "      {{title}}\n" +
475        "    {{else}}\n" +
476        "      {{id}}\n" +
477        "    {{/if}}{{#unless @last}}, {{/unless}}\n" +
478        "  {{/each}}\n" +
479        "</p>";
480    const dirItemItemTemplate = "<!-- If Directory Source = Database: DB Object fields are available in this template -->\n" +
481        "<!-- If Directory Source = Regions: Region fields are available in this template -->\n" +
482        "{{title}}";
483    const DefaultOptions = {
484        source: "",
485        markerLastID: 0,
486        regionLastID: 0,
487        dataLastID: 1,
488        disableAll: false,
489        width: null,
490        height: null,
491        lockAspectRatio: false,
492        padding: { top: 0, left: 0, right: 0, bottom: 0 },
493        maxWidth: null,
494        maxHeight: null,
495        minWidth: null,
496        minHeight: null,
497        loadingText: "Loading map...",
498        colorsIgnore: false,
499        colors: {
500            baseDefault: "#000000",
501            background: "#eeeeee",
502            selected: 40,
503            hover: 20,
504            directory: "#fafafa",
505            detailsView: "",
506            status: {},
507            clusters: "",
508            clustersBorders: "",
509            clustersText: "",
510            clustersHover: "",
511            clustersHoverBorders: "",
512            clustersHoverText: "",
513            markers: {
514                base: { opacity: 100, saturation: 100 },
515                hovered: { opacity: 100, saturation: 100 },
516                unhovered: { opacity: 40, saturation: 100 },
517                active: { opacity: 100, saturation: 100 },
518                inactive: { opacity: 40, saturation: 100 },
519            },
520        },
521        regions: {},
522        clustering: { on: false },
523        viewBox: [],
524        cursor: "default",
525        manualRegions: false,
526        onClick: null,
527        mouseOver: null,
528        mouseOut: null,
529        menuOnClick: null,
530        beforeLoad: null,
531        afterLoad: null,
532        zoom: {
533            on: true,
534            limit: [0, 22],
535            delta: 2,
536            buttons: { on: true, location: "right" },
537            mousewheel: true,
538            fingers: true,
539            hideSvg: false,
540            hideSvgZoomLevel: 7,
541        },
542        scroll: { on: true, limit: false, background: false, spacebar: false },
543        responsive: true,
544        tooltips: { on: false, position: "bottom-right", template: "", maxWidth: "", minWidth: 100 },
545        popovers: {
546            on: false,
547            position: "top",
548            template: "",
549            centerOn: true,
550            width: 300,
551            maxWidth: 50,
552            maxHeight: 50,
553        },
554        multiSelect: false,
555        regionStatuses: {
556            "1": { label: "Enabled", value: "1", color: "", disabled: false },
557            "0": { label: "Disabled", value: "0", color: "", disabled: true },
558        },
559        events: {
560            afterLoad: "function(){\n" +
561                "  // var mapsvg = this;\n" +
562                "  // var regions = mapsvg.regions;\n" +
563                "  // var dbObjects = mapsvg.database.getLoaded();\n" +
564                "}",
565            beforeLoad: "function(){\n" +
566                "  // var mapsvg = this;\n" +
567                "  // var settings = mapsvg.options;\n" +
568                "  // console.log(settings);\n" +
569                "}",
570            databaseLoaded: "function (){\n" +
571                "  // var mapsvg = this;\n" +
572                "  // var dbObjects = mapsvg.database.getLoaded();\n" +
573                "}",
574            "click.region": "function (e, mapsvg){\n" +
575                "  // var region = this;\n" +
576                "  // console.log(region);\n" +
577                "}",
578            "mouseover.region": "function (e, mapsvg){\n" +
579                "  // var region = this;\n" +
580                "  // console.log(region);\n" +
581                "}",
582            "mouseout.region": "function (e, mapsvg){\n" +
583                "  // var region = this;\n" +
584                "  // console.log(region);\n" +
585                "}",
586            "click.marker": "function (e, mapsvg){\n" +
587                "  // var marker = this;\n" +
588                "  // console.log(marker);\n" +
589                "}",
590            "mouseover.marker": "function (e, mapsvg){\n" +
591                "  // var marker = this;\n" +
592                "  // console.log(marker);\n" +
593                "}",
594            "mouseout.marker": "function (e, mapsvg){\n" +
595                "  // var marker = this;\n" +
596                "  // console.log(marker);\n" +
597                "}",
598            "click.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
599            "mouseover.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
600            "mouseout.directoryItem": "function (e, regionOrObject, mapsvg){\n" + "  // var itemjQueryObject = this;\n" + "}",
601            "shown.popover": "function (mapsvg){\n" + "  // var popoverjQueryObject = this;\n" + "}",
602            "closed.popover": "function (mapsvg){\n" + "  // var popoverjQueryObject = this;\n" + "}",
603            "closed.detailsView": "function (mapsvg){\n" + "  // var detailsjQueryObject = this;\n" + "}",
604            "shown.detailsView": "function (mapsvg){\n" + "  // var detailsjQueryObject = this;\n" + "}",
605        },
606        css: "#mapsvg-map-%id% .mapsvg-tooltip {\n\n}\n" +
607            "#mapsvg-map-%id% .mapsvg-popover {\n\n}\n" +
608            "#mapsvg-map-%id% .mapsvg-details-container {\n\n}\n" +
609            "#mapsvg-map-%id% .mapsvg-directory-item {\n\n}\n" +
610            "#mapsvg-map-%id% .mapsvg-region-label {\n" +
611            "  /* background-color: rgba(255,255,255,.6); */\n" +
612            "  font-size: 11px;\n" +
613            "  padding: 3px 5px;\n" +
614            "  border-radius: 4px;\n" +
615            "}\n" +
616            "#mapsvg-map-%id% .mapsvg-marker-label {\n" +
617            "  padding: 3px 5px;\n" +
618            "  /*\n" +
619            "  border-radius: 4px;\n" +
620            "  background-color: white;\n" +
621            "  margin-top: -4px;\n" +
622            "  */\n}\n" +
623            "#mapsvg-map-%id% .mapsvg-filters-wrap {\n\n}\n" +
624            "\n\n\n\n\n\n",
625        templates: {
626            popoverRegion: defRegionTemplate
627                .replace(/%templateType%/g, "Popover")
628                .replace(/%templateTypeSnake%/g, "popover"),
629            popoverMarker: defDBTemplate
630                .replace(/%templateType%/g, "Popover")
631                .replace(/%templateTypeSnake%/g, "popover"),
632            tooltipRegion: "<!-- Region fields are available in this template -->\n{{id}} - {{title}}",
633            tooltipMarker: "<!-- DB Object fields are available in this template -->\n{{title}}",
634            directoryItem: dirItemItemTemplate,
635            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>',
636            detailsView: defDBTemplate
637                .replace(/%templateType%/g, "Details View")
638                .replace(/%templateTypeSnake%/g, "detailsView"),
639            detailsViewRegion: defRegionTemplate
640                .replace(/%templateType%/g, "Details View")
641                .replace(/%templateTypeSnake%/g, "detailsView"),
642            labelMarker: "<!-- DB Object fields are available in this template -->\n{{title}}",
643            labelRegion: "<!-- Region fields are available in this template -->\n{{title}}",
644            labelLocation: "You are here!",
645        },
646        choropleth: {
647            on: false,
648            source: "regions",
649            sourceFieldSelect: {
650                on: false,
651                variants: [],
652            },
653            bubbleMode: false,
654            bubbleSize: {
655                min: 20,
656                max: 40,
657            },
658            labels: { low: "low", high: "high" },
659            colors: { lowRGB: null, highRGB: null, low: "#550000", high: "#ee0000", noData: "#333333" },
660            min: 0,
661            max: 0,
662            coloring: {
663                mode: "gradient",
664                noData: {
665                    color: "#999999",
666                    description: "No data",
667                },
668                gradient: {
669                    colors: {
670                        lowRGB: null,
671                        highRGB: null,
672                        diffRGB: null,
673                        low: "#550000",
674                        high: "#ee0000",
675                    },
676                    labels: {
677                        low: "low",
678                        high: "high",
679                    },
680                    values: {
681                        min: null,
682                        max: null,
683                        maxAdjusted: null,
684                    },
685                },
686                palette: {
687                    outOfRange: {
688                        color: "#ececec",
689                        description: "Out of range",
690                    },
691                    colors: [
692                        {
693                            color: "#550000",
694                            valueFrom: 0,
695                            valueTo: 50,
696                            description: "",
697                        },
698                    ],
699                },
700                legend: {
701                    on: true,
702                    layout: "vertical",
703                    container: "bottom-left",
704                    title: "Choropleth map",
705                    text: "",
706                    description: "",
707                    width: "20%",
708                    height: "20%",
709                },
710            },
711        },
712        filters: {
713            on: true,
714            source: "database",
715            location: "header",
716            modalLocation: "map",
717            width: "100%",
718            hide: false,
719            showButtonText: "Filters",
720            clearButtonText: "Clear all",
721            clearButton: false,
722            searchButton: false,
723            searchButtonText: "Search",
724            padding: "",
725        },
726        menu: {
727            on: false,
728            hideOnMobile: true,
729            location: "leftSidebar",
730            locationMobile: "leftSidebar",
731            search: false,
732            containerId: "",
733            searchPlaceholder: "Search...",
734            searchFallback: false,
735            source: "database",
736            showFirst: "map",
737            showMapOnClick: true,
738            minHeight: "400",
739            sortBy: "id",
740            sortDirection: "desc",
741            categories: {
742                on: false,
743                groupBy: "",
744                hideEmpty: true,
745                collapse: true,
746                collapseOther: true,
747            },
748            clickActions: {
749                region: "default",
750                marker: "default",
751                directoryItem: {
752                    triggerClick: true,
753                    showPopover: false,
754                    showDetails: true,
755                },
756            },
757            detailsViewLocation: "overDirectory",
758            noResultsText: "No results found",
759            filterout: { field: "", cond: "=", val: "" },
760        },
761        database: {
762            pagination: {
763                on: true,
764                perpage: 30,
765                next: "Next",
766                prev: "Prev.",
767                showIn: "directory",
768            },
769            loadOnStart: true,
770            table: "",
771        },
772        actions: {
773            map: {
774                afterLoad: {
775                    selectRegion: false,
776                },
777            },
778            region: {
779                mouseover: {
780                    showTooltip: false,
781                },
782                click: {
783                    addIdToUrl: false,
784                    showDetails: true,
785                    showDetailsFor: "region",
786                    filterDirectory: false,
787                    loadObjects: false,
788                    showPopover: false,
789                    showPopoverFor: "region",
790                    goToLink: false,
791                    linkField: "Region.link",
792                },
793                touch: {
794                    showPopover: false,
795                },
796            },
797            marker: {
798                mouseover: {
799                    showTooltip: false,
800                },
801                click: {
802                    showDetails: true,
803                    showPopover: false,
804                    goToLink: false,
805                    linkField: "Object.link",
806                },
807                touch: {
808                    showPopover: false,
809                },
810            },
811            directoryItem: {
812                click: {
813                    showDetails: true,
814                    showPopover: false,
815                    goToLink: false,
816                    selectRegion: true,
817                    fireRegionOnClick: true,
818                    linkField: "Object.link",
819                },
820                hover: {
821                    centerOnMarker: false,
822                },
823            },
824        },
825        detailsView: {
826            location: "map",
827            containerId: "",
828            width: "100%",
829            mobileFullscreen: true,
830        },
831        mobileView: {
832            labelMap: "Map",
833            labelList: "List",
834            labelClose: "Close",
835        },
836        googleMaps: {
837            on: false,
838            apiKey: "",
839            loaded: false,
840            center: "auto",
841            type: "roadmap",
842            minZoom: 1,
843            style: "default",
844            styleJSON: [],
845        },
846        groups: [],
847        floors: [],
848        layersControl: {
849            on: false,
850            position: "top-left",
851            label: "Show on map",
852            expanded: true,
853            maxHeight: "100%",
854        },
855        floorsControl: {
856            on: false,
857            position: "top-left",
858            label: "Floors",
859            expanded: false,
860            maxHeight: "100%",
861        },
862        containers: {
863            leftSidebar: { on: false, width: "250px" },
864            rightSidebar: { on: false, width: "250px" },
865            header: { on: true, height: "auto" },
866            footer: { on: false, height: "auto" },
867        },
868        labelsMarkers: { on: false },
869        labelsRegions: { on: false },
870        svgFileVersion: 1,
871        fitMarkers: false,
872        fitMarkersOnStart: false,
873        fitSingleMarkerZoom: 20,
874        controls: {
875            location: "right",
876            zoom: true,
877            zoomReset: false,
878            userLocation: false,
879            previousMap: false,
880        },
881        previousMapsIds: [],
882    };
883
884    // TinyColor v1.4.1
885    // https://github.com/bgrins/TinyColor
886    // Brian Grinstead, MIT License
887
888    //(function(Math) {
889
890    var trimLeft = /^\s+/,
891        trimRight = /\s+$/,
892        tinyCounter = 0,
893        mathRound = Math.round,
894        mathMin = Math.min,
895        mathMax = Math.max,
896        mathRandom = Math.random;
897
898    function tinycolor(color, opts) {
899        color = color ? color : "";
900        opts = opts || {};
901
902        // If input is already a tinycolor, return itself
903        if (color instanceof tinycolor) {
904            return color;
905        }
906        // If we are called as a function, call using new instead
907        if (!(this instanceof tinycolor)) {
908            return new tinycolor(color, opts);
909        }
910
911        var rgb = inputToRGB(color);
912        (this._originalInput = color),
913            (this._r = rgb.r),
914            (this._g = rgb.g),
915            (this._b = rgb.b),
916            (this._a = rgb.a),
917            (this._roundA = mathRound(100 * this._a) / 100),
918            (this._format = opts.format || rgb.format);
919        this._gradientType = opts.gradientType;
920
921        // Don't let the range of [0,255] come back in [0,1].
922        // Potentially lose a little bit of precision here, but will fix issues where
923        // .5 gets interpreted as half of the total, instead of half of 1
924        // If it was supposed to be 128, this was already taken care of b
vendor: 11,167 bytes, lines 924-1242
924y `inputToRgb`
925        if (this._r < 1) {
926            this._r = mathRound(this._r);
927        }
928        if (this._g < 1) {
929            this._g = mathRound(this._g);
930        }
931        if (this._b < 1) {
932            this._b = mathRound(this._b);
933        }
934
935        this._ok = rgb.ok;
936        this._tc_id = tinyCounter++;
937    }
938
939    tinycolor.prototype = {
940        isDark: function () {
941            return this.getBrightness() < 128;
942        },
943        isLight: function () {
944            return !this.isDark();
945        },
946        isValid: function () {
947            return this._ok;
948        },
949        getOriginalInput: function () {
950            return this._originalInput;
951        },
952        getFormat: function () {
953            return this._format;
954        },
955        getAlpha: function () {
956            return this._a;
957        },
958        getBrightness: function () {
959            //http://www.w3.org/TR/AERT#color-contrast
960            var rgb = this.toRgb();
961            return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
962        },
963        getLuminance: function () {
964            //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
965            var rgb = this.toRgb();
966            var RsRGB, GsRGB, BsRGB, R, G, B;
967            RsRGB = rgb.r / 255;
968            GsRGB = rgb.g / 255;
969            BsRGB = rgb.b / 255;
970
971            if (RsRGB <= 0.03928) {
972                R = RsRGB / 12.92;
973            } else {
974                R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);
975            }
976            if (GsRGB <= 0.03928) {
977                G = GsRGB / 12.92;
978            } else {
979                G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);
980            }
981            if (BsRGB <= 0.03928) {
982                B = BsRGB / 12.92;
983            } else {
984                B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);
985            }
986            return 0.2126 * R + 0.7152 * G + 0.0722 * B;
987        },
988        setAlpha: function (value) {
989            this._a = boundAlpha(value);
990            this._roundA = mathRound(100 * this._a) / 100;
991            return this;
992        },
993        toHsv: function () {
994            var hsv = rgbToHsv(this._r, this._g, this._b);
995            return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
996        },
997        toHsvString: function () {
998            var hsv = rgbToHsv(this._r, this._g, this._b);
999            var h = mathRound(hsv.h * 360),
1000                s = mathRound(hsv.s * 100),
1001                v = mathRound(hsv.v * 100);
1002            return this._a == 1
1003                ? "hsv(" + h + ", " + s + "%, " + v + "%)"
1004                : "hsva(" + h + ", " + s + "%, " + v + "%, " + this._roundA + ")";
1005        },
1006        toHsl: function () {
1007            var hsl = rgbToHsl(this._r, this._g, this._b);
1008            return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
1009        },
1010        toHslString: function () {
1011            var hsl = rgbToHsl(this._r, this._g, this._b);
1012            var h = mathRound(hsl.h * 360),
1013                s = mathRound(hsl.s * 100),
1014                l = mathRound(hsl.l * 100);
1015            return this._a == 1
1016                ? "hsl(" + h + ", " + s + "%, " + l + "%)"
1017                : "hsla(" + h + ", " + s + "%, " + l + "%, " + this._roundA + ")";
1018        },
1019        toHex: function (allow3Char) {
1020            return rgbToHex(this._r, this._g, this._b, allow3Char);
1021        },
1022        toHexString: function (allow3Char) {
1023            return "#" + this.toHex(allow3Char);
1024        },
1025        toHex8: function (allow4Char) {
1026            return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
1027        },
1028        toHex8String: function (allow4Char) {
1029            return "#" + this.toHex8(allow4Char);
1030        },
1031        toRgb: function () {
1032            return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
1033        },
1034        toRgbString: function () {
1035            return this._a == 1
1036                ? "rgb(" +
1037                      mathRound(this._r) +
1038                      ", " +
1039                      mathRound(this._g) +
1040                      ", " +
1041                      mathRound(this._b) +
1042                      ")"
1043                : "rgba(" +
1044                      mathRound(this._r) +
1045                      ", " +
1046                      mathRound(this._g) +
1047                      ", " +
1048                      mathRound(this._b) +
1049                      ", " +
1050                      this._roundA +
1051                      ")";
1052        },
1053        toPercentageRgb: function () {
1054            return {
1055                r: mathRound(bound01(this._r, 255) * 100) + "%",
1056                g: mathRound(bound01(this._g, 255) * 100) + "%",
1057                b: mathRound(bound01(this._b, 255) * 100) + "%",
1058                a: this._a,
1059            };
1060        },
1061        toPercentageRgbString: function () {
1062            return this._a == 1
1063                ? "rgb(" +
1064                      mathRound(bound01(this._r, 255) * 100) +
1065                      "%, " +
1066                      mathRound(bound01(this._g, 255) * 100) +
1067                      "%, " +
1068                      mathRound(bound01(this._b, 255) * 100) +
1069                      "%)"
1070                : "rgba(" +
1071                      mathRound(bound01(this._r, 255) * 100) +
1072                      "%, " +
1073                      mathRound(bound01(this._g, 255) * 100) +
1074                      "%, " +
1075                      mathRound(bound01(this._b, 255) * 100) +
1076                      "%, " +
1077                      this._roundA +
1078                      ")";
1079        },
1080        toName: function () {
1081            if (this._a === 0) {
1082                return "transparent";
1083            }
1084
1085            if (this._a < 1) {
1086                return false;
1087            }
1088
1089            return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
1090        },
1091        toFilter: function (secondColor) {
1092            var hex8String = "#" + rgbaToArgbHex(this._r, this._g, this._b, this._a);
1093            var secondHex8String = hex8String;
1094            var gradientType = this._gradientType ? "GradientType = 1, " : "";
1095
1096            if (secondColor) {
1097                var s = tinycolor(secondColor);
1098                secondHex8String = "#" + rgbaToArgbHex(s._r, s._g, s._b, s._a);
1099            }
1100
1101            return (
1102                "progid:DXImageTransform.Microsoft.gradient(" +
1103                gradientType +
1104                "startColorstr=" +
1105                hex8String +
1106                ",endColorstr=" +
1107                secondHex8String +
1108                ")"
1109            );
1110        },
1111        toString: function (format) {
1112            var formatSet = !!format;
1113            format = format || this._format;
1114
1115            var formattedString = false;
1116            var hasAlpha = this._a < 1 && this._a >= 0;
1117            var needsAlphaFormat =
1118                !formatSet &&
1119                hasAlpha &&
1120                (format === "hex" ||
1121                    format === "hex6" ||
1122                    format === "hex3" ||
1123                    format === "hex4" ||
1124                    format === "hex8" ||
1125                    format === "name");
1126
1127            if (needsAlphaFormat) {
1128                // Special case for "transparent", all other non-alpha formats
1129                // will return rgba when there is transparency.
1130                if (format === "name" && this._a === 0) {
1131                    return this.toName();
1132                }
1133                return this.toRgbString();
1134            }
1135            if (format === "rgb") {
1136                formattedString = this.toRgbString();
1137            }
1138            if (format === "prgb") {
1139                formattedString = this.toPercentageRgbString();
1140            }
1141            if (format === "hex" || format === "hex6") {
1142                formattedString = this.toHexString();
1143            }
1144            if (format === "hex3") {
1145                formattedString = this.toHexString(true);
1146            }
1147            if (format === "hex4") {
1148                formattedString = this.toHex8String(true);
1149            }
1150            if (format === "hex8") {
1151                formattedString = this.toHex8String();
1152            }
1153            if (format === "name") {
1154                formattedString = this.toName();
1155            }
1156            if (format === "hsl") {
1157                formattedString = this.toHslString();
1158            }
1159            if (format === "hsv") {
1160                formattedString = this.toHsvString();
1161            }
1162
1163            return formattedString || this.toHexString();
1164        },
1165        clone: function () {
1166            return tinycolor(this.toString());
1167        },
1168
1169        _applyModification: function (fn, args) {
1170            var color = fn.apply(null, [this].concat([].slice.call(args)));
1171            this._r = color._r;
1172            this._g = color._g;
1173            this._b = color._b;
1174            this.setAlpha(color._a);
1175            return this;
1176        },
1177        lighten: function () {
1178            return this._applyModification(lighten, arguments);
1179        },
1180        brighten: function () {
1181            return this._applyModification(brighten, arguments);
1182        },
1183        darken: function () {
1184            return this._applyModification(darken, arguments);
1185        },
1186        desaturate: function () {
1187            return this._applyModification(desaturate, arguments);
1188        },
1189        saturate: function () {
1190            return this._applyModification(saturate, arguments);
1191        },
1192        greyscale: function () {
1193            return this._applyModification(greyscale, arguments);
1194        },
1195        spin: function () {
1196            return this._applyModification(spin, arguments);
1197        },
1198
1199        _applyCombination: function (fn, args) {
1200            return fn.apply(null, [this].concat([].slice.call(args)));
1201        },
1202        analogous: function () {
1203            return this._applyCombination(analogous, arguments);
1204        },
1205        complement: function () {
1206            return this._applyCombination(complement, arguments);
1207        },
1208        monochromatic: function () {
1209            return this._applyCombination(monochromatic, arguments);
1210        },
1211        splitcomplement: function () {
1212            return this._applyCombination(splitcomplement, arguments);
1213        },
1214        triad: function () {
1215            return this._applyCombination(triad, arguments);
1216        },
1217        tetrad: function () {
1218            return this._applyCombination(tetrad, arguments);
1219        },
1220    };
1221
1222    // If input is an object, force 1 into "1.0" to handle ratios properly
1223    // String input requires "1.0" as input, so 1 will be treated as 1
1224    tinycolor.fromRatio = function (color, opts) {
1225        if (typeof color == "object") {
1226            var newColor = {};
1227            for (var i in color) {
1228                if (color.hasOwnProperty(i)) {
1229                    if (i === "a") {
1230                        newColor[i] = color[i];
1231                    } else {
1232                        newColor[i] = convertToPercentage(color[i]);
1233                    }
1234                }
1235            }
1236            color = newColor;
1237        }
1238
1239        return tinycolor(color, opts);
1240    };
1241
1242    // Given a string or object, convert that input to RGB
vendor: 8,705 bytes, lines 1243-1523
1243    // Possible string inputs:
1244    //
1245    //     "red"
1246    //     "#f00" or "f00"
1247    //     "#ff0000" or "ff0000"
1248    //     "#ff000000" or "ff000000"
1249    //     "rgb 255 0 0" or "rgb (255, 0, 0)"
1250    //     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
1251    //     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
1252    //     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
1253    //     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
1254    //     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
1255    //     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
1256    //
1257    function inputToRGB(color) {
1258        var rgb = { r: 0, g: 0, b: 0 };
1259        var a = 1;
1260        var s = null;
1261        var v = null;
1262        var l = null;
1263        var ok = false;
1264        var format = false;
1265
1266        if (typeof color == "string") {
1267            color = stringInputToObject(color);
1268        }
1269
1270        if (typeof color == "object") {
1271            if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
1272                rgb = rgbToRgb(color.r, color.g, color.b);
1273                ok = true;
1274                format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
1275            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
1276                s = convertToPercentage(color.s);
1277                v = convertToPercentage(color.v);
1278                rgb = hsvToRgb(color.h, s, v);
1279                ok = true;
1280                format = "hsv";
1281            } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
1282                s = convertToPercentage(color.s);
1283                l = convertToPercentage(color.l);
1284                rgb = hslToRgb(color.h, s, l);
1285                ok = true;
1286                format = "hsl";
1287            }
1288
1289            if (color.hasOwnProperty("a")) {
1290                a = color.a;
1291            }
1292        }
1293
1294        a = boundAlpha(a);
1295
1296        return {
1297            ok: ok,
1298            format: color.format || format,
1299            r: mathMin(255, mathMax(rgb.r, 0)),
1300            g: mathMin(255, mathMax(rgb.g, 0)),
1301            b: mathMin(255, mathMax(rgb.b, 0)),
1302            a: a,
1303        };
1304    }
1305
1306    // Conversion Functions
1307    // --------------------
1308
1309    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
1310    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
1311
1312    // `rgbToRgb`
1313    // Handle bounds / percentage checking to conform to CSS color spec
1314    // <http://www.w3.org/TR/css3-color/>
1315    // *Assumes:* r, g, b in [0, 255] or [0, 1]
1316    // *Returns:* { r, g, b } in [0, 255]
1317    function rgbToRgb(r, g, b) {
1318        return {
1319            r: bound01(r, 255) * 255,
1320            g: bound01(g, 255) * 255,
1321            b: bound01(b, 255) * 255,
1322        };
1323    }
1324
1325    // `rgbToHsl`
1326    // Converts an RGB color value to HSL.
1327    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
1328    // *Returns:* { h, s, l } in [0,1]
1329    function rgbToHsl(r, g, b) {
1330        r = bound01(r, 255);
1331        g = bound01(g, 255);
1332        b = bound01(b, 255);
1333
1334        var max = mathMax(r, g, b),
1335            min = mathMin(r, g, b);
1336        var h,
1337            s,
1338            l = (max + min) / 2;
1339
1340        if (max == min) {
1341            h = s = 0; // achromatic
1342        } else {
1343            var d = max - min;
1344            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1345            switch (max) {
1346                case r:
1347                    h = (g - b) / d + (g < b ? 6 : 0);
1348                    break;
1349                case g:
1350                    h = (b - r) / d + 2;
1351                    break;
1352                case b:
1353                    h = (r - g) / d + 4;
1354                    break;
1355            }
1356
1357            h /= 6;
1358        }
1359
1360        return { h: h, s: s, l: l };
1361    }
1362
1363    // `hslToRgb`
1364    // Converts an HSL color value to RGB.
1365    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
1366    // *Returns:* { r, g, b } in the set [0, 255]
1367    function hslToRgb(h, s, l) {
1368        var r, g, b;
1369
1370        h = bound01(h, 360);
1371        s = bound01(s, 100);
1372        l = bound01(l, 100);
1373
1374        function hue2rgb(p, q, t) {
1375            if (t < 0) t += 1;
1376            if (t > 1) t -= 1;
1377            if (t < 1 / 6) return p + (q - p) * 6 * t;
1378            if (t < 1 / 2) return q;
1379            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
1380            return p;
1381        }
1382
1383        if (s === 0) {
1384            r = g = b = l; // achromatic
1385        } else {
1386            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1387            var p = 2 * l - q;
1388            r = hue2rgb(p, q, h + 1 / 3);
1389            g = hue2rgb(p, q, h);
1390            b = hue2rgb(p, q, h - 1 / 3);
1391        }
1392
1393        return { r: r * 255, g: g * 255, b: b * 255 };
1394    }
1395
1396    // `rgbToHsv`
1397    // Converts an RGB color value to HSV
1398    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
1399    // *Returns:* { h, s, v } in [0,1]
1400    function rgbToHsv(r, g, b) {
1401        r = bound01(r, 255);
1402        g = bound01(g, 255);
1403        b = bound01(b, 255);
1404
1405        var max = mathMax(r, g, b),
1406            min = mathMin(r, g, b);
1407        var h,
1408            s,
1409            v = max;
1410
1411        var d = max - min;
1412        s = max === 0 ? 0 : d / max;
1413
1414        if (max == min) {
1415            h = 0; // achromatic
1416        } else {
1417            switch (max) {
1418                case r:
1419                    h = (g - b) / d + (g < b ? 6 : 0);
1420                    break;
1421                case g:
1422                    h = (b - r) / d + 2;
1423                    break;
1424                case b:
1425                    h = (r - g) / d + 4;
1426                    break;
1427            }
1428            h /= 6;
1429        }
1430        return { h: h, s: s, v: v };
1431    }
1432
1433    // `hsvToRgb`
1434    // Converts an HSV color value to RGB.
1435    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
1436    // *Returns:* { r, g, b } in the set [0, 255]
1437    function hsvToRgb(h, s, v) {
1438        h = bound01(h, 360) * 6;
1439        s = bound01(s, 100);
1440        v = bound01(v, 100);
1441
1442        var i = Math.floor(h),
1443            f = h - i,
1444            p = v * (1 - s),
1445            q = v * (1 - f * s),
1446            t = v * (1 - (1 - f) * s),
1447            mod = i % 6,
1448            r = [v, q, p, p, t, v][mod],
1449            g = [t, v, v, q, p, p][mod],
1450            b = [p, p, t, v, v, q][mod];
1451
1452        return { r: r * 255, g: g * 255, b: b * 255 };
1453    }
1454
1455    // `rgbToHex`
1456    // Converts an RGB color to hex
1457    // Assumes r, g, and b are contained in the set [0, 255]
1458    // Returns a 3 or 6 character hex
1459    function rgbToHex(r, g, b, allow3Char) {
1460        var hex = [
1461            pad2(mathRound(r).toString(16)),
1462            pad2(mathRound(g).toString(16)),
1463            pad2(mathRound(b).toString(16)),
1464        ];
1465
1466        // Return a 3 character hex if possible
1467        if (
1468            allow3Char &&
1469            hex[0].charAt(0) == hex[0].charAt(1) &&
1470            hex[1].charAt(0) == hex[1].charAt(1) &&
1471            hex[2].charAt(0) == hex[2].charAt(1)
1472        ) {
1473            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1474        }
1475
1476        return hex.join("");
1477    }
1478
1479    // `rgbaToHex`
1480    // Converts an RGBA color plus alpha transparency to hex
1481    // Assumes r, g, b are contained in the set [0, 255] and
1482    // a in [0, 1]. Returns a 4 or 8 character rgba hex
1483    function rgbaToHex(r, g, b, a, allow4Char) {
1484        var hex = [
1485            pad2(mathRound(r).toString(16)),
1486            pad2(mathRound(g).toString(16)),
1487            pad2(mathRound(b).toString(16)),
1488            pad2(convertDecimalToHex(a)),
1489        ];
1490
1491        // Return a 4 character hex if possible
1492        if (
1493            allow4Char &&
1494            hex[0].charAt(0) == hex[0].charAt(1) &&
1495            hex[1].charAt(0) == hex[1].charAt(1) &&
1496            hex[2].charAt(0) == hex[2].charAt(1) &&
1497            hex[3].charAt(0) == hex[3].charAt(1)
1498        ) {
1499            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
1500        }
1501
1502        return hex.join("");
1503    }
1504
1505    // `rgbaToArgbHex`
1506    // Converts an RGBA color to an ARGB Hex8 string
1507    // Rarely used, but required for "toFilter()"
1508    function rgbaToArgbHex(r, g, b, a) {
1509        var hex = [
1510            pad2(convertDecimalToHex(a)),
1511            pad2(mathRound(r).toString(16)),
1512            pad2(mathRound(g).toString(16)),
1513            pad2(mathRound(b).toString(16)),
1514        ];
1515
1516        return hex.join("");
1517    }
1518
1519    // `equals`
1520    // Can be called with any tinycolor input
1521    tinycolor.equals = function (color1, color2) {
1522        if (!color1 || !color2) {
1523            return false;
vendor: 4,315 bytes, lines 1524-1661
1524        }
1525        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
1526    };
1527
1528    tinycolor.random = function () {
1529        return tinycolor.fromRatio({
1530            r: mathRandom(),
1531            g: mathRandom(),
1532            b: mathRandom(),
1533        });
1534    };
1535
1536    // Modification Functions
1537    // ----------------------
1538    // Thanks to less.js for some of the basics here
1539    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
1540
1541    function desaturate(color, amount) {
1542        amount = amount === 0 ? 0 : amount || 10;
1543        var hsl = tinycolor(color).toHsl();
1544        hsl.s -= amount / 100;
1545        hsl.s = clamp01(hsl.s);
1546        return tinycolor(hsl);
1547    }
1548
1549    function saturate(color, amount) {
1550        amount = amount === 0 ? 0 : amount || 10;
1551        var hsl = tinycolor(color).toHsl();
1552        hsl.s += amount / 100;
1553        hsl.s = clamp01(hsl.s);
1554        return tinycolor(hsl);
1555    }
1556
1557    function greyscale(color) {
1558        return tinycolor(color).desaturate(100);
1559    }
1560
1561    function lighten(color, amount) {
1562        amount = amount === 0 ? 0 : amount || 10;
1563        var hsl = tinycolor(color).toHsl();
1564        hsl.l += amount / 100;
1565        hsl.l = clamp01(hsl.l);
1566        return tinycolor(hsl);
1567    }
1568
1569    function brighten(color, amount) {
1570        amount = amount === 0 ? 0 : amount || 10;
1571        var rgb = tinycolor(color).toRgb();
1572        rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * -(amount / 100))));
1573        rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * -(amount / 100))));
1574        rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * -(amount / 100))));
1575        return tinycolor(rgb);
1576    }
1577
1578    function darken(color, amount) {
1579        amount = amount === 0 ? 0 : amount || 10;
1580        var hsl = tinycolor(color).toHsl();
1581        hsl.l -= amount / 100;
1582        hsl.l = clamp01(hsl.l);
1583        return tinycolor(hsl);
1584    }
1585
1586    // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
1587    // Values outside of this range will be wrapped into this range.
1588    function spin(color, amount) {
1589        var hsl = tinycolor(color).toHsl();
1590        var hue = (hsl.h + amount) % 360;
1591        hsl.h = hue < 0 ? 360 + hue : hue;
1592        return tinycolor(hsl);
1593    }
1594
1595    // Combination Functions
1596    // ---------------------
1597    // Thanks to jQuery xColor for some of the ideas behind these
1598    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
1599
1600    function complement(color) {
1601        var hsl = tinycolor(color).toHsl();
1602        hsl.h = (hsl.h + 180) % 360;
1603        return tinycolor(hsl);
1604    }
1605
1606    function triad(color) {
1607        var hsl = tinycolor(color).toHsl();
1608        var h = hsl.h;
1609        return [
1610            tinycolor(color),
1611            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1612            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }),
1613        ];
1614    }
1615
1616    function tetrad(color) {
1617        var hsl = tinycolor(color).toHsl();
1618        var h = hsl.h;
1619        return [
1620            tinycolor(color),
1621            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1622            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1623            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }),
1624        ];
1625    }
1626
1627    function splitcomplement(color) {
1628        var hsl = tinycolor(color).toHsl();
1629        var h = hsl.h;
1630        return [
1631            tinycolor(color),
1632            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }),
1633            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l }),
1634        ];
1635    }
1636
1637    function analogous(color, results, slices) {
1638        results = results || 6;
1639        slices = slices || 30;
1640
1641        var hsl = tinycolor(color).toHsl();
1642        var part = 360 / slices;
1643        var ret = [tinycolor(color)];
1644
1645        for (hsl.h = (hsl.h - ((part * results) >> 1) + 720) % 360; --results; ) {
1646            hsl.h = (hsl.h + part) % 360;
1647            ret.push(tinycolor(hsl));
1648        }
1649        return ret;
1650    }
1651
1652    function monochromatic(color, results) {
1653        results = results || 6;
1654        var hsv = tinycolor(color).toHsv();
1655        var h = hsv.h,
1656            s = hsv.s,
1657            v = hsv.v;
1658        var ret = [];
1659        var modification = 1 / results;
1660
1661        while (results--) {
vendor: 4,157 bytes, lines 1662-1770
1662            ret.push(tinycolor({ h: h, s: s, v: v }));
1663            v = (v + modification) % 1;
1664        }
1665
1666        return ret;
1667    }
1668
1669    // Utility Functions
1670    // ---------------------
1671
1672    tinycolor.mix = function (color1, color2, amount) {
1673        amount = amount === 0 ? 0 : amount || 50;
1674
1675        var rgb1 = tinycolor(color1).toRgb();
1676        var rgb2 = tinycolor(color2).toRgb();
1677
1678        var p = amount / 100;
1679
1680        var rgba = {
1681            r: (rgb2.r - rgb1.r) * p + rgb1.r,
1682            g: (rgb2.g - rgb1.g) * p + rgb1.g,
1683            b: (rgb2.b - rgb1.b) * p + rgb1.b,
1684            a: (rgb2.a - rgb1.a) * p + rgb1.a,
1685        };
1686
1687        return tinycolor(rgba);
1688    };
1689
1690    // Readability Functions
1691    // ---------------------
1692    // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
1693
1694    // `contrast`
1695    // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
1696    tinycolor.readability = function (color1, color2) {
1697        var c1 = tinycolor(color1);
1698        var c2 = tinycolor(color2);
1699        return (
1700            (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) /
1701            (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05)
1702        );
1703    };
1704
1705    // `isReadable`
1706    // Ensure that foreground and background color combinations meet WCAG2 guidelines.
1707    // The third argument is an optional Object.
1708    //      the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
1709    //      the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
1710    // If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
1711
1712    // *Example*
1713    //    tinycolor.isReadable("#000", "#111") => false
1714    //    tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
1715    tinycolor.isReadable = function (color1, color2, wcag2) {
1716        var readability = tinycolor.readability(color1, color2);
1717        var wcag2Parms, out;
1718
1719        out = false;
1720
1721        wcag2Parms = validateWCAG2Parms(wcag2);
1722        switch (wcag2Parms.level + wcag2Parms.size) {
1723            case "AAsmall":
1724            case "AAAlarge":
1725                out = readability >= 4.5;
1726                break;
1727            case "AAlarge":
1728                out = readability >= 3;
1729                break;
1730            case "AAAsmall":
1731                out = readability >= 7;
1732                break;
1733        }
1734        return out;
1735    };
1736
1737    // `mostReadable`
1738    // Given a base color and a list of possible foreground or background
1739    // colors for that base, returns the most readable color.
1740    // Optionally returns Black or White if the most readable color is unreadable.
1741    // *Example*
1742    //    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
1743    //    tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString();  // "#ffffff"
1744    //    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
1745    //    tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
1746    tinycolor.mostReadable = function (baseColor, colorList, args) {
1747        var bestColor = null;
1748        var bestScore = 0;
1749        var readability;
1750        var includeFallbackColors, level, size;
1751        args = args || {};
1752        includeFallbackColors = args.includeFallbackColors;
1753        level = args.level;
1754        size = args.size;
1755
1756        for (var i = 0; i < colorList.length; i++) {
1757            readability = tinycolor.readability(baseColor, colorList[i]);
1758            if (readability > bestScore) {
1759                bestScore = readability;
1760                bestColor = tinycolor(colorList[i]);
1761            }
1762        }
1763
1764        if (
1765            tinycolor.isReadable(baseColor, bestColor, { level: level, size: size }) ||
1766            !includeFallbackColors
1767        ) {
1768            return bestColor;
1769        } else {
1770            args.includeFallbackColors = false;
vendor: 12,185 bytes, lines 1771-2144
1771            return tinycolor.mostReadable(baseColor, ["#fff", "#000"], args);
1772        }
1773    };
1774
1775    // Big List of Colors
1776    // ------------------
1777    // <http://www.w3.org/TR/css3-color/#svg-color>
1778    var names = (tinycolor.names = {
1779        aliceblue: "f0f8ff",
1780        antiquewhite: "faebd7",
1781        aqua: "0ff",
1782        aquamarine: "7fffd4",
1783        azure: "f0ffff",
1784        beige: "f5f5dc",
1785        bisque: "ffe4c4",
1786        black: "000",
1787        blanchedalmond: "ffebcd",
1788        blue: "00f",
1789        blueviolet: "8a2be2",
1790        brown: "a52a2a",
1791        burlywood: "deb887",
1792        burntsienna: "ea7e5d",
1793        cadetblue: "5f9ea0",
1794        chartreuse: "7fff00",
1795        chocolate: "d2691e",
1796        coral: "ff7f50",
1797        cornflowerblue: "6495ed",
1798        cornsilk: "fff8dc",
1799        crimson: "dc143c",
1800        cyan: "0ff",
1801        darkblue: "00008b",
1802        darkcyan: "008b8b",
1803        darkgoldenrod: "b8860b",
1804        darkgray: "a9a9a9",
1805        darkgreen: "006400",
1806        darkgrey: "a9a9a9",
1807        darkkhaki: "bdb76b",
1808        darkmagenta: "8b008b",
1809        darkolivegreen: "556b2f",
1810        darkorange: "ff8c00",
1811        darkorchid: "9932cc",
1812        darkred: "8b0000",
1813        darksalmon: "e9967a",
1814        darkseagreen: "8fbc8f",
1815        darkslateblue: "483d8b",
1816        darkslategray: "2f4f4f",
1817        darkslategrey: "2f4f4f",
1818        darkturquoise: "00ced1",
1819        darkviolet: "9400d3",
1820        deeppink: "ff1493",
1821        deepskyblue: "00bfff",
1822        dimgray: "696969",
1823        dimgrey: "696969",
1824        dodgerblue: "1e90ff",
1825        firebrick: "b22222",
1826        floralwhite: "fffaf0",
1827        forestgreen: "228b22",
1828        fuchsia: "f0f",
1829        gainsboro: "dcdcdc",
1830        ghostwhite: "f8f8ff",
1831        gold: "ffd700",
1832        goldenrod: "daa520",
1833        gray: "808080",
1834        green: "008000",
1835        greenyellow: "adff2f",
1836        grey: "808080",
1837        honeydew: "f0fff0",
1838        hotpink: "ff69b4",
1839        indianred: "cd5c5c",
1840        indigo: "4b0082",
1841        ivory: "fffff0",
1842        khaki: "f0e68c",
1843        lavender: "e6e6fa",
1844        lavenderblush: "fff0f5",
1845        lawngreen: "7cfc00",
1846        lemonchiffon: "fffacd",
1847        lightblue: "add8e6",
1848        lightcoral: "f08080",
1849        lightcyan: "e0ffff",
1850        lightgoldenrodyellow: "fafad2",
1851        lightgray: "d3d3d3",
1852        lightgreen: "90ee90",
1853        lightgrey: "d3d3d3",
1854        lightpink: "ffb6c1",
1855        lightsalmon: "ffa07a",
1856        lightseagreen: "20b2aa",
1857        lightskyblue: "87cefa",
1858        lightslategray: "789",
1859        lightslategrey: "789",
1860        lightsteelblue: "b0c4de",
1861        lightyellow: "ffffe0",
1862        lime: "0f0",
1863        limegreen: "32cd32",
1864        linen: "faf0e6",
1865        magenta: "f0f",
1866        maroon: "800000",
1867        mediumaquamarine: "66cdaa",
1868        mediumblue: "0000cd",
1869        mediumorchid: "ba55d3",
1870        mediumpurple: "9370db",
1871        mediumseagreen: "3cb371",
1872        mediumslateblue: "7b68ee",
1873        mediumspringgreen: "00fa9a",
1874        mediumturquoise: "48d1cc",
1875        mediumvioletred: "c71585",
1876        midnightblue: "191970",
1877        mintcream: "f5fffa",
1878        mistyrose: "ffe4e1",
1879        moccasin: "ffe4b5",
1880        navajowhite: "ffdead",
1881        navy: "000080",
1882        oldlace: "fdf5e6",
1883        olive: "808000",
1884        olivedrab: "6b8e23",
1885        orange: "ffa500",
1886        orangered: "ff4500",
1887        orchid: "da70d6",
1888        palegoldenrod: "eee8aa",
1889        palegreen: "98fb98",
1890        paleturquoise: "afeeee",
1891        palevioletred: "db7093",
1892        papayawhip: "ffefd5",
1893        peachpuff: "ffdab9",
1894        peru: "cd853f",
1895        pink: "ffc0cb",
1896        plum: "dda0dd",
1897        powderblue: "b0e0e6",
1898        purple: "800080",
1899        rebeccapurple: "663399",
1900        red: "f00",
1901        rosybrown: "bc8f8f",
1902        royalblue: "4169e1",
1903        saddlebrown: "8b4513",
1904        salmon: "fa8072",
1905        sandybrown: "f4a460",
1906        seagreen: "2e8b57",
1907        seashell: "fff5ee",
1908        sienna: "a0522d",
1909        silver: "c0c0c0",
1910        skyblue: "87ceeb",
1911        slateblue: "6a5acd",
1912        slategray: "708090",
1913        slategrey: "708090",
1914        snow: "fffafa",
1915        springgreen: "00ff7f",
1916        steelblue: "4682b4",
1917        tan: "d2b48c",
1918        teal: "008080",
1919        thistle: "d8bfd8",
1920        tomato: "ff6347",
1921        turquoise: "40e0d0",
1922        violet: "ee82ee",
1923        wheat: "f5deb3",
1924        white: "fff",
1925        whitesmoke: "f5f5f5",
1926        yellow: "ff0",
1927        yellowgreen: "9acd32",
1928    });
1929
1930    // Make it easy to access colors via `hexNames[hex]`
1931    var hexNames = (tinycolor.hexNames = flip(names));
1932
1933    // Utilities
1934    // ---------
1935
1936    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
1937    function flip(o) {
1938        var flipped = {};
1939        for (var i in o) {
1940            if (o.hasOwnProperty(i)) {
1941                flipped[o[i]] = i;
1942            }
1943        }
1944        return flipped;
1945    }
1946
1947    // Return a valid alpha value [0,1] with all invalid values being set to 1
1948    function boundAlpha(a) {
1949        a = parseFloat(a);
1950
1951        if (isNaN(a) || a < 0 || a > 1) {
1952            a = 1;
1953        }
1954
1955        return a;
1956    }
1957
1958    // Take input from [0, n] and return it as [0, 1]
1959    function bound01(n, max) {
1960        if (isOnePointZero(n)) {
1961            n = "100%";
1962        }
1963
1964        var processPercent = isPercentage(n);
1965        n = mathMin(max, mathMax(0, parseFloat(n)));
1966
1967        // Automatically convert percentage into number
1968        if (processPercent) {
1969            n = parseInt(n * max, 10) / 100;
1970        }
1971
1972        // Handle floating point rounding errors
1973        if (Math.abs(n - max) < 0.000001) {
1974            return 1;
1975        }
1976
1977        // Convert into [0, 1] range if it isn't already
1978        return (n % max) / parseFloat(max);
1979    }
1980
1981    // Force a number between 0 and 1
1982    function clamp01(val) {
1983        return mathMin(1, mathMax(0, val));
1984    }
1985
1986    // Parse a base-16 hex value into a base-10 integer
1987    function parseIntFromHex(val) {
1988        return parseInt(val, 16);
1989    }
1990
1991    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
1992    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
1993    function isOnePointZero(n) {
1994        return typeof n == "string" && n.indexOf(".") != -1 && parseFloat(n) === 1;
1995    }
1996
1997    // Check to see if string passed in is a percentage
1998    function isPercentage(n) {
1999        return typeof n === "string" && n.indexOf("%") != -1;
2000    }
2001
2002    // Force a hex value to have 2 characters
2003    function pad2(c) {
2004        return c.length == 1 ? "0" + c : "" + c;
2005    }
2006
2007    // Replace a decimal with it's percentage value
2008    function convertToPercentage(n) {
2009        if (n <= 1) {
2010            n = n * 100 + "%";
2011        }
2012
2013        return n;
2014    }
2015
2016    // Converts a decimal to a hex value
2017    function convertDecimalToHex(d) {
2018        return Math.round(parseFloat(d) * 255).toString(16);
2019    }
2020    // Converts a hex value to a decimal
2021    function convertHexToDecimal(h) {
2022        return parseIntFromHex(h) / 255;
2023    }
2024
2025    var matchers = (function () {
2026        // <http://www.w3.org/TR/css3-values/#integers>
2027        var CSS_INTEGER = "[-\\+]?\\d+%?";
2028
2029        // <http://www.w3.org/TR/css3-values/#number-value>
2030        var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
2031
2032        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
2033        var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
2034
2035        // Actual matching.
2036        // Parentheses and commas are optional, but not required.
2037        // Whitespace can take the place of commas or opening paren
2038        var PERMISSIVE_MATCH3 =
2039            "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
2040        var PERMISSIVE_MATCH4 =
2041            "[\\s|\\(]+(" +
2042            CSS_UNIT +
2043            ")[,|\\s]+(" +
2044            CSS_UNIT +
2045            ")[,|\\s]+(" +
2046            CSS_UNIT +
2047            ")[,|\\s]+(" +
2048            CSS_UNIT +
2049            ")\\s*\\)?";
2050
2051        return {
2052            CSS_UNIT: new RegExp(CSS_UNIT),
2053            rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
2054            rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
2055            hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
2056            hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
2057            hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
2058            hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
2059            hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2060            hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2061            hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
2062            hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
2063        };
2064    })();
2065
2066    // `isValidCSSUnit`
2067    // Take in a single string / number and check to see if it looks like a CSS unit
2068    // (see `matchers` above for definition).
2069    function isValidCSSUnit(color) {
2070        return !!matchers.CSS_UNIT.exec(color);
2071    }
2072
2073    // `stringInputToObject`
2074    // Permissive string parsing.  Take in a number of formats, and output an object
2075    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
2076    function stringInputToObject(color) {
2077        color = color.replace(trimLeft, "").replace(trimRight, "").toLowerCase();
2078        var named = false;
2079        if (names[color]) {
2080            color = names[color];
2081            named = true;
2082        } else if (color == "transparent") {
2083            return { r: 0, g: 0, b: 0, a: 0, format: "name" };
2084        }
2085
2086        // Try to match string input using regular expressions.
2087        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
2088        // Just return an object and let the conversion functions handle that.
2089        // This way the result will be the same whether the tinycolor is initialized with string or object.
2090        var match;
2091        if ((match = matchers.rgb.exec(color))) {
2092            return { r: match[1], g: match[2], b: match[3] };
2093        }
2094        if ((match = matchers.rgba.exec(color))) {
2095            return { r: match[1], g: match[2], b: match[3], a: match[4] };
2096        }
2097        if ((match = matchers.hsl.exec(color))) {
2098            return { h: match[1], s: match[2], l: match[3] };
2099        }
2100        if ((match = matchers.hsla.exec(color))) {
2101            return { h: match[1], s: match[2], l: match[3], a: match[4] };
2102        }
2103        if ((match = matchers.hsv.exec(color))) {
2104            return { h: match[1], s: match[2], v: match[3] };
2105        }
2106        if ((match = matchers.hsva.exec(color))) {
2107            return { h: match[1], s: match[2], v: match[3], a: match[4] };
2108        }
2109        if ((match = matchers.hex8.exec(color))) {
2110            return {
2111                r: parseIntFromHex(match[1]),
2112                g: parseIntFromHex(match[2]),
2113                b: parseIntFromHex(match[3]),
2114                a: convertHexToDecimal(match[4]),
2115                format: named ? "name" : "hex8",
2116            };
2117        }
2118        if ((match = matchers.hex6.exec(color))) {
2119            return {
2120                r: parseIntFromHex(match[1]),
2121                g: parseIntFromHex(match[2]),
2122                b: parseIntFromHex(match[3]),
2123                format: named ? "name" : "hex",
2124            };
2125        }
2126        if ((match = matchers.hex4.exec(color))) {
2127            return {
2128                r: parseIntFromHex(match[1] + "" + match[1]),
2129                g: parseIntFromHex(match[2] + "" + match[2]),
2130                b: parseIntFromHex(match[3] + "" + match[3]),
2131                a: convertHexToDecimal(match[4] + "" + match[4]),
2132                format: named ? "name" : "hex8",
2133            };
2134        }
2135        if ((match = matchers.hex3.exec(color))) {
2136            return {
2137                r: parseIntFromHex(match[1] + "" + match[1]),
2138                g: parseIntFromHex(match[2] + "" + match[2]),
2139                b: parseIntFromHex(match[3] + "" + match[3]),
2140                format: named ? "name" : "hex",
2141            };
2142        }
2143
2144        return false;
2145    }
2146
2147    function validateWCAG2Parms(parms) {
2148        // return valid WCAG2 parms for isReadable.
2149        // If input parms are invalid, return {"level":"AA", "size":"small"}
2150        var level, size;
2151        parms = parms || { level: "AA", size: "small" };
2152        level = (parms.level || "AA").toUpperCase();
2153        size = (parms.size || "small").toLowerCase();
2154        if (level !== "AA" && level !== "AAA") {
2155            level = "AA";
2156        }
2157        if (size !== "small" && size !== "large") {
2158            size = "small";
2159        }
2160        return { level: level, size: size };
2161    }
2162
2163    const $$1 = jQuery;
2164    class Server {
2165        constructor() {
2166            this.apiUrl = "/wp-json/mapsvg/v1/";
2167        }
2168        getUrl(path) {
2169            return this.apiUrl + path;
2170        }
2171        get(path, data) {
2172            return $$1.ajax({
2173                url: this.apiUrl + path,
2174                type: "GET",
2175                data: data,
2176                beforeSend: function (xhr) {
2177                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2178                },
2179            });
2180        }
2181        post(path, data) {
2182            const ajaxParams = {
2183                url: this.apiUrl + path,
2184                type: "POST",
2185                data: data,
2186                beforeSend: function (xhr) {
2187                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2188                }
2189            };
2190            if (data instanceof FormData) {
2191                ajaxParams["processData"] = false;
2192                ajaxParams["contentType"] = false;
2193            }
2194            return $$1.ajax(ajaxParams);
2195        }
2196        put(path, data) {
2197            const ajaxParams = {
2198                url: this.apiUrl + path,
2199                type: "PUT",
2200                data: data,
2201                beforeSend: function (xhr) {
2202                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2203                }
2204            };
2205            if (data instanceof FormData) {
2206                ajaxParams["processData"] = false;
2207                ajaxParams["contentType"] = false;
2208            }
2209            return $$1.ajax(ajaxParams);
2210        }
2211        delete(path, data) {
2212            return $$1.ajax({
2213                url: this.apiUrl + path,
2214                type: "DELETE",
2215                data: data,
2216                beforeSend: function (xhr) {
2217                    xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2218                },
2219            });
2220        }
2221        ajax(path, data) {
2222            data.url = this.getUrl(path);
2223            data.beforeSend = function (xhr) {
2224                xhr.setRequestHeader("X-WP-Nonce", MapSVG.nonce());
2225            };
2226            return $$1.ajax(data);
2227        }
2228    }
2229
2230    class Events {
2231        constructor(context) {
2232            this.events = {};
2233            this.context = context;
2234        }
2235        on(event, callbackOrObjectType, callback) {
2236            if (!this.events[event])
2237                this.events[event] = [];
2238            let callbackFunction;
2239            if (typeof callbackOrObjectType === "string") {
2240                callbackFunction = callback;
2241            }
2242            else {
2243                callbackFunction = callbackOrObjectType;
2244            }
2245            let duplicatedEvent = false;
2246            this.events[event].forEach(function (existingCallback) {
2247                if (existingCallback.toString() === callbackFunction.toString()) {
2248                    duplicatedEvent = true;
2249                }
2250            });
2251            if (duplicatedEvent === false) {
2252                this.events[event].push(callbackFunction);
2253            }
2254            return this;
2255        }
2256        off(event, callback) {
2257            const _this = this;
2258            if (this.events[event] && this.events[event].length) {
2259                this.events[event].forEach(function (_callback, index) {
2260                    if (typeof callback === "undefined") {
2261                        _this.events[event].splice(index, 1);
2262                    }
2263                    else if (_callback === callback) {
2264                        _this.events[event].splice(index, 1);
2265                    }
2266                });
2267            }
2268            return this;
2269        }
2270        trigger(event, thisArg, args) {
2271            if (this.events[event] && this.events[event].length)
2272                this.events[event].forEach((callback) => {
2273                    try {
2274                        callback && callback.apply(thisArg || this.context, args || [this.context]);
2275                    }
2276                    catch (err) {
2277                        console.error(err);
2278                    }
2279                });
2280            return this;
2281        }
2282    }
2283
2284    class ArrayIndexed extends Array {
2285        constructor(indexKey, items, options) {
2286            if (items) {
2287                super(...items);
2288            }
2289            else {
2290                super();
2291            }
2292            this.key = indexKey;
2293            this.dict = {};
2294            this.nextId = 1;
2295            if (options) {
2296                this.options = options;
2297            }
2298            else {
2299                this.options = { autoId: false, unique: false };
2300            }
2301            if (this.length > 0) {
2302                let i = 0;
2303                const _this = this;
2304                if (this.options.autoId) {
2305                    let maxId = 0;
2306                    let missingIds = false;
2307                    this.forEach(function (item) {
2308                        if (item[_this.key] != null) {
2309                            if (item[_this.key] > maxId) {
2310                                maxId = item[_this.key];
2311                            }
2312                        }
2313                        else {
2314                            missingIds = true;
2315                        }
2316                    });
2317                    this.nextId = ++maxId;
2318                    if (missingIds) {
2319                        this.forEach(function (item) {
2320                            if (item[_this.key] == null) {
2321                                item[_this.key] = _this.nextId;
2322                                _this.nextId++;
2323                            }
2324                        });
2325                    }
2326                }
2327                this.forEach(function (item) {
2328                    _this.dict[item[_this.key]] = i;
2329                    i++;
2330                });
2331            }
2332        }
2333        push(item) {
2334            const length = super.push(item);
2335            if (this.options.autoId === true) {
2336                item[this.key] = this.nextId;
2337                this.nextId++;
2338            }
2339            this.dict[item[this.key]] = length - 1;
2340            return length;
2341        }
2342        pop() {
2343            const item = this[this.length - 1];
2344            const id = item[this.key];
2345            const length = super.pop();
2346            delete this.dict[id];
2347            this.reindex();
2348            return super.pop();
2349        }
2350        update(data) {
2351            if (data[this.key] != null) {
2352                const obj = this.get(data[this.key]);
2353                for (const i in data) {
2354                    obj[i] = data[i];
2355                }
2356                return obj;
2357            }
2358            return false;
2359        }
2360        get(id) {
2361            return this.findById(id);
2362        }
2363        findById(id) {
2364            return this[this.dict[id]];
2365        }
2366        deleteById(id) {
2367            const index = this.dict[id];
2368            if (typeof index !== "undefined") {
2369                delete this.dict[id];
2370                this.splice(index, 1);
2371            }
2372        }
2373        delete(id) {
2374            this.deleteById(id);
2375        }
2376        clear() {
2377            this.length = 0;
2378            this.reindex();
2379        }
2380        reindex() {
2381            const _this = this;
2382            this.dict = {};
2383            this.forEach(function (item, index) {
2384                _this.dict[item[_this.key]] = index;
2385            });
2386        }
2387        sort(compareFn) {
2388            super.sort(compareFn);
2389            this.reindex();
2390            return this;
2391        }
2392        splice(start, deleteCount) {
2393            const res = super.splice(start, deleteCount);
2394            this.reindex();
2395            return res;
2396        }
2397    }
2398
2399    class SchemaField {
2400        constructor(field) {
2401            const booleans = ["visible", "searchable", "readonly", "protected"];
2402            for (const key in field) {
2403                this[key] = field[key];
2404            }
2405            booleans.forEach((paramName) => {
2406                if (typeof this[paramName] !== "undefined") {
2407                    this[paramName] = MapSVG.parseBoolean(this[paramName]);
2408                }
2409                else {
2410                    this[paramName] = false;
2411                }
2412            });
2413            if (typeof this.options !== "undefined") {
2414                if (!(this.options instanceof ArrayIndexed)) {
2415                    this.options = new ArrayIndexed("value", this.options);
2416                }
2417            }
2418        }
2419    }
2420
2421    class Schema {
2422        constructor(options) {
2423            this.fields = new ArrayIndexed("name");
2424            this.build(options);
2425            this.lastChangeTime = Date.now();
2426            this.events = new Events(this);
2427        }
2428        build(options) {
2429            const allowedParams = ["id", "title", "type", "name", "fields"];
2430            allowedParams.forEach((paramName) => {
2431                const setter = "set" + MapSVG.ucfirst(paramName);
2432                if (typeof options[paramName] !== "undefined" && typeof this[setter] == "function") {
2433                    this[setter](options[paramName]);
2434                }
2435            });
2436        }
2437        update(options) {
2438            this.build(options);
2439        }
2440        setId(id) {
2441            this.id = id;
2442        }
2443        setTitle(title) {
2444            this.title = title;
2445        }
2446        setName(name) {
2447            this.name = name;
2448        }
2449        loaded() {
2450            return this.fields.length !== 0;
2451        }
2452        setFields(fields) {
2453            if (fields) {
2454                this.fields.clear();
2455                fields.forEach((fieldParams) => {
2456                    this.fields.push(new SchemaField(fieldParams));
2457                });
2458            }
2459        }
2460        getFields() {
2461            return this.fields;
2462        }
2463        getFieldsAsArray() {
2464            return this.fields;
2465        }
2466        getFieldNames() {
2467            return this.fields.map((f) => f.name);
2468        }
2469        getField(field) {
2470            return this.fields.findById(field);
2471        }
2472        getFieldByType(type) {
2473            let f = null;
2474            this.fields.forEach(function (field) {
2475                if (field.type === type)
2476                    f = field;
2477            });
2478            return f;
2479        }
2480        getColumns(filters) {
2481            filters = filters || {};
2482            const columns = this.fields;
2483            const needfilters = Object.keys(filters).length !== 0;
2484            let results = [];
2485            if (needfilters) {
2486                let filterpass;
2487                columns.forEach(function (obj) {
2488                    filterpass = true;
2489                    for (const param in filters) {
2490                        filterpass = obj[param] == filters[param];
2491                    }
2492                    filterpass && results.push(obj);
2493                });
2494            }
2495            else {
2496                results = columns;
2497            }
2498            return results;
2499        }
2500        getData() {
2501            const data = {
2502                id: this.id,
2503                title: this.title,
2504                name: this.name,
2505                fields: this.fields,
2506                type: this.type,
2507            };
2508            return data;
2509        }
2510    }
2511
2512    class Query {
2513        constructor(options) {
2514            this.filters = {};
2515            this.filterout = {};
2516            this.page = 1;
2517            if (options) {
2518                for (const i in options) {
2519                    if (typeof options[i] !== "undefined") {
2520                        this[i] = options[i];
2521                    }
2522                }
2523            }
2524        }
2525        setFields(fields) {
2526            const _this = this;
2527            for (const key in fields) {
2528                if (key == "filters") {
2529                    _this.setFilters(fields[key]);
2530                }
2531                else {
2532                    _this[key] = fields[key];
2533                }
2534            }
2535        }
2536        update(query) {
2537            for (const i in query) {
2538                if (typeof query[i] !== "undefined") {
2539                    if (i === "filters") {
2540                        this.setFilters(query[i]);
2541                    }
2542                    else {
2543                        this[i] = query[i];
2544                    }
2545                }
2546            }
2547        }
2548        get() {
2549            return {
2550                search: this.search,
2551                searchField: this.searchField,
2552                searchFallback: this.searchFallback,
2553                filters: this.filters,
2554                filterout: this.filterout,
2555                page: this.page,
2556                sort: this.sort,
2557                perpage: this.perpage,
2558                lastpage: this.lastpage,
2559            };
2560        }
2561        clearFilters() {
2562            this.resetFilters();
2563        }
2564        setFilters(fields) {
2565            const _this = this;
2566            for (const key in fields) {
2567                if (fields[key] === null || fields[key] === "" || fields[key] === undefined) {
2568                    if (_this.filters[key]) {
2569                        delete _this.filters[key];
2570                    }
2571                }
2572                else {
2573                    _this.filters[key] = fields[key];
2574                }
2575            }
2576        }
2577        setSearch(search) {
2578            this.search = search;
2579        }
2580        setFilterOut(fields) {
2581            this.filterout = fields;
2582        }
2583        resetFilters(fields) {
2584            this.filters = {};
2585            this.setSearch("");
2586        }
2587        setFilterField(field, value) {
2588            this.filters[field] = value;
2589        }
2590        hasFilters() {
2591            return Object.keys(this.filters).length > 0;
2592        }
2593        removeFilter(fieldName) {
2594            this.filters[fieldName] = null;
2595            delete this.filters[fieldName];
2596        }
2597        requestSchema(requestSchema) {
2598            this.withSchema = requestSchema ? requestSchema : true;
2599        }
2600    }
2601
2602    class LocationAddress {
2603        constructor(fields) {
2604            for (const i in fields) {
2605                this[i] = fields[i];
2606            }
2607        }
2608        getData() {
2609            const copy = {};
2610            [
2611                "route",
2612                "address_formatted",
2613                "administrative_area_level_1",
2614                "administrative_area_level_1_short",
2615                "administrative_area_level_2",
2616                "administrative_area_level_2_short",
2617                "country",
2618                "country_short",
2619                "postal_code",
2620            ].forEach((field) => {
2621                if (this[field]) {
2622                    copy[field] = this[field];
2623                }
2624            });
2625            return copy;
2626        }
2627        get state() {
2628            return this.country_short === "US" ? this.administrative_area_level_1 : null;
2629        }
2630        get state_short() {
2631            return this.country_short === "US" ? this.administrative_area_level_1_short : null;
2632        }
2633        get county() {
2634            return this.country_short === "US" ? this.administrative_area_level_2 : null;
2635        }
2636        get zip() {
2637            return this.postal_code;
2638        }
2639    }
2640
2641    class ScreenPoint {
2642        constructor(x, y) {
2643            this.x = x;
2644            this.y = y;
2645        }
2646    }
2647    class SVGPoint {
2648        constructor(x, y) {
2649            let _x, _y;
2650            if (typeof x === "object") {
2651                if (x.x && x.y) {
2652                    _x = parseFloat(x.x + "");
2653                    _y = parseFloat(x.y + "");
2654                }
2655                else {
2656                    console.error("MapSVG: incorrect format of {x, y} object for SVGPoint.");
2657                    _x = 0;
2658                    _y = 0;
2659                }
2660            }
2661            else {
2662                _x = parseFloat(x + "");
2663                _y = parseFloat(y + "");
2664            }
2665            this.x = _x;
2666            this.y = _y;
2667        }
2668    }
2669    class GeoPoint {
2670        constructor(lat, lng) {
2671            let _lat, _lng;
2672            if (typeof lat === "object") {
2673                if (lat.lat && lat.lng) {
2674                    _lat = parseFloat(lat.lat + "");
2675                    _lng = parseFloat(lat.lng + "");
2676                }
2677                else {
2678                    console.error("MapSVG: incorrect format of {lat, lng} object for GeoPoint.");
2679                    _lat = 0;
2680                    _lng = 0;
2681                }
2682            }
2683            else {
2684                _lat = parseFloat(lat + "");
2685                _lng = parseFloat(lng + "");
2686            }
2687            this.lat = _lat;
2688            this.lng = _lng;
2689        }
2690    }
2691    class Location {
2692        constructor(options) {
2693            this.update(options);
2694        }
2695        update(options) {
2696            if (options.img) {
2697                this.setImage(options.img);
2698            }
2699            if (options.address) {
2700                this.setAddress(options.address);
2701            }
2702            if (options.svgPoint) {
2703                this.setSvgPoint(options.svgPoint);
2704            }
2705            if (options.geoPoint) {
2706                this.setGeoPoint(options.geoPoint);
2707            }
2708        }
2709        setImage(imgUrl) {
2710            if (typeof imgUrl !== "string") {
2711                return;
2712            }
2713            let src = imgUrl.split("/").pop();
2714            if (imgUrl.indexOf("uploads") !== -1) {
2715                src = "uploads/" + src;
2716            }
2717            this.img = src;
2718            this.imagePath = this.getImageUrl();
2719            if (this.marker && this.marker.src !== this.imagePath) {
2720                this.marker.setImage(this.imagePath);
2721            }
2722        }
2723        getImageUrl() {
2724            if (this.img && this.img.indexOf("uploads/") === 0) {
2725                return MapSVG.urls.uploads + "markers/" + this.img.replace("uploads/", "");
2726            }
2727            else {
2728                return MapSVG.urls.root + "markers/" + (this.img || "_pin_default.png");
2729            }
2730        }
2731        setAddress(address) {
2732            this.address = new LocationAddress(address);
2733        }
2734        setSvgPoint(svgPoint) {
2735            this.svgPoint = svgPoint instanceof SVGPoint ? svgPoint : new SVGPoint(svgPoint);
2736            if (this.marker) {
2737                this.marker.setSvgPointFromLocation();
2738            }
2739        }
2740        setGeoPoint(geoPoint) {
2741            this.geoPoint = geoPoint instanceof GeoPoint ? geoPoint : new GeoPoint(geoPoint);
2742            if (this.marker) {
2743                this.marker.setSvgPointFromLocation();
2744            }
2745        }
2746        getMarkerImageUrl() {
2747            if (this.img && this.img.indexOf("uploads/") === 0) {
2748                return MapSVG.urls.uploads + "markers/" + this.img.replace("uploads/", "");
2749            }
2750            else {
2751                return MapSVG.urls.root + "markers/" + (this.img || "_pin_default.png");
2752            }
2753        }
2754        getData() {
2755            const data = {
2756                img: this.img,
2757                imagePath: this.imagePath,
2758                address: this.address,
2759            };
2760            if (this.geoPoint) {
2761                data.geoPoint = { lat: this.geoPoint.lat, lng: this.geoPoint.lng };
2762            }
2763            if (this.svgPoint) {
2764                data.svgPoint = { x: this.svgPoint.x, y: this.svgPoint.y };
2765            }
2766            return data;
2767        }
2768    }
2769
2770    class CustomObject {
2771        constructor(params, schema) {
2772            this.initialLoad = true;
2773            this.schema = schema;
2774            this.fields = schema.getFieldNames();
2775            this.dirtyFields = [];
2776            this.regions = [];
2777            this._regions = {};
2778            if (params.id !== undefined) {
2779                this.id = params.id;
2780            }
2781            this.initialLoad = true;
2782            this.build(params);
2783            this.initialLoad = false;
2784            if (this.id) {
2785                this.clearDirtyFields();
2786            }
2787        }
2788        build(params) {
2789            for (const fieldName in params) {
2790                const field = this.schema.getField(fieldName);
2791                if (field) {
2792                    if (!this.initialLoad) {
2793                        this.dirtyFields.push(fieldName);
2794                    }
2795                    switch (field.type) {
2796                        case "region":
2797                            this.regions = params[fieldName];
2798                            break;
2799                        case "location":
2800                            if (params[fieldName] != null &&
2801                                params[fieldName] != "" &&
2802                                Object.keys(params[fieldName]).length !== 0) {
2803                                const data = {
2804                                    img: params[fieldName].img,
2805                                    address: new LocationAddress(params[fieldName].address),
2806                                };
2807                                if (params[fieldName].geoPoint &&
2808                                    params[fieldName].geoPoint.lat &&
2809                                    params[fieldName].geoPoint.lng) {
2810                                    data.geoPoint = new GeoPoint(params[fieldName].geoPoint);
2811                                }
2812                                else if (params[fieldName].svgPoint &&
2813                                    params[fieldName].svgPoint.x &&
2814                                    params[fieldName].svgPoint.y) {
2815                                    data.svgPoint = new SVGPoint(params[fieldName].svgPoint);
2816                                }
2817                                if (this.location != null) {
2818                                    this.location.update(data);
2819                                }
2820                                else {
2821                                    this.location = new Location(data);
2822                                }
2823                            }
2824                            else {
2825                                this.location = null;
2826                            }
2827                            break;
2828                        case "post":
2829                            if (params.post) {
2830                                this.post = params.post;
2831                            }
2832                            break;
2833                        case "select":
2834                            this[fieldName] = params[fieldName];
2835                            if (!field.multiselect) {
2836                                this[fieldName + "_text"] = this.getEnumLabel(field, params, fieldName);
2837                            }
2838                            break;
2839                        case "radio":
2840                            this[fieldName] = params[fieldName];
2841                            this[fieldName + "_text"] = this.getEnumLabel(field, params, fieldName);
2842                            break;
2843                        default:
2844                            this[fieldName] = params[fieldName];
2845                            break;
2846                    }
2847                }
2848            }
2849        }
2850        getEnumLabel(field, params, fieldName) {
2851            const value = field.options.get(params[fieldName]);
2852            if (typeof value !== "undefined") {
2853                return value.label;
2854            }
2855            else {
2856                return "";
2857            }
2858        }
2859        update(params) {
2860            this.build(params);
2861        }
2862        getDirtyFields() {
2863            const data = {};
2864            this.dirtyFields.forEach((field) => {
2865                data[field] = this[field];
2866            });
2867            data.id = this.id;
2868            if (data.location != null) {
2869                data.location = data.location.getData();
2870            }
2871            if (this.schema.getFieldByType("region")) {
2872                data.regions = this.regions;
2873            }
2874            return data;
2875        }
2876        clearDirtyFields() {
2877            this.dirtyFields = [];
2878        }
2879        getData() {
2880            const data = {};
2881            const fields = this.schema.getFields();
2882            fields.forEach((field) => {
2883                switch (field.type) {
2884                    case "region":
2885                        data[field.name] = this[field.name];
2886                        break;
2887                    case "select":
2888                        data[field.name] = this[field.name];
2889                        if (!field.multiselect) {
2890                            data[field.name + "_text"] = this[field.name + "_text"];
2891                        }
2892                        break;
2893                    case "post":
2894                        data[field.name] = this[field.name];
2895                        data["post"] = this.post;
2896                    case "radio":
2897                        data[field.name] = this[field.name];
2898                        data[field.name + "_text"] = this[field.name + "_text"];
2899                        break;
2900                    case "location":
2901                        data[field.name] = this[field.name] ? this[field.name].getData() : null;
2902                        break;
2903                    default:
2904                        data[field.name] = this[field.name];
2905                        break;
2906                }
2907            });
2908            return data;
2909        }
2910        getRegions(regionsTableName) {
2911            return this.regions;
2912        }
2913        getRegionsForTable(regionsTableName) {
2914            return this.regions
2915                ? this.regions.filter((region) => !region.tableName || region.tableName === regionsTableName)
2916                : [];
2917        }
2918    }
2919
2920    const $$2 = jQuery;
2921    class Repository {
2922        constructor(objectName, path) {
2923            this.server = new Server();
2924            this.query = new Query();
2925            this.events = new Events(this);
2926            this.className = "";
2927            this.objectNameSingle = objectName;
2928            this.objectNameMany = objectName + "s";
2929            this.setPath(path);
2930            this.objects = new ArrayIndexed("id");
2931            this.completeChunks = 0;
2932        }
2933        setDataSource(path) {
2934            this.setPath(path);
2935            this.query = new Query({ withSchema: true });
2936            return this.find().done(() => {
2937                this.query.update({ withSchema: false });
2938            });
2939        }
2940        setPath(path) {
2941            this.path = path.replace(/\/+$/, "") + "/";
2942        }
2943        setSchema(schema) {
2944            this.schema = schema;
2945        }
2946        getSchema() {
2947            return this.schema;
2948        }
2949        loadDataFromResponse(response) {
2950            let data;
2951            data = this.decodeData(response);
2952            this.objects.clear();
2953            if (data[this.objectNameMany] && data[this.objectNameMany].length) {
2954                this.hasMoreRecords =
2955                    this.query.perpage && data[this.objectNameMany].length > this.query.perpage;
2956                if (this.hasMoreRecords) {
2957                    data[this.objectNameMany].pop();
2958                }
2959                data[this.objectNameMany].forEach((obj) => {
2960                    this.objects.push(obj);
2961                });
2962            }
2963            else {
2964                this.hasMoreRecords = false;
2965            }
2966            this.loaded = true;
2967            this.events.trigger("loaded");
2968        }
2969        reload() {
2970            return this.find();
2971        }
2972        create(object) {
2973            const defer = jQuery.Deferred();
2974            defer.promise();
2975            const data = {};
2976            data[this.objectNameSingle] = this.encodeData(object);
2977            this.server
2978                .post(this.path, data)
2979                .done((response) => {
2980                const data = this.decodeData(response);
2981                const object = data[this.objectNameSingle];
2982                this.objects.push(object);
2983                defer.resolve(object);
2984                this.events.trigger("created", this, [object]);
2985            })
2986                .fail(() => {
2987                defer.reject();
2988            });
2989            return defer;
2990        }
2991        findById(id, nocache = false) {
2992            const defer = jQuery.Deferred();
2993            defer.promise();
2994            let object;
2995            if (!nocache) {
2996                object = this.objects.findById(id.toString());
2997            }
2998            if (!nocache && object) {
2999                defer.resolve(object);
3000            }
3001            else {
3002                this.server
3003                    .get(this.path + id)
3004                    .done((response) => {
3005                    const data = this.decodeData(response);
3006                    defer.resolve(data[this.objectNameSingle]);
3007                })
3008                    .fail(() => {
3009                    defer.reject();
3010                });
3011            }
3012            return defer;
3013        }
3014        find(query) {
3015            this.events.trigger("load");
3016            const defer = jQuery.Deferred();
3017            defer.promise();
3018            if (typeof query !== "undefined") {
3019                this.query.update(query);
3020            }
3021            this.server
3022                .get(this.path, this.query)
3023                .done((response) => {
3024                this.loadDataFromResponse(response);
3025                defer.resolve(this.getLoaded());
3026            })
3027                .fail(() => {
3028                defer.reject();
3029            });
3030            return defer;
3031        }
3032        getLoaded() {
3033            return this.objects;
3034        }
3035        getLoadedObject(id) {
3036            return this.objects.findById(id.toString());
3037        }
3038        getLoadedAsArray() {
3039            return this.objects;
3040        }
3041        update(object) {
3042            const defer = jQuery.Deferred();
3043            defer.promise();
3044            const data = {};
3045            const objectUpdatedFields = "getDirtyFields" in object ? object.getDirtyFields() : object;
3046            data[this.objectNameSingle] = this.encodeData(objectUpdatedFields);
3047            this.server
3048                .put(this.path + objectUpdatedFields.id, data)
3049                .done((response) => {
3050                if ("clearDirtyFields" in object) {
3051                    object.clearDirtyFields();
3052                }
3053                defer.resolve(object);
3054                this.events.trigger("updated", this, object);
3055            })
3056                .fail(() => {
3057                defer.reject();
3058            });
3059            return defer;
3060        }
3061        delete(id) {
3062            const defer = jQuery.Deferred();
3063            defer.promise();
3064            this.server
3065                .delete(this.path + id)
3066                .done((response) => {
3067                this.objects.delete(id.toString());
3068                this.events.trigger("deleted");
3069                defer.resolve();
3070            })
3071                .fail(() => {
3072                defer.reject();
3073            });
3074            return defer;
3075        }
3076        clear() {
3077            const defer = jQuery.Deferred();
3078            defer.promise();
3079            this.server
3080                .delete(this.path)
3081                .done((response) => {
3082                this.objects.clear();
3083                this.events.trigger("loaded");
3084                this.events.trigger("cleared");
3085                defer.resolve();
3086            })
3087                .fail(() => {
3088                defer.reject();
3089            });
3090            return defer;
3091        }
3092        onFirstPage() {
3093            return this.query.page === 1;
3094        }
3095        onLastPage() {
3096            return this.hasMoreRecords === false;
3097        }
3098        encodeData(params) {
3099            return params;
3100        }
3101        decodeData(dataJSON) {
3102            let data;
3103            if (typeof dataJSON === "string") {
3104                data = JSON.parse(dataJSON);
3105            }
3106            else {
3107                data = dataJSON;
3108            }
3109            if ((data.object || data.region || data.regions || data.objects) && data.schema) {
3110                this.setSchema(new Schema(data.schema));
3111            }
3112            const dataFormatted = {};
3113            for (const key in data) {
3114                switch (key) {
3115                    case "object":
3116                    case "region":
3117                        dataFormatted[key] = new CustomObject(data[key], this.schema);
3118                        break;
3119                    case "objects":
3120                    case "regions":
3121                        dataFormatted[key] = data[key].map((obj) => new CustomObject(obj, this.schema));
3122                        break;
3123                    case "schema":
3124                        dataFormatted[key] = this.schema || new Schema(data[key]);
3125                        break;
3126                    case "schemas":
3127                        dataFormatted[key] = data[key].map((obj) => new Schema(obj));
3128                        break;
3129                }
3130            }
3131            return dataFormatted;
3132        }
3133        import(data, convertLatlngToAddress, mapsvg) {
3134            const _this = this;
3135            const locationField = _this.schema.getFieldByType("location");
3136            let language = "en";
3137            if (locationField && locationField.language) {
3138                language = locationField.language;
3139            }
3140            data = this.formatCSV(data, mapsvg);
3141            return this.importByChunks(data, language, convertLatlngToAddress).done(function () {
3142                _this.find();
3143            });
3144        }
3145        importByChunks(data, language, convertLatlngToAddress) {
3146            const _this = this;
3147            let i, j, temparray, chunk = 50;
3148            const chunks = [];
3149            for (i = 0, j = data.length; i < j; i += chunk) {
3150                temparray = data.slice(i, i + chunk);
3151                chunks.push(temparray);
3152            }
3153            if (chunks.length > 0) {
3154                let delay = 0;
3155                const delayPlus = chunks[0][0] && chunks[0][0].location ? 1000 : 0;
3156                var defer = $$2.Deferred();
3157                defer.promise();
3158                _this.completeChunks = 0;
3159                chunks.forEach(function (chunk) {
3160                    delay += delayPlus;
3161                    setTimeout(function () {
3162                        const data = {
3163                            language: language,
3164                            convertLatlngToAddress: convertLatlngToAddress,
3165                        };
3166                        data[_this.objectNameMany] = JSON.stringify(chunk);
3167                        _this.server.post(_this.path + "import", data).done(function (_data) {
3168                            _this.completeChunk(chunks, defer);
3169                        });
3170                    }, delay);
3171                });
3172            }
3173            return defer;
3174        }
3175        completeChunk(chunks, defer) {
3176            const _this = this;
3177            _this.completeChunks++;
3178            if (_this.completeChunks === chunks.length) {
3179                defer.resolve();
3180            }
3181        }
3182        formatCSV(data, mapsvg) {
3183            const _this = this;
3184            const latLngRegex = /^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/g;
3185            const regionsTable = mapsvg.regionsRepository.getSchema().name;
3186            data.forEach(function (object, index) {
3187                const newObject = {};
3188                for (const key in object) {
3189                    let field = _this.schema.getField(key);
3190                    if (key === 'post') {
3191                        field = { type: "post" };
3192                    }
3193                    if (field !== undefined) {
3194                        switch (field.type) {
3195                            case "region":
3196                                newObject[key] = {};
3197                                newObject[key][regionsTable] = object[key]
3198                                    .split(",")
3199                                    .map(function (regionId) {
3200                                    return regionId.trim();
3201                                })
3202                                    .filter(function (rId) {
3203                                    return (mapsvg.getRegion(rId) !== undefined ||
3204                                        mapsvg.regions.find(function (item) {
3205                                            return item.title === rId;
3206                                        }) !== undefined);
3207                                })
3208                                    .map(function (rId) {
3209                                    let r = mapsvg.getRegion(rId);
3210                                    if (typeof r === "undefined") {
3211                                        r = mapsvg.regions.find(function (item) {
3212                                            return item.title === rId;
3213                                        });
3214                                    }
3215                                    return { id: r.id, title: r.title };
3216                                });
3217                                break;
3218                            case "location":
3219                                if (object[key].match(latLngRegex)) {
3220                                    const coords = object[key].split(",").map(function (n) {
3221                                        return parseFloat(n);
3222                                    });
3223                                    if (coords.length == 2 &&
3224                                        coords[0] > -90 &&
3225                                        coords[0] < 90 &&
3226                                        coords[1] > -180 &&
3227                                        coords[1] < 180) {
3228                                        newObject[key] = {
3229                                            geoPoint: { lat: coords[0], lng: coords[1] },
3230                                        };
3231                                    }
3232                                    else {
3233                                        newObject[key] = "";
3234                                    }
3235                                }
3236                                else if (object[key]) {
3237                                    newObject[key] = { address: object[key] };
3238                                }
3239                                if (typeof newObject[key] == "object") {
3240                                    newObject[key].img = mapsvg.options.defaultMarkerImage;
3241                                }
3242                                break;
3243                            case "select":
3244                                const field = _this.schema.getField(key);
3245                                if (field.multiselect) {
3246                                    const labels = _this.schema.getField(key).options.map(function (f) {
3247                                        return f.label;
3248                                    });
3249                                    newObject[key] = object[key]
3250                                        .split(",")
3251                                        .map(function (label) {
3252                                        return label.trim();
3253                                    })
3254                                        .filter(function (label) {
3255                                        return labels.indexOf(label) !== -1;
3256                                    })
3257                                        .map(function (label) {
3258                                        return _this.schema
3259                                            .getField(key)
3260                                            .options.filter(function (option) {
3261                                            return option.label == label;
3262                                        })[0];
3263                                    });
3264                                }
3265                                else {
3266                                    newObject[key] = object[key];
3267                                }
3268                                break;
3269                            case "radio":
3270                            case "text":
3271                            case "textarea":
3272                            case "status":
3273                            default:
3274                                newObject[key] = object[key];
3275                                break;
3276                        }
3277                    }
3278                }
3279                data[index] = newObject;
3280            });
3281            return data;
3282        }
3283    }
3284
3285    class MapsRepository extends Repository {
3286        constructor() {
3287            super("map", "maps");
3288            this.path = "maps/";
3289        }
3290        encodeData(params) {
3291            const data = {};
3292            if (typeof params.options !== "undefined") {
3293                data.options = JSON.stringify(params.options);
3294                data.options = data.options.replace(/select/g, "!mapsvg-encoded-slct");
3295                data.options = data.options.replace(/table/g, "!mapsvg-encoded-tbl");
3296                data.options = data.options.replace(/database/g, "!mapsvg-encoded-db");
3297                data.options = data.options.replace(/varchar/g, "!mapsvg-encoded-vc");
3298            }
3299            if (typeof params.title !== "undefined") {
3300                data.title = params.title;
3301            }
3302            if (typeof params.id !== "undefined") {
3303                data.id = params.id;
3304            }
3305            if (typeof params.status !== "undefined") {
3306                data.status = params.status;
3307            }
3308            return data;
3309        }
3310        decodeData(dataJSON) {
3311            let data;
3312            if (typeof dataJSON === "string") {
3313                data = JSON.parse(dataJSON);
3314            }
3315            else {
3316                data = dataJSON;
3317            }
3318            return data;
3319        }
3320        copy(id, title) {
3321            const defer = jQuery.Deferred();
3322            defer.promise();
3323            const data = { options: { title: title } };
3324            this.server
3325                .post(this.path + id + "/copy", this.encodeData(data))
3326                .done((response) => {
3327                const data = this.decodeData(response);
3328                this.objects.clear();
3329                this.events.trigger("loaded");
3330                this.events.trigger("cleared");
3331                defer.resolve(data.map);
3332            })
3333                .fail(() => {
3334                defer.reject();
3335            });
3336            return defer;
3337        }
3338        createFromV2(object) {
3339            const defer = jQuery.Deferred();
3340            defer.promise();
3341            const data = {};
3342            data[this.objectNameSingle] = this.encodeData(object);
3343            this.server
3344                .post(this.path + "/createFromV2", data)
3345                .done((response) => {
3346                const data = this.decodeData(response);
3347                const object = data[this.objectNameSingle];
3348                this.objects.push(object);
3349                defer.resolve(object);
3350                this.events.trigger("created", this, [object]);
3351            })
3352                .fail(() => {
3353                defer.reject();
3354            });
3355            return defer;
3356        }
3357        delete(id) {
3358            const defer = jQuery.Deferred();
3359            defer.promise();
3360            this.server
3361                .delete(this.path + id)
3362                .done((response) => {
3363                this.objects.delete(id.toString());
3364                this.events.trigger("deleted");
3365                defer.resolve();
3366            })
3367                .fail(() => {
3368                defer.reject();
3369            });
3370            return defer;
3371        }
3372    }
3373
3374    class MapsV2Repository extends Repository {
3375        constructor() {
3376            super("map", "maps");
3377            this.path = "maps-v2/";
3378        }
3379        encodeData(params) {
3380            const data = {};
3381            data.options = JSON.stringify(params.options);
3382            data.options = data.options.replace(/select/g, "!mapsvg-encoded-slct");
3383            data.options = data.options.replace(/table/g, "!mapsvg-encoded-tbl");
3384            data.options = data.options.replace(/database/g, "!mapsvg-encoded-db");
3385            data.options = data.options.replace(/varchar/g, "!mapsvg-encoded-vc");
3386            data.id = params.id;
3387            data.title = params.title;
3388            return data;
3389        }
3390        decodeData(dataJSON) {
3391            let data;
3392            if (typeof dataJSON === "string") {
3393                data = JSON.parse(dataJSON);
3394            }
3395            else {
3396                data = dataJSON;
3397            }
3398            return data;
3399        }
3400    }
3401
3402    class Converter {
3403        constructor(mapElement, defViewBox, viewBox, geoViewBox) {
3404            this.mapElement = mapElement;
3405            this.defViewBox = defViewBox;
3406            this.viewBox = viewBox;
3407            this.yShift = 0;
3408            if (geoViewBox) {
3409                this.setGeoViewBox(geoViewBox);
3410            }
3411        }
3412        setYShift() {
3413            if (this.defViewBox.width === 20426) {
3414                this.yShift = 0;
3415                return;
3416            }
3417            if (this.geoViewBox) {
3418                const topLeftPoint = this.convertGeoToSVG(this.geoViewBox.ne);
3419                this.yShift = topLeftPoint.y - this.defViewBox.y;
3420            }
3421        }
3422        setGeoViewBox(geoViewBox) {
3423            this.geoViewBox = geoViewBox;
3424            this.mapLonDelta = this.geoViewBox.ne.lng - this.geoViewBox.sw.lng;
3425            this.mapLatBottomDegree = (this.geoViewBox.sw.lat * Math.PI) / 180;
3426            this.worldMapWidth = (this.defViewBox.width / this.mapLonDelta) * 360;
3427            this.worldMapRadius = ((this.defViewBox.width / this.mapLonDelta) * 360) / (2 * Math.PI);
3428            this.setYShift();
3429        }
3430        setWorldShift(on) {
3431            this.worldShift = on;
3432        }
3433        getScale() {
3434            return this.mapElement.clientWidth / this.viewBox.width;
3435        }
3436        convertSVGToPixel(svgPoint) {
3437            const scale = this.getScale();
3438            let shiftXByGM = 0;
3439            const shiftYByGM = 0;
3440            if (this.worldShift) {
3441                if (this.viewBox.x - this.defViewBox.x > this.defViewBox.width) {
3442                    shiftXByGM =
3443                        this.worldMapWidth *
3444                            Math.floor((this.viewBox.x - this.defViewBox.x) / this.defViewBox.width);
3445                }
3446            }
3447            return new ScreenPoint((svgPoint.x - this.viewBox.x + shiftXByGM) * scale, (svgPoint.y - this.viewBox.y + shiftYByGM) * scale);
3448        }
3449        convertPixelToSVG(screenPoint) {
3450            const scale = this.getScale();
3451            return new SVGPoint(screenPoint.x / scale + this.viewBox.x, screenPoint.y / scale + this.viewBox.y);
3452        }
3453        convertGeoToSVG(geoPoint) {
3454            if (!this.geoViewBox) {
3455                throw new Error("Can't do convertGeoToSVG() - geoViewBox is not provided.");
3456            }
3457            let x = (geoPoint.lng - this.geoViewBox.sw.lng) * (this.defViewBox.width / this.mapLonDelta);
3458            const lat = (geoPoint.lat * Math.PI) / 180;
3459            const mapOffsetY = (this.worldMapRadius / 2) *
3460                Math.log((1 + Math.sin(this.mapLatBottomDegree)) / (1 - Math.sin(this.mapLatBottomDegree)));
3461            let y = this.defViewBox.height -
3462                ((this.worldMapRadius / 2) * Math.log((1 + Math.sin(lat)) / (1 - Math.sin(lat))) -
3463                    mapOffsetY);
3464            x += this.defViewBox.x;
3465            y += this.defViewBox.y;
3466            y -= this.yShift;
3467            return new SVGPoint(x, y);
3468        }
3469        convertSVGToGeo(svgPoint) {
3470            if (!this.geoViewBox) {
3471                throw new Error("Can't do convertSVGToGeo() - geoViewBox is not provided.");
3472            }
3473            const tx = svgPoint.x - this.defViewBox.x;
3474            const ty = svgPoint.y - this.defViewBox.y;
3475            const mapOffsetY = (this.worldMapRadius / 2) *
3476                Math.log((1 + Math.sin(this.mapLatBottomDegree)) / (1 - Math.sin(this.mapLatBottomDegree)));
3477            const equatorY = this.defViewBox.height + mapOffsetY;
3478            const a = (equatorY - ty) / this.worldMapRadius;
3479            let lat = (180 / Math.PI) * (2 * Math.atan(Math.exp(a)) - Math.PI / 2);
3480            let lng = this.geoViewBox.sw.lng + (tx / this.defViewBox.width) * this.mapLonDelta;
3481            lat = parseFloat(lat.toFixed(6));
3482            lng = parseFloat(lng.toFixed(6));
3483            return new GeoPoint(lat, lng);
3484        }
3485    }
3486
3487    const $$3 = jQuery;
3488    class ResizeSensor {
3489        constructor(element, callback) {
3490            const _this = this;
3491            _this.element = element;
3492            _this.callback = callback;
3493            const style = getComputedStyle(element);
3494            let zIndex = parseInt(style.zIndex);
3495            if (isNaN(zIndex)) {
3496                zIndex = 0;
3497            }
3498            zIndex--;
3499            _this.expand = document.createElement("div");
3500            _this.expand.style.position = "absolute";
3501            _this.expand.style.left = "0px";
3502            _this.expand.style.top = "0px";
3503            _this.expand.style.right = "0px";
3504            _this.expand.style.bottom = "0px";
3505            _this.expand.style.overflow = "hidden";
3506            _this.expand.style.zIndex = zIndex.toString();
3507            _this.expand.style.visibility = "hidden";
3508            const expandChild = document.createElement("div");
3509            expandChild.style.position = "absolute";
3510            expandChild.style.left = "0px";
3511            expandChild.style.top = "0px";
3512            expandChild.style.width = "10000000px";
3513            expandChild.style.height = "10000000px";
3514            _this.expand.appendChild(expandChild);
3515            _this.shrink = document.createElement("div");
3516            _this.shrink.style.position = "absolute";
3517            _this.shrink.style.left = "0px";
3518            _this.shrink.style.top = "0px";
3519            _this.shrink.style.right = "0px";
3520            _this.shrink.style.bottom = "0px";
3521            _this.shrink.style.overflow = "hidden";
3522            _this.shrink.style.zIndex = zIndex.toString();
3523            _this.shrink.style.visibility = "hidden";
3524            const shrinkChild = document.createElement("div");
3525            shrinkChild.style.position = "absolute";
3526            shrinkChild.style.left = "0px";
3527            shrinkChild.style.top = "0px";
3528            shrinkChild.style.width = "200%";
3529            shrinkChild.style.height = "200%";
3530            _this.shrink.appendChild(shrinkChild);
3531            _this.element.appendChild(_this.expand);
3532            _this.element.appendChild(_this.shrink);
3533            const size = element.getBoundingClientRect();
3534            _this.currentWidth = size.width;
3535            _this.currentHeight = size.height;
3536            _this.setScroll();
3537            _this.expand.addEventListener("scroll", function () {
3538                _this.onScroll();
3539            });
3540            _this.shrink.addEventListener("scroll", function () {
3541                _this.onScroll();
3542            });
3543        }
3544        onScroll() {
3545            const _this = this;
3546            const size = _this.element.getBoundingClientRect();
3547            const newWidth = size.width;
3548            const newHeight = size.height;
3549            if (newWidth != _this.currentWidth || newHeight != _this.currentHeight) {
3550                _this.currentWidth = newWidth;
3551                _this.currentHeight = newHeight;
3552                _this.callback();
3553            }
3554            this.setScroll();
3555        }
3556        setScroll() {
3557            this.expand.scrollLeft = 10000000;
3558            this.expand.scrollTop = 10000000;
3559            this.shrink.scrollLeft = 10000000;
3560            this.shrink.scrollTop = 10000000;
3561        }
3562        destroy() {
3563            this.expand.remove();
3564            this.shrink.remove();
3565        }
3566    }
3567
3568    class ViewBox {
3569        constructor(x, y, width, height) {
3570            if (typeof x === "object") {
3571                if (x.hasOwnProperty("x") &&
3572                    x.hasOwnProperty("y") &&
3573                    x.hasOwnProperty("width") &&
3574                    x.hasOwnProperty("height")) {
3575                    this.x = typeof x.x === "string" ? parseFloat(x.x) : x.x;
3576                    this.y = typeof x.y === "string" ? parseFloat(x.y) : x.y;
3577                    this.width = typeof x.width === "string" ? parseFloat(x.width) : x.width;
3578                    this.height = typeof x.height === "string" ? parseFloat(x.height) : x.height;
3579                }
3580                else if (typeof x === "object" && x.length && x.length === 4) {
3581                    this.x = typeof x[0] === "string" ? parseFloat(x[0]) : x[0];
3582                    this.y = typeof x[1] === "string" ? parseFloat(x[1]) : x[1];
3583                    this.width = typeof x[2] === "string" ? parseFloat(x[2]) : x[2];
3584                    this.height = typeof x[3] === "string" ? parseFloat(x[3]) : x[3];
3585                }
3586            }
3587            else {
3588                this.x = typeof x === "string" ? parseFloat(x) : x;
3589                this.y = typeof y === "string" ? parseFloat(y) : y;
3590                this.width = typeof width === "string" ? parseFloat(width) : width;
3591                this.height = typeof height === "string" ? parseFloat(height) : height;
3592            }
3593        }
3594        update(newViewBox) {
3595            this.x = newViewBox.x;
3596            this.y = newViewBox.y;
3597            this.width = newViewBox.width;
3598            this.height = newViewBox.height;
3599        }
3600        toString() {
3601            return this.x + " " + this.y + " " + this.width + " " + this.height;
3602        }
3603        toArray() {
3604            return [this.x, this.y, this.width, this.height];
3605        }
3606        fitsInViewBox(viewBox, atLeastByOneDimension) {
3607            if (atLeastByOneDimension === true) {
3608                return viewBox.width >
3608 this.width || viewBox.height > this.height;
3609            }
3610            else {
3611                return viewBox.width > this.width && viewBox.height > this.height;
3612            }
3613        }
3614        addPadding(padding) {
3615            if (padding.top) {
3616                this.y -= padding.top;
3617                this.height += padding.top;
3618            }
3619            if (padding.right) {
3620                this.width += padding.right;
3621            }
3622            if (padding.bottom) {
3623                this.height += padding.bottom;
3624            }
3625            if (padding.left) {
3626                this.x -= padding.left;
3627                this.width += padding.left;
3628            }
3629        }
3630    }
3631    class GeoViewBox {
3632        constructor(sw, ne) {
3633            this.sw = sw;
3634            this.ne = ne;
3635        }
3636    }
3637
3638    const $$4 = jQuery;
3639    class MapObject {
3640        constructor(element, mapsvg) {
3641            this.id = "";
3642            this.objects = [];
3643            this.events = new Events(this);
3644            this.element = element;
3645            this.mapsvg = mapsvg;
3646        }
3647        getBBox() {
3648            return new ViewBox(1, 2, 3, 4);
3649        }
3650        getGeoBounds() {
3651            const bbox = this.getBBox();
3652            const pointSW = new SVGPoint(bbox.x, bbox.y + bbox.height);
3653            const pointNE = new SVGPoint(bbox.x + bbox.width, bbox.y);
3654            const sw = this.mapsvg.converter.convertSVGToGeo(pointSW);
3655            const ne = this.mapsvg.converter.convertSVGToGeo(pointNE);
3656            return { sw: sw, ne: ne };
3657        }
3658        getComputedStyle(prop, elem) {
3659            elem = elem || this.element;
3660            const _p1 = elem.getAttribute(prop);
3661            if (_p1) {
3662                return _p1;
3663            }
3664            const _p2 = elem.getAttribute("style");
3665            if (_p2) {
3666                const s = _p2.split(";");
3667                const z = s.filter(function (e) {
3668                    e = e.trim();
3669                    const attr = e.split(":");
3670                    if (attr[0] == prop)
3671                        return true;
3672                });
3673                if (z.length) {
3674                    return z[0].split(":").pop().trim();
3675                }
3676            }
3677            const parent = elem.parentElement;
3678            const elemType = parent ? parent.tagName : null;
3679            if (elemType && elemType != "svg")
3680                return this.getComputedStyle(prop, parent);
3681            else
3682                return undefined;
3683        }
3684        getStyle(prop) {
3685            const _p1 = this.attr(prop);
3686            if (_p1) {
3687                return _p1;
3688            }
3689            const _p2 = this.attr("style");
3690            if (_p2) {
3691                const s = _p2.split(";");
3692                const z = s.filter(function (e) {
3693                    var e = e.trim();
3694                    if (e.indexOf(prop) === 0)
3695                        return e;
3696                });
3697                return z.length ? z[0].split(":").pop().trim() : undefined;
3698            }
3699            return "";
3700        }
3701        getCenter() {
3702            const x = this.element.getBoundingClientRect().left;
3703            const y = this.element.getBoundingClientRect().top;
3704            const w = this.element.getBoundingClientRect().width;
3705            const h = this.element.getBoundingClientRect().height;
3706            const point = new ScreenPoint(x + w / 2, y + h / 2);
3707            return point;
3708        }
3709        getCenterSVG() {
3710            const bbox = this.getBBox();
3711            const point = new SVGPoint(bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
3712            return point;
3713        }
3714        getCenterLatLng(yShift) {
3715            yShift = yShift ? yShift : 0;
3716            const bbox = this.getBBox();
3717            const x = bbox.x + bbox.width / 2;
3718            const y = bbox.y + bbox.height / 2 - yShift;
3719            const point = new SVGPoint(x, y);
3720            return this.mapsvg.converter.convertSVGToGeo(point);
3721        }
3722        attr(v1, v2 = null) {
3723            const svgDom = this.element;
3724            if (typeof v1 == "object") {
3725                for (const key in v1) {
3726                    const item = v1[key];
3727                    if (typeof item === "string" || typeof item === "number") {
3728                        svgDom.setAttribute(key, "" + item);
3729                    }
3730                }
3731            }
3732            else if (typeof v1 == "string" && (typeof v2 == "string" || typeof v2 == "number")) {
3733                svgDom.setAttribute(v1, "" + v2);
3734            }
3735            else if (v2 == undefined) {
3736                return svgDom.getAttribute(v1);
3737            }
3738        }
3739        setId(id) {
3740            if (id !== undefined) {
3741                this.id = id;
3742                this.element.setAttribute("id", id);
3743            }
3744        }
3745    }
3746
3747    const $$5 = jQuery;
3748    class Marker extends MapObject {
3749        constructor(params) {
3750            super(null, params.mapsvg);
3751            this.src = params.location.getMarkerImageUrl();
3752            this.element = $$5("<div />").addClass("mapsvg-marker")[0];
3753            this.image = $$5('<img src="' + this.src + '" />').addClass("mapsvg-marker-image")[0];
3754            $$5(this.element).append(this.image);
3755            this.location = params.location;
3756            this.location.marker = this;
3757            this.mapsvg = params.mapsvg;
3758            params.object && this.setObject(params.object);
3759            if (params.width && params.height) {
3760                this.setSize(params.width, params.height);
3761            }
3762            else {
3763                this.setSize(15, 24);
3764            }
3765            this.setId(this.mapsvg.markerId());
3766            this.setSvgPointFromLocation();
3767            this.setImage(this.src);
3768            this.setAltAttr();
3769        }
3770        setSize(width, height) {
3771            this.width = width;
3772            this.height = height;
3773            this.setCentered(this.width === this.height);
3774        }
3775        setSvgPointFromLocation() {
3776            this.setSvgPoint(this.location.geoPoint &&
3777                this.location.geoPoint.lat !== 0 &&
3778                this.location.geoPoint.lng !== 0
3779                ? this.mapsvg.converter.convertGeoToSVG(this.location.geoPoint)
3780                : this.location.svgPoint);
3781        }
3782        setId(id) {
3783            MapObject.prototype.setId.call(this, id);
3784            this.mapsvg.markers.reindex();
3785        }
3786        getBBox() {
3787            if (this.centered) {
3788                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);
3789            }
3790            else {
3791                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);
3792            }
3793        }
3794        getOptions() {
3795            const o = {
3796                id: this.id,
3797                src: this.src,
3798                svgPoint: this.svgPoint,
3799                geoPoint: this.geoPoint,
3800            };
3801            $$5.each(o, function (key, val) {
3802                if (val == undefined) {
3803                    delete o[key];
3804                }
3805            });
3806            return o;
3807        }
3808        update(data) {
3809            for (const key in data) {
3810                const setter = "set" + MapSVG.ucfirst(key);
3811                if (setter in this)
3812                    this[setter](data[key]);
3813            }
3814        }
3815        setImage(src) {
3816            if (!src)
3817                return;
3818            src = MapSVG.safeURL(src);
3819            const img = new Image();
3820            const marker = this;
3821            this.src = src;
3822            if (marker.image.getAttribute("src") !== "src") {
3823                marker.image.setAttribute("src", src);
3824            }
3825            img.onload = function () {
3826                marker.setSize(this.width, this.height);
3827                marker.adjustScreenPosition();
3828            };
3829            img.src = src;
3830            if (this.location && this.location.imagePath !== src) {
3831                this.location.setImage(src);
3832            }
3833            this.events.trigger("change");
3834        }
3835        setAltAttr() {
3836            const marker = this;
3837            marker.altAttr =
3838                typeof marker.object != "undefined" &&
3839                    typeof marker.object.title != "undefined" &&
3840                    marker.object.title !== ""
3841                    ? marker.object.title
3842                    : marker.id;
3843            marker.element.setAttribute("alt", marker.altAttr);
3844        }
3845        setSvgPoint(svgPoint) {
3846            this.svgPoint = svgPoint;
3847            this.adjustScreenPosition();
3848            this.events.trigger("change");
3849        }
3850        adjustScreenPosition() {
3851            const pos = this.mapsvg.converter.convertSVGToPixel(this.svgPoint);
3852            pos.x -= this.width / 2;
3853            pos.y -= !this.centered ? this.height : this.height / 2;
3854            this.setScreenPosition(pos.x, pos.y);
3855        }
3856        moveSrceenPositionBy(deltaX, deltaY) {
3857            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
3858            this.setScreenPosition(x, y);
3859        }
3860        setScreenPosition(x, y) {
3861            if (this.screenPoint instanceof ScreenPoint) {
3862                this.screenPoint.x = x;
3863                this.screenPoint.y = y;
3864            }
3865            else {
3866                this.screenPoint = new ScreenPoint(x, y);
3867            }
3868            this.updateVisibility();
3869            if (this.visible === true) {
3870                this.element.style.transform = "translate(" + x + "px," + y + "px)";
3871                this.adjustLabelScreenPosition();
3872            }
3873        }
3874        adjustLabelScreenPosition() {
3875            if (this.label) {
3876                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());
3877            }
3878        }
3879        inViewBox() {
3880            const x = this.screenPoint.x, y = this.screenPoint.y, mapFullWidth = this.mapsvg.containers.map.offsetWidth, mapFullHeight = this.mapsvg.containers.map.offsetHeight;
3881            return (x - this.width / 2 < 2 * mapFullWidth &&
3882                x + this.width / 2 > -mapFullWidth &&
3883                y - this.height / 2 < 2 * mapFullHeight &&
3884                y + this.height / 2 > -mapFullHeight);
3885        }
3886        updateVisibility() {
3887            if (this.inViewBox() === true) {
3888                this.visible = true;
3889                this.element.classList.remove("mapsvg-out-of-sight");
3890                if (this.label) {
3891                    this.label.classList.remove("mapsvg-out-of-sight");
3892                }
3893            }
3894            else {
3895                this.visible = false;
3896                this.element.classList.add("mapsvg-out-of-sight");
3897                if (this.label) {
3898                    this.label.classList.add("mapsvg-out-of-sight");
3899                }
3900            }
3901            return this.visible;
3902        }
3903        isMoving() {
3904            return this.moving;
3905        }
3906        setMoving(value) {
3907            this.moving = value;
3908        }
3909        drag(startCoords, scale, endCallback, clickCallback) {
3910            const _this = this;
3911            this.svgPointBeforeDrag = new SVGPoint(this.svgPoint.x, this.svgPoint.y);
3912            this.setMoving(true);
3913            $$5("body").on("mousemove.drag.mapsvg", function (e) {
3914                e.preventDefault();
3915                $$5(_this.mapsvg.containers.map).addClass("no-transitions");
3916                const mouseNew = MapSVG.mouseCoords(e);
3917                const dx = mouseNew.x - startCoords.x;
3918                const dy = mouseNew.y - startCoords.y;
3919                const newSvgPoint = new SVGPoint(_this.svgPointBeforeDrag.x + dx / scale, _this.svgPointBeforeDrag.y + dy / scale);
3920                _this.setSvgPoint(newSvgPoint);
3921            });
3922            $$5("body").on("mouseup.drag.mapsvg", function (e) {
3923                e.preventDefault();
3924                _this.undrag();
3925                const mouseNew = MapSVG.mouseCoords(e);
3926                const dx = mouseNew.x - startCoords.x;
3927                const dy = mouseNew.y - startCoords.y;
3928                const newSvgPoint = new SVGPoint(_this.svgPointBeforeDrag.x + dx / scale, _this.svgPointBeforeDrag.y + dy / scale);
3929                _this.setSvgPoint(newSvgPoint);
3930                if (_this.mapsvg.isGeo()) {
3931                    _this.geoPoint = _this.mapsvg.converter.convertSVGToGeo(newSvgPoint);
3932                }
3933                endCallback && endCallback.call(_this);
3934                if (_this.svgPointBeforeDrag.x == _this.svgPoint.x &&
3935                    _this.svgPointBeforeDrag.y == _this.svgPoint.y)
3936                    clickCallback && clickCallback.call(_this);
3937            });
3938        }
3939        undrag() {
3940            this.setMoving(false);
3941            $$5("body").off(".drag.mapsvg");
3942            $$5(this.mapsvg.containers.map).removeClass("no-transitions");
3943        }
3944        delete() {
3945            if (this.label) {
3946                this.label.remove();
3947                this.label = null;
3948            }
3949            $$5(this.element).empty().remove();
3950        }
3951        setObject(obj) {
3952            this.object = obj;
3953            $$5(this.element).attr("data-object-id", this.object.id);
3954        }
3955        hide() {
3956            $$5(this.element).addClass("mapsvg-marker-hidden");
3957            if (this.label) {
3958                $$5(this.label).hide();
3959            }
3960        }
3961        show() {
3962            $$5(this.element).removeClass("mapsvg-marker-hidden");
3963            if (this.label) {
3964                $$5(this.label).show();
3965            }
3966        }
3967        highlight() {
3968            $$5(this.element).addClass("mapsvg-marker-hover");
3969        }
3970        unhighlight() {
3971            $$5(this.element).removeClass("mapsvg-marker-hover");
3972        }
3973        select() {
3974            this.selected = true;
3975            $$5(this.element).addClass("mapsvg-marker-active");
3976        }
3977        deselect() {
3978            this.selected = false;
3979            $$5(this.element).removeClass("mapsvg-marker-active");
3980        }
3981        getData() {
3982            return this.object;
3983        }
3984        getChoroplethColor() {
3985            const markerValue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
3986            let color;
3987            if (!markerValue) {
3988                color = this.mapsvg.options.choropleth.coloring.noData.color;
3989            }
3990            else if (this.mapsvg.options.choropleth.coloring.mode === "gradient") {
3991                const gradient = this.mapsvg.options.choropleth.coloring.gradient, w = gradient.values.maxAdjusted === 0
3992                    ? 0
3993                    : (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);
3994                color = "rgba(" + r + "," + g + "," + b + "," + a + ")";
3995            }
3996            else {
3997                const paletteColors = this.mapsvg.options.choropleth.coloring.palette.colors;
3998                if (!paletteColors[0].valueFrom && markerValue < paletteColors[0].valueTo) {
3999                    color = paletteColors[0].color;
4000                }
4001                else if (!paletteColors[paletteColors.length - 1].valueTo &&
4002                    markerValue > paletteColors[paletteColors.length - 1].valueFrom) {
4003                    color = paletteColors[paletteColors.length - 1].color;
4004                }
4005                else {
4006                    paletteColors.forEach(function (paletteColor) {
4007                        if (markerValue >= paletteColor.valueFrom &&
4008                            markerValue < paletteColor.valueTo) {
4009                            color = paletteColor.color;
4010                        }
4011                    });
4012                    color = color
4013                        ? color
4014                        : this.mapsvg.options.choropleth.coloring.palette.outOfRange.color;
4015                }
4016            }
4017            return color;
4018        }
4019        getBubbleSize() {
4020            let bubbleSize;
4021            if (this.object[this.mapsvg.options.choropleth.sourceField]) {
4022                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]);
4023                bubbleSize =
4024                    ((sourceFieldvalue - minSourceFieldvalue) /
4025                        (maxSourceFieldvalue - minSourceFieldvalue)) *
4026                        (maxBubbleSize - minBubbleSize) +
4027                        Number(minBubbleSize);
4028            }
4029            else {
4030                bubbleSize = false;
4031            }
4032            return bubbleSize;
4033        }
4034        getBubbleScreenPosition() {
4035            const bubbleSize = Number(this.getBubbleSize());
4036            return {
4037                x: this.width / 2 - bubbleSize / 2,
4038                y: this.height - bubbleSize / 2,
4039            };
4040        }
4041        drawBubble() {
4042            const bubbleId = "mapsvg-bubble-" + this.object.id;
4043            const bubbleValue = parseFloat(this.object[this.mapsvg.options.choropleth.sourceField]);
4044            if (bubbleValue) {
4045                if (!this.bubble) {
4046                    this.bubble = $$5('<div id="' +
4047                        bubbleId +
4048                        '" data-marker-id="' +
4049                        this.element.id +
4050                        '" class="mapsvg-bubble mapsvg-marker-bubble"></div>')[0];
4051                    $$5(this.element).append(this.bubble);
4052                }
4053                const color = this.getChoroplethColor(), bubbleSize = Number(this.getBubbleSize());
4054                $$5(this.bubble)
4055                    .css("background-color", color)
4056                    .css("width", bubbleSize + "px")
4057                    .css("height", bubbleSize + "px")
4058                    .css("lineHeight", bubbleSize - 2 + "px");
4059            }
4060            else {
4061                $$5("#" + bubbleId).remove();
4062                delete this.bubble;
4063            }
4064        }
4065        setBubbleMode(bubbleMode) {
4066            this.bubbleMode = bubbleMode;
4067            if (bubbleMode) {
4068                this.setCentered(true);
4069                this.drawBubble();
4070                if (this.bubble) {
4071                    this.width = this.bubble.offsetWidth;
4072                    this.height = this.bubble.offsetHeight;
4073                    this.adjustScreenPosition();
4074                }
4075            }
4076            else {
4077                this.setImage(this.src);
4078            }
4079        }
4080        setLabel(html) {
4081            if (!this.label) {
4082                this.label = $$5("<div />").addClass("mapsvg-marker-label")[0];
4083                $$5(this.element).append(this.label);
4084            }
4085            $$5(this.label).html(html);
4086        }
4087        setCentered(on) {
4088            this.centered = on;
4089        }
4090    }
4091
4092    const $$6 = jQuery;
4093    class MarkerCluster extends MapObject {
4094        constructor(options, mapsvg) {
4095            super(null, mapsvg);
4096            this.svgPoint = options.svgPoint;
4097            this.cellX = options.cellX;
4098            this.cellY = options.cellY;
4099            this.markers = options.markers || [];
4100            this.cellSize = 50;
4101            this.width = 30;
4102            this.elem = $$6('<div class="mapsvg-marker-cluster">' + this.markers.length + "</div>")[0];
4103            $$6(this.elem).data("cluster", this);
4104            if (this.markers.length < 2) {
4105                $$6(this.elem).hide();
4106            }
4107            this.adjustScreenPosition();
4108        }
4109        addMarker(marker) {
4110            this.markers.push(marker);
4111            if (this.markers.length > 1) {
4112                if (this.markers.length === 2) {
4113                    $$6(this.elem).show();
4114                }
4115                if (this.markers.length === 2) {
4116                    const x = this.markers.map(function (m) {
4117                        return m.svgPoint.x;
4118                    });
4119                    this.min_x = Math.min.apply(null, x);
4120                    this.max_x = Math.max.apply(null, x);
4121                    const y = this.markers.map(function (m) {
4122                        return m.svgPoint.y;
4123                    });
4124                    this.min_y = Math.min.apply(null, y);
4125                    this.max_y = Math.max.apply(null, y);
4126                    this.svgPoint.x = this.min_x + (this.max_x - this.min_x) / 2;
4127                    this.svgPoint.y = this.min_y + (this.max_y - this.min_y) / 2;
4128                }
4129                if (this.markers.length > 2) {
4130                    if (marker.svgPoint.x < this.min_x) {
4131                        this.min_x = marker.svgPoint.x;
4132                    }
4133                    else if (marker.svgPoint.x > this.max_x) {
4134                        this.max_x = marker.svgPoint.x;
4135                    }
4136                    if (marker.svgPoint.y < this.min_y) {
4137                        this.min_y = marker.svgPoint.y;
4138                    }
4139                    else if (marker.svgPoint.x > this.max_x) {
4140                        this.max_y = marker.svgPoint.y;
4141                    }
4142                    this.svgPoint.x = this.min_x + (this.max_x - this.min_x) / 2;
4143                    this.svgPoint.y = this.min_y + (this.max_y - this.min_y) / 2;
4144                }
4145            }
4146            else {
4147                this.svgPoint.x = marker.svgPoint.x;
4148                this.svgPoint.y = marker.svgPoint.y;
4149            }
4150            $$6(this.elem).text(this.markers.length);
4151            this.adjustScreenPosition();
4152        }
4153        canTakeMarker(marker) {
4154            const _this = this;
4155            const screenPoint = _this.mapsvg.converter.convertSVGToPixel(marker.svgPoint);
4156            return (this.cellX === Math.ceil(screenPoint.x / this.cellSize) &&
4157                this.cellY === Math.ceil(screenPoint.y / this.cellSize));
4158        }
4159        destroy() {
4160            this.markers = null;
4161            $$6(this.elem).remove();
4162        }
4163        adjustScreenPosition() {
4164            const pos = this.mapsvg.converter.convertSVGToPixel(this.svgPoint);
4165            pos.x -= this.width / 2;
4166            pos.y -= this.width / 2;
4167            this.setScreenPosition(pos.x, pos.y);
4168        }
4169        moveSrceenPositionBy(deltaX, deltaY) {
4170            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
4171            this.setScreenPosition(x, y);
4172        }
4173        setScreenPosition(x, y) {
4174            if (this.screenPoint instanceof ScreenPoint) {
4175                this.screenPoint.x = x;
4176                this.screenPoint.y = y;
4177            }
4178            else {
4179                this.screenPoint = new ScreenPoint(x, y);
4180            }
4181            this.updateVisibility();
4182            if (this.visible === true) {
4183                this.elem.style.transform = "translate(" + x + "px," + y + "px)";
4184            }
4185        }
4186        inViewBox() {
4187            const x = this.screenPoint.x, y = this.screenPoint.y, mapFullWidth = this.mapsvg.containers.map.offsetWidth, mapFullHeight = this.mapsvg.containers.map.offsetHeight;
4188            return (x - this.width / 2 < mapFullWidth &&
4189                x + this.width / 2 > 0 &&
4190                y - this.width / 2 < mapFullHeight &&
4191                y + this.width / 2 > 0);
4192        }
4193        updateVisibility() {
4194            if (this.inViewBox() === true) {
4195                this.visible = true;
4196                this.elem.classList.remove("mapsvg-out-of-sight");
4197            }
4198            else {
4199                this.visible = false;
4200                this.elem.classList.add("mapsvg-out-of-sight");
4201            }
4202            return this.visible;
4203        }
4204        getBBox() {
4205            let bbox = {
4206                x: this.svgPoint.x,
4207                y: this.svgPoint.y,
4208                width: this.cellSize / this.mapsvg.getScale(),
4209                height: this.cellSize / this.mapsvg.getScale(),
4210            };
4211            bbox = $$6.extend(true, {}, bbox);
4212            return new ViewBox(bbox.x, bbox.y, bbox.width, bbox.height);
4213        }
4214        getData() {
4215            return this.markers.map((m) => m.object);
4216        }
4217    }
4218
4219    const $$7 = jQuery;
4220    class Region extends MapObject {
4221        constructor(element, mapsvg) {
4222            super(element, mapsvg);
4223            this.id = this.element.getAttribute("id");
4224            if (this.id && this.mapsvg.options.regionPrefix) {
4225                this.setId(this.id.replace(this.mapsvg.options.regionPrefix, ""));
4226            }
4227            this.id_no_spaces = this.id.replace(/\s/g, "_");
4228            this.element.setAttribute("class", (this.element.className || "") + " mapsvg-region");
4229            this.setStyleInitial();
4230            const regionOptions = this.mapsvg.options.regions && this.mapsvg.options.regions[this.id]
4231                ? this.mapsvg.options.regions[this.id]
4232                : null;
4233            this.disabled = this.getDisabledState();
4234            this.disabled && this.attr("class", this.attr("class") + " mapsvg-disabled");
4235            this.default_attr = {};
4236            this.selected_attr = {};
4237            this.hover_attr = {};
4238            let selected = false;
4239            if (regionOptions && regionOptions.selected) {
4240                selected = true;
4241                delete regionOptions.selected;
4242            }
4243            regionOptions && this.update(regionOptions);
4244            this.setFill();
4245            if (selected) {
4246                this.setSelected();
4247            }
4248            this.saveState();
4249        }
4250        adjustStroke(scale) {
4251            $$7(this.element).css({ "stroke-width": this.style["stroke-width"] / scale });
4252        }
4253        setStyleInitial() {
4254            this.style = { fill: this.getComputedStyle("fill") };
4255            this.style.stroke = this.getComputedStyle("stroke") || "";
4256            let w;
4257            w = this.getComputedStyle("stroke-width");
4258            w = w ? w.replace("px", "") : "1";
4259            w = w == "1" ? 1.2 : parseFloat(w);
4260            this.style["stroke-width"] = w;
4261        }
4262        saveState() {
4263            this.initialState = JSON.stringify(this.getOptions());
4264        }
4265        getBBox() {
4266            const _bbox = this.element.getBBox();
4267            const bbox = new ViewBox(_bbox.x, _bbox.y, _bbox.width, _bbox.height);
4268            const matrix = this.element.getTransformToElement(this.mapsvg.containers.svg);
4269            const x2 = bbox.x + bbox.width;
4270            const y2 = bbox.y + bbox.height;
4271            let position = this.mapsvg.containers.svg.createSVGPoint();
4272            position.x = bbox.x;
4273            position.y = bbox.y;
4274            position = position.matrixTransform(matrix);
4275            bbox.x = position.x;
4276            bbox.y = position.y;
4277            position.x = x2;
4278            position.y = y2;
4279            position = position.matrixTransform(matrix);
4280            bbox.width = position.x - bbox.x;
4281            bbox.height = position.y - bbox.y;
4282            return bbox;
4283        }
4284        changed() {
4285            return JSON.stringify(this.getOptions()) != this.initialState;
4286        }
4287        edit() {
4288            this.elemOriginal = $$7(this.element).clone()[0];
4289        }
4290        editCommit() {
4291            this.elemOriginal = null;
4292        }
4293        editCancel() {
4294            this.mapsvg.containers.svg.appendChild(this.elemOriginal);
4295            this.element = this.elemOriginal;
4296            this.elemOriginal = null;
4297        }
4298        getOptions(forTemplate) {
4299            let o;
4300            o = {
4301                id: this.id,
4302                id_no_spaces: this.id_no_spaces,
4303                title: this.title,
4304                fill: this.mapsvg.options.regions[this.id] && this.mapsvg.options.regions[this.id].fill,
4305                data: this.data,
4306                choroplethValue: this.choroplethValue,
4307            };
4308            if (forTemplate) {
4309                o.disabled = this.disabled;
4310                o.dataCounter = (this.data && this.data.length) || 0;
4311            }
4312            for (const key in o) {
4313                if (typeof o[key] === "undefined") {
4314                    delete o[key];
4315                }
4316            }
4317            if (this.customAttrs) {
4318                const that = this;
4319                this.customAttrs.forEach(function (attr) {
4320                    o[attr] = that[attr];
4321                });
4322            }
4323            return o;
4324        }
4325        forTemplate() {
4326            const data = {
4327                id: this.id,
4328                title: this.title,
4329                objects: this.objects,
4330                data: this.data,
4331            };
4332            for (const key in this.data) {
4333                if (key != "title" && key != "id")
4334                    data[key] = this.data[key];
4335            }
4336            return data;
4337        }
4338        getData() {
4339            return this.forTemplate();
4340        }
4341        update(options) {
4342            for (const key in options) {
4343                const setter = "set" + MapSVG.ucfirst(key);
4344                if (setter in this)
4345                    this[setter](options[key]);
4346                else {
4347                    this[key] = options[key];
4348                    this.customAttrs = this.customAttrs || [];
4349                    this.customAttrs.push(key);
4350                }
4351            }
4352        }
4353        setTitle(title) {
4354            if (title) {
4355                this.title = title;
4356            }
4357            this.element.setAttribute("title", this.title);
4358        }
4359        setStyle(style) {
4360            $$7.extend(true, this.style, style);
4361            this.setFill();
4362        }
4363        getChoroplethColor() {
4364            const o = this.mapsvg.options.choropleth;
4365            let color = "";
4366            if (this.data &&
4367                (this.data[this.mapsvg.options.regionChoroplethField] ||
4368                    this.data[this.mapsvg.options.regionChoroplethField] === 0)) {
4369                const w = o.maxAdjusted === 0
4370                    ? 0
4371                    : (parseFloat(this.data[this.mapsvg.options.regionChoroplethField]) - o.min) /
4372                        o.maxAdjusted;
4373                const c = {
4374                    r: Math.round(o.colors.diffRGB.r * w + o.colors.lowRGB.r),
4375                    g: Math.round(o.colors.diffRGB.g * w + o.colors.lowRGB.g),
4376                    b: Math.round(o.colors.diffRGB.b * w + o.colors.lowRGB.b),
4377                    a: (o.colors.diffRGB.a * w + o.colors.lowRGB.a).toFixed(2),
4378                };
4379                color = "rgba(" + c.r + "," + c.g + "," + c.b + "," + c.a + ")";
4380            }
4381            else {
4382                color = o.colors.noData;
4383            }
4384            return color;
4385        }
4386        _new_getChoroplethColor() {
4387            let regionValue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]), color;
4388            if (!regionValue) {
4389                color = this.mapsvg.options.choropleth.coloring.noData.color;
4390            }
4391            else if (this.mapsvg.options.choropleth.coloring.mode === "gradient") {
4392                const gradient = this.mapsvg.options.choropleth.coloring.gradient, w = gradient.values.maxAdjusted === 0
4393                    ? 0
4394                    : (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);
4395                color = "rgba(" + r + "," + g + "," + b + "," + a + ")";
4396            }
4397            else {
4398                const paletteColors = this.mapsvg.options.choropleth.coloring.palette.colors;
4399                if (!paletteColors[0].valueFrom && regionValue < paletteColors[0].valueTo) {
4400                    color = paletteColors[0].color;
4401                }
4402                else if (!paletteColors[paletteColors.length - 1].valueTo &&
4403                    regionValue > paletteColors[paletteColors.length - 1].valueFrom) {
4404                    color = paletteColors[paletteColors.length - 1].color;
4405                }
4406                else {
4407                    paletteColors.forEach(function (paletteColor) {
4408                        if (regionValue >= paletteColor.valueFrom &&
4409                            regionValue < paletteColor.valueTo) {
4410                            color = paletteColor.color;
4411                        }
4412                    });
4413                    color = color
4414                        ? color
4415                        : this.mapsvg.options.choropleth.coloring.palette.outOfRange.color;
4416                }
4417            }
4418            return color;
4419        }
4420        getBubbleSize() {
4421            let bubbleSize;
4422            if (this.data[this.mapsvg.options.choropleth.sourceField]) {
4423                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]);
4424                bubbleSize =
4425                    ((sourceFieldvalue - minSourceFieldvalue) /
4426                        (maxSourceFieldvalue - minSourceFieldvalue)) *
4427                        (maxBubbleSize - minBubbleSize) +
4428                        minBubbleSize;
4429            }
4430            else {
4431                bubbleSize = false;
4432            }
4433            return bubbleSize;
4434        }
4435        setFill(fill) {
4436            if (this.mapsvg.options.colorsIgnore) {
4437                $$7(this.element).css(this.style);
4438                return;
4439            }
4440            if (fill) {
4441                const regions = {};
4442                regions[this.id] = { fill: fill };
4443                $$7.extend(true, this.mapsvg.options, { regions: regions });
4444            }
4445            else if (!fill &&
4446                fill !== undefined &&
4447                this.mapsvg.options.regions &&
4448                this.mapsvg.options.regions[this.id] &&
4449                this.mapsvg.options.regions[this.id].fill) {
4450                delete this.mapsvg.options.regions[this.id].fill;
4451            }
4452            if (this.mapsvg.options.choropleth.on) {
4453                this.default_attr["fill"] = this.getChoroplethColor();
4454            }
4455            else if (this.status !== undefined &&
4456                this.mapsvg.regions &&
4457                this.mapsvg.regionsRepository.getSchema().getFieldByType("status") &&
4458                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict &&
4459                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict[this.status] &&
4460                this.mapsvg.regionsRepository.getSchema().getFieldByType("status").optionsDict[this.status].color) {
4461                this.default_attr["fill"] = this.mapsvg.regionsRepository
4462                    .getSchema()
4463                    .getFieldByType("status").optionsDict[this.status].color;
4464            }
4465            else if (this.mapsvg.options.regions[this.id] &&
4466                this.mapsvg.options.regions[this.id].fill) {
4467                this.default_attr["fill"] = this.mapsvg.options.regions[this.id].fill;
4468            }
4469            else if (this.mapsvg.options.colors.base) {
4470                this.default_attr["fill"] = this.mapsvg.options.colors.base;
4471            }
4472            else if (this.style.fill != "none") {
4473                this.default_attr["fill"] = this.style.fill
4474                    ? this.style.fill
4475                    : this.mapsvg.options.colors.baseDefault;
4476            }
4477            else {
4478                this.default_attr["fill"] = "none";
4479            }
4480            if (MapSVG.isNumber(this.mapsvg.options.colors.selected))
4481                this.selected_attr["fill"] = tinycolor(this.default_attr.fill)
4482                    .lighten(parseFloat("" + this.mapsvg.options.colors.selected))
4483                    .toRgbString();
4484            else
4485                this.selected_attr["fill"] = this.mapsvg.options.colors.selected;
4486            if (MapSVG.isNumber(this.mapsvg.options.colors.hover))
4487                this.hover_attr["fill"] = tinycolor(this.default_attr.fill)
4488                    .lighten(parseFloat("" + this.mapsvg.options.colors.hover))
4489                    .toRgbString();
4490            else
4491                this.hover_attr["fill"] = this.mapsvg.options.colors.hover;
4492            $$7(this.element).css("fill", this.default_attr["fill"]);
4493            this.fill = this.default_attr["fill"];
4494            if (this.style.stroke != "none" && this.mapsvg.options.colors.stroke != undefined) {
4495                $$7(this.element).css("stroke", this.mapsvg.options.colors.stroke);
4496            }
4497            else {
4498                const s = this.style.stroke == undefined ? "" : this.style.stroke;
4499                $$7(this.element).css("stroke", s);
4500            }
4501            if (this.selected)
4502                this.setSelected();
4503        }
4504        setDisabled(on, skipSetFill) {
4505            on = on !== undefined ? MapSVG.parseBoolean(on) : this.getDisabledState();
4506            const prevDisabled = this.disabled;
4507            this.disabled = on;
4508            this.attr("class", this.attr("class").replace("mapsvg-disabled", ""));
4509            if (on) {
4510                this.attr("class", this.attr("class") + " mapsvg-disabled");
4511            }
4512            if (this.disabled != prevDisabled)
4513                this.mapsvg.deselectRegion(this);
4514            !skipSetFill && this.setFill();
4515        }
4516        setStatus(status) {
4517            const statusOptions = this.mapsvg.options.regionStatuses && this.mapsvg.options.regionStatuses[status];
4518            if (statusOptions) {
4519                this.status = status;
4520                this.data.status = status;
4521                this.data.status_text = statusOptions.label;
4522                this.setDisabled(statusOptions.disabled, true);
4523            }
4524            else {
4525                this.status = undefined;
4526                this.data.status = undefined;
4527                this.data.status_text = undefined;
4528                this.setDisabled(false, true);
4529            }
4530            this.setFill();
4531        }
4532        setSelected() {
4533            this.mapsvg.selectRegion(this);
4534        }
4535        setchoroplethValue(val) {
4536            if ($$7.isNumeric(val)) {
4537                if (typeof val === "string") {
4538                    val = parseFloat(val);
4539                }
4540                this.choroplethValue = val;
4541            }
4542            else {
4543                this.choroplethValue = undefined;
4544            }
4545        }
4546        getDisabledState(asDefault) {
4547            const opts = this.mapsvg.options.regions[this.id];
4548            if (!asDefault && opts && opts.disabled !== undefined) {
4549                return opts.disabled;
4550            }
4551            else {
4552                return (this.mapsvg.options.disableAll ||
4553                    this.style.fill === "none" ||
4554                    this.id == "labels" ||
4555                    this.id == "Labels");
4556            }
4557        }
4558        highlight() {
4559            $$7(this.element).css({ fill: this.hover_attr.fill });
4560            $$7(this.element).addClass("mapsvg-region-hover");
4561        }
4562        unhighlight() {
4563            $$7(this.element).css({ fill: this.default_attr.fill });
4564            $$7(this.element).removeClass("mapsvg-region-hover");
4565        }
4566        select() {
4567            $$7(this.element).css({ fill: this.selected_attr.fill });
4568            this.selected = true;
4569            $$7(this.element).addClass("mapsvg-region-active");
4570        }
4571        deselect() {
4572            $$7(this.element).css({ fill: this.default_attr.fill });
4573            this.selected = false;
4574            $$7(this.element).removeClass("mapsvg-region-active");
4575        }
4576        setData(data) {
4577            this.data = data;
4578            this.setTitle(data.title);
4579        }
4580        drawBubble() {
4581            if (this.data) {
4582                const bubbleId = "mapsvg-bubble-" + this.id;
4583                const bubbleValue = parseFloat(this.data[this.mapsvg.options.choropleth.sourceField]);
4584                if (bubbleValue) {
4585                    if (!this.center) {
4586                        this.center = this.getCenterSVG();
4587                    }
4588                    const pos = this.mapsvg.converter.convertSVGToPixel(this.center);
4589                    if (!this.bubble) {
4590                        this.bubble = $$7('<div id="' +
4591                            bubbleId +
4592                            '" class="mapsvg-bubble mapsvg-region-bubble"></div>')[0];
4593                        $$7(this.mapsvg.layers.bubbles).append(this.bubble);
4594                    }
4595                    const color = this.getChoroplethColor();
4596                    const bubbleSize = Number(this.getBubbleSize());
4597                    $$7(this.bubble)
4598                        .css("transform", "translate(-50%,-50%) translate(" + pos.x + "px," + pos.y + "px)")
4599                        .css("background-color", color)
4600                        .css("width", bubbleSize + "px")
4601                        .css("height", bubbleSize + "px")
4602                        .css("lineHeight", bubbleSize - 2 + "px");
4603                }
4604                else {
4605                    delete this.bubble;
4606                }
4607            }
4608        }
4609        adjustLabelScreenPosition() {
4610            if (this.label) {
4611                if (!this.center) {
4612                    this.center = this.getCenterSVG();
4613                }
4614                const pos = this.mapsvg.converter.convertSVGToPixel(this.center), x = pos.x - this.label.offsetWidth / 2, y = pos.y - this.label.offsetHeight / 2;
4615                this.setLabelScreenPosition(x, y);
4616            }
4617        }
4618        adjustBubbleScreenPosition() {
4619            if (this.bubble) {
4620                if (!this.center) {
4621                    this.center = this.getCenterSVG();
4622                }
4623                const pos = this.mapsvg.converter.convertSVGToPixel(this.center), x = pos.x - this.bubble.offsetWidth / 2, y = pos.y - this.bubble.offsetHeight / 2;
4624                this.setBubbleScreenPosition(x, y);
4625            }
4626        }
4627        moveLabelScreenPositionBy(deltaX, deltaY) {
4628            if (this.label) {
4629                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;
4630                this.setLabelScreenPosition(x, y);
4631            }
4632        }
4633        moveBubbleScreenPositionBy(deltaX, deltaY) {
4634            if (this.bubble) {
4635                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;
4636                this.setBubbleScreenPosition(x, y);
4637            }
4638        }
4639        setLabelScreenPosition(x, y) {
4640            if (this.label) {
4641                this.label.style.transform = "translate(" + x + "px," + y + "px)";
4642            }
4643        }
4644        setBubbleScreenPosition(x, y) {
4645            if (this.bubble) {
4646                this.bubble.style.transform = "translate(" + x + "px," + y + "px)";
4647            }
4648        }
4649    }
4650
4651    class SchemaRepository extends Repository {
4652        constructor() {
4653            const objectName = "schema";
4654            super(objectName, +objectName + "s");
4655            this.className = "Schema";
4656            this.objectNameSingle = objectName;
4657            this.objectNameMany = objectName + "s";
4658            this.path = objectName + "s/";
4659            this.events = new Events(this);
4660        }
4661        create(schema) {
4662            const defer = jQuery.Deferred();
4663            defer.promise();
4664            const data = {};
4665            data[this.objectNameSingle] = this.encodeData(schema);
4666            this.server
4667                .post(this.path, data)
4668                .done((response) => {
4669                const data = this.decodeData(response);
4670                schema.id = data[this.objectNameSingle].id;
4671                this.objects.push(schema);
4672                this.events.trigger("created");
4673                schema.events.trigger("created");
4674                defer.resolve(schema);
4675            })
4676                .fail(() => {
4677                defer.reject();
4678            });
4679            return defer;
4680        }
4681        update(schema) {
4682            const defer = jQuery.Deferred();
4683            defer.promise();
4684            const data = {};
4685            data[this.objectNameSingle] = this.encodeData(schema);
4686            this.server
4687                .put(this.path + schema.id, data)
4688                .done((response) => {
4689                const data = this.decodeData(response);
4690                this.objects.push(schema);
4691                defer.resolve(schema);
4692                this.events.trigger("changed");
4693                schema.events.trigger("changed");
4694            })
4695                .fail(() => {
4696                defer.reject();
4697            });
4698            return defer;
4699        }
4700        encodeData(schema) {
4701            const _schema = schema.getData();
4702            let fieldsJsonString = JSON.stringify(_schema);
4703            fieldsJsonString = fieldsJsonString.replace(/select/g, "!mapsvg-encoded-slct");
4704            fieldsJsonString = fieldsJsonString.replace(/table/g, "!mapsvg-encoded-tbl");
4705            fieldsJsonString = fieldsJsonString.replace(/database/g, "!mapsvg-encoded-db");
4706            fieldsJsonString = fieldsJsonString.replace(/varchar/g, "!mapsvg-encoded-vc");
4707            return JSON.parse(fieldsJsonString);
4708        }
4709    }
4710
4711    const $$8 = jQuery;
4712    class Controller {
4713        constructor(options) {
4714            this.containers = {
4715                main: options.container,
4716            };
4717            this.mapsvg = options.mapsvg;
4718            this.template = options.template || "";
4719            this.scrollable = options.scrollable === undefined ? true : options.scrollable;
4720            this.withToolbar = options.withToolbar === undefined ? true : options.withToolbar;
4721            this.autoresize = MapSVG.parseBoolean(options.autoresize);
4722            this.templates = {
4723                toolbar: Handlebars.compile(this.getToolbarTemplate()),
4724                main: Handlebars.compile(this.getMainTemplate()),
4725            };
4726            this.data = options.data;
4727            this.width = options.width;
4728            this.color = options.color;
4729            this.events = new Events(this);
4730            if (options.events) {
4731                for (const eventName in options.events) {
4732                    if (typeof options.events[eventName] === "function") {
4733                        this.events.on(eventName, options.events[eventName]);
4734                    }
4735                }
4736            }
4737        }
4738        viewDidLoad() {
4739            const _this = this;
4740            _this.updateScroll();
4741            if (this.autoresize) {
4742                _this.adjustHeight();
4743                this.resizeSensor.setScroll();
4744            }
4745        }
4746        _viewDidLoad() {
4747            this.updateScroll();
4748        }
4749        viewDidAppear() { }
4750        viewDidDisappear() { }
4751        updateScroll() {
4752            if (!this.scrollable)
4753                return;
4754            const _this = this;
4755            $$8(this.containers.contentWrap).nanoScroller({
4756                preventPageScrolling: true,
4757                iOSNativeScrolling: true,
4758            });
4759            setTimeout(function () {
4760                $$8(_this.containers.contentWrap).nanoScroller({
4761                    preventPageScrolling: true,
4762                    iOSNativeScrolling: true,
4763                });
4764            }, 300);
4765        }
4766        adjustHeight() {
4767            const _this = this;
4768            $$8(_this.containers.main).height($$8(_this.containers.main).find(".mapsvg-auto-height").outerHeight() +
4769                (_this.containers.toolbar ? $$8(_this.containers.toolbar).outerHeight() : 0));
4770        }
4771        _init() {
4772            const _this = this;
4773            _this.render();
4774            _this.init();
4775        }
4776        init() { }
4777        getToolbarTemplate() {
4778            return "";
4779        }
4780        setMainTemplate(template) {
4781            return (this.templates.main = Handlebars.compile(template));
4782        }
4783        getMainTemplate() {
4784            return this.template;
4785        }
4786        render() {
4787            const _this = this;
4788            this.containers.view = $$8("<div />")
4789                .attr("id", "mapsvg-controller-" + this.name)
4790                .addClass("mapsvg-controller-view")[0];
4791            this.containers.contentWrap = $$8("<div />").addClass("mapsvg-controller-view-wrap")[0];
4792            this.containers.contentWrap2 = $$8("<div />")[0];
4793            this.containers.sizer = $$8("<div />").addClass("mapsvg-auto-height")[0];
4794            this.containers.contentView = $$8("<div />").addClass("mapsvg-controller-view-content")[0];
4795            this.containers.sizer.appendChild(this.containers.contentView);
4796            if (this.scrollable) {
4797                $$8(this.containers.contentWrap).addClass("nano");
4798                $$8(this.containers.contentWrap2).addClass("nano-content");
4799            }
4800            this.containers.contentWrap.appendChild(this.containers.contentWrap2);
4801            this.containers.contentWrap2.appendChild(this.containers.sizer);
4802            if (this.withToolbar && this.templates.toolbar) {
4803                this.containers.toolbar = $$8("<div />").addClass("mapsvg-controller-view-toolbar")[0];
4804                this.containers.view.appendChild(this.containers.toolbar);
4805            }
4806            this.containers.view.append(this.containers.contentWrap);
4807            this.containers.main.appendChild(this.containers.view);
4808            $$8(this.containers.main).data("controller", this);
4809            if (this.width)
4810                this.containers.view.style.width = this.width;
4811            if (this.color)
4812                this.containers.view.style["background-color"] = this.color;
4813            _this.viewReadyToFill();
4814            this.redraw();
4815            setTimeout(function () {
4816                _this._viewDidLoad();
4817                _this.viewDidLoad();
4818                _this.setEventHandlersCommon();
4819                _this.setEventHandlers();
4820            }, 1);
4821        }
4822        viewReadyToFill() {
4823            const _this = this;
4824            if (_this.autoresize) {
4825                _this.resizeSensor = new ResizeSensor(this.containers.sizer[0], function () {
4826                    _this.adjustHeight();
4827                    _this.updateScroll();
4828                    _this.events.trigger("resize", this, [this]);
4829                });
4830            }
4831        }
4832        redraw(data) {
4833            if (data !== undefined) {
4834                this.data = data;
4835            }
4836            try {
4837                $$8(this.containers.contentView).html(this.templates.main(this.data));
4838            }
4839            catch (err) {
4840                console.error(err);
4841                $$8(this.containers.contentView).html("");
4842            }
4843            if (this.withToolbar && this.templates.toolbar)
4844                $$8(this.containers.toolbar).html(this.templates.toolbar(this.data));
4845            this.updateTopShift();
4846            if (this.noPadding)
4847                this.containers.contentView.style.padding = "0";
4848            this.updateScroll();
4849        }
4850        updateTopShift() {
4851            const _this = this;
4852            if (!this.withToolbar)
4853                return;
4854            $$8(_this.containers.contentWrap).css({
4855                top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
4856            });
4857            setTimeout(function () {
4858                $$8(_this.containers.contentWrap).css({
4859                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
4860                });
4861            }, 100);
4862            setTimeout(function () {
4863                $$8(_this.containers.contentWrap).css({
4864                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
4865                });
4866            }, 200);
4867            setTimeout(function () {
4868                $$8(_this.containers.contentWrap).css({
4869                    top: $$8(_this.containers.toolbar).outerHeight(true) + "px",
4870                });
4871                _this.updateScroll();
4872            }, 500);
4873        }
4874        setEventHandlersCommon() { }
4875        setEventHandlers() { }
4876        destroy() {
4877            delete this.resizeSensor;
4878            $$8(this.containers.view).empty().remove();
4879        }
4880    }
4881
4882    const $$9 = jQuery;
4883    class DirectoryController extends Controller {
4884        constructor(options) {
4885            super(options);
4886            this.repository = options.repository;
4887            this.noPadding = true;
4888            this.position = options.position;
4889            this.search = options.search;
4890        }
4891        getToolbarTemplate() {
4892            let t = '<div class="mapsvg-directory-search-wrap">';
4893            t += '<div class="mapsvg-directory-filter-wrap filter-wrap"></div>';
4894            t += "</div>";
4895            t += "</div>";
4896            return t;
4897        }
4898        viewDidLoad() {
4899            const _this = this;
4900            this.menuBtn = $$9('<div class="mapsvg-button-menu"><i class="mapsvg-icon-menu"></i> ' +
4901                this.mapsvg.options.mobileView.labelList +
4902                "</div>")[0];
4903            this.mapBtn = $$9('<div class="mapsvg-button-map"><i class="mapsvg-icon-map"></i> ' +
4904                this.mapsvg.options.mobileView.labelMap +
4905                "</div>")[0];
4906            if (MapSVG.isPhone && _this.mapsvg.options.menu.hideOnMobile) {
4907                if (this.mapsvg.options.menu.showFirst == "map") {
4908                    this.toggle(false);
4909                }
4910                else {
4911                    this.toggle(true);
4912                }
4913            }
4914            this.mobileButtons = $$9('<div class="mapsvg-mobile-buttons"></div>')[0];
4915            this.mobileButtons.append(this.menuBtn, this.mapBtn);
4916            if (this.mapsvg.options.menu.on !== false) {
4917                this.mapsvg.containers.wrapAll.appendChild(this.mobileButtons);
4918            }
4919            this.events.trigger("shown", this.containers.view);
4920        }
4921        setEventHandlers() {
4922            const _this = this;
4923            $$9(window).on("resize", function () {
4924                _this.updateTopShift();
4925            });
4926            $$9(this.menuBtn).on("click", function () {
4927                _this.toggle(true);
4928            });
4929            $$9(this.mapBtn).on("click", function () {
4930                _this.toggle(false);
4931                _this.mapsvg.redraw();
4932            });
4933            $$9(this.containers.view)
4934                .on("click.menu.mapsvg", ".mapsvg-directory-item", function (e) {
4935                if (e.target.nodeName == "A") {
4936                    return;
4937                }
4938                e.preventDefault();
4939                const objID = $$9(this).data("object-id");
4940                let regions;
4941                let marker;
4942                let detailsViewObject;
4943                let eventObject;
4944                _this.deselectItems();
4945                _this.selectItems(objID);
4946                if (MapSVG.isPhone && _this.mapsvg.options.menu.showMapOnClick) {
4947                    _this.toggle(false);
4948                }
4949                if (_this.mapsvg.options.menu.source == "regions") {
4950                    regions = [_this.mapsvg.getRegion(objID)];
4951                    eventObject = regions[0];
4952                    detailsViewObject = regions[0];
4953                }
4954                else {
4955                    detailsViewObject = _this.repository.getLoadedObject(objID);
4956                    eventObject = detailsViewObject;
4957                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
4958                    if (_regions) {
4959                        regions = _regions
4960                            .map(function (region) {
4961                            return _this.mapsvg.getRegion(region.id);
4962                        })
4963                            .filter(function (r) {
4964                            return r !== undefined;
4965                        });
4966                    }
4967                }
4968                if (detailsViewObject.location && detailsViewObject.location.marker)
4969                    marker = detailsViewObject.location.marker;
4970                if (_this.mapsvg.options.actions.directoryItem.click.showDetail
4970s) {
4971                    _this.mapsvg.loadDetailsView(detailsViewObject);
4972                }
4973                if (regions && regions.length > 0) {
4974                    if (_this.mapsvg.options.actions.directoryItem.click.zoom) {
4975                        _this.mapsvg.zoomTo(regions, _this.mapsvg.options.actions.directoryItem.click.zoomToLevel);
4976                    }
4977                    if (regions.length > 1) {
4978                        _this.mapsvg.setMultiSelect(true);
4979                    }
4980                    regions.forEach(function (region) {
4981                        const center = region.getCenter();
4982                        e.clientX = center[0];
4983                        e.clientY = center[1];
4984                        if (_this.mapsvg.options.actions.directoryItem.click.selectRegion) {
4985                            _this.mapsvg.selectRegion(region, true);
4986                        }
4987                        if (_this.mapsvg.options.actions.directoryItem.click.showRegionPopover) {
4988                            if (_this.mapsvg.options.actions.directoryItem.click.zoom) {
4989                                setTimeout(function () {
4990                                    _this.mapsvg.showPopover(region);
4991                                }, 500);
4992                            }
4993                            else {
4994                                _this.mapsvg.showPopover(region);
4995                            }
4996                        }
4997                        if (_this.mapsvg.options.actions.directoryItem.click.fireRegionOnClick) {
4998                            _this.mapsvg.events.trigger("click.region", region, [region]);
4999                        }
5000                    });
5001                    if (regions.length > 1) {
5002                        _this.mapsvg.setMultiSelect(false, false);
5003                    }
5004                }
5005                if (marker) {
5006                    if (_this.mapsvg.options.actions.directoryItem.click.zoomToMarker) {
5007                        _this.mapsvg.zoomTo(marker, _this.mapsvg.options.actions.directoryItem.click.zoomToMarkerLevel);
5008                    }
5009                    if (_this.mapsvg.options.actions.directoryItem.click.showMarkerPopover) {
5010                        if (_this.mapsvg.options.actions.directoryItem.click.zoomToMarker) {
5011                            setTimeout(function () {
5012                                _this.mapsvg.showPopover(detailsViewObject);
5013                            }, 500);
5014                        }
5015                        else {
5016                            _this.mapsvg.showPopover(detailsViewObject);
5017                        }
5018                    }
5019                    if (_this.mapsvg.options.actions.directoryItem.click.fireMarkerOnClick) {
5020                        _this.mapsvg.events.trigger("click.marker", marker, [e, _this.mapsvg]);
5021                    }
5022                    _this.mapsvg.selectMarker(marker);
5023                }
5024                _this.events.trigger("click", this, [e, eventObject, _this.mapsvg]);
5025                const actions = _this.mapsvg.options.actions;
5026                if (actions.directoryItem.click.goToLink) {
5027                    const linkParts = actions.directoryItem.click.linkField.split(".");
5028                    let url;
5029                    if (linkParts.length > 1) {
5030                        const obj = linkParts.shift();
5031                        const attr = "." + linkParts.join(".");
5032                        if (obj == "Region") {
5033                            if (regions[0] && regions[0].data)
5034                                url = eval("regions[0].data" + attr);
5035                        }
5036                        else {
5037                            if (detailsViewObject)
5038                                url = eval("detailsViewObject" + attr);
5039                        }
5040                        if (url) {
5041                            if (actions.directoryItem.click.newTab) {
5042                                const win = window.open(url, "_blank");
5043                                win.focus();
5044                            }
5045                            else {
5046                                window.location.href = url;
5047                            }
5048                        }
5049                    }
5050                }
5051                if (actions.directoryItem.click.showAnotherMap) {
5052                    if (_this.mapsvg.editMode) {
5053                        alert('"Show another map" action is disabled in the preview');
5054                        return true;
5055                    }
5056                    const linkParts2 = actions.directoryItem.click.showAnotherMapField.split(".");
5057                    if (linkParts2.length > 1) {
5058                        const obj2 = linkParts2.shift();
5059                        const attr2 = "." + linkParts2.join(".");
5060                        let map_id;
5061                        if (obj2 == "Region") {
5062                            if (regions[0] && regions[0].data)
5063                                map_id = eval("regions[0].data" + attr2);
5064                        }
5065                        else {
5066                            if (detailsViewObject)
5067                                map_id = eval("detailsViewObject" + attr2);
5068                        }
5069                        if (map_id) {
5070                            const container = actions.directoryItem.click.showAnotherMapContainerId
5071                                ? $$9("#" + actions.directoryItem.click.showAnotherMapContainerId)[0]
5072                                : $$9(_this.mapsvg.containers.map)[0];
5073                            _this.mapsvg.loadMap(map_id, container);
5074                        }
5075                    }
5076                }
5077            })
5078                .on("mouseover.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5079                const objID = $$9(this).data("object-id");
5080                let regions;
5081                let detailsViewObject;
5082                let eventObject;
5083                let marker;
5084                if (_this.mapsvg.options.menu.source == "regions") {
5085                    regions = [_this.mapsvg.getRegion(objID)];
5086                    eventObject = regions[0];
5087                    detailsViewObject = regions[0];
5088                }
5089                else {
5090                    detailsViewObject = _this.repository.getLoadedObject(objID);
5091                    eventObject = detailsViewObject;
5092                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5093                    if (_regions) {
5094                        regions = _regions.map(function (region) {
5095                            return _this.mapsvg.getRegion(region.id);
5096                        });
5097                    }
5098                    if (detailsViewObject.location) {
5099                        marker = detailsViewObject.location.marker;
5100                    }
5101                }
5102                if (regions && regions.length) {
5103                    _this.mapsvg.highlightRegions(regions);
5104                }
5105                if (marker) {
5106                    _this.mapsvg.highlightMarker(marker);
5107                    if (_this.mapsvg.options.actions.directoryItem.hover.centerOnMarker) {
5108                        _this.mapsvg.centerOn(marker);
5109                    }
5110                }
5111                _this.events.trigger("mouseover", $$9(this), [e, eventObject, _this.mapsvg]);
5112            })
5113                .on("mouseout.menu.mapsvg", ".mapsvg-directory-item", function (e) {
5114                const objID = $$9(this).data("object-id");
5115                let regions;
5116                let detailsViewObject;
5117                let eventObject;
5118                let marker;
5119                if (_this.mapsvg.options.menu.source == "regions") {
5120                    regions = [_this.mapsvg.getRegion(objID)];
5121                    eventObject = regions[0];
5122                    detailsViewObject = regions[0];
5123                }
5124                else {
5125                    detailsViewObject = _this.repository.getLoadedObject(objID);
5126                    eventObject = detailsViewObject;
5127                    const _regions = detailsViewObject.getRegions(_this.mapsvg.regionsRepository.schema.name);
5128                    if (_regions) {
5129                        regions = _regions.map(function (region) {
5130                            return _this.mapsvg.getRegion(region.id);
5131                        });
5132                    }
5133                    if (detailsViewObject.location) {
5134                        marker = detailsViewObject.location.marker;
5135                    }
5136                }
5137                if (regions && regions.length) {
5138                    _this.mapsvg.unhighlightRegions();
5139                }
5140                if (marker) {
5141                    _this.mapsvg.unhighlightMarker();
5142                }
5143                _this.events.trigger("mouseout", $$9(this), [e, eventObject, _this.mapsvg]);
5144            });
5145            $$9(this.containers.contentView).on("click", ".mapsvg-category-item", function () {
5146                const panel = $$9(this).next(".mapsvg-category-block");
5147                if (panel[0].style.maxHeight || panel.hasClass("active")) {
5148                    panel[0].style.maxHeight = null;
5149                }
5150                else {
5151                    panel[0].style.maxHeight = panel[0].scrollHeight + "px";
5152                }
5153                if ($$9(this).hasClass("active")) {
5154                    $$9(this).toggleClass("active", false);
5155                    $$9(this).next(".mapsvg-category-block").addClass("collapsed").removeClass("active");
5156                }
5157                else {
5158                    if (_this.mapsvg.options.menu.categories.collapseOther) {
5159                        $$9(this).parent().find(".mapsvg-category-item.active").removeClass("active");
5160                        $$9(this)
5161                            .parent()
5162                            .find(".mapsvg-category-block.active")
5163                            .removeClass("active")
5164                            .addClass("collapsed");
5165                    }
5166                    $$9(this).toggleClass("active", true);
5167                    $$9(this).next(".mapsvg-category-block").removeClass("collapsed").addClass("active");
5168                }
5169                const panels = $$9(".mapsvg-category-block.collapsed");
5170                panels.each(function (i, panel) {
5171                    panel.style.maxHeight = null;
5172                });
5173            });
5174        }
5175        highlightItems(ids) {
5176            const _this = this;
5177            if (typeof ids != "object")
5178                ids = [ids];
5179            ids.forEach(function (id) {
5180                $$9(_this.containers.view)
5181                    .find("#mapsvg-directory-item-" + id)
5182                    .addClass("hover");
5183            });
5184        }
5185        unhighlightItems() {
5186            $$9(this.containers.view).find(".mapsvg-directory-item").removeClass("hover");
5187        }
5188        selectItems(ids) {
5189            const _this = this;
5190            if (typeof ids != "object")
5191                ids = [ids];
5192            ids.forEach(function (id) {
5193                $$9(_this.containers.view)
5194                    .find("#mapsvg-directory-item-" + id)
5195                    .addClass("selected");
5196            });
5197            if ($$9("#mapsvg-directory-item-" + ids[0]).length > 0) {
5198                _this.scrollable &&
5199                    $$9(_this.containers.contentWrap).nanoScroller({
5200                        scrollTo: $$9(_this.containers.view).find("#mapsvg-directory-item-" + ids[0]),
5201                    });
5202            }
5203        }
5204        deselectItems() {
5205            $$9(this.containers.view).find(".mapsvg-directory-item").removeClass("selected");
5206        }
5207        removeItems(ids) {
5208            $$9(this.containers.view)
5209                .find("#mapsvg-directory-item-" + ids)
5210                .remove();
5211        }
5212        filterOut(items) {
5213            return items;
5214        }
5215        loadItemsToDirectory() {
5216            let items = [];
5217            const _this = this;
5218            if (!_this.repository.loaded)
5219                return false;
5220            if (_this.mapsvg.options.menu.categories &&
5221                _this.mapsvg.options.menu.categories.on &&
5222                _this.mapsvg.options.menu.categories.groupBy) {
5223                const categoryField = _this.mapsvg.options.menu.categories.groupBy;
5224                if (_this.repository.getSchema().getField(categoryField) === undefined ||
5225                    _this.repository.getSchema().getField(categoryField).options === undefined) {
5226                    return false;
5227                }
5228                const categories = _this.repository.getSchema().getField(categoryField).options;
5229                categories.forEach(function (category) {
5230                    let dbItems = _this.repository.getLoaded();
5231                    dbItems = _this.filterOut(dbItems);
5232                    const itemArr = [];
5233                    dbItems.forEach((item) => {
5234                        itemArr.push(item);
5235                    });
5236                    const catItems = itemArr.filter(function (object) {
5237                        if (categoryField === "regions") {
5238                            const objectRegions = typeof object[categoryField] !== "undefined" &&
5239                                object[categoryField].length
5240                                ? object[categoryField]
5241                                : [];
5242                            const objectRegionIDs = objectRegions.map(function (region) {
5243                                return region.id;
5244                            });
5245                            return objectRegionIDs.indexOf(category.id) !== -1;
5246                        }
5247                        else {
5248                            return object[categoryField] == category.value;
5249                        }
5250                    });
5251                    category.counter = catItems.length;
5252                    if (categoryField === "regions") {
5253                        category.label = category.title;
5254                        category.value = category.id;
5255                    }
5256                    items.push({ category: category, items: catItems });
5257                });
5258                if (_this.mapsvg.options.menu.categories.hideEmpty) {
5259                    items = items.filter(function (item) {
5260                        return item.category.counter > 0;
5261                    });
5262                }
5263            }
5264            else {
5265                if (_this.mapsvg.options.menu.source === "regions") {
5266                    items = _this.repository.getLoaded().map((r) => {
5267                        const data = r.getData();
5268                        data.objects = _this.mapsvg.getRegion(data.id).objects;
5269                        return data;
5270                    });
5271                }
5272                else {
5273                    items = _this.repository
5274                        .getLoaded()
5275                        .map((r) => r.getData(_this.mapsvg.regionsRepository.schema.name));
5276                }
5277            }
5278            try {
5279                $$9(this.containers.contentView).html(this.templates.main({ items: items }));
5280            }
5281            catch (err) {
5282                console.error('MapSVG: Error in the "Directory item" template');
5283                console.error(err);
5284            }
5285            if (items.length === 0) {
5286                $$9(this.containers.contentView).html('<div class="mapsvg-no-results">' +
5287                    this.mapsvg.options.menu.noResultsText +
5288                    "</div>");
5289            }
5290            if (_this.mapsvg.options.menu.categories.on) {
5291                if (_this.mapsvg.options.menu.categories.collapse && items.length > 1) {
5292                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("collapsed");
5293                }
5294                else if (_this.mapsvg.options.menu.categories.collapse && items.length === 1) {
5295                    $$9(this.containers.contentView).find(".mapsvg-category-item").addClass("active");
5296                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("active");
5297                    const panel = $$9(this.containers.contentView).find(".mapsvg-category-block")[0];
5298                    panel.style.maxHeight = panel.scrollHeight + "px";
5299                }
5300                else if (!_this.mapsvg.options.menu.categories.collapse) {
5301                    $$9(this.containers.contentView).find(".mapsvg-category-item").addClass("active");
5302                    $$9(this.containers.contentView).find(".mapsvg-category-block").addClass("active");
5303                    const panels = $$9(this.containers.contentView).find(".mapsvg-category-block");
5304                    panels.each(function (i, panel) {
5305                        panel.style.maxHeight = panel.scrollHeight + "px";
5306                    });
5307                }
5308            }
5309            this.updateTopShift();
5310            this.updateScroll();
5311        }
5312        toggle(on) {
5313            const _this = this;
5314            if (on) {
5315                $$9(this.containers.main).parent().show();
5316                $$9(_this.mapsvg.containers.mapContainer).hide();
5317                $$9(this.menuBtn).addClass("active");
5318                $$9(this.mapBtn).removeClass("active");
5319            }
5320            else {
5321                $$9(this.containers.main).parent().hide();
5322                $$9(_this.mapsvg.containers.mapContainer).show();
5323                $$9(this.menuBtn).removeClass("active");
5324                $$9(this.mapBtn).addClass("active");
5325            }
5326            if (!$$9(this.containers.main).parent().is(":visible")) {
5327                if (MapSVG.isPhone) {
5328                    $$9(_this.mapsvg.containers.wrap).css("height", "auto");
5329                    _this.updateScroll();
5330                }
5331            }
5332            else {
5333                if (MapSVG.isPhone &&
5334                    $$9(this.containers.main).height() < parseInt(this.mapsvg.options.menu.minHeight)) {
5335                    $$9(_this.mapsvg.containers.wrap).css("height", parseInt(this.mapsvg.options.menu.minHeight) + "px");
5336                    _this.updateScroll();
5337                }
5338            }
5339            this.updateTopShift();
5340        }
5341        addPagination(pager) {
5342            $$9(this.containers.contentView).append('<div class="mapsvg-pagination-container"></div>');
5343            $$9(this.containers.contentView).find(".mapsvg-pagination-container").html(pager);
5344        }
5345    }
5346
5347    const $$a = jQuery;
5348    class DetailsController extends Controller {
5349        constructor(options) {
5350            super(options);
5351            this.modal = options.modal;
5352        }
5353        getToolbarTemplate() {
5354            if (this.withToolbar)
5355                return '<div class="mapsvg-popover-close mapsvg-details-close"></div>';
5356            else
5357                return "";
5358        }
5359        viewDidLoad() {
5360            const _this = this;
5361            this.events.trigger("shown", _this, [_this]);
5362            if (this.modal &&
5363                MapSVG.isPhone &&
5364                this.mapsvg.options.detailsView.mobileFullscreen &&
5365                !this.mobileCloseBtn) {
5366                this.mobileCloseBtn = $$a('<button class="mapsvg-mobile-modal-close mapsvg-btn">' +
5367                    _this.mapsvg.options.mobileView.labelClose +
5368                    "</button>")[0];
5369                this.containers.view.appendChild(this.mobileCloseBtn);
5370            }
5371        }
5372        setEventHandlers() {
5373            const _this = this;
5374            $$a(this.containers.toolbar).on("click", ".mapsvg-popover-close, .mapsvg-mobile-modal-close", function (e) {
5375                e.stopPropagation();
5376                _this.destroy();
5377                _this.events.trigger("closed", _this, [_this]);
5378            });
5379        }
5380    }
5381
5382    const $$b = jQuery;
5383    class FormElement {
5384        constructor(options, formBuilder, external) {
5385            this.readonly = typeof options.readonly !== "undefined" ? options.readonly : false;
5386            this.protected = typeof options.protected !== "undefined" ? options.protected : false;
5387            this.auto_increment =
5388                typeof options.auto_increment !== "undefined" ? options.auto_increment : false;
5389            this.not_null = typeof options.not_null !== "undefined" ? options.not_null : false;
5390            this.searchable = typeof options.searchable !== "undefined" ? options.searchable : false;
5391            this.visible = typeof options.visible !== "undefined" ? options.visible : true;
5392            this.formBuilder = formBuilder;
5393            this.events = new Events(this);
5394            this.type = options.type;
5395            this.value = options.value;
5396            this.db_type = options.db_type || "varchar(255)";
5397            this.label = this.label || (options.label === undefined ? "Label" : options.label);
5398            this.name = this.name || options.name || "label";
5399            this.help = options.help || "";
5400            this.placeholder = options.placeholder;
5401            this.setExternal(external);
5402            let t = this.type;
5403            if (t === "marker" && this.mapIsGeo) {
5404                t = "marker-geo";
5405            }
5406            if (t === "location" && this.mapIsGeo) {
5407                t = "location-geo";
5408            }
5409            if (this.filtersMode) {
5410                this.parameterName = options.parameterName || "";
5411                this.parameterNameShort = this.parameterName.split(".")[1];
5412                this.name = this.parameterNameShort;
5413                this.placeholder = options.placeholder || "";
5414                this.templates = {
5415                    main: Handlebars.compile($$b("#mapsvg-filters-tmpl-" + t + "-view").html()),
5416                };
5417            }
5418            else {
5419                this.templates = {
5420                    main: Handlebars.compile($$b("#mapsvg-data-tmpl-" + t + "-view").html()),
5421                };
5422            }
5423            this.inputs = {};
5424        }
5425        init() {
5426            this.setDomElements();
5427            this.setEventHandlers();
5428        }
5429        setDomElements() {
5430            this.domElements = {
5431                main: $$b(this.templates.main(this.getDataForTemplate()))[0],
5432            };
5433            $$b(this.domElements.main).data("formElement", this);
5434            this.addSelect2();
5435        }
5436        setEventHandlers() {
5437            const _this = this;
5438            if (this.formBuilder.editMode) {
5439                $$b(this.domElements.main).on("click", function () {
5440                    _this.events.trigger("click", _this, [_this]);
5441                });
5442            }
5443        }
5444        addSelect2() {
5445            if ($$b().mselect2) {
5446                $$b(this.domElements.main)
5447                    .find("select")
5448                    .css({ width: "100%", display: "block" })
5449                    .mselect2()
5450                    .on("select2:focus", function () {
5451                    $$b(this).mselect2("open");
5452                });
5453                $$b(this.domElements.main)
5454                    .find(".select2-selection--multiple .select2-search__field")
5455                    .css("width", "100%");
5456            }
5457        }
5458        setEditorEventHandlers() {
5459            const _this = this;
5460            $$b(this.domElements.edit).on("click", "button.mapsvg-remove", function () {
5461                $$b(_this.domElements.main).empty().remove();
5462                $$b(_this.domElements.edit).empty().remove();
5463                _this.events.trigger("delete", _this, [_this]);
5464            });
5465            $$b(this.domElements.edit).on("click", ".mapsvg-filter-insert-options", function () {
5466                const objType = _this.parameterName.split(".")[0];
5467                const fieldName = _this.parameterName.split(".")[1];
5468                let field;
5469                if (objType == "Object") {
5470                    field = _this.formBuilder.mapsvg.objectsRepository.getSchema().getField(fieldName);
5471                }
5472                else {
5473                    if (fieldName == "id") {
5474                        const options = [];
5475                        _this.formBuilder.mapsvg.regions.forEach(function (r) {
5476                            options.push({ label: r.id, value: r.id });
5477                        });
5478                        field = {
5479                            options: options,
5480                        };
5481                    }
5482                    else if (fieldName == "region_title") {
5483                        const options = [];
5484                        _this.formBuilder.mapsvg.regions.forEach(function (r) {
5485                            options.push({ label: r.title, value: r.title });
5486                        });
5487                        field = { options: options };
5488                    }
5489                    else {
5490                        field = _this.formBuilder.mapsvg.regionsRepository
5491                            .getSchema()
5492                            .getField(fieldName);
5493                    }
5494                }
5495                if (field && field.options) {
5496                    let options;
5497                    if (fieldName == "regions") {
5498                        if (field.options[0].title && field.options[0].title.length)
5499                            field.options.sort(function (a, b) {
5500                                if (a.title < b.title)
5501                                    return -1;
5502                                if (a.title > b.title)
5503                                    return 1;
5504                                return 0;
5505                            });
5506                        options = field.options.map(function (o) {
5507                            return (o.title || o.id) + ":" + o.id;
5508                        });
5509                    }
5510                    else {
5511                        options = field.options.map(function (o) {
5512                            return o.label + ":" + o.value;
5513                        });
5514                    }
5515                    $$b(this)
5516                        .closest(".form-group")
5517                        .find("textarea")
5518                        .val(options.join("\n"))
5519                        .trigger("change");
5520                }
5521            });
5522            $$b(this.domElements.edit).on("keyup change paste", "input, textarea, select", function () {
5523                const prop = $$b(this).attr("name");
5524                const array = $$b(this).data("array");
5525                if (_this.type === "status" && array) {
5526                    const param = $$b(this).data("param");
5527                    const index = $$b(this).closest("tr").index();
5528                    _this.options[index] = _this.options[index] || {
5529                        label: "",
5530                        value: "",
5531                        color: "",
5532                        disabled: false,
5533                    };
5534                    _this.options[index][param] = $$b(this).is(":checkbox")
5535                        ? $$b(this).prop("checked")
5536                        : $$b(this).val();
5537                    _this.redraw();
5538                }
5539                else if (_this.type === "distance" && array) {
5540                    const param = $$b(this).data("param");
5541                    const index = $$b(this).closest("tr").index();
5542                    if (!_this.options[index]) {
5543                        _this.options[index] = { value: "", default: false };
5544                    }
5545                    if (param === "default") {
5546                        _this.options.forEach(function (option) {
5547                            option.default = false;
5548                        });
5549                        _this.options[index].default = $$b(this).prop("checked");
5550                    }
5551                    else {
5552                        _this.options[index].value = $$b(this).val();
5553                    }
5554                    _this.redraw();
5555                }
5556                else if (prop == "label" || prop == "name") {
5557                    return false;
5558                }
5559                else {
5560                    let value;
5561                    value =
5562                        $$b(this).attr("type") == "checkbox" ? $$b(this).prop("checked") : $$b(this).val();
5563                    if ($$b(this).attr("type") == "radio") {
5564                        const name = $$b(this).attr("name");
5565                        value = $$b('input[name="' + name + '"]:checked').val();
5566                    }
5567                    _this.update(prop, value);
5568                }
5569            });
5570            $$b(this.domElements.edit).on("keyup change paste", 'input[name="label"]', function () {
5571                if (!_this.nameChanged) {
5572                    _this.label = $$b(this).val() + "";
5573                    if (_this.type != "region" && _this.type != "location" && _this.type != "title") {
5574                        let str = $$b(this).val() + "";
5575                        str = str.toLowerCase().replace(/ /g, "_").replace(/\W/g, "");
5576                        if (str.length < 64) {
5577                            $$b(_this.domElements.edit).find('input[name="name"]').val(str);
5578                        }
5579                        _this.name = str + "";
5580                    }
5581                    $$b(_this.domElements.main).find("label").first().html(_this.label);
5582                    if (!_this.filtersMode) {
5583                        $$b(_this.domElements.main)
5584                            .find("label")
5585                            .first()
5586                            .append('<div class="field-name">' + _this.name + "</div>");
5587                    }
5588                }
5589            });
5590            $$b(this.domElements.edit).on("keyup change paste", 'input[name="name"]', function (e) {
5591                if (e.target.value) {
5592                    if (e.target.value.match(/[^a-zA-Z0-9_]/g)) {
5593                        e.target.value = e.target.value.replace(/[^a-zA-Z0-9_]/g, "");
5594                        $$b(e.target).trigger("change");
5595                    }
5596                    if (e.target.value[0].match(/[^a-zA-Z_]/g)) {
5597                        e.target.value =
5598                            e.target.value[0].replace(/[^a-zA-Z_]/g, "") + e.target.value.slice(1);
5599                        $$b(e.target).trigger("change");
5600                    }
5601                }
5602                if (_this.type != "region")
5603                    _this.name = e.target.value;
5604                $$b(_this.domElements.main)
5605                    .find("label")
5606                    .html(_this.label + '<div class="field-name">' + _this.name + "</div>");
5607                _this.nameChanged = true;
5608            });
5609            $$b(this.domElements.edit).on("keyup change paste", 'textarea[name="help"]', function (e) {
5610                $$b(_this.domElements.main).find(".form-text").text(e.target.value);
5611            });
5612        }
5613        getEditor() {
5614            if (!this.filtersMode) {
5615                this.templates.edit =
5616                    this.templates.edit ||
5617                        Handlebars.compile($$b("#mapsvg-data-tmpl-" + this.type + "-control").html());
5618            }
5619            else {
5620                this.templates.edit =
5621                    this.templates.edit ||
5622                        Handlebars.compile($$b("#mapsvg-filters-tmpl-" + this.type + "-control").html());
5623            }
5624            this.domElements.edit = $$b("<div>" + this.templates.edit(this.getDataForTemplate()) + "</div>")[0];
5625            return this.domElements.edit;
5626        }
5627        destroyEditor() {
5628            $$b(this.domElements.edit).empty().remove();
5629        }
5630        initEditor() {
5631            $$b(this.domElements.edit).find("input").first().select();
5632            if ($$b().colorpicker) {
5633                $$b(this.domElements.edit)
5634                    .find(".cpicker")
5635                    .colorpicker()
5636                    .on("changeColor.colorpicker", function (event) {
5637                    const input = $$b(this).find("input");
5638                    if (input.val() == "")
5639                        $$b(this).find("i").css({ "background-color": "" });
5640                });
5641            }
5642            if ($$b().mselect2) {
5643                if (this.type !== "distance") {
5644                    $$b(this.domElements.edit)
5645                        .find("select")
5646                        .css({ width: "100%", display: "block" })
5647                        .mselect2();
5648                }
5649            }
5650            this.setEditorEventHandlers();
5651        }
5652        getSchema() {
5653            let data;
5654            data = {
5655                type: this.type,
5656                db_type: this.db_type,
5657                label: this.label,
5658                name: this.name,
5659                value: this.value,
5660                searchable: this.searchable,
5661                help: this.help,
5662                visible: this.visible === undefined ? true : this.visible,
5663                readonly: this.readonly,
5664                placeholder: this.placeholder,
5665                protected: this.protected,
5666                auto_increment: this.auto_increment,
5667                not_null: this.not_null,
5668            };
5669            if (this.options) {
5670                data.options = this.getSchemaFieldOptionsList();
5671            }
5672            if (this.filtersMode) {
5673                data.parameterName = this.parameterName;
5674                data.parameterNameShort = this.parameterName.split(".")[1];
5675            }
5676            return data;
5677        }
5678        getSchemaFieldOptionsList() {
5679            const options = [];
5680            this.options.forEach((option, index) => {
5681                if (this.options[index].value !== "") {
5682                    options.push(this.options[index]);
5683                }
5684            });
5685            return options;
5686        }
5687        getDataForTemplate() {
5688            const data = this.getSchema();
5689            data._name = data.name;
5690            if (this.namespace) {
5691                data.name = this.name.split("[")[0];
5692                let suffix = this.name.split("[")[1] || "";
5693                if (suffix)
5694                    suffix = "[" + suffix;
5695                data.name = this.namespace + "[" + data.name + "]" + suffix;
5696            }
5697            data.external = this.external;
5698            return data;
5699        }
5700        update(prop, value) {
5701            const _this = this;
5702            if (prop == "options") {
5703                const options = [];
5704                value = value.split("\n").forEach(function (row) {
5705                    row = row.trim().split(":");
5706                    if (_this.type == "checkbox" && row.length == 3) {
5707                        options.push({
5708                            label: row[0],
5709                            name: row[1],
5710                            value: row[2],
5711                        });
5712                    }
5713                    else if ((_this.type == "radio" ||
5714                        _this.type == "select" ||
5715                        _this.type == "checkboxes") &&
5716                        row.length == 2) {
5717                        options.push({
5718                            label: row[0],
5719                            value: row[1],
5720                        });
5721                    }
5722                });
5723                this.options = options;
5724            }
5725            else {
5726                this[prop] = value;
5727            }
5728            if (prop == "parameterName") {
5729                $$b(this.domElements.edit).find(".mapsvg-filter-param-name").text(value);
5730            }
5731        }
5732        redraw() {
5733            const _this = this;
5734            const newView = $$b(this.templates.main(this.getDataForTemplate()));
5735            $$b(this.domElements.main).html(newView.html());
5736            if ($$b().mselect2) {
5737                if (this.type !== "distance") {
5738                    $$b(this.domElements.main)
5739                        .find("select")
5740                        .css({ width: "100%", display: "block" })
5741                        .mselect2()
5742                        .on("select2:focus", function () {
5743                        $$b(this).mselect2("open");
5744                    });
5745                }
5746                else {
5747                    $$b(this.domElements.main)
5748                        .find("select")
5749                        .mselect2()
5750                        .on("select2:focus", function () {
5751                        $$b(this).mselect2("open");
5752                    });
5753                }
5754            }
5755            if (this.domElements.edit) {
5756                $$b(this.domElements.edit).empty();
5757                $$b(this.domElements.edit).html("<div>" + this.templates.edit(this.getDataForTemplate()) + "</div>");
5758                _this.initEditor();
5759            }
5760        }
5761        setOptions(options) {
5762            if (options) {
5763                this.options = [];
5764                this.optionsDict = {};
5765                options.forEach((value, key) => {
5766                    this.options.push(value);
5767                    this.optionsDict[key] = value;
5768                });
5769                return this.options;
5770            }
5771            else {
5772                return this.setOptions([
5773                    { label: "Option one", name: "option_one", value: 1 },
5774                    { label: "Option two", name: "option_two", value: 2 },
5775                ]);
5776            }
5777        }
5778        getData() {
5779            return { name: this.name, value: this.getValue() };
5780        }
5781        destroy() {
5782            if ($$b().mselect2) {
5783                const sel = $$b(this.domElements.main).find(".mapsvg-select2");
5784                if (sel.length) {
5785                    sel.mselect2("destroy");
5786                }
5787            }
5788        }
5789        show() {
5790            $$b(this.domElements.main).show();
5791        }
5792        hide() {
5793            $$b(this.domElements.main).hide();
5794        }
5795        setExternal(params) {
5796            this.external = params;
5797            if (typeof this.external.mapIsGeo !== "undefined") {
5798                this.mapIsGeo = this.external.mapIsGeo;
5799            }
5800            if (typeof this.external.editMode !== "undefined") {
5801                this.editMode = this.external.editMode;
5802            }
5803            if (typeof this.external.filtersMode !== "undefined") {
5804                this.filtersMode = this.external.filtersMode;
5805            }
5806            if (typeof this.external.namespace !== "undefined") {
5807                this.namespace = this.external.namespace;
5808            }
5809        }
5810        getValue() {
5811            return this.value;
5812        }
5813        setValue(value, updateInput = true) {
5814            this.value = value;
5815            if (updateInput) {
5816                this.setInputValue(value);
5817            }
5818        }
5819        setInputValue(value) {
5820            return;
5821        }
5822        triggerChanged() {
5823            this.events.trigger("changed", this, [this]);
5824        }
5825    }
5826
5827    const $$c = jQuery;
5828    class CheckboxFormElement extends FormElement {
5829        constructor(options, formBuilder, external) {
5830            super(options, formBuilder, external);
5831            if (typeof options.showAsSwitch === "undefined") {
5832                this.showAsSwitch = true;
5833            }
5834            else {
5835                this.showAsSwitch = options.showAsSwitch;
5836            }
5837            this.db_type = "tinyint(1)";
5838            this.checkboxLabel = options.checkboxLabel;
5839            this.checkboxValue = options.checkboxValue;
5840        }
5841        setDomElements() {
5842            super.setDomElements();
5843            this.inputs.checkbox = $$c(this.domElements.main).find("input")[0];
5844            this.inputs.switch = $$c(this.domElements.main).find("input")[0];
5845        }
5846        setEventHandlers() {
5847            super.setEventHandlers();
5848            $$c(this.inputs.checkbox).on("change", (e) => {
5849                this.setValue(e.target.checked, false);
5850                this.triggerChanged();
5851            });
5852        }
5853        setEditorEventHandlers() {
5854            super.setEditorEventHandlers();
5855            $$c(this.domElements.edit).on("change", "[name='showAsSwitch']", (e) => {
5856                if (this.showAsSwitch) {
5857                    $$c(this.domElements.main)
5858                        .find("[name='checkboxToSwitch']")
5859                        .addClass("form-switch form-check form-switch-md");
5860                }
5861                if (!this.showAsSwitch) {
5862                    $$c(this.domElements.main)
5863                        .find("[name='checkboxToSwitch']")
5864                        .removeClass("form-switch form-check form-switch-md");
5865                }
5866            });
5867            $$c(this.domElements.edit).on("keyup change paste", '[name="checkboxLabel"]', 
5867(e) => {
5868                $$c(this.domElements.main).find(".form-check-label").text(e.target.value);
5869            });
5870        }
5871        getSchema() {
5872            const schema = super.getSchema();
5873            if (this.checkboxLabel) {
5874                schema.checkboxLabel = this.checkboxLabel;
5875            }
5876            if (this.checkboxValue) {
5877                schema.checkboxValue = this.checkboxValue;
5878            }
5879            schema.showAsSwitch = this.showAsSwitch;
5880            return schema;
5881        }
5882        setInputValue(value) {
5883            this.inputs.checkbox.checked = value === true;
5884        }
5885    }
5886
5887    const $$d = jQuery;
5888    class CheckboxesFormElement extends FormElement {
5889        constructor(options, formBuilder, external) {
5890            super(options, formBuilder, external);
5891            this.db_type = "text";
5892            this.checkboxLabel = options.checkboxLabel;
5893            this.setOptions(options.options);
5894        }
5895        setDomElements() {
5896            super.setDomElements();
5897            this.$checkboxes = $$d(this.domElements.main).find('input[type="checkbox"]');
5898            this.setInputValue(this.value || []);
5899        }
5900        setEventHandlers() {
5901            super.setEventHandlers();
5902            this.$checkboxes.on("change", (e) => {
5903                const values = [];
5904                $$d(this.domElements.main)
5905                    .find("input:checked")
5906                    .each((i, el) => {
5907                    values.push(jQuery(el).attr("value"));
5908                });
5909                this.setValue(values, false);
5910                this.triggerChanged();
5911            });
5912        }
5913        setInputValue(values) {
5914            values.forEach((value) => {
5915                $$d(this.domElements.main).find(`input[value="${value}"]`).prop("checked", true);
5916            });
5917        }
5918    }
5919
5920    const $$e = jQuery;
5921    class DateFormElement extends FormElement {
5922        constructor(options, formBuilder, external) {
5923            super(options, formBuilder, external);
5924            if (this.formBuilder.admin) {
5925                this.languages = [
5926                    "en-GB",
5927                    "ar",
5928                    "az",
5929                    "bg",
5930                    "bs",
5931                    "ca",
5932                    "cs",
5933                    "cy",
5934                    "da",
5935                    "de",
5936                    "el",
5937                    "es",
5938                    "et",
5939                    "eu",
5940                    "fa",
5941                    "fi",
5942                    "fo",
5943                    "fr",
5944                    "gl",
5945                    "he",
5946                    "hr",
5947                    "hu",
5948                    "hy",
5949                    "id",
5950                    "is",
5951                    "it",
5952                    "ja",
5953                    "ka",
5954                    "kh",
5955                    "kk",
5956                    "kr",
5957                    "lt",
5958                    "lv",
5959                    "mk",
5960                    "ms",
5961                    "nb",
5962                    "nl",
5963                    "nl-BE",
5964                    "no",
5965                    "pl",
5966                    "pt-BR",
5967                    "pt",
5968                    "ro",
5969                    "rs",
5970                    "rs-latin",
5971                    "ru",
5972                    "sk",
5973                    "sl",
5974                    "sq",
5975                    "sr",
5976                    "sr-latin",
5977                    "sv",
5978                    "sw",
5979                    "th",
5980                    "tr",
5981                    "uk",
5982                    "vi",
5983                    "zh-CN",
5984                    "zh-TW",
5985                ];
5986            }
5987            this.db_type = "varchar(50)";
5988            this.language = options.language;
5989        }
5990        setDomElements() {
5991            super.setDomElements();
5992            this.inputs.date = $$e(this.domElements.main).find("input")[0];
5993        }
5994        setEventHandlers() {
5995            super.setEventHandlers();
5996            $$e(this.inputs.date).on("change", (e) => {
5997                this.setValue(e.target.value, false);
5998                this.triggerChanged();
5999            });
6000        }
6001        getSchema() {
6002            const schema = super.getSchema();
6003            schema.language = this.language;
6004            return schema;
6005        }
6006        getDataForTemplate() {
6007            const data = super.getDataForTemplate();
6008            if (this.formBuilder.admin)
6009                data.languages = this.languages;
6010            data.language = this.language;
6011            return data;
6012        }
6013    }
6014
6015    const $$f = jQuery;
6016    class DistanceFormElement extends FormElement {
6017        constructor(options, formBuilder, external) {
6018            super(options, formBuilder, external);
6019            this.name = "distance";
6020            this.label = this.label || (options.label === undefined ? "Search radius" : options.label);
6021            this.distanceControl = options.distanceControl || "select";
6022            this.distanceUnits = options.distanceUnits || "km";
6023            this.distanceUnitsLabel = options.distanceUnitsLabel || "km";
6024            this.fromLabel = options.fromLabel || "from";
6025            this.placeholder = options.placeholder;
6026            this.userLocationButton = options.userLocationButton || false;
6027            this.type = options.type;
6028            this.addressField = options.addressField || true;
6029            this.addressFieldPlaceholder = options.addressFieldPlaceholder || "Address";
6030            this.languages = [
6031                { value: "sq", label: "Albanian" },
6032                { value: "ar", label: "Arabic" },
6033                {
6034                    value: "eu",
6035                    label: "Basque",
6036                },
6037                { value: "be", label: "Belarusian" },
6038                { value: "bg", label: "Bulgarian" },
6039                {
6040                    value: "my",
6041                    label: "Burmese",
6042                },
6043                { value: "bn", label: "Bengali" },
6044                { value: "ca", label: "Catalan" },
6045                {
6046                    value: "zh-cn",
6047                    label: "Chinese (simplified)",
6048                },
6049                { value: "zh-tw", label: "Chinese (traditional)" },
6050                {
6051                    value: "hr",
6052                    label: "Croatian",
6053                },
6054                { value: "cs", label: "Czech" },
6055                { value: "da", label: "Danish" },
6056                {
6057                    value: "nl",
6058                    label: "Dutch",
6059                },
6060                { value: "en", label: "English" },
6061                {
6062                    value: "en-au",
6063                    label: "English (australian)",
6064                },
6065                { value: "en-gb", label: "English (great Britain)" },
6066                {
6067                    value: "fa",
6068                    label: "Farsi",
6069                },
6070                { value: "fi", label: "Finnish" },
6071                { value: "fil", label: "Filipino" },
6072                {
6073                    value: "fr",
6074                    label: "French",
6075                },
6076                { value: "gl", label: "Galician" },
6077                { value: "de", label: "German" },
6078                {
6079                    value: "el",
6080                    label: "Greek",
6081                },
6082                { value: "gu", label: "Gujarati" },
6083                { value: "iw", label: "Hebrew" },
6084                {
6085                    value: "hi",
6086                    label: "Hindi",
6087                },
6088                { value: "hu", label: "Hungarian" },
6089                { value: "id", label: "Indonesian" },
6090                {
6091                    value: "it",
6092                    label: "Italian",
6093                },
6094                { value: "ja", label: "Japanese" },
6095                { value: "kn", label: "Kannada" },
6096                {
6097                    value: "kk",
6098                    label: "Kazakh",
6099                },
6100                { value: "ko", label: "Korean" },
6101                { value: "ky", label: "Kyrgyz" },
6102                {
6103                    value: "lt",
6104                    label: "Lithuanian",
6105                },
6106                { value: "lv", label: "Latvian" },
6107                { value: "mk", label: "Macedonian" },
6108                {
6109                    value: "ml",
6110                    label: "Malayalam",
6111                },
6112                { value: "mr", label: "Marathi" },
6113                { value: "no", label: "Norwegian" },
6114                {
6115                    value: "pl",
6116                    label: "Polish",
6117                },
6118                { value: "pt", label: "Portuguese" },
6119                {
6120                    value: "pt-br",
6121                    label: "Portuguese (brazil)",
6122                },
6123                { value: "pt-pt", label: "Portuguese (portugal)" },
6124                {
6125                    value: "pa",
6126                    label: "Punjabi",
6127                },
6128                { value: "ro", label: "Romanian" },
6129                { value: "ru", label: "Russian" },
6130                {
6131                    value: "sr",
6132                    label: "Serbian",
6133                },
6134                { value: "sk", label: "Slovak" },
6135                { value: "sl", label: "Slovenian" },
6136                {
6137                    value: "es",
6138                    label: "Spanish",
6139                },
6140                { value: "sv", label: "Swedish" },
6141                { value: "tl", label: "Tagalog" },
6142                {
6143                    value: "ta",
6144                    label: "Tamil",
6145                },
6146                { value: "te", label: "Telugu" },
6147                { value: "th", label: "Thai" },
6148                {
6149                    value: "tr",
6150                    label: "Turkish",
6151                },
6152                { value: "uk", label: "Ukrainian" },
6153                { value: "uz", label: "Uzbek" },
6154                {
6155                    value: "vi",
6156                    label: "Vietnamese",
6157                },
6158            ];
6159            this.countries = MapSVG.countries;
6160            this.country = options.country;
6161            this.language = options.language;
6162            this.searchByZip = options.searchByZip;
6163            this.zipLength = options.zipLength || 5;
6164            this.userLocationButton = MapSVG.parseBoolean(options.userLocationButton);
6165            this.options = options.options || [
6166                { value: "10", default: true },
6167                { value: "30", default: false },
6168                { value: "50", default: false },
6169                { value: "100", default: false },
6170            ];
6171            let selected = false;
6172            if (this.value) {
6173                this.options.forEach((option) => {
6174                    if (option.value === this.value.length) {
6175                        option.selected = true;
6176                        selected = true;
6177                    }
6178                });
6179            }
6180            if (!selected) {
6181                this.options.forEach(function (option) {
6182                    if (option.default) {
6183                        option.selected = true;
6184                    }
6185                });
6186            }
6187            const defLengthOption = this.options.find((opt) => opt.selected === true);
6188            this.defaultLength = defLengthOption.value;
6189            this.setDefaultValue();
6190        }
6191        setDefaultValue() {
6192            this.value = {
6193                units: this.distanceUnits,
6194                geoPoint: { lat: null, lng: null },
6195                length: this.defaultLength,
6196                address: "",
6197                country: this.country,
6198            };
6199        }
6200        setDomElements() {
6201            super.setDomElements();
6202            this.inputs.units = ($$f(this.domElements.main).find('[name="distanceUnits"]')[0]);
6203            this.inputs.geoPoint = ($$f(this.domElements.main).find('[name="distanceGeoPoint"]')[0]);
6204            this.inputs.length = ($$f(this.domElements.main).find('[name="distanceLength"]')[0]);
6205            this.inputs.address = ($$f(this.domElements.main).find('[name="distanceAddress"]')[0]);
6206        }
6207        getSchema() {
6208            const schema = super.getSchema();
6209            schema.distanceControl = this.distanceControl;
6210            schema.distanceUnits = this.distanceUnits;
6211            schema.distanceUnitsLabel = this.distanceUnitsLabel;
6212            schema.fromLabel = this.fromLabel;
6213            schema.addressField = this.addressField;
6214            schema.addressFieldPlaceholder = this.addressFieldPlaceholder;
6215            schema.userLocationButton = this.userLocationButton;
6216            schema.placeholder = this.placeholder;
6217            schema.language = this.language;
6218            schema.country = this.country;
6219            schema.searchByZip = this.searchByZip;
6220            schema.zipLength = this.zipLength;
6221            schema.userLocationButton = MapSVG.parseBoolean(this.userLocationButton);
6222            if (schema.distanceControl === "none") {
6223                schema.distanceDefault = schema.options.filter(function (o) {
6224                    return o.default;
6225                })[0].value;
6226            }
6227            schema.options.forEach(function (option, index) {
6228                if (schema.options[index].value === "") {
6229                    schema.options.splice(index, 1);
6230                }
6231                else {
6232                    schema.options[index].default = MapSVG.parseBoolean(schema.options[index].default);
6233                }
6234            });
6235            return schema;
6236        }
6237        getDataForTemplate() {
6238            const data = super.getDataForTemplate();
6239            if (this.formBuilder.admin) {
6240                data.languages = this.languages;
6241                data.countries = this.countries;
6242            }
6243            data.language = this.language;
6244            data.country = this.country;
6245            data.searchByZip = this.searchByZip;
6246            data.zipLength = this.zipLength;
6247            data.userLocationButton = MapSVG.parseBoolean(this.userLocationButton);
6248            return data;
6249        }
6250        destroy() {
6251            if ($$f().mselect2) {
6252                const sel = $$f(this.domElements.main).find(".mapsvg-select2");
6253                if (sel.length) {
6254                    sel.mselect2("destroy");
6255                }
6256            }
6257        }
6258        initEditor() {
6259            super.initEditor();
6260            this.mayBeAddDistanceRow();
6261            if ($$f().mselect2) {
6262                $$f(this.domElements.edit).find("select").mselect2();
6263            }
6264        }
6265        setEventHandlers() {
6266            super.setEventHandlers();
6267            const _this = this;
6268            $$f(this.domElements.edit).on("keyup change paste", ".mapsvg-edit-distance-row input", function () {
6269                _this.mayBeAddDistanceRow();
6270            });
6271            const server = new Server();
6272            const locations = new Bloodhound({
6273                datumTokenizer: Bloodhound.tokenizers.obj.whitespace("formatted_address"),
6274                queryTokenizer: Bloodhound.tokenizers.whitespace,
6275                remote: {
6276                    url: server.getUrl("geocoding") +
6277                        "?address=" +
6278                        (this.searchByZip === true ? "zip%20" : "") +
6279                        "%QUERY%&language=" +
6280                        this.language +
6281                        (this.country ? "&country=" + this.country : ""),
6282                    wildcard: "%QUERY%",
6283                    transform: function (response) {
6284                        if (response.error_message) {
6285                            alert(response.error_message);
6286                        }
6287                        return response.results;
6288                    },
6289                    rateLimitWait: 600,
6290                },
6291            });
6292            const thContainer = $$f(this.domElements.main).find(".typeahead");
6293            if (this.searchByZip) {
6294                $$f(this.domElements.main).find(".mapsvg-distance-fields").addClass("search-by-zip");
6295                thContainer.on("change keyup", (e) => {
6296                    if ($$f(e.target).val().toString().length === _this.zipLength) {
6297                        locations.search($$f(e.target).val(), null, (data) => {
6298                            if (data && data[0]) {
6299                                this.setValue({ geoPoint: data[0].geometry.location });
6300                                this.triggerChanged();
6301                            }
6302                        });
6303                    }
6304                });
6305            }
6306            else {
6307                const spinner = $$f("<span class='spinner-border spinner-border-sm'></span>");
6308                const tH = thContainer
6309                    .typeahead({ minLength: 3 }, {
6310                    name: "mapsvg-addresses",
6311                    display: "formatted_address",
6312                    source: locations,
6313                    limit: 5,
6314                })
6315                    .on("typeahead:asyncrequest", function (e) {
6316                    spinner.appendTo($$f(e.target).closest(".twitter-typeahead"));
6317                })
6318                    .on("typeahead:asynccancel typeahead:asyncreceive", function (e) {
6319                    spinner.remove();
6320                });
6321                $$f(this.domElements.main).find(".mapsvg-distance-fields").removeClass("search-by-zip");
6322            }
6323            if (_this.userLocationButton) {
6324                const userLocationButton = $$f(this.domElements.main).find(".user-location-button");
6325                userLocationButton.on("click", () => {
6326                    _this.formBuilder.mapsvg.showUserLocation((location) => {
6327                        locations.search(location.geoPoint.lat + "," + location.geoPoint.lng, null, function (data) {
6328                            if (data && data[0]) {
6329                                _this.setAddress(data[0].formatted_address);
6330                            }
6331                            else {
6332                                _this.setAddress(location.geoPoint.lat + "," + location.geoPoint.lng);
6333                            }
6334                        });
6335                        this.setValue({ geoPoint: location.geoPoint });
6336                        this.triggerChanged();
6337                    });
6338                });
6339            }
6340            thContainer.on("change keyup", (e) => {
6341                const input = e.target;
6342                if (input.value === "" && this.getValue() !== null) {
6343                    this.setValue(null);
6344                    this.triggerChanged();
6345                }
6346            });
6347            thContainer.on("typeahead:select", (ev, item) => {
6348                this.setValue({ address: item.formatted_address, geoPoint: item.geometry.location });
6349                this.triggerChanged();
6350                thContainer.blur();
6351            });
6352            $$f(this.inputs.geoPoint).on("change", (e) => {
6353                const geoPoint = e.target.value.split(",").map((value) => parseFloat(value));
6354                this.setValue({ geoPoint: { lat: geoPoint[0], lng: geoPoint[1] } }, false);
6355                this.triggerChanged();
6356            });
6357            $$f(this.inputs.length).on("change", (e) => {
6358                this.setLength(parseInt(e.target.value), false);
6359                this.triggerChanged();
6360            });
6361        }
6362        addSelect2() {
6363            if ($$f().mselect2) {
6364                $$f(this.domElements.main)
6365                    .find("select")
6366                    .mselect2()
6367                    .on("select2:focus", function () {
6368                    $$f(this).mselect2("open");
6369                });
6370            }
6371        }
6372        mayBeAddDistanceRow() {
6373            const _this = this;
6374            const editDistanceRow = $$f($$f("#mapsvg-edit-distance-row").html());
6375            const z = $$f(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child input");
6376            if (z && z.last() && z.last().val() && z.last().val().toString().trim().length) {
6377                const newRow = editDistanceRow.clone();
6378                newRow.insertAfter($$f(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child"));
6379            }
6380            const rows = $$f(_this.domElements.edit).find(".mapsvg-edit-distance-row");
6381            const row1 = rows.eq(rows.length - 2);
6382            const row2 = rows.eq(rows.length - 1);
6383            if (row1.length &&
6384                row2.length &&
6385                !row1.find("input:eq(0)").val().toString().trim() &&
6386                !row2.find("input:eq(0)").val().toString().trim()) {
6387                row2.remove();
6388            }
6389        }
6390        setValue(value, updateInput = true) {
6391            if (value === null) {
6392                this.setGeoPoint(null);
6393                this.setAddress("");
6394            }
6395            else {
6396                for (const key in value) {
6397                    if (typeof this.value[key] !== undefined) {
6398                        const method = "set" + MapSVG.ucfirst(key);
6399                        if (typeof this[method] === "function") {
6400                            this[method](value[key], updateInput);
6401                        }
6402                    }
6403                }
6404            }
6405        }
6406        setGeoPoint(geoPoint, updateInput = true) {
6407            this.value.geoPoint = geoPoint === null ? { lat: null, lng: null } : geoPoint;
6408            if (updateInput) {
6409                this.setInputGeoPointValue(geoPoint);
6410            }
6411        }
6412        setInputGeoPointValue(geoPoint) {
6413            this.inputs.geoPoint.value = geoPoint ? geoPoint.lat + "," + geoPoint.lng : "";
6414        }
6415        setLength(length, updateInput = true) {
6416            this.value.length = parseInt(length.toString());
6417            this.defaultLength = this.value.length;
6418            if (updateInput) {
6419                this.setInputLengthValue(this.value.length);
6420            }
6421        }
6422        setInputLengthValue(length) {
6423            this.inputs.length.value = length.toString();
6424        }
6425        setAddress(address, updateInput = true) {
6426            this.value.address = address !== null ? address : "";
6427            if (updateInput) {
6428                this.setInputAddressValue(this.value.address);
6429            }
6430        }
6431        setInputAddressValue(address) {
6432            this.inputs.address.value = address;
6433        }
6434        getValue() {
6435            return this.value.geoPoint.lat === null ? null : this.value;
6436        }
6437    }
6438
6439    const $$g = jQuery;
6440    class EmptyFormElement extends FormElement {
6441        constructor(options, formBuilder, external) {
6442            super(options, formBuilder, external);
6443            this.readonly = true;
6444        }
6445    }
6446
6447    class IdFormElement extends FormElement {
6448        constructor(options, formBuilder, external) {
6449            super(options, formBuilder, external);
6450        }
6451        getData() {
6452            return { name: "id", value: this.value };
6453        }
6454    }
6455
6456    function createCommonjsModule(fn, module) {
6457    	return module = { exports: {} }, fn(module, module.exports), module.exports;
6458    }
6459
6460    var sortable_min = createCommonjsModule(function (module) {
6461    /**!
6462     * Sortable
6463     * @author	RubaXa   <[email protected]>
6464     * @license MIT
6465     */
6466
6467    (function sortableModule(factory) {
6468
6469        {
6470            module.exports = factory();
6471        }
6472    })(function sortableFactory() {
6473
6474        if (typeof window == "undefined" || !window.document) {
6475            return function sortableError() {
6476                throw new Error("Sortable.js requires a window with a document");
6477            };
6478        }
6479
6480        var dragEl,
6481            parentEl,
6482            ghostEl,
6483            cloneEl,
6484            rootEl,
6485            nextEl,
6486            scrollEl,
6487            scrollParentEl,
6488            scrollCustomFn,
6489            lastEl,
6490            lastCSS,
6491            lastParentCSS,
6492            oldIndex,
6493            newIndex,
6494            activeGroup,
6495            putSortable,
6496            autoScroll = {},
6497            tapEvt,
6498            touchEvt,
6499            moved,
6500            /** @const */
6501            RSPACE = /\s+/g,
6502            expando = "Sortable" + new Date().getTime(),
6503            win = window,
6504            document = win.document,
6505            parseInt = win.parseInt,
6506            $ = win.jQuery || win.Zepto,
6507            Polymer = win.Polymer,
6508            supportDraggable = !!("draggable" in document.createElement("div")),
6509            supportCssPointerEvents = (function (el) {
6510                // false when IE11
6511                if (navigator.userAgent.match(/Trident.*rv[ :]?11\./)) {
6512                    return false;
6513                }
6514                el = document.createElement("x");
6515                el.style.cssText = "pointer-events:auto";
6516                return el.style.pointerEvents === "auto";
6517            })(),
6518            _silent = false,
6519            abs = Math.abs,
6520            min = Math.min,
6521            touchDragOverListeners = [],
6522            _autoScroll = _throttle(function (
6523                /**Event*/ evt,
6524                /**Object*/ options,
6525                /**HTMLElement*/ rootEl
6526            ) {
6527                // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
6528                if (rootEl && options.scroll) {
6529                    var el,
6530                        rect,
6531                        sens = options.scrollSensitivity,
6532                        speed = options.scrollSpeed,
6533                        x = evt.clientX,
6534                        y = evt.clientY,
6535                        winWidth = window.innerWidth,
6536                        winHeight = window.innerHeight,
6537                        vx,
6538                        vy,
6539                        scrollOffsetX,
6540                        scrollOffsetY;
6541
6542                    // Delect scrollEl
6543                    if (scrollParentEl !== rootEl) {
6544                        scrollEl = options.scroll;
6545                        scrollParentEl = rootEl;
6546                        scrollCustomFn = options.scrollFn;
6547
6548                        if (scrollEl === true) {
6549                            scrollEl = rootEl;
6550
6551                            do {
6552                                if (
6553                                    scrollEl.offsetWidth < scrollEl.scrollWidth ||
6554                                    scrollEl.offsetHeight < scrollEl.scrollHeight
6555                                ) {
6556                                    break;
6557                                }
6558                                /* jshint boss:true */
6559                            } while ((scrollEl = scrollEl.parentNode));
6560                        }
6561                    }
6562
6563                    if (scrollEl) {
6564                        el = scrollEl;
6565                        rect = scrollEl.getBoundingClientRect();
6566                        vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
6567                        vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
6568                    }
6569
6570                    if (!(vx || vy)) {
6571                        vx = (winWidth - x <= sens) - (x <= sens);
6572                        vy = (winHeight - y <= sens) - (y <= sens);
6573
6574                        /* jshint expr:true */
6575                        (vx || vy) && (el = win);
6576                    }
6577
6578                    if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
6579                        autoScroll.el = el;
6580                        autoScroll.vx = vx;
6581                        autoScroll.vy = vy;
6582
6583                        clearInterval(autoScroll.pid);
6584
6585                        if (el) {
6586                            autoScroll.pid = setInterval(function () {
6587                                scrollOffsetY = vy ? vy * speed : 0;
6588                                scrollOffsetX = vx ? vx * speed : 0;
6589
6590                                if ("function" === typeof scrollCustomFn) {
6591                                    return scrollCustomFn.call(
6592                                        _this,
6593                                        scrollOffsetX,
6594                                        scrollOffsetY,
6595                                        evt
6596                                    );
6597                                }
6598
6599                                if (el === win) {
6600                                    win.scrollTo(
6601                                        win.pageXOffset + scrollOffsetX,
6602                                        win.pageYOffset + scrollOffsetY
6603                                    );
6604                                } else {
6605                                    el.scrollTop += scrollOffsetY;
6606                                    el.scrollLeft += scrollOffsetX;
6607                                }
6608                            }, 24);
6609                        }
6610                    }
6611                }
6612            },
6613            30),
6614            _prepareGroup = function (options) {
6615                function toFn(value, pull) {
6616                    if (value === void 0 || value === true) {
6617                        value = group.name;
6618                    }
6619
6620                    if (typeof value === "function") {
6621                        return value;
6622                    } else {
6623                        return function (to, from) {
6624                            var fromGroup = from.options.group.name;
6625
6626                            return pull
6627                                ? value
6628                                : value &&
6629                                      (value.join ? value.indexOf(fromGroup) > -1 : fromGroup == value);
6630                        };
6631                    }
6632                }
6633
6634                var group = {};
6635                var originalGroup = options.group;
6636
6637                if (!originalGroup || typeof originalGroup != "object") {
6638                    originalGroup = { name: originalGroup };
6639                }
6640
6641                group.name = originalGroup.name;
6642                group.checkPull = toFn(originalGroup.pull, true);
6643                group.checkPut = toFn(originalGroup.put);
6644
6645                options.group = group;
6646            };
6647        /**
6648         * @class  Sortable
6649         * @param  {HTMLElement}  el
6650         * @param  {Object}       [options]
6651         */
6652        function Sortable(el, options) {
6653            if (!(el && el.nodeType && el.nodeType === 1)) {
6654                throw "Sortable: `el` must be HTMLElement, and not " + {}.toString.call(el);
6655            }
6656
6657            this.el = el; // root element
6658            this.options = options = _extend({}, options);
6659
6660            // Export instance
6661            el[expando] = this;
6662
6663            // Default options
6664            var defaults = {
6665                group: Math.random(),
6666                sort: true,
6667                disabled: false,
6668                store: null,
6669                handle: null,
6670                scroll: true,
6671                scrollSensitivity: 30,
6672                scrollSpeed: 10,
6673                draggable: /[uo]l/i.test(el.nodeName) ? "li" : ">*",
6674                ghostClass: "sortable-ghost",
6675                chosenClass: "sortable-chosen",
6676                dragClass: "sortable-drag",
6677                ignore: "a, img",
6678                filter: null,
6679                animation: 0,
6680                setData: function (dataTransfer, dragEl) {
6681                    dataTransfer.setData("Text", dragEl.textContent);
6682                },
6683                dropBubble: false,
6684                dragoverBubble: false,
6685                dataIdAttr: "data-id",
6686                delay: 0,
6687                forceFallback: false,
6688                fallbackClass: "sortable-fallback",
6689                fallbackOnBody: false,
6690                fallbackTolerance: 0,
6691                fallbackOffset: { x: 0, y: 0 },
6692            };
6693
6694            // Set default options
6695            for (var name in defaults) {
6696                !(name in options) && (options[name] = defaults[name]);
6697            }
6698
6699            _prepareGroup(options);
6700
6701            // Bind all private methods
6702            for (var fn in this) {
6703                if (fn.charAt(0) === "_" && typeof this[fn] === "function") {
6704                    this[fn] = this[fn].bind(this);
6705                }
6706            }
6707
6708            // Setup drag mode
6709            this.nativeDraggable = options.forceFallback ? false : supportDraggable;
6710
6711            // Bind events
6712            _on(el, "mousedown", this._onTapStart);
6713            _on(el, "touchstart", this._onTapStart);
6714
6715            if (this.nativeDraggable) {
6716                _on(el, "dragover", this);
6717                _on(el, "dragenter", this);
6718            }
6719
6720            touchDragOverListeners.push(this._onDragOver);
6721
6722            // Restore sorting
6723            options.store && this.sort(options.store.get(this));
6724        }
6725
6726        Sortable.prototype = /** @lends Sortable.prototype */ {
6727            constructor: Sortable,
6728
6729            _onTapStart: function (/** Event|TouchEvent */ evt) {
6730                if (evt.target.tagName == "i" || evt.target.tagName == "I") {
6731                    evt.target.click();
6732                    return;
6733                }
6734                var _this = this,
6735                    el = this.el,
6736                    options = this.options,
6737                    type = evt.type,
6738                    touch = evt.touches && evt.touches[0],
6739                    target = (touch || evt).target,
6740                    originalTarget = (evt.target.shadowRoot && evt.path[0]) || target,
6741                    filter = options.filter,
6742                    startIndex;
6743
6744                // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
6745                if (dragEl) {
6746                    return;
6747                }
6748
6749                if ((type === "mousedown" && evt.button !== 0) || options.disabled) {
6750                    return; // only left button or enabled
6751                }
6752
6753                if (options.handle && !_closest(originalTarget, options.handle, el)) {
6754                    return;
6755                }
6756
6757                target = _closest(target, options.draggable, el);
6758
6759                if (!target) {
6760                    return;
6761                }
6762
6763                // Get the index of the dragged element within its parent
6764                startIndex = _index(target, options.draggable);
6765
6766                // Check filter
6767                if (typeof filter === "function") {
6768                    if (filter.call(this, evt, target, this)) {
6769                        _dispatchEvent(_this, originalTarget, "filter", target, el, startIndex);
6770                        evt.preventDefault();
6771                        return; // cancel dnd
6772                    }
6773                } else if (filter) {
6774                    filter = filter.split(",").some(function (criteria) {
6775                        criteria = _closest(originalTarget, criteria.trim(), el);
6776
6777                        if (criteria) {
6778                            _dispatchEvent(_this, criteria, "filter", target, el, startIndex);
6779                            return true;
6780                        }
6781                    });
6782
6783                    if (filter) {
6784                        evt.preventDefault();
6785                        return; // cancel dnd
6786                    }
6787                }
6788
6789                // Prepare `dragstart`
6790                this._prepareDragStart(evt, touch, target, startIndex);
6791            },
6792
6793            _prepareDragStart: function (
6794                /** Event */ evt,
6795                /** Touch */ touch,
6796                /** HTMLElement */ target,
6797                /** Number */ startIndex
6798            ) {
6799                var _this = this,
6800                    el = _this.el,
6801                    options = _this.options,
6802                    ownerDocument = el.ownerDocument,
6803                    dragStartFn;
6804
6805                if (target && !dragEl && target.parentNode === el) {
6806                    tapEvt = evt;
6807
6808                    rootEl = el;
6809                    dragEl = target;
6810                    parentEl = dragEl.parentNode;
6811                    nextEl = dragEl.nextSibling;
6812                    activeGroup = options.group;
6813                    oldIndex = startIndex;
6814
6815                    this._lastX = (touch || evt).clientX;
6816                    this._lastY = (touch || evt).clientY;
6817
6818                    dragEl.style["will-change"] = "transform";
6819
6820                    dragStartFn = function () {
6821                        // Delayed drag has been triggered
6822                        // we can re-enable the events: touchmove/mousemove
6823                        _this._disableDelayedDrag();
6824
6825                        // Make the element draggable
6826                        dragEl.draggable = _this.nativeDraggable;
6827
6828                        // Chosen item
6829                        _toggleClass(dragEl, options.chosenClass, true);
6830
6831                        // Bind the events: dragstart/dragend
6832                        _this._triggerDragStart(touch);
6833
6834                        // Drag start event
6835                        _dispatchEvent(_this, rootEl, "choose", dragEl, rootEl, oldIndex);
6836                    };
6837
6838                    // Disable "draggable"
6839                    options.ignore.split(",").forEach(function (criteria) {
6840                        _find(dragEl, criteria.trim(), _disableDraggable);
6841                    });
6842
6843                    _on(ownerDocument, "mouseup", _this._onDrop);
6844                    _on(ownerDocument, "touchend", _this._onDrop);
6845                    _on(ownerDocument, "touchcancel", _this._onDrop);
6846
6847                    if (options.delay) {
6848                        // If the user moves the pointer or let go the click or touch
6849                        // before the delay has been reached:
6850                        // disable the delayed drag
6851                        _on(ownerDocument, "mouseup", _this._disableDelayedDrag);
6852                        _on(ownerDocument, "touchend", _this._disableDelayedDrag);
6853                        _on(ownerDocument, "touchcancel", _this._disableDelayedDrag);
6854                        _on(ownerDocument, "mousemove", _this._disableDelayedDrag);
6855                        _on(ownerDocument, "touchmove", _this._disableDelayedDrag);
6856
6857                        _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
6858                    } else {
6859                        dragStartFn();
6860                    }
6861                }
6862            },
6863
6864            _disableDelayedDrag: function () {
6865                var ownerDocument = this.el.ownerDocument;
6866
6867                clearTimeout(this._dragStartTimer);
6868                _off(ownerDocument, "mouseup", this._disableDelayedDrag);
6869                _off(ownerDocument, "touchend", this._disableDelayedDrag);
6870                _off(ownerDocument, "touchcancel", this._disableDelayedDrag);
6871                _off(ownerDocument, "mousemove", this._disableDelayedDrag);
6872                _off(ownerDocument, "touchmove", this._disableDelayedDrag);
6873            },
6874
6875            _triggerDragStart: function (/** Touch */ touch) {
6876                if (touch) {
6877                    // Touch device support
6878                    tapEvt = {
6879                        target: dragEl,
6880                        clientX: touch.clientX,
6881                        clientY: touch.clientY,
6882                    };
6883
6884                    this._onDragStart(tapEvt, "touch");
6885                } else if (!this.nativeDraggable) {
6886                    this._onDragStart(tapEvt, true);
6887                } else {
6888                    _on(dragEl, "dragend", this);
6889                    _on(rootEl, "dragstart", this._onDragStart);
6890                }
6891
6892                try {
6893                    if (document.selection) {
6894                        // Timeout neccessary for IE9
6895                        setTimeout(function () {
6896                            document.selection.empty();
6897                        });
6898                    } else {
6899                        window.getSelection().removeAllRanges();
6900                    }
6901                } catch (err) {}
6902            },
6903
6904            _dragStarted: function () {
6905                if (rootEl && dragEl) {
6906                    var options = this.options;
6907
6908                    // Apply effect
6909                    _toggleClass(dragEl, options.ghostClass, true);
6910                    _toggleClass(dragEl, options.dragClass, false);
6911
6912                    Sortable.active = this;
6913
6914                    // Drag start event
6915                    _dispatchEvent(this, rootEl, "start", dragEl, rootEl, oldIndex);
6916                }
6917            },
6918
6919            _emulateDragOver: function () {
6920                if (touchEvt) {
6921                    if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
6922                        return;
6923                    }
6924
6925                    this._lastX = touchEvt.clientX;
6926                    this._lastY = touchEvt.clientY;
6927
6928                    if (!supportCssPointerEvents) {
6929                        _css(ghostEl, "display", "none");
6930                    }
6931
6932                    var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
6933                        parent = target,
6934                        i = touchDragOverListeners.length;
6935
6936                    if (parent) {
6937                        do {
6938                            if (parent[expando]) {
6939                                while (i--) {
6940                                    touchDragOverListeners[i]({
6941                                        clientX: touchEvt.clientX,
6942                                        clientY: touchEvt.clientY,
6943                                        target: target,
6944                                        rootEl: parent,
6945                                    });
6946                                }
6947
6948                                break;
6949                            }
6950
6951                            target = parent; // store last element
6952                        } while (
6953                            /* jshint boss:true */
6954                            (parent = parent.parentNode)
6955                        );
6956                    }
6957
6958                    if (!supportCssPointerEvents) {
6959                        _css(ghostEl, "display", "");
6960                    }
6961                }
6962            },
6963
6964            _onTouchMove: function (/**TouchEvent*/ evt) {
6965                if (tapEvt) {
6966                    var options = this.options,
6967                        fallbackTolerance = options.fallbackTolerance,
6968                        fallbackOffset = options.fallbackOffset,
6969                        touch = evt.touches ? evt.touches[0] : evt,
6970                        dx = touch.clientX - tapEvt.clientX + fallbackOffset.x,
6971                        dy = touch.clientY - tapEvt.clientY + fallbackOffset.
6971y,
6972                        translate3d = evt.touches
6973                            ? "translate3d(" + dx + "px," + dy + "px,0)"
6974                            : "translate(" + dx + "px," + dy + "px)";
6975
6976                    // only set the status to dragging, when we are actually dragging
6977                    if (!Sortable.active) {
6978                        if (
6979                            fallbackTolerance &&
6980                            min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) <
6981                                fallbackTolerance
6982                        ) {
6983                            return;
6984                        }
6985
6986                        this._dragStarted();
6987                    }
6988
6989                    // as well as creating the ghost element on the document body
6990                    this._appendGhost();
6991
6992                    moved = true;
6993                    touchEvt = touch;
6994
6995                    _css(ghostEl, "webkitTransform", translate3d);
6996                    _css(ghostEl, "mozTransform", translate3d);
6997                    _css(ghostEl, "msTransform", translate3d);
6998                    _css(ghostEl, "transform", translate3d);
6999
7000                    evt.preventDefault();
7001                }
7002            },
7003
7004            _appendGhost: function () {
7005                if (!ghostEl) {
7006                    var rect = dragEl.getBoundingClientRect(),
7007                        css = _css(dragEl),
7008                        options = this.options,
7009                        ghostRect;
7010
7011                    ghostEl = dragEl.cloneNode(true);
7012
7013                    _toggleClass(ghostEl, options.ghostClass, false);
7014                    _toggleClass(ghostEl, options.fallbackClass, true);
7015                    _toggleClass(ghostEl, options.dragClass, true);
7016
7017                    _css(ghostEl, "top", rect.top - parseInt(css.marginTop, 10));
7018                    _css(ghostEl, "left", rect.left - parseInt(css.marginLeft, 10));
7019                    _css(ghostEl, "width", rect.width);
7020                    _css(ghostEl, "height", rect.height);
7021                    _css(ghostEl, "opacity", "0.8");
7022                    _css(ghostEl, "position", "fixed");
7023                    _css(ghostEl, "zIndex", "100000");
7024                    _css(ghostEl, "pointerEvents", "none");
7025
7026                    (options.fallbackOnBody && document.body.appendChild(ghostEl)) ||
7027                        rootEl.appendChild(ghostEl);
7028
7029                    // Fixing dimensions.
7030                    ghostRect = ghostEl.getBoundingClientRect();
7031                    _css(ghostEl, "width", rect.width * 2 - ghostRect.width);
7032                    _css(ghostEl, "height", rect.height * 2 - ghostRect.height);
7033                }
7034            },
7035
7036            _onDragStart: function (/**Event*/ evt, /**boolean*/ useFallback) {
7037                var dataTransfer = evt.dataTransfer,
7038                    options = this.options;
7039
7040                this._offUpEvents();
7041
7042                if (activeGroup.checkPull(this, this, dragEl, evt) == "clone") {
7043                    cloneEl = _clone(dragEl);
7044                    _css(cloneEl, "display", "none");
7045                    rootEl.insertBefore(cloneEl, dragEl);
7046                    _dispatchEvent(this, rootEl, "clone", dragEl);
7047                }
7048
7049                _toggleClass(dragEl, options.dragClass, true);
7050
7051                if (useFallback) {
7052                    if (useFallback === "touch") {
7053                        // Bind touch events
7054                        _on(document, "touchmove", this._onTouchMove);
7055                        _on(document, "touchend", this._onDrop);
7056                        _on(document, "touchcancel", this._onDrop);
7057                    } else {
7058                        // Old brwoser
7059                        _on(document, "mousemove", this._onTouchMove);
7060                        _on(document, "mouseup", this._onDrop);
7061                    }
7062
7063                    this._loopId = setInterval(this._emulateDragOver, 50);
7064                } else {
7065                    if (dataTransfer) {
7066                        dataTransfer.effectAllowed = "move";
7067                        options.setData && options.setData.call(this, dataTransfer, dragEl);
7068                    }
7069
7070                    _on(document, "drop", this);
7071                    setTimeout(this._dragStarted, 0);
7072                }
7073            },
7074
7075            _onDragOver: function (/**Event*/ evt) {
7076                var el = this.el,
7077                    target,
7078                    dragRect,
7079                    targetRect,
7080                    revert,
7081                    options = this.options,
7082                    group = options.group,
7083                    activeSortable = Sortable.active,
7084                    isOwner = activeGroup === group,
7085                    canSort = options.sort;
7086
7087                if (evt.preventDefault !== void 0) {
7088                    evt.preventDefault();
7089                    !options.dragoverBubble && evt.stopPropagation();
7090                }
7091
7092                moved = true;
7093
7094                if (
7095                    activeGroup &&
7096                    !options.disabled &&
7097                    (isOwner
7098                        ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
7099                        : putSortable === this ||
7100                          (activeGroup.checkPull(this, activeSortable, dragEl, evt) &&
7101                              group.checkPut(this, activeSortable, dragEl, evt))) &&
7102                    (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
7103                ) {
7104                    // Smart auto-scrolling
7105                    _autoScroll(evt, options, this.el);
7106
7107                    if (_silent) {
7108                        return;
7109                    }
7110
7111                    target = _closest(evt.target, options.draggable, el);
7112                    dragRect = dragEl.getBoundingClientRect();
7113                    putSortable = this;
7114
7115                    if (revert) {
7116                        _cloneHide(true);
7117                        parentEl = rootEl; // actualization
7118
7119                        if (cloneEl || nextEl) {
7120                            rootEl.insertBefore(dragEl, cloneEl || nextEl);
7121                        } else if (!canSort) {
7122                            rootEl.appendChild(dragEl);
7123                        }
7124
7125                        return;
7126                    }
7127
7128                    if (
7129                        el.children.length === 0 ||
7130                        el.children[0] === ghostEl ||
7131                        (el === evt.target && (target = _ghostIsLast(el, evt)))
7132                    ) {
7133                        if (target) {
7134                            if (target.animated) {
7135                                return;
7136                            }
7137
7138                            targetRect = target.getBoundingClientRect();
7139                        }
7140
7141                        _cloneHide(isOwner);
7142
7143                        if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
7144                            if (!dragEl.contains(el)) {
7145                                el.appendChild(dragEl);
7146                                parentEl = el; // actualization
7147                            }
7148
7149                            this._animate(dragRect, dragEl);
7150                            target && this._animate(targetRect, target);
7151                        }
7152                    } else if (
7153                        target &&
7154                        !target.animated &&
7155                        target !== dragEl &&
7156                        target.parentNode[expando] !== void 0
7157                    ) {
7158                        if (lastEl !== target) {
7159                            lastEl = target;
7160                            lastCSS = _css(target);
7161                            lastParentCSS = _css(target.parentNode);
7162                        }
7163
7164                        targetRect = target.getBoundingClientRect();
7165
7166                        var width = targetRect.right - targetRect.left,
7167                            height = targetRect.bottom - targetRect.top,
7168                            floating =
7169                                /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display) ||
7170                                (lastParentCSS.display == "flex" &&
7171                                    lastParentCSS["flex-direction"].indexOf("row") === 0),
7172                            isWide = target.offsetWidth > dragEl.offsetWidth,
7173                            isLong = target.offsetHeight > dragEl.offsetHeight,
7174                            halfway =
7175                                (floating
7176                                    ? (evt.clientX - targetRect.left) / width
7177                                    : (evt.clientY - targetRect.top) / height) > 0.5,
7178                            nextSibling = target.nextElementSibling,
7179                            moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt),
7180                            after;
7181
7182                        if (moveVector !== false) {
7183                            _silent = true;
7184                            setTimeout(_unsilent, 30);
7185
7186                            _cloneHide(isOwner);
7187
7188                            if (moveVector === 1 || moveVector === -1) {
7189                                after = moveVector === 1;
7190                            } else if (floating) {
7191                                var elTop = dragEl.offsetTop,
7192                                    tgTop = target.offsetTop;
7193
7194                                if (elTop === tgTop) {
7195                                    after =
7196                                        (target.previousElementSibling === dragEl && !isWide) ||
7197                                        (halfway && isWide);
7198                                } else if (
7199                                    target.previousElementSibling === dragEl ||
7200                                    dragEl.previousElementSibling === target
7201                                ) {
7202                                    after = (evt.clientY - targetRect.top) / height > 0.5;
7203                                } else {
7204                                    after = tgTop > elTop;
7205                                }
7206                            } else {
7207                                after = (nextSibling !== dragEl && !isLong) || (halfway && isLong);
7208                            }
7209
7210                            if (!dragEl.contains(el)) {
7211                                if (after && !nextSibling) {
7212                                    el.appendChild(dragEl);
7213                                } else {
7214                                    target.parentNode.insertBefore(
7215                                        dragEl,
7216                                        after ? nextSibling : target
7217                                    );
7218                                }
7219                            }
7220
7221                            parentEl = dragEl.parentNode; // actualization
7222
7223                            this._animate(dragRect, dragEl);
7224                            this._animate(targetRect, target);
7225                        }
7226                    }
7227                }
7228            },
7229
7230            _animate: function (prevRect, target) {
7231                var ms = this.options.animation;
7232
7233                if (ms) {
7234                    var currentRect = target.getBoundingClientRect();
7235
7236                    _css(target, "transition", "none");
7237                    _css(
7238                        target,
7239                        "transform",
7240                        "translate3d(" +
7241                            (prevRect.left - currentRect.left) +
7242                            "px," +
7243                            (prevRect.top - currentRect.top) +
7244                            "px,0)"
7245                    );
7246
7247                    target.offsetWidth; // repaint
7248
7249                    _css(target, "transition", "all " + ms + "ms");
7250                    _css(target, "transform", "translate3d(0,0,0)");
7251
7252                    clearTimeout(target.animated);
7253                    target.animated = setTimeout(function () {
7254                        _css(target, "transition", "");
7255                        _css(target, "transform", "");
7256                        target.animated = false;
7257                    }, ms);
7258                }
7259            },
7260
7261            _offUpEvents: function () {
7262                var ownerDocument = this.el.ownerDocument;
7263
7264                _off(document, "touchmove", this._onTouchMove);
7265                _off(ownerDocument, "mouseup", this._onDrop);
7266                _off(ownerDocument, "touchend", this._onDrop);
7267                _off(ownerDocument, "touchcancel", this._onDrop);
7268            },
7269
7270            _onDrop: function (/**Event*/ evt) {
7271                var el = this.el,
7272                    options = this.options;
7273
7274                clearInterval(this._loopId);
7275                clearInterval(autoScroll.pid);
7276                clearTimeout(this._dragStartTimer);
7277
7278                // Unbind events
7279                _off(document, "mousemove", this._onTouchMove);
7280
7281                if (this.nativeDraggable) {
7282                    _off(document, "drop", this);
7283                    _off(el, "dragstart", this._onDragStart);
7284                }
7285
7286                this._offUpEvents();
7287
7288                if (evt) {
7289                    if (moved) {
7290                        evt.preventDefault();
7291                        !options.dropBubble && evt.stopPropagation();
7292                    }
7293
7294                    ghostEl && ghostEl.parentNode.removeChild(ghostEl);
7295
7296                    if (dragEl) {
7297                        if (this.nativeDraggable) {
7298                            _off(dragEl, "dragend", this);
7299                        }
7300
7301                        _disableDraggable(dragEl);
7302                        dragEl.style["will-change"] = "";
7303
7304                        // Remove class's
7305                        _toggleClass(dragEl, this.options.ghostClass, false);
7306                        _toggleClass(dragEl, this.options.chosenClass, false);
7307
7308                        if (rootEl !== parentEl) {
7309                            newIndex = _index(dragEl, options.draggable);
7310
7311                            if (newIndex >= 0) {
7312                                // Add event
7313                                _dispatchEvent(
7314                                    null,
7315                                    parentEl,
7316                                    "add",
7317                                    dragEl,
7318                                    rootEl,
7319                                    oldIndex,
7320                                    newIndex
7321                                );
7322
7323                                // Remove event
7324                                _dispatchEvent(
7325                                    this,
7326                                    rootEl,
7327                                    "remove",
7328                                    dragEl,
7329                                    rootEl,
7330                                    oldIndex,
7331                                    newIndex
7332                                );
7333
7334                                // drag from one list and drop into another
7335                                _dispatchEvent(
7336                                    null,
7337                                    parentEl,
7338                                    "sort",
7339                                    dragEl,
7340                                    rootEl,
7341                                    oldIndex,
7342                                    newIndex
7343                                );
7344                                _dispatchEvent(
7345                                    this,
7346                                    rootEl,
7347                                    "sort",
7348                                    dragEl,
7349                                    rootEl,
7350                                    oldIndex,
7351                                    newIndex
7352                                );
7353                            }
7354                        } else {
7355                            // Remove clone
7356                            cloneEl && cloneEl.parentNode.removeChild(cloneEl);
7357
7358                            if (dragEl.nextSibling !== nextEl) {
7359                                // Get the index of the dragged element within its parent
7360                                newIndex = _index(dragEl, options.draggable);
7361
7362                                if (newIndex >= 0) {
7363                                    // drag & drop within the same list
7364                                    _dispatchEvent(
7365                                        this,
7366                                        rootEl,
7367                                        "update",
7368                                        dragEl,
7369                                        rootEl,
7370                                        oldIndex,
7371                                        newIndex
7372                                    );
7373                                    _dispatchEvent(
7374                                        this,
7375                                        rootEl,
7376                                        "sort",
7377                                        dragEl,
7378                                        rootEl,
7379                                        oldIndex,
7380                                        newIndex
7381                                    );
7382                                }
7383                            }
7384                        }
7385
7386                        if (Sortable.active) {
7387                            /* jshint eqnull:true */
7388                            if (newIndex == null || newIndex === -1) {
7389                                newIndex = oldIndex;
7390                            }
7391
7392                            _dispatchEvent(this, rootEl, "end", dragEl, rootEl, oldIndex, newIndex);
7393
7394                            // Save sorting
7395                            this.save();
7396                        }
7397                    }
7398                }
7399
7400                this._nulling();
7401            },
7402
7403            _nulling: function () {
7404                rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = scrollEl = scrollParentEl = tapEvt = touchEvt = moved = newIndex = lastEl = lastCSS = putSortable = activeGroup = Sortable.active = null;
7405            },
7406
7407            handleEvent: function (/**Event*/ evt) {
7408                var type = evt.type;
7409
7410                if (type === "dragover" || type === "dragenter") {
7411                    if (dragEl) {
7412                        this._onDragOver(evt);
7413                        _globalDragOver(evt);
7414                    }
7415                } else if (type === "drop" || type === "dragend") {
7416                    this._onDrop(evt);
7417                }
7418            },
7419
7420            /**
7421             * Serializes the item into an array of string.
7422             * @returns {String[]}
7423             */
7424            toArray: function () {
7425                var order = [],
7426                    el,
7427                    children = this.el.children,
7428                    i = 0,
7429                    n = children.length,
7430                    options = this.options;
7431
7432                for (; i < n; i++) {
7433                    el = children[i];
7434                    if (_closest(el, options.draggable, this.el)) {
7435                        order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
7436                    }
7437                }
7438
7439                return order;
7440            },
7441
7442            /**
7443             * Sorts the elements according to the array.
7444             * @param  {String[]}  order  order of the items
7445             */
7446            sort: function (order) {
7447                var items = {},
7448                    rootEl = this.el;
7449
7450                this.toArray().forEach(function (id, i) {
7451                    var el = rootEl.children[i];
7452
7453                    if (_closest(el, this.options.draggable, rootEl)) {
7454                        items[id] = el;
7455                    }
7456                }, this);
7457
7458                order.forEach(function (id) {
7459                    if (items[id]) {
7460                        rootEl.removeChild(items[id]);
7461                        rootEl.appendChild(items[id]);
7462                    }
7463                });
7464            },
7465
7466            /**
7467             * Save the current sorting
7468             */
7469            save: function () {
7470                var store = this.options.store;
7471                store && store.set(this);
7472            },
7473
7474            /**
7475             * 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.
7476             * @param   {HTMLElement}  el
7477             * @param   {String}       [selector]  default: `options.draggable`
7478             * @returns {HTMLElement|null}
7479             */
7480            closest: function (el, selector) {
7481                return _closest(el, selector || this.options.draggable, this.el);
7482            },
7483
7484            /**
7485             * Set/get option
7486             * @param   {string} name
7487             * @param   {*}      [value]
7488             * @returns {*}
7489             */
7490            option: function (name, value) {
7491                var options = this.options;
7492
7493                if (value === void 0) {
7494                    return options[name];
7495                } else {
7496                    options[name] = value;
7497
7498                    if (name === "group") {
7499                        _prepareGroup(options);
7500                    }
7501                }
7502            },
7503
7504            /**
7505             * Destroy
7506             */
7507            destroy: function () {
7508                var el = this.el;
7509
7510                el[expando] = null;
7511
7512                _off(el, "mousedown", this._onTapStart);
7513                _off(el, "touchstart", this._onTapStart);
7514
7515                if (this.nativeDraggable) {
7516                    _off(el, "dragover", this);
7517                    _off(el, "dragenter", this);
7518                }
7519
7520                // Remove draggable attributes
7521                Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function (el) {
7522                    el.removeAttribute("draggable");
7523                });
7524
7525                touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
7526
7527                this._onDrop();
7528
7529                this.el = el = null;
7530            },
7531        };
7532
7533        function _cloneHide(state) {
7534            if (cloneEl && cloneEl.state !== state) {
7535                _css(cloneEl, "display", state ? "none" : "");
7536                !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl);
7537                cloneEl.state = state;
7538            }
7539        }
7540
7541        function _closest(/**HTMLElement*/ el, /**String*/ selector, /**HTMLElement*/ ctx) {
7542            if (el) {
7543                ctx = ctx || document;
7544
7545                do {
7546                    if ((selector === ">*" && el.parentNode === ctx) || _matches(el, selector)) {
7547                        return el;
7548                    }
7549                    /* jshint boss:true */
7550                } while ((el = _getParentOrHost(el)));
7551            }
7552
7553            return null;
7554        }
7555
7556        function _getParentOrHost(el) {
7557            var parent = el.host;
7558
7559            return parent && parent.nodeType ? parent : el.parentNode;
7560        }
7561
7562        function _globalDragOver(/**Event*/ evt) {
7563            if (evt.dataTransfer) {
7564                evt.dataTransfer.dropEffect = "move";
7565            }
7566            evt.preventDefault();
7567        }
7568
7569        function _on(el, event, fn) {
7570            el.addEventListener(event, fn, false);
7571        }
7572
7573        function _off(el, event, fn) {
7574            el.removeEventListener(event, fn, false);
7575        }
7576
7577        function _toggleClass(el, name, state) {
7578            if (el) {
7579                if (el.classList) {
7580                    el.classList[state ? "add" : "remove"](name);
7581                } else {
7582                    var className = (" " + el.className + " ")
7583                        .replace(RSPACE, " ")
7584                        .replace(" " + name + " ", " ");
7585                    el.className = (className + (state ? " " + name : "")).replace(RSPACE, " ");
7586                }
7587            }
7588        }
7589
7590        function _css(el, prop, val) {
7591            var style = el && el.style;
7592
7593            if (style) {
7594                if (val === void 0) {
7595                    if (document.defaultView && document.defaultView.getComputedStyle) {
7596                        val = document.defaultView.getComputedStyle(el, "");
7597                    } else if (el.currentStyle) {
7598                        val = el.currentStyle;
7599                    }
7600
7601                    return prop === void 0 ? val : val[prop];
7602                } else {
7603                    if (!(prop in style)) {
7604                        prop = "-webkit-" + prop;
7605                    }
7606
7607                    style[prop] = val + (typeof val === "string" ? "" : "px");
7608                }
7609            }
7610        }
7611
7612        function _find(ctx, tagName, iterator) {
7613            if (ctx) {
7614                var list = ctx.getElementsByTagName(tagName),
7615                    i = 0,
7616                    n = list.length;
7617
7618                if (iterator) {
7619                    for (; i < n; i++) {
7620                        iterator(list[i], i);
7621                    }
7622                }
7623
7624                return list;
7625            }
7626
7627            return [];
7628        }
7629
7630        function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) {
7631            sortable = sortable || rootEl[expando];
7632
7633            var evt = document.createEvent("Event"),
7634                options = sortable.options,
7635                onName = "on" + name.charAt(0).toUpperCase() + name.substr(1);
7636
7637            evt.initEvent(name, true, true);
7638
7639            evt.to = rootEl;
7640            evt.from = fromEl || rootEl;
7641            evt.item = targetEl || rootEl;
7642            evt.clone = cloneEl;
7643
7644            evt.oldIndex = startIndex;
7645            evt.newIndex = newIndex;
7646
7647            rootEl.dispatchEvent(evt);
7648
7649            if (options[onName]) {
7650                options[onName].call(sortable, evt);
7651            }
7652        }
7653
7654        function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt) {
7655            var evt,
7656                sortable = fromEl[expando],
7657                onMoveFn = sortable.options.onMove,
7658                retVal;
7659
7660            evt = document.createEvent("Event");
7661            evt.initEvent("move", true, true);
7662
7663            evt.to = toEl;
7664            evt.from = fromEl;
7665            evt.dragged = dragEl;
7666            evt.draggedRect = dragRect;
7667            evt.related = targetEl || toEl;
7668            evt.relatedRect = targetRect || toEl.getBoundingClientRect();
7669
7670            fromEl.dispatchEvent(evt);
7671
7672            if (onMoveFn) {
7673                retVal = onMoveFn.call(sortable, evt, originalEvt);
7674            }
7675
7676            return retVal;
7677        }
7678
7679        function _disableDraggable(el) {
7680            el.draggable = false;
7681        }
7682
7683        function _unsilent() {
7684            _silent = false;
7685        }
7686
7687        /** @returns {HTMLElement|false} */
7688        function _ghostIsLast(el, evt) {
7689            var lastEl = el.lastElementChild,
7690                rect = lastEl.getBoundingClientRect();
7691
7692            // 5 — min delta
7693            // abs — нельзя добавлять, а то глюки при наведении сверху
7694            return (
7695                (evt.clientY - (rect.top + rect.height) > 5 ||
7696                    evt.clientX - (rect.right + rect.width) > 5) &&
7697                lastEl
7698            );
7699        }
7700
7701        /**
7702         * Generate id
7703         * @param   {HTMLElement} el
7704         * @returns {String}
7705         * @private
7706         */
7707        function _generateId(el) {
7708            var str = el.tagName + el.className + el.src + el.href + el.textContent,
7709                i = str.length,
7710                sum = 0;
7711
7712            while (i--) {
7713                sum += str.charCodeAt(i);
7714            }
7715
7716            return sum.toString(36);
7717        }
7718
7719        /**
7720         * Returns the index of an element within its parent for a selected set of
7721         * elements
7722         * @param  {HTMLElement} el
7723         * @param  {selector} selector
7724         * @return {number}
7725         */
7726        function _index(el, selector) {
7727            var index = 0;
7728
7729            if (!el || !el.parentNode) {
7730                return -1;
7731            }
7732
7733            while (el && (el = el.previousElementSibling)) {
7734                if (
7735                    el.nodeName.toUpperCase() !== "TEMPLATE" &&
7736                    (selector === ">*" || _matches(el, selector))
7737                ) {
7738                    index++;
7739                }
7740            }
7741
7742            return index;
7743        }
7744
7745        function _matches(/**HTMLElement*/ el, /**String*/ selector) {
7746            if (el) {
7747                selector = selector.split(".");
7748
7749                var tag = selector.shift().toUpperCase(),
7750                    re = new RegExp("\\s(" + selector.join("|") + ")(?=\\s)", "g");
7751
7752                return (
7753                    (tag === "" || el.nodeName.toUpperCase() == tag) &&
7754                    (!selector.length ||
7755                        ((" " + el.className + " ").match(re) || []).length == selector.length)
7756                );
7757            }
7758
7759            return false;
7760        }
7761
7762        function _throttle(callback, ms) {
7763            var args, _this;
7764
7765            return function () {
7766                if (args === void 0) {
7767                    args = arguments;
7768                    _this = this;
7769
7770                    setTimeout(function () {
7771                        if (args.length === 1) {
7772                            callback.call(_this, args[0]);
7773                        } else {
7774                            callback.apply(_this, args);
7775                        }
7776
7777                        args = void 0;
7778                    }, ms);
7779                }
7780            };
7781        }
7782
7783        function _extend(dst, src) {
7784            if (dst && src) {
7785                for (var key in src) {
7786                    if (src.hasOwnProperty(key)) {
7787                        dst[key] = src[key];
7788                    }
7789                }
7790            }
7791
7792            return dst;
7793        }
7794
7795        function _clone(el) {
7796            return $
7797                ? $(el).clone(true)[0]
7798                : Polymer && Polymer.dom
7799                ? Polymer.dom(el).cloneNode(true)
7800                : el.cloneNode(true);
7801        }
7802
7803        // Export utils
7804        Sortable.utils = {
7805            on: _on,
7806            off: _off,
7807            css: _css,
7808            find: _find,
7809            is: function (el, selector) {
7810                return !!_closest(el, selector, el);
7811            },
7812            extend: _extend,
7813            throttle: _throttle,
7814            closest: _closest,
7815            toggleClass: _toggleClass,
7816            clone: _clone,
7817            index: _index,
7818        };
7819
7820        /**
7821         * Create sortable instance
7822         * @param {HTMLElement}  el
7823         * @param {Object}      [options]
7824         */
7825        Sortable.create = function (el, options) {
7826            return new Sortable(el, options);
7827        };
7828
7829        // Export
7830        Sortable.version = "1.4.2";
7831        return Sortable;
7832    });
7833    });
7834
7835    const $$h = jQuery;
7836    class ImagesFormElement extends FormElement {
7837        constructor(options, formBuilder, external) {
7838            super(options, formBuilder, external);
7839            this.searchType = options.searchType || "fulltext";
7840            this.mediaUploader = external.mediaUploader;
7841            this.button_text = options.button_text || "Browse...";
7842            this.db_type = "text";
7843            this.label = options.label || "Images";
7844            this.name = options.name || "images";
7845            this.images = this.value || [];
7846            this.value = JSON.stringify(this.value);
7847        }
7848        init() {
7849            super.init();
7850            this.redrawImages();
7851        }
7852        setDomElements() {
7853            super.setDomElements();
7854        }
7855        getData() {
7856            this.updateData();
7857            return { name: this.name, value: this.images };
7858        }
7859        getSchema() {
7860            const schema = super.getSchema();
7861            schema.button_text = this.button_text;
7862            return schema;
7863        }
7864        updateData() {
7865            const newListOfImages = [];
7866            $$h(this.domElements.main)
7867                .find(".mapsvg-thumbnail-wrap")
7868                .each(function (index, el) {
7869                const imageData = $$h(el).data("image");
7870                newListOfImages.push(imageData);
7871            });
7872            this.images = newListOfImages;
7873            this.value = JSON.stringify(this.images);
7874            $$h(this.domElements.main).find("input").val(this.value);
7875        }
7876        setEventHandlers() {
7877            super.setEventHandlers();
7878            if (this.formBuilder.editMode) {
7879                return;
7880            }
7881            const _this = this;
7882            const imageDOM = $$h(this.domElements.main).find(".mapsvg-data-images");
7883            this.external.mediaUploader.on("select", () => {
7884                const attachments = _this.external.mediaUploader.state().get("selection").toJSON();
7885                attachments.forEach(function (img) {
7886                    const image = { sizes: {} };
7887                    for (const type in img.sizes) {
7888                        image[type] = img.sizes[type].url
7889                            .replace("http://", "//")
7890                            .replace("https://", "//");
7891                        image.sizes[type] = {
7892                            width: img.sizes[type].width,
7893                            height: img.sizes[type].height,
7894                        };
7895                    }
7896                    if (!image.thumbnail) {
7897                        image.thumbnail = image.full;
7898                        image.sizes.thumbnail = {
7899                            width: img.sizes.full.width,
7900                            height: img.sizes.full.height,
7901                        };
7902                    }
7903                    if (!image.medium) {
7904                        image.medium = image.full;
7905                        image.sizes.medium = {
7906                            width: img.sizes.full.width,
7907                            height: img.sizes.full.height,
7908                        };
7909                    }
7910                    image.caption = img.caption;
7911                    image.description = img.description;
7912                    _this.images.push(image);
7913                });
7914                this.setValue(this.images);
7915                _this.redrawImages();
7916            });
7917            $$h(_this.domElements.main).on("click", ".mapsvg-upload-image", function (e) {
7918                e.preventDefault();
7919                _this.external.mediaUploader.open();
7920            });
7921            $$h(_this.domElements.main).on("click", ".mapsvg-image-delete", function (e) {
7922                e.preventDefault();
7923                $$h(this).closest(".mapsvg-thumbnail-wrap").remove();
7924                _this.updateData();
7925            });
7926            _this.sortable = new sortable_min(imageDOM[0], {
7927                animation: 150,
7928                onStart: function () {
7929                    $$h(_this.domElements.main).addClass("sorting");
7930                },
7931                onEnd: function (evt) {
7932                    _this.images = [];
7933                    $$h(_this.domElements.main)
7934                        .find("img")
7935                        .each(function (i, image) {
7936                        _this.images.push($$h(image).data("image"));
7937                    });
7938                    this.value = JSON.stringify(_this.images);
7939                    $$h(_this.domElements.main).find("input").val(this.value);
7940                    $$h(_this.domElements.main).removeClass("sorting");
7941                },
7942            });
7943        }
7944        redrawImages() {
7945            const imageDOM = $$h(this.domElements.main).find(".mapsvg-data-images");
7946            imageDOM.empty();
7947            this.images &&
7948                this.images.forEach(function (image) {
7949                    const img = $$h('<img class="mapsvg-data-thumbnail" />')
7950                        .attr("src", image.thumbnail)
7951                        .data("image", image);
7952                    const imgContainer = $$h('<div class="mapsvg-thumbnail-wrap"></div>').data("image", image);
7953                    imgContainer.append(img);
7954                    imgContainer.append('<i class="fa fa-times  mapsvg-image-delete"></i>');
7955                    imageDOM.append(imgContainer);
7956                });
7957            $$h(this.domElements.main).find("input").val(this.value);
7958        }
7959    }
7960
7961    const $$i = jQuery;
7962    class LocationFormElement extends FormElement {
7963        constructor(options, formBuilder, external) {
7964            super(options, formBuilder, external);
7965            this.label = this.label || (options.label === undefined ? "Location" : options.label);
7966            this.name = "location";
7967            this.db_type = "text";
7968            this.languages = [
7969                { value: "sq", label: "Albanian" },
7970                { value: "ar", label: "Arabic" },
7971                {
7972                    value: "eu",
7973                    label: "Basque",
7974                },
7975                { value: "be", label: "Belarusian" },
7976                { value: "bg", label: "Bulgarian" },
7977                {
7978                    value: "my",
7979                    label: "Burmese",
7980                },
7981                { value: "bn", label: "Bengali" },
7982                { value: "ca", label: "Catalan" },
7983                {
7984                    value: "zh-cn",
7985                    label: "Chinese (simplified)",
7986                },
7987                { value: "zh-tw", label: "Chinese (traditional)" },
7988                {
7989                    value: "hr",
7990                    label: "Croatian",
7991                },
7992                { value: "cs", label: "Czech" },
7993                { value: "da", label: "Danish" },
7994                {
7995                    value: "nl",
7996                    label: "Dutch",
7997                },
7998                { value: "en", label: "English" },
7999                {
8000                    value: "en-au",
8001                    label: "English (australian)",
8002                },
8003                { value: "en-gb", label: "English (great Britain)" },
8004                {
8005                    value: "fa",
8006                    label: "Farsi",
8007                },
8008                { value: "fi", label: "Finnish" },
8009                { value: "fil", label: "Filipino" },
8010                {
8011                    value: "fr",
8012                    label: "French",
8013                },
8014                { value: "gl", label: "Galician" },
8015                { value: "de", label: "German" },
8016                {
8017                    value: "el",
8018                    label: "Greek",
8019                },
8020                { value: "gu", label: "Gujarati" },
8021                { value: "iw", label: "Hebrew" },
8022                {
8023                    value: "hi",
8024                    label: "Hindi",
8025                },
8026                { value: "hu", label: "Hungarian" },
8027                { value: "id", label: "Indonesian" },
8028                {
8029                    value: "it",
8030                    label: "Italian",
8031                },
8032                { value: "ja", label: "Japanese" },
8033                { value: "kn", label: "Kannada" },
8034                {
8035                    value: "kk",
8036                    label: "Kazakh",
8037                },
8038                { value: "ko", label: "Korean" },
8039                { value: "ky", label: "Kyrgyz" },
8040                {
8041                    value: "lt",
8042                    label: "Lithuanian",
8043                },
8044                { value: "lv", label: "Latvian" },
8045                { value: "mk", label: "Macedonian" },
8046                {
8047                    value: "ml",
8048                    label: "Malayalam",
8049                },
8050                { value: "mr", label: "Marathi" },
8051                { value: "no", label: "Norwegian" },
8052                {
8053                    value: "pl",
8054                    label: "Polish",
8055                },
8056                { value: "pt", label: "Portuguese" },
8057                {
8058                    value: "pt-br",
8059                    label: "Portuguese (brazil)",
8060                },
8061                { value: "pt-pt", label: "Portuguese (portugal)" },
8062                {
8063                    value: "pa",
8064                    label: "Punjabi",
8065                },
8066                { value: "ro", label: "Romanian" },
8067                { value: "ru", label: "Russian" },
8068                {
8069                    value: "sr",
8070                    label: "Serbian",
8071                },
8072                { value: "sk", label: "Slovak" },
8073                { value: "sl", label: "Slovenian" },
8074                {
8075                    value: "es",
8076                    label: "Spanish",
8077                },
8078                { value: "sv", label: "Swedish" },
8079                { value: "tl", label: "Tagalog" },
8080                {
8081                    value: "ta",
8082                    label: "Tamil",
8083                },
8084                { value: "te", label: "Telugu" },
8085                { value: "th", label: "Thai" },
8086                {
8087                    value: "tr",
8088                    label: "Turkish",
8089                },
8090                { value: "uk", label: "Ukrainian" },
8091                { value: "uz", label: "Uzbek" },
8092                {
8093                    value: "vi",
8094                    label: "Vietnamese",
8095                },
8096            ];
8097            this.language = options.language;
8098            this.markerImages = MapSVG.markerImages;
8099            this.markersByField = options.markersByField;
8100            this.markerField = options.markerField;
8101            this.markersByFieldEnabled = MapSVG.parseBoolean(options.markersByFieldEnabled);
8102            this.templates.marker = Handlebars.compile($$i("#mapsvg-data-tmpl-marker").html());
8103        }
8104        init() {
8105            super.init();
8106            if (this.value) {
8107                this.renderMarker();
8108            }
8109            this.renderMarkerSelector();
8110        }
8111        getSchema() {
8112            const schema = super.getSchema();
8113            schema.language = this.language;
8114            schema.markersByField = this.markersByField;
8115            schema.markerField = this.markerField;
8116            schema.markersByFieldEnabled = MapSVG.parseBoolean(this.markersByFieldEnabled);
8117            return schema;
8118        }
8119        getData() {
8120            return { name: this.name, value: this.value };
8121        }
8122        getDataForTemplate() {
8123            const data = super.getDataForTemplate();
8124            if (this.formBuilder.admin) {
8125                data.languages = this.languages;
8126                data.markerImages = MapSVG.markerImages;
8127                data.markersByField = this.markersByField;
8128                data.markerField = this.markerField;
8129                data.markersByFieldEnabled = MapSVG.parseBoolean(this.markersByFieldEnabled);
8130                const _this = this;
8131                data.markerImages.forEach(function (m) {
8132                    if (m.path === _this.formBuilder.mapsvg.getData().options.defaultMarkerImage) {
8133                        m.default = true;
8134                    }
8135                    else {
8136                        m.default = false;
8137                    }
8138                });
8139            }
8140            data.language = this.language;
8141            if (this.value) {
8142                data.location = this.value;
8143                if (data.location.marker) {
8144                    data.location.img =
8145                        (this.value.marker.src.indexOf(MapSVG.urls.uploads) === 0 ? "uploads/" : "") +
8146                            this.value.marker.src.split("/").pop();
8147                }
8148            }
8149            data.showUploadBtn = data.external.filtersMode;
8150            return data;
8151        }
8152        initEditor() {
8153            super.initEditor();
8154            this.renderMarkerSelector();
8155            this.fillMarkersByFieldOptions(this.markerField);
8156        }
8157        setDomElements() {
8158            super.setDomElements();
8159            this.domElements.markerImageButton = $$i(this.domElements.main).find("img")[0];
8160        }
8161        setEventHandlers() {
8162            super.setEventHandlers();
8163            const _this = this;
8164            const server = new Server();
8165            if (_this.formBuilder.mapsvg.isGeo()) {
8166                const locations = new Bloodhound({
8167                    datumTokenizer: Bloodhound.tokenizers.obj.whitespace("formatted_address"),
8168                    queryTokenizer: Bloodhound.tokenizers.whitespace,
8169                    remote: {
8170                        url: server.getUrl("geocoding") + "?address=%QUERY%&language=" + this.language,
8171                        wildcard: "%QUERY%",
8172                        transform: function (response) {
8173                            if (response.error_message) {
8174                                alert(response.error_message);
8175                            }
8176                            return response.results;
8177                        },
8178                        rateLimitWait: 600,
8179                    },
8180                });
8181                const thContainer = $$i(this.domElements.main).find(".typeahead");
8182                const tH = thContainer
8183                    .typeahead({
8184                    minLength: 3,
8185                }, {
8186                    name: "mapsvg-addresses",
8187                    display: "formatted_address",
8188                    source: locations,
8189                })
8190                    .on("typeahead:asyncrequest", function (e) {
8191                    $$i(e.target).addClass("tt-loading");
8192                })
8193                    .on("typeahead:asynccancel typeahead:asyncreceive", function (e) {
8194                    $$i(e.target).removeClass("tt-loading");
8195                });
8196                thContainer.on("typeahead:select", (ev, item) => {
8197                    this.setValue(null, false);
8198                    const address = {};
8199                    address.formatted = item.formatted_address;
8200                    item.address_components.forEach((addr_item) => {
8201                        const type = addr_item.types[0];
8202                        address[type] = addr_item.long_name;
8203                        if (addr_item.short_name != addr_item.long_name) {
8204                            address[type + "_short"] = addr_item.short_name;
8205                        }
8206                    });
8207                    const locationData = {
8208                        address: address,
8209                        geoPoint: new GeoPoint(item.geometry.location.lat, item.geometry.location.lng),
8210                        img: this.formBuilder.mapsvg.getMarkerImage(this.formBuilder.getData()),
8211                        imagePath: this.formBuilder.mapsvg.getMarkerImage(this.formBuilder.getData()),
8212                    };
8213                    this.setValue(locationData, false);
8214                    thContainer.typeahead("val", "");
8215                    this.triggerChanged();
8216                });
8217                $$i(this.domElements.main).on("change", ".marker-file-uploader", function () {
8218                    _this.markerIconUpload(this);
8219                });
8220            }
8221            $$i(this.domElements.main).on("click", ".mapsvg-marker-image-btn-trigger", function (e) {
8222                e.preventDefault();
8223                $$i(this).toggleClass("active");
8224                _this.toggleMarkerSelector();
8225            });
8226            $$i(this.domElements.main).on("click", ".mapsvg-marker-delete", function (e) {
8227                e.preventDefault();
8228                _this.setValue(null);
8229                _this.triggerChanged();
8230            });
8231        }
8232        setEditorEventHandlers() {
8233            super.setEditorEventHandlers();
8234            const _this = this;
8235            $$i(this.domElements.edit).on("change", ".marker-file-uploader", function () {
8236                _this.markerIconUpload(this);
8237            });
8238            $$i(this.domElements.edit).on("change", 'select[name="markerField"]', function () {
8239                const fieldName = $$i(this).val();
8240                _this.fillMarkersByFieldOptions(fieldName);
8241            });
8242            $$i(this.domElements.edit).on("click", ".mapsvg-marker-image-selector button", function (e) {
8243                e.preventDefault();
8244                const src = $$i(this).find("img").attr("src");
8245                $$i(this).parent().find("button").removeClass("active");
8246                $$i(this).addClass("active");
8247                _this.formBuilder.mapsvg.setDefaultMarkerImage(src);
8248            });
8249            $$i(this.domElements.edit).on("click", ".mapsvg-marker-image-btn-trigger", function (e) {
8250                $$i(this).toggleClass("active");
8251                _this.toggleMarkerSelectorInLocationEditor.call(_this, $$i(this), e);
8252            });
8253        }
8254        markerIconUpload(input) {
8255            const uploadBtn = $$i(input).closest(".btn-file").buttonLoading(true);
8256            for (let i = 0; i < input.files.length; i++) {
8257                const data = new FormData();
8258                data.append("file", input.files[0]);
8259                const server = new Server();
8260                server
8261                    .ajax("markers", {
8262                    type: "POST",
8263                    data: data,
8264                    processData: false,
8265                    contentType: false,
8266                })
8267                    .done((resp) => {
8268                    if (resp.error) {
8269                        alert(resp.error);
8270                    }
8271                    else {
8272                        const marker = resp.marker;
8273                        const newMarker = `
8274                            <button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose active">
8275                                <img src="${marker.path}" />
8276                            </button>
8277                            </button>
8278                        `;
8279                        $$i(this.domElements.markerSelector)
8280                            .find(".mapsvg-marker-image-btn.active")
8281                            .removeClass("active");
8282                        $$i(newMarker).appendTo(this.domElements.markerSelector);
8283                        this.setMarkerImage(marker.path);
8284                        MapSVG.markerImages.push(marker);
8285                    }
8286                })
8287                    .always(function () {
8288                    uploadBtn.buttonLoading(false);
8289                });
8290            }
8291        }
8292        mayBeAddDistanceRow() {
8293            const _this = this;
8294            if (!this.domElements.editDistanceRow) {
8295                this.domElements.editDistanceRow = $$i($$i("#mapsvg-edit-distance-row").html())[0];
8296            }
8297            const z = $$i(this.domElements.edit).find(".mapsvg-edit-distance-row:last-child input");
8298            if (z && z.last() && z.last().val() && (z.last().val() + "").trim().length) {
8299                const newRow = $$i(this.templates.editDistanceRow).clone();
8300                newRow.insertAfter($$i(_this.domElements.edit).find(".mapsvg-edit-distance-row:last-child"));
8301            }
8302            const rows = $$i(_this.domElements.edit).find(".mapsvg-edit-distance-row");
8303            const row1 = rows.eq(rows.length - 2);
8304            const row2 = rows.eq(rows.length - 1);
8305            if (row1.length &&
8306                row2.length &&
8307                !row1.find("input:eq(0)").val().toString().trim() &&
8308                !row2.find("input:eq(0)").val().toString().trim()) {
8309                row2.remove();
8310            }
8311        }
8312        fillMarkersByFieldOptions(fieldName) {
8313            const _this = this;
8314            const field = _this.formBuilder.mapsvg.objectsRepository.getSchema().getField(fieldName);
8315            if (field) {
8316                const markerImg = _this.formBuilder.mapsvg.options.defaultMarkerImage;
8317                const rows = [];
8318                field.options.forEach(function (option) {
8319                    const img = _this.markersByField && _this.markersByField[option.value]
8320                        ? _this.markersByField[option.value]
8321                        : markerImg;
8322                    rows.push('<tr data-option-id="' +
8323                        option.value +
8324                        '"><td>' +
8325                        option.label +
8326                        '</td><td><button class="btn dropdown-toggle btn-outline-secondary mapsvg-marker-image-btn-trigger mapsvg-marker-image-btn"><img src="' +
8327                        img +
8328                        '" class="new-marker-img" /><span class="caret"></span></button></td></tr>');
8329                });
8330                $$i("#markers-by-field").empty().append(rows);
8331            }
8332        }
8333        renderMarker(marker) {
8334            if (marker && marker.location) {
8335                this.value = marker.location.getData();
8336            }
8337            this.renderMarkerHtml();
8338        }
8339        renderMarkerHtml() {
8340            if (!this.value) {
8341                $$i(this.domElements.main).find(".mapsvg-new-marker").hide();
8342            }
8343            else {
8344                $$i(this.domElements.main)
8345                    .find(".mapsvg-new-marker")
8346                    .show()
8347                    .html(this.templates.marker(this.value));
8348            }
8349        }
8350        toggleMarkerSelector() {
8351            if (this.domElements.markerSelectorWrap &&
8352                $$i(this.domElements.markerSelectorWrap).is(":visible")) {
8353                $$i(this.domElements.markerSelectorWrap).hide();
8354                return;
8355            }
8356            if (this.domElements.markerSelectorWrap &&
8357                $$i(this.domElements.markerSelectorWrap).not(":visible")) {
8358                $$i(this.domElements.markerSelector).find(".active").removeClass("active");
8359                if (this.value && this.value.imagePath) {
8360                    $$i(this.domElements.markerSelector)
8361                        .find('[src="' + this.value.imagePath + '"]')
8362                        .parent()
8363                        .addClass("active");
8364                }
8365                $$i(this.domElements.markerSelectorWrap).show();
8366                return;
8367            }
8368        }
8369        renderMarkerSelector() {
8370            const _this = this;
8371            const view = this.formBuilder.editMode ? this.domElements.edit : this.domElements.main;
8372            if (!view)
8373                return;
8374            const currentImage = this.value ? this.value.imagePath : null;
8375            const images = MapSVG.markerImages.map(function (image) {
8376                return ('<button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose ' +
8377                    (currentImage == image.path ? "active" : "") +
8378                    '"><img src="' +
8379                    image.path +
8380                    '" /></button>');
8381            });
8382            this.domElements.markerSelectorWrap = $$i(view).find(".mapsvg-marker-image-selector")[0];
8383            this.domElements.markerSelector = $$i(this.domElements.markerSelectorWrap).find(".mapsvg-marker-images")[0];
8384            if (this.domElements.markerSelector) {
8385                $$i(this.domElements.markerSelector).empty();
8386            }
8387            if (!this.formBuilder.editMode) {
8388                this.domElements.markerSelectorWrap.style.display = "none";
8389                $$i(this.domElements.markerSelector).on("click", ".mapsvg-marker-image-btn-choose", function (e) {
8390                    e.preventDefault();
8391                    const src = $$i(this).find("img").attr("src");
8392                    $$i(_this.domElements.markerSelectorWrap).hide();
8393                    $$i(_this.domElements.markerSelector).find(".active").removeClass("active");
8394                    $$i(this).addClass("active");
8395                    $$i(_this.domElements.main)
8396                        .find(".mapsvg-marker-image-btn-trigger")
8397                        .toggleClass("active", false);
8398                    $$i(_this.domElements.markerImageButton).attr("src", src);
8399                    _this.setMarkerImage(src);
8400                });
8401            }
8402            $$i(this.domElements.markerSelector).html(images.join(""));
8403        }
8404        setMarkerImage(src) {
8405            this.formBuilder.mapsvg.setDefaultMarkerImage(src);
8406            const value = this.value;
8407            if (value) {
8408                value.img = src;
8409                value.imagePath = src;
8410                this.setValue(value);
8411                this.triggerChanged();
8412                this.renderMarker();
8413            }
8414        }
8415        toggleMarkerSelectorInLocationEditor(jQueryObj, e) {
8416            e.preventDefault();
8417            const _this = this;
8418            if (jQueryObj.data("markerSelector") && jQueryObj.data("markerSelector").is(":visible")) {
8419                jQueryObj.data("markerSelector").hide();
8420                return;
8421            }
8422            if (jQueryObj.data("markerSelector") && jQueryObj.data("markerSelector").not(":visible")) {
8423                jQueryObj.data("markerSelector").show();
8424                return;
8425            }
8426            const markerBtn = $$i(this).closest("td").find(".mapsvg-marker-image-btn-trigger");
8427            const currentImage = markerBtn.attr("src");
8428            const images = MapSVG.markerImages.map(function (image) {
8429                return ('<button class="btn btn-outline-secondary mapsvg-marker-image-btn mapsvg-marker-image-btn-choose ' +
8430                    (currentImage == image.path ? "active" : "") +
8431                    '"><img src="' +
8432                    image.path +
8433                    '" /></button>');
8434            });
8435            if (!jQueryObj.data("markerSelector")) {
8436                const ms = $$i('<div class="mapsvg-marker-image-selector"></div>');
8437                jQueryObj.closest("td").append(ms);
8438                jQueryObj.data("markerSelector", ms);
8439            }
8440            else {
8441                jQueryObj.data("markerSelector").empty();
8442            }
8443            jQueryObj.data("markerSelector").html(images.join(""));
8444            jQueryObj
8445                .data("markerSelector")
8446                .on("click", ".mapsvg-marker-image-btn-choose", function (e) {
8447                e.preventDefault();
8448                const src = $$i(this).find("img").attr("src");
8449                jQueryObj.data("markerSelector").hide();
8450                const td = $$i(this).closest("td");
8451                const fieldId = $$i(this).closest("tr").data("option-id");
8452                const btn = td.find(".mapsvg-marker-image-btn-trigger");
8453                btn.toggleClass("active", false);
8454                btn.find("img").attr("src", src);
8455                _this.setMarkerByField(fieldId, src);
8456            });
8457        }
8458        setMarkerByField(fieldId, markerImg) {
8459            this.markersByField = this.markersByField || {};
8460            this.markersByField[fieldId] = markerImg;
8461        }
8462        deleteMarker() {
8463            $$i(this.domElements.main).find(".mapsvg-new-marker").hide();
8464            $$i(this.domElements.main).find(".mapsvg-marker-id").attr("disabled", "disabled");
8465        }
8466        destroy() {
8467            if ($$i().mselect2) {
8468                const sel = $$i(this.domElements.main).find(".mapsvg-select2");
8469                if (sel.length) {
8470                    sel.mselect2("destroy");
8471                }
8472            }
8473            this.domElements.markerSelector && $$i(this.domElements.markerSelector).popover("d
8473ispose");
8474        }
8475        setValue(value, updateInput = true) {
8476            this.value = value;
8477            this.renderMarker();
8478        }
8479    }
8480
8481    const $$j = jQuery;
8482    class ModalFormElement extends FormElement {
8483        constructor(options, formBuilder, external) {
8484            super(options, formBuilder, external);
8485            this.showButtonText = options.showButtonText;
8486        }
8487        getSchema() {
8488            const schema = super.getSchema();
8489            schema.showButtonText = this.showButtonText;
8490            return schema;
8491        }
8492    }
8493
8494    const $$k = jQuery;
8495    class PostFormElement extends FormElement {
8496        constructor(options, formBuilder, external) {
8497            super(options, formBuilder, external);
8498            if (this.formBuilder.admin)
8499                this.post_types = this.formBuilder.admin.getPostTypes();
8500            this.post_type = options.post_type || this.post_types[0];
8501            this.add_fields = MapSVG.parseBoolean(options.add_fields);
8502            this.db_type = "int(11)";
8503            this.name = "post";
8504            this.post = options.post;
8505        }
8506        setDomElements() {
8507            super.setDomElements();
8508            this.inputs.postSelect = ($$k(this.domElements.main).find(".mapsvg-find-post")[0]);
8509        }
8510        getSchema() {
8511            const schema = super.getSchema();
8512            schema.post_type = this.post_type;
8513            schema.add_fields = this.add_fields;
8514            return schema;
8515        }
8516        destroy() {
8517            if ($$k().mselect2) {
8518                const sel = $$k(this.domElements.main).find(".mapsvg-select2");
8519                if (sel.length) {
8520                    sel.mselect2("destroy");
8521                }
8522            }
8523        }
8524        getDataForTemplate() {
8525            const data = super.getDataForTemplate();
8526            if (this.formBuilder.admin)
8527                data.post_types = this.formBuilder.admin.getPostTypes();
8528            data.post_type = this.post_type;
8529            data.post = this.post;
8530            data.add_fields = this.add_fields || 0;
8531            return data;
8532        }
8533        setEventHandlers() {
8534            super.setEventHandlers();
8535            const server = new Server();
8536            $$k(this.inputs.postSelect)
8537                .mselect2({
8538                placeholder: "Search post by title",
8539                allowClear: true,
8540                disabled: this.readonly,
8541                ajax: {
8542                    url: server.getUrl("posts"),
8543                    dataType: "json",
8544                    delay: 250,
8545                    data: (params) => {
8546                        return {
8547                            filters: { post_type: this.post_type },
8548                            search: params.term,
8549                            page: params.page,
8550                        };
8551                    },
8552                    processResults: (data, params) => {
8553                        params.page = params.page || 1;
8554                        return {
8555                            results: data.posts ? data.posts : [],
8556                            pagination: {
8557                                more: false,
8558                            },
8559                        };
8560                    },
8561                    cache: true,
8562                },
8563                escapeMarkup: (markup) => {
8564                    return markup;
8565                },
8566                minimumInputLength: 1,
8567                templateResult: this.formatRepo,
8568                templateSelection: this.formatRepoSelection,
8569            })
8570                .on("select2:select", (e) => {
8571                const post = e.params.data;
8572                this.setValue(post);
8573                this.setInputValue(post);
8574                this.triggerChanged();
8575            })
8576                .on("change", (e) => {
8577                if (e.target.value === "") {
8578                    $$k(this.domElements.main).find(".mapsvg-post-id").text("");
8579                    $$k(this.domElements.main).find(".mapsvg-post-url").text("");
8580                    this.setValue(null, false);
8581                    this.triggerChanged();
8582                }
8583            });
8584        }
8585        formatRepo(repo) {
8586            if (repo.loading) {
8587                return repo.text;
8588            }
8589            else {
8590                return "<div class='select2-result-repository clearfix'>" + repo.post_title + "</div>";
8591            }
8592        }
8593        formatRepoSelection(repo) {
8594            return repo.post_title || repo.text;
8595        }
8596        setValue(post, updateInput = true) {
8597            this.value = post;
8598            if (updateInput) {
8599                this.setInputValue(post);
8600            }
8601        }
8602        setInputValue(post) {
8603            $$k(this.domElements.main).find(".mapsvg-post-id").text(post.id);
8604            $$k(this.domElements.main).find(".mapsvg-post-url").text(post.url).attr("href", post.url);
8605        }
8606    }
8607
8608    const $$l = jQuery;
8609    class RadioFormElement extends FormElement {
8610        constructor(options, formBuilder, external) {
8611            super(options, formBuilder, external);
8612            this.setOptions(options.options);
8613        }
8614        setDomElements() {
8615            super.setDomElements();
8616            this.inputs.radios = this.formBuilder.getForm().elements[this.name];
8617            this.$radios = $$l(this.domElements.main).find('input[type="radio"]');
8618        }
8619        setEventHandlers() {
8620            super.setEventHandlers();
8621            this.$radios.on("change", (e) => {
8622                this.setValue(e.target.value, false);
8623                this.triggerChanged();
8624            });
8625        }
8626        setInputValue(value) {
8627            this.inputs.radios.value = value;
8628        }
8629    }
8630
8631    const $$m = jQuery;
8632    class RegionsFormElement extends FormElement {
8633        constructor(options, formBuilder, external) {
8634            super(options, formBuilder, external);
8635            this.searchable = MapSVG.parseBoolean(options.searchable);
8636            this.options = this.formBuilder.getRegionsList();
8637            this.label = options.label === undefined ? "Regions" : options.label;
8638            this.name = "regions";
8639            this.db_type = "text";
8640            if (typeof this.value === "undefined") {
8641                this.value = [];
8642            }
8643            this.regionsTableName = this.formBuilder.mapsvg.regionsRepository.getSchema().name;
8644        }
8645        setDomElements() {
8646            super.setDomElements();
8647            this.inputs.select = $$m(this.domElements.main).find("select")[0];
8648        }
8649        getData() {
8650            return { name: "regions", value: this.value };
8651        }
8652        getSchema() {
8653            const schema = super.getSchema();
8654            if (schema.multiselect)
8655                schema.db_type = "text";
8656            const opts = $$m.extend(true, {}, { options: this.options });
8657            schema.options = opts.options;
8658            schema.optionsDict = {};
8659            schema.options.forEach(function (option) {
8660                schema.optionsDict[option.id] = option.title || option.id;
8661            });
8662            return schema;
8663        }
8664        getDataForTemplate() {
8665            const data = super.getDataForTemplate();
8666            data.regionsTableName = this.regionsTableName;
8667            data.regionsFromCurrentTable = this.getRegionsForCurrentTable();
8668            return data;
8669        }
8670        getRegionsForCurrentTable() {
8671            return this.value
8672                ? this.value.filter((region) => region.tableName === this.regionsTableName)
8673                : [];
8674        }
8675        setEventHandlers() {
8676            super.setEventHandlers();
8677            $$m(this.inputs.select).on("change", (e) => {
8678                const selectedOptions = Array.from(this.inputs.select.selectedOptions);
8679                const selectedValues = selectedOptions.map((option) => option.value);
8680                this.setValue(selectedValues, false);
8681                this.triggerChanged();
8682            });
8683        }
8684        destroy() {
8685            if ($$m().mselect2) {
8686                const sel = $$m(this.domElements.main).find(".mapsvg-select2");
8687                if (sel.length) {
8688                    sel.mselect2("destroy");
8689                }
8690            }
8691        }
8692        setValue(regionIds, updateInput = true) {
8693            const regionsFromOtherTables = this.value.filter((region) => region.tableName !== this.regionsTableName);
8694            const regions = [];
8695            regionIds.forEach((regionId) => {
8696                const region = this.formBuilder.mapsvg.getRegion(regionId);
8697                regions.push({ id: region.id, title: region.title, tableName: this.regionsTableName });
8698            });
8699            this.value = regions.concat(regionsFromOtherTables);
8700            if (updateInput) {
8701                this.setInputValue(regionIds);
8702            }
8703        }
8704    }
8705
8706    const $$n = jQuery;
8707    class SaveFormElement extends FormElement {
8708        constructor(options, formBuilder, external) {
8709            super(options, formBuilder, external);
8710            this.readonly = true;
8711        }
8712        setDomElements() {
8713            super.setDomElements();
8714            this.inputs.btnSave = $$n(this.domElements.main).find(".btn-save")[0];
8715            this.inputs.btnClose = $$n(this.domElements.main).find(".mapsvg-close")[0];
8716        }
8717        setEventHandlers() {
8718            super.setEventHandlers();
8719            $$n(this.inputs.btnSave).on("click", (e) => {
8720                e.preventDefault();
8721                this.events.trigger("click.btn.save");
8722            });
8723            $$n(this.inputs.btnClose).on("click", (e) => {
8724                e.preventDefault();
8725                this.events.trigger("click.btn.close");
8726            });
8727        }
8728    }
8729
8730    const $$o = jQuery;
8731    class SearchFormElement extends FormElement {
8732        constructor(options, formBuilder, external) {
8733            super(options, formBuilder, external);
8734            this.searchType = options.searchType || "fulltext";
8735        }
8736        setDomElements() {
8737            super.setDomElements();
8738            this.inputs.text = $$o(this.domElements.main).find("input")[0];
8739        }
8740        setEventHandlers() {
8741            super.setEventHandlers();
8742            $$o(this.inputs.text).on("change keyup paste", (e) => {
8743                this.setValue(e.target.value, false);
8744                this.triggerChanged();
8745            });
8746        }
8747        getSchema() {
8748            const schema = super.getSchema();
8749            schema.searchFallback = MapSVG.parseBoolean(this.searchFallback);
8750            schema.placeholder = this.placeholder;
8751            schema.noResultsText = this.noResultsText;
8752            schema.width = this.width;
8753            return schema;
8754        }
8755    }
8756
8757    const $$p = jQuery;
8758    class SelectFormElement extends FormElement {
8759        constructor(options, formBuilder, external) {
8760            super(options, formBuilder, external);
8761            this.searchable = MapSVG.parseBoolean(options.searchable);
8762            this.multiselect = MapSVG.parseBoolean(options.multiselect);
8763            this.optionsGrouped = options.optionsGrouped;
8764            this.db_type = this.multiselect ? "text" : "varchar(255)";
8765            this.setOptions(options.options);
8766        }
8767        setDomElements() {
8768            super.setDomElements();
8769            this.inputs.select = $$p(this.domElements.main).find("select")[0];
8770        }
8771        getSchema() {
8772            const schema = super.getSchema();
8773            schema.multiselect = MapSVG.parseBoolean(this.multiselect);
8774            if (schema.multiselect)
8775                schema.db_type = "text";
8776            schema.optionsGrouped = this.optionsGrouped;
8777            const opts = $$p.extend(true, {}, { options: this.options });
8778            schema.options = opts.options || [];
8779            schema.optionsDict = {};
8780            schema.options.forEach(function (option) {
8781                schema.optionsDict[option.value] = option.label;
8782            });
8783            return schema;
8784        }
8785        setEventHandlers() {
8786            super.setEventHandlers();
8787            $$p(this.inputs.select).on("change", (e) => {
8788                if (this.multiselect) {
8789                    const selectedOptions = Array.from(this.inputs.select.selectedOptions);
8790                    const selectedValues = selectedOptions.map((option) => {
8791                        return { label: option.label, value: option.value };
8792                    });
8793                    this.setValue(selectedValues, false);
8794                    this.triggerChanged();
8795                }
8796                else {
8797                    this.setValue(this.inputs.select.value, false);
8798                    this.triggerChanged();
8799                }
8800            });
8801        }
8802        addSelect2() {
8803            if ($$p().mselect2) {
8804                const select2Options = {};
8805                if (this.formBuilder.filtersMode && this.type == "select") {
8806                    select2Options.placeholder = this.placeholder;
8807                    if (!this.multiselect) {
8808                        select2Options.allowClear = true;
8809                    }
8810                }
8811                $$p(this.domElements.main)
8812                    .find("select")
8813                    .css({ width: "100%", display: "block" })
8814                    .mselect2(select2Options)
8815                    .on("select2:focus", function () {
8816                    $$p(this).mselect2("open");
8817                });
8818                $$p(this.domElements.main)
8819                    .find(".select2-selection--multiple .select2-search__field")
8820                    .css("width", "100%");
8821            }
8822        }
8823        setOptions(options) {
8824            if (options) {
8825                this.options = [];
8826                this.optionsDict = {};
8827                options.forEach((value, key) => {
8828                    this.options.push(value);
8829                    if (this.optionsGrouped) {
8830                        value.options.forEach((value2, key2) => {
8831                            this.optionsDict[value2.value] = value2;
8832                        });
8833                    }
8834                    else {
8835                        this.optionsDict[key] = value;
8836                    }
8837                });
8838                return this.options;
8839            }
8840            else {
8841                return this.setOptions([
8842                    { label: "Option one", name: "option_one", value: 1 },
8843                    { label: "Option two", name: "option_two", value: 2 },
8844                ]);
8845            }
8846        }
8847        setInputValue(value) {
8848            this.inputs.select.value = value;
8849            $$p(this.inputs.select).trigger("change.select2");
8850        }
8851    }
8852
8853    const $$q = jQuery;
8854    class StatusFormElement extends FormElement {
8855        constructor(options, formBuilder, external) {
8856            super(options, formBuilder, external);
8857            this.label = options.label || "Status";
8858            this.name = "status";
8859            this.setOptions(options.options);
8860        }
8861        setDomElements() {
8862            super.setDomElements();
8863            this.inputs.select = $$q(this.domElements.main).find("select")[0];
8864            if ($$q().colorpicker) {
8865                $$q(this.domElements.main)
8866                    .find(".cpicker")
8867                    .colorpicker()
8868                    .on("changeColor.colorpicker", function (event) {
8869                    const input = $$q(this).find("input");
8870                    if (input.val() == "")
8871                        $$q(this).find("i").css({ "background-color": "" });
8872                });
8873                this.domElements.edit &&
8874                    $$q(this.domElements.edit)
8875                        .find(".cpicker")
8876                        .colorpicker()
8877                        .on("changeColor.colorpicker", function (event) {
8878                        const input = $$q(this).find("input");
8879                        if (input.val() == "")
8880                            $$q(this).find("i").css({ "background-color": "" });
8881                    });
8882            }
8883        }
8884        destroy() {
8885            if ($$q().mselect2) {
8886                const sel = $$q(this.domElements.main).find(".mapsvg-select2");
8887                if (sel.length) {
8888                    sel.mselect2("destroy");
8889                }
8890            }
8891        }
8892        setEditorEventHandlers() {
8893            super.setEditorEventHandlers();
8894            const _this = this;
8895            $$q(this.domElements.edit).on("keyup change paste", ".mapsvg-edit-status-row input", function () {
8896                _this.mayBeAddStatusRow();
8897            });
8898        }
8899        initEditor() {
8900            super.initEditor();
8901            const _this = this;
8902            $$q(_this.domElements.edit)
8903                .find(".cpicker")
8904                .colorpicker()
8905                .on("changeColor.colorpicker", function (event) {
8906                const input = $$q(this).find("input");
8907                const index = $$q(this).closest("tr").index();
8908                if (input.val() == "")
8909                    $$q(this).find("i").css({ "background-color": "" });
8910                _this.options[index] = _this.options[index] || {
8911                    label: "",
8912                    value: "",
8913                    color: "",
8914                    disabled: false,
8915                };
8916                _this.options[index]["color"] = input.val();
8917            });
8918            _this.mayBeAddStatusRow();
8919        }
8920        mayBeAddStatusRow() {
8921            const _this = this;
8922            const editStatusRow = $$q($$q("#mapsvg-edit-status-row").html());
8923            const z = $$q(_this.domElements.edit).find(".mapsvg-edit-status-label:last-child");
8924            if (z && z.last() && z.last().val() && (z.last().val() + "").trim().length) {
8925                const newRow = editStatusRow.clone();
8926                newRow.insertAfter($$q(_this.domElements.edit).find(".mapsvg-edit-status-row:last-child"));
8927                newRow
8928                    .find(".cpicker")
8929                    .colorpicker()
8930                    .on("changeColor.colorpicker", function (event) {
8931                    const input = $$q(this).find("input");
8932                    const index = $$q(this).closest("tr").index();
8933                    if (input.val() == "")
8934                        $$q(this).find("i").css({ "background-color": "" });
8935                    _this.options[index] = _this.options[index] || {
8936                        label: "",
8937                        value: "",
8938                        color: "",
8939                        disabled: false,
8940                    };
8941                    _this.options[index]["color"] = input.val();
8942                });
8943            }
8944            const rows = $$q(_this.domElements.edit).find(".mapsvg-edit-status-row");
8945            const row1 = rows.eq(rows.length - 2);
8946            const row2 = rows.eq(rows.length - 1);
8947            if (row1.length &&
8948                row2.length &&
8949                !(row1.find("input:eq(0)").val().toString().trim() ||
8950                    row1.find("input:eq(1)").val().toString().trim() ||
8951                    row1.find("input:eq(2)").val().toString().trim()) &&
8952                !(row2.find("input:eq(0)").val().toString().trim() ||
8953                    row2.find("input:eq(1)").val().toString().trim() ||
8954                    row2.find("input:eq(2)").val().toString().trim())) {
8955                row2.remove();
8956            }
8957        }
8958        setEventHandlers() {
8959            super.setEventHandlers();
8960            $$q(this.inputs.select).on("change keyup paste", (e) => {
8961                this.setValue(e.target.value, false);
8962                this.triggerChanged();
8963            });
8964        }
8965        getSchema() {
8966            const schema = super.getSchema();
8967            const opts = $$q.extend(true, {}, { options: this.options });
8968            schema.options = opts.options;
8969            schema.optionsDict = {};
8970            schema.options.forEach(function (option, index) {
8971                if (schema.options[index].value === "") {
8972                    schema.options.splice(index, 1);
8973                }
8974                else {
8975                    schema.options[index].disabled = MapSVG.parseBoolean(schema.options[index].disabled);
8976                    schema.optionsDict[option.value] = option;
8977                }
8978            });
8979            return schema;
8980        }
8981        setInputValue(value) {
8982            this.inputs.select.value = value;
8983        }
8984    }
8985
8986    const $$r = jQuery;
8987    class TextareaFormElement extends FormElement {
8988        constructor(options, formBuilder, external) {
8989            super(options, formBuilder, external);
8990            this.searchType = options.searchType || "fulltext";
8991            this.searchable = MapSVG.parseBoolean(options.searchable);
8992            this.autobr = options.autobr;
8993            this.html = options.html;
8994            this.db_type = "text";
8995        }
8996        setDomElements() {
8997            super.setDomElements();
8998            this.inputs.textarea = $$r(this.domElements.main).find("textarea")[0];
8999            if (this.html) {
9000                this.editor = CodeMirror.fromTextArea(this.inputs.textarea, {
9001                    mode: { name: "handlebars", base: "text/html" },
9002                    matchBrackets: true,
9003                    lineNumbers: true,
9004                });
9005                if (this.formBuilder.admin) {
9006                    this.editor.on("change", this.setTextareaValue);
9007                }
9008            }
9009        }
9010        setEventHandlers() {
9011            super.setEventHandlers();
9012            $$r(this.inputs.textarea).on("change keyup paste", (e) => {
9013                this.setValue(e.target.value, false);
9014                this.triggerChanged();
9015            });
9016        }
9017        getSchema() {
9018            const schema = super.getSchema();
9019            schema.autobr = this.autobr;
9020            schema.html = this.html;
9021            return schema;
9022        }
9023        getDataForTemplate() {
9024            const data = super.getDataForTemplate();
9025            data.html = this.html;
9026            return data;
9027        }
9028        setTextareaValue(codemirror, changeobj) {
9029            const handler = codemirror.getValue();
9030            const textarea = $$r(codemirror.getTextArea());
9031            textarea.val(handler).trigger("change");
9032        }
9033        destroy() {
9034            const cm = $$r(this.domElements.main).find(".CodeMirror");
9035            if (cm.length) {
9036                cm.empty().remove();
9037            }
9038        }
9039    }
9040
9041    const $$s = jQuery;
9042    class TextFormElement extends FormElement {
9043       
9043 constructor(options, formBuilder, external) {
9044            super(options, formBuilder, external);
9045            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9046            this.width =
9047                this.formBuilder.filtersHide && !this.formBuilder.modal
9048                    ? null
9049                    : options.width || "100%";
9050            this.db_type = "varchar(255)";
9051        }
9052        setDomElements() {
9053            super.setDomElements();
9054            this.inputs.text = $$s(this.domElements.main).find('input[type="text"]')[0];
9055        }
9056        getSchema() {
9057            const schema = super.getSchema();
9058            schema.searchType = this.searchType;
9059            return schema;
9060        }
9061        setEventHandlers() {
9062            super.setEventHandlers();
9063            $$s(this.inputs.text).on("change keyup paste", (e) => {
9064                this.setValue(e.target.value, false);
9065                this.triggerChanged();
9066            });
9067        }
9068        setInputValue(value) {
9069            this.inputs.text.value = value;
9070        }
9071    }
9072
9073    const $$t = jQuery;
9074    class TitleFormElement extends FormElement {
9075        constructor(options, formBuilder, external) {
9076            super(options, formBuilder, external);
9077            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9078            this.width =
9079                this.formBuilder.filtersHide && !this.formBuilder.modal
9080                    ? null
9081                    : options.width || "100%";
9082            this.db_type = "varchar(255)";
9083        }
9084        setDomElements() {
9085            super.setDomElements();
9086            this.inputs.text = $$t(this.domElements.main).find('input[type="text"]')[0];
9087        }
9088        getSchema() {
9089            const schema = super.getSchema();
9090            schema.searchType = this.searchType;
9091            return schema;
9092        }
9093        setEventHandlers() {
9094            super.setEventHandlers();
9095            $$t(this.inputs.text).on("change keyup paste", (e) => {
9096                this.setValue(e.target.value, false);
9097                this.triggerChanged();
9098            });
9099        }
9100        setInputValue(value) {
9101            this.inputs.text.value = value;
9102        }
9103    }
9104
9105    const $$u = jQuery;
9106    class ColorPickerFormElement extends FormElement {
9107        constructor(options, formBuilder, external) {
9108            super(options, formBuilder, external);
9109            this.searchFallback = MapSVG.parseBoolean(options.searchFallback);
9110            this.width =
9111                this.formBuilder.filtersHide && !this.formBuilder.modal
9112                    ? null
9113                    : options.width || "100%";
9114            this.db_type = "varchar(255)";
9115        }
9116        setDomElements() {
9117            super.setDomElements();
9118            this.inputs.text = $$u(this.domElements.main).find("input.cpicker")[0];
9119            $$u(this.domElements.main).find(".colorpicker-element").colorpicker();
9120        }
9121        getSchema() {
9122            const schema = super.getSchema();
9123            schema.searchType = this.searchType;
9124            return schema;
9125        }
9126        setEventHandlers() {
9127            super.setEventHandlers();
9128            $$u(this.inputs.text).on("change keyup paste", (e) => {
9129                this.setValue(e.target.value, false);
9130                this.triggerChanged();
9131            });
9132            $$u(this.domElements.main).find(".colorpicker-element").colorpicker().on("changeColor.colorpicker", (e) => {
9133                this.setValue(this.inputs.text.value, false);
9134                this.triggerChanged();
9135            });
9136        }
9137        setInputValue(value) {
9138            this.inputs.text.value = value;
9139        }
9140    }
9141
9142    const $$v = jQuery;
9143    class FormElementFactory {
9144        constructor(options) {
9145            this.mapsvg = options.mapsvg;
9146            this.editMode = options.editMode;
9147            this.filtersMode = options.filtersMode;
9148            this.namespace = options.namespace;
9149            this.mediaUploader = options.mediaUploader;
9150            this.formBuilder = options.formBuilder;
9151            this.showNames = options.showNames !== false;
9152        }
9153        create(options) {
9154            const types = {
9155                checkbox: CheckboxFormElement,
9156                checkboxes: CheckboxesFormElement,
9157                date: DateFormElement,
9158                distance: DistanceFormElement,
9159                empty: EmptyFormElement,
9160                id: IdFormElement,
9161                image: ImagesFormElement,
9162                location: LocationFormElement,
9163                modal: ModalFormElement,
9164                post: PostFormElement,
9165                radio: RadioFormElement,
9166                region: RegionsFormElement,
9167                save: SaveFormElement,
9168                search: SearchFormElement,
9169                select: SelectFormElement,
9170                status: StatusFormElement,
9171                text: TextFormElement,
9172                textarea: TextareaFormElement,
9173                title: TitleFormElement,
9174                colorpicker: ColorPickerFormElement,
9175            };
9176            const formElement = new types[options.type](options, this.formBuilder, this.getExtraParams());
9177            formElement.init();
9178            return formElement;
9179        }
9180        getExtraParams() {
9181            const databaseFields = [];
9182            let databaseFieldsFilterableShort = [];
9183            const regionFields = [];
9184            const regions = [];
9185            let mapIsGeo = false;
9186            if (this.mapsvg) {
9187                mapIsGeo = this.mapsvg.isGeo();
9188                const schemaObjects = this.mapsvg.objectsRepository.getSchema();
9189                if (schemaObjects) {
9190                    schemaObjects.getFields().forEach(function (obj) {
9191                        if (obj.type == "text" ||
9192                            obj.type == "region" ||
9193                            obj.type == "textarea" ||
9194                            obj.type == "post" ||
9195                            obj.type == "select" ||
9196                            obj.type == "radio" ||
9197                            obj.type == "checkbox") {
9198                            if (obj.type == "post") {
9199                                databaseFields.push("Object.post.post_title");
9200                            }
9201                            else {
9202                                databaseFields.push("Object." + obj.name);
9203                            }
9204                        }
9205                    });
9206                    databaseFieldsFilterableShort = schemaObjects
9207                        .getFieldsAsArray()
9208                        .filter(function (obj) {
9209                        return obj.type == "select" || obj.type == "radio" || obj.type == "region";
9210                    })
9211                        .map(function (obj) {
9212                        return obj.name;
9213                    });
9214                }
9215                const schemaRegions = this.mapsvg.regionsRepository.getSchema();
9216                if (schemaRegions) {
9217                    const regionFields = schemaRegions.getFieldsAsArray().map(function (obj) {
9218                        if (obj.type == "status" ||
9219                            obj.type == "text" ||
9220                            obj.type == "textarea" ||
9221                            obj.type == "post" ||
9222                            obj.type == "select" ||
9223                            obj.type == "radio" ||
9224                            obj.type == "checkbox") {
9225                            if (obj.type == "post") {
9226                                return "Region.post.post_title";
9227                            }
9228                            else {
9229                                return "Region." + obj.name;
9230                            }
9231                        }
9232                    });
9233                }
9234                const regions = new ArrayIndexed("id");
9235                this.mapsvg.regions.forEach((region) => {
9236                    regions.push({ id: region.id, title: region.title });
9237                });
9238            }
9239            return {
9240                databaseFields: databaseFields,
9241                databaseFieldsFilterableShort: databaseFieldsFilterableShort,
9242                regionFields: regionFields,
9243                regions: regions,
9244                mapIsGeo: mapIsGeo,
9245                mediaUploader: this.mediaUploader,
9246                filtersMode: this.filtersMode,
9247                showNames: this.showNames,
9248            };
9249        }
9250    }
9251
9252    const $$w = jQuery;
9253    class FormBuilder {
9254        constructor(options) {
9255            const _this = this;
9256            this.events = new Events();
9257            this.container = options.container;
9258            this.namespace = options.namespace;
9259            this.mediaUploader = options.mediaUploader;
9260            this.schema = options.schema || [];
9261            this.editMode = options.editMode == undefined ? false : options.editMode;
9262            this.filtersMode = options.filtersMode == undefined ? false : options.filtersMode;
9263            this.filtersHide = options.filtersHide == undefined ? false : options.filtersHide;
9264            this.modal = options.modal == undefined ? false : options.modal;
9265            this.admin = options.admin;
9266            this.mapsvg = options.mapsvg;
9267            this.data = options.data || {};
9268            this.clearButton = options.clearButton || false;
9269            this.clearButtonText = options.clearButtonText || "";
9270            this.searchButton = options.searchButton || false;
9271            this.searchButtonText = options.searchButtonText || "";
9272            this.showButtonText = options.showButtonText || "";
9273            this.scrollable =
9274                typeof options.scrollable !== "undefined"
9275                    ? options.scrollable
9276                    : !_this.editMode && !_this.filtersMode;
9277            this.showNames = typeof options.showNames !== "undefined" ? options.showNames : true;
9278            this.formElementFactory = new FormElementFactory({
9279                mapsvg: this.mapsvg,
9280                formBuilder: this,
9281                mediaUploader: this.mediaUploader,
9282                editMode: this.editMode,
9283                filtersMode: this.filtersMode,
9284                namespace: this.namespace,
9285                showNames: this.showNames,
9286            });
9287            this.events = new Events(this);
9288            if (options.events && Object.keys(options.events).length > 0) {
9289                for (const eventName in options.events) {
9290                    this.events.on(eventName, options.events[eventName]);
9291                }
9292            }
9293            this.template = "form-builder";
9294            this.closeOnSave = options.closeOnSave === true;
9295            this.newRecord = options.newRecord === true;
9296            this.types = options.types || [
9297                "text",
9298                "textarea",
9299                "checkbox",
9300                "radio",
9301                "select",
9302                "image",
9303                "region",
9304                "location",
9305                "post",
9306                "date",
9307            ];
9308            this.templates = {};
9309            this.elements = {};
9310            this.view = $$w("<div />").addClass("mapsvg-form-builder")[0];
9311            if (this.editMode)
9312                $$w(this.view).addClass("full-flex");
9313            if (!this.showNames) {
9314                $$w(this.view).addClass("hide-names");
9315            }
9316            this.formElements = new ArrayIndexed("name");
9317            if (!MapSVG.templatesLoaded[this.template]) {
9318                this.loadTemplates(() => this.init());
9319            }
9320            else {
9321                this.init();
9322            }
9323        }
9324        loadTemplates(callback) {
9325            $$w.get(MapSVG.urls.root + "dist/" + this.template + ".html", (data) => {
9326                $$w(data).appendTo("body");
9327                MapSVG.templatesLoaded[this.template] = true;
9328                Handlebars.registerPartial("dataMarkerPartial", $$w("#mapsvg-data-tmpl-marker").html());
9329                if (this.editMode) {
9330                    Handlebars.registerPartial("markerByFieldPartial", $$w("#mapsvg-markers-by-field-tmpl-partial").html());
9331                }
9332                callback();
9333            });
9334        }
9335        init() {
9336            const _this = this;
9337            MapSVG.formBuilder = this;
9338            this.form = document.createElement("form");
9339            this.form.className = "mapsvg-data-form-view";
9340            if (!this.filtersMode) {
9341                this.form.classList.add("form-horizontal");
9342            }
9343            if (this.editMode) {
9344                const template = document.getElementById("mapsvg-form-editor-tmpl-ui").innerHTML;
9345                const templateCompiled = Handlebars.compile(template);
9346                this.view.innerHTML = templateCompiled({ types: this.types });
9347                this.view.classList.add("edit");
9348                this.form.classList.add("mapsvg-data-flex-full");
9349                this.form.classList.add("mapsvg-data-container");
9350                $$w(this.view).find(".mapsvg-data-preview").prepend(this.form);
9351                this.formEditor = $$w(this.view).find("#mapsvg-data-form-edit")[0];
9352            }
9353            else {
9354                this.view.appendChild(this.form);
9355            }
9356            _this.elements = {
9357                buttons: {
9358                    text: $$w(_this.view).find("#mapsvg-data-btn-text")[0],
9359                    textarea: $$w(_this.view).find("#mapsvg-data-btn-textarea")[0],
9360                    checkbox: $$w(_this.view).find("#mapsvg-data-btn-checkbox")[0],
9361                    radio: $$w(_this.view).find("#mapsvg-data-btn-radio")[0],
9362                    select: $$w(_this.view).find("#mapsvg-data-btn-select")[0],
9363                    image: $$w(_this.view).find("#mapsvg-data-btn-image")[0],
9364                    region: $$w(_this.view).find("#mapsvg-data-btn-region")[0],
9365                    marker: $$w(_this.view).find("#mapsvg-data-btn-marker")[0],
9366                    saveSchema: $$w(_this.view).find("#mapsvg-data-btn-save-schema")[0],
9367                },
9368                containers: {
9369                    buttons_add: $$w(_this.view).find("#mapsvg-data-buttons-add")[0],
9370                },
9371            };
9372            _this.redraw();
9373        }
9374        getForm() {
9375            return this.form;
9376        }
9377        getFormEditor() {
9378            return this.formEditor;
9379        }
9380        viewDidLoad() { }
9381        setEventHandlers() {
9382            const _this = this;
9383            if (this.filtersMode && this.clearButton) {
9384                $$w(this.elements.buttons.clearButton).on("click", () => {
9385                    this.clearAllFields();
9386                });
9387            }
9388            $$w(window)
9389                .off("keydown.form.mapsvg")
9390                .on("keydown.form.mapsvg", function (e) {
9391                if (MapSVG.formBuilder) {
9392                    if ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
9393                        MapSVG.formBuilder.save();
9394                    else if (e.keyCode == 27)
9395                        MapSVG.formBuilder.close();
9396                }
9397            });
9398            if (this.editMode) {
9399                $$w(this.view).on("click", "#mapsvg-data-buttons-add button", function (e) {
9400                    e.preventDefault();
9401                    const type = $$w(this).data("create");
9402                    const formElement = _this.formElementFactory.create({ type: type });
9403                    _this.addField(formElement);
9404                });
9405                $$w(this.view).on("click", "#mapsvg-data-btn-save-schema", function (e) {
9406                    e.preventDefault();
9407                    const fields = _this.getSchema();
9408                    const counts = {};
9409                    _this.formElements.forEach(function (elem) {
9410                        counts[elem.name] = (counts[elem.name] || 0) + 1;
9411                    });
9412                    $$w(_this.getForm()).find(".form-group").removeClass("has-error");
9413                    const errors = [];
9414                    const reservedFields = [
9415                        "lat",
9416                        "lon",
9417                        "lng",
9418                        "location",
9419                        "location_lat",
9420                        "location_lon",
9421                        "location_lng",
9422                        "location_address",
9423                        "location_img",
9424                        "marker",
9425                        "marker_id",
9426                        "regions",
9427                        "region_id",
9428                        "post",
9429                        "post_title",
9430                        "post_url",
9431                        "keywords",
9432                        "status",
9433                    ];
9434                    const reservedFieldsToTypes = {
9435                        regions: "region",
9436                        status: "status",
9437                        post: "post",
9438                        marker: "marker",
9439                        location: "location",
9440                    };
9441                    let errUnique, errEmpty;
9442                    _this.formElements.forEach(function (formElement, index) {
9443                        let err = false;
9444                        if (!_this.filtersMode) {
9445                            if (counts[formElement.name] > 1) {
9446                                if (!errUnique) {
9447                                    errUnique = "Field names should be unique";
9448                                    errors.push(errUnique);
9449                                    err = true;
9450                                }
9451                            }
9452                            else if (formElement.name.length === 0) {
9453                                if (!errEmpty) {
9454                                    errEmpty = "Field name can't be empty";
9455                                    errors.push(errEmpty);
9456                                    err = true;
9457                                }
9458                            }
9459                            else if (reservedFields.indexOf(formElement.name) != -1) {
9460                                if (!reservedFieldsToTypes[formElement.name] ||
9461                                    (reservedFieldsToTypes[formElement.name] &&
9462                                        reservedFieldsToTypes[formElement.name] != formElement.type)) {
9463                                    const msg = 'Field name "' +
9464                                        formElement.name +
9465                                        '" is reserved, please set another name';
9466                                    errors.push(msg);
9467                                    err = true;
9468                                }
9469                            }
9470                        }
9471                        if (formElement.options &&
9472                            formElement.type != "region" &&
9473                            formElement.type != "marker") {
9474                            const vals = formElement.options.map(function (obj) {
9475                                return obj.value;
9476                            });
9477                            const uniq = [...Array.from(new Set(vals).values())];
9478                            if (vals.length != uniq.length) {
9479                                errors.push('Check "Options" list - values should not repeat');
9480                                err = true;
9481                            }
9482                        }
9483                        err && $$w(formElement.domElements.main).addClass("has-error");
9484                    });
9485                    if (errors.length === 0) {
9486                        _this.events.trigger("saveSchema", _this, [_this, fields]);
9487                    }
9488                    else {
9489                        jQuery.growl.error({ title: "Errors", message: errors.join("<br />") });
9490                    }
9491                });
9492                setTimeout(function () {
9493                    const el = _this.getForm();
9494                    _this.sortable = new Sortable(el, {
9495                        animation: 150,
9496                        onStart: function () {
9497                            $$w(_this.getForm()).addClass("sorting");
9498                        },
9499                        onEnd: function () {
9500                            setTimeout(function () {
9501                                $$w(_this.getForm()).removeClass("sorting");
9502                                _this.formElements.clear();
9503                                $$w(el)
9504                                    .find(".form-group")
9505                                    .each(function (index, elem) {
9506                                    _this.formElements.push($$w(elem).data("formElement"));
9507                                });
9508                            }, 500);
9509                        },
9510                    });
9511                }, 1000);
9512            }
9513            new ResizeSensor(this.view, function () {
9514                _this.scrollApi && _this.scrollApi.reinitialise();
9515            });
9516        }
9517        clearAllFields() {
9518            $$w(this.getForm())
9519                .find("input")
9520                .not(":button, :submit, :reset, :hidden, :checkbox, :radio")
9521                .val("")
9522                .prop("selected", false);
9523            $$w(this.getForm()).find('input[type="radio"]').prop("checked", false);
9524            $$w(this.getForm()).find('input[type="checkbox"]').prop("checked", false);
9525            $$w(this.getForm()).find("select").val("").trigger("change.select2");
9526            this.events.trigger("cleared");
9527        }
9528        setFormElementEventHandlers(formElement) {
9529            const _this = this;
9530            if (this.editMode) {
9531                formElement.events.on("click", (elem) => {
9532                    this.edit(elem);
9533                });
9534                formElement.events.on("delete", (elem) => {
9535                    this.deleteField(elem);
9536                });
9537            }
9538            else {
9539                formElement.events.on("changed", (_formElement) => {
9540                    const name = _formElement.name;
9541                    const value = _formElement.value;
9542                    if (_formElement.type !== "search") {
9543                        this.events.trigger("changed.field", _formElement, [_formElement, name, value]);
9544                    }
9545                    else {
9546                        this.events.trigger("changed.search", _formElement, [_formElement, value]);
9547                    }
9548                });
9549                const locationField = _this.mapsvg &&
9550                    _this.mapsvg.objectsRepository &&
9551                    _this.mapsvg.objectsRepository.getSchema() &&
9552                    _this.mapsvg.objectsRepository.getSchema().getField("location");
9553                if (locationField &&
9554                    locationField.markersByFieldEnabled &&
9555                    locationField.markerField &&
9556                    formElement.name == locationField.markerField &&
9557                    Object.values(locationField.markersByField).length > 0) {
9558                    formElement.events.on("changed", (_formElement) => {
9559                        const name = _formElement.name;
9560                        const value = _formElement.value;
9561                        const src = locationField.markersByField[value];
9562                        if (src) {
9563                            if (_this.markerBackup) {
9564                                const marker = _this.mapsvg.getMarker(_this.markerBackup.id);
9565                                marker.setImage(src);
9566                                $$w(_this.view).find(".mapsvg-marker-image-btn img").attr("src", src);
9567                            }
9568                        }
9569                    });
9570                }
9571            }
9572        }
9573        save() {
9574            const _this = this;
9575            if (_this.markerBackup) {
9576                const marker = _this.mapsvg.getEditingMarker();
9577                marker.events.off("change");
9578                _this.markerBackup = marker.getOptions();
9579                _this.mapsvg.unsetEditingMarker();
9580            }
9581            const data = _this.getData();
9582            _this.saved = true;
9583            this.events.trigger("save", _this, [_this, data]);
9584        }
9585        getFormElementByType(type) {
9586            return this.formElements.find((el) => el.type === type);
9587        }
9588        getData() {
9589            const data = {};
9590            this.formElements.forEach((formElement) => {
9591                if (formElement.readonly === false || formElement.type === "id") {
9592                    const _formElementData = formElement.getData();
9593                    data[_formElementData.name] = _formElementData.value;
9594                }
9595            });
9596            return data;
9597        }
9598        reset() {
9599            this.formElements.forEach((formElement) => {
9600                formElement.setValue(null);
9601            });
9602        }
9603        update(data) {
9604            this.schema.getFields().forEach((field) => {
9605                const formElement = this.formElements.get(field.name);
9606                if (formElement) {
9607                    if (typeof data[field.name] !== "undefined") {
9608                        formElement.setValue(data[field.name]);
9609                    }
9610                    else {
9611                        formElement.setValue(null);
9612                    }
9613                }
9614            });
9615        }
9616        redraw() {
9617            const _this = this;
9618            delete _this.markerBackup;
9619            $$w(this.container).empty();
9620            $$w(this.getForm()).empty();
9621            this.formElements.clear();
9622            this.schema &&
9623                this.schema.fields.length > 0 &&
9624                this.schema.fields.forEach((fieldSettings) => {
9625                    if (this.filtersMode) {
9626                        if (fieldSettings.type == "distance") {
9627                            fieldSettings.value = this.data.distance
9628                                ? this.data.distance
9629                                : fieldSettings.value !== undefined
9630                                    ? fieldSettings.value
9631                                    : null;
9632                        }
9633                        else {
9634                            fieldSettings.value = this.data[fieldSettings.parameterNameShort];
9635                        }
9636                    }
9637                    else {
9638                        fieldSettings.value = this.data
9639                            ? this.data[fieldSettings.name]
9640                            : fieldSettings.value !== undefined
9641                                ? fieldSettings.value
9642                                : null;
9643                    }
9644                    if (fieldSettings.type == "location" && !this.editMode) {
9645                        if (fieldSettings.value &&
9646                            fieldSettings.value.marker &&
9647                            fieldSettings.value.marker.id) ;
9648                        this.admin && this.admin.setMode && this.admin.setMode("editMarkers");
9649                        this.admin && this.admin.enableMarkersMode(true);
9650                    }
9651                    else if (fieldSettings.type == "post") {
9652                        fieldSettings.post = this.data["post"];
9653                    }
9654                    else if (fieldSettings.type === "region") {
9655                        fieldSettings.options = new ArrayIndexed("id", this.getRegionsList());
9656                    }
9657                    const formElement = this.formElementFactory.create(fieldSettings);
9658                    if (this.filtersMode) {
9659                        if (!this.filtersHide ||
9660                            (this.filtersHide && this.modal && fieldSettings.type !== "search") ||
9661                            (!this.modal && fieldSettings.type === "search")) {
9662                            this.addField(formElement);
9663                        }
9664                    }
9665                    else {
9666                        this.addField(formElement);
9667                    }
9668                });
9669            if (!_this.editMode) {
9670                if (this.schema.fields.length === 0 && !this.filtersMode) {
9671                    const formElement = this.formElementFactory.create({ type: "empty" });
9672                    _this.addField(formElement);
9673                }
9674                else {
9675                    if (_this.admin && !_this.admin.isMetabox) {
9676                        const formElement = this.formElementFactory.create({ type: "save" });
9677                        formElement.events.on("click.btn.save", () => {
9678                            this.save();
9679                        });
9680                        formElement.events.on("click.btn.close", () => {
9681                            this.close();
9682                        });
9683                        _this.addField(formElement);
9684                    }
9685                }
9686            }
9687            if (_this.filtersMode && _this.filtersHide && !_this.modal) {
9688                const formElement = this.formElementFactory.create({
9689                    type: "modal",
9690                    showButtonText: _this.showButtonText,
9691                });
9692                this.showFiltersButton = _this.addField(formElement);
9693            }
9694            if (this.scrollable) {
9695                const nano = $$w('<div class="nano"></div>');
9696                const nanoContent = $$w('<div class="nano-content"></div>');
9697                nano.append(nanoContent);
9698                nanoContent.append(this.view);
9699                $$w(_this.container).append(nano);
9700                nano.jScrollPane({ contentWidth: "0px", mouseWheelSpeed: 30 });
9701                _this.scrollApi = nano.data("jsp");
9702            }
9703            else {
9704                $$w(_this.container).append(this.view);
9705            }
9706            if (_this.filtersMode && _this.clearButton) {
9707                _this.elements.buttons.clearButton = $$w('<div class="form-group mapsvg-filters-reset-container"><button class="btn btn-outline-secondary mapsvg-filters-reset">' +
9708                    _this.clearButtonText +
9709                    "</button></div>")[0];
9710                $$w(this.getForm()).append(_this.elements.buttons.clearButton);
9711            }
9712            if (_this.filtersMode && _this.searchButton) {
9713                _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">' +
9714                    _this.searchButtonText +
9715                    "</button></div>")[0];
9716                $$w(this.getForm()).append(_this.elements.buttons.searchButton);
9717            }
9718            if (!this.editMode && !_this.filtersMode)
9719                $$w(this.view).find("input:visible,textarea:visible").not(".tt-hint").first().focus();
9720            const cm = $$w(this.container).find(".CodeMirror");
9721            cm.each(function (index, el) {
9722                el && el.CodeMirror.refresh();
9723            });
9724            _this.setEventHandlers();
9725            this.events.trigger("init", this, [this, this.getData()]);
9726            this.events.trigger("loaded", this, [this]);
9727        }
9728        updateExtraParamsInFormElements() {
9729            this.formElements.forEach((formElement) => {
9730                formElement.setExternal(this.formElementFactory.getExtraParams());
9731                if (formElement.type === "location") {
9732                    formElement.redraw();
9733                }
9734            });
9735        }
9736        deleteField(formElement) {
9737            const _this = this;
9738            _this.formElements.delete(formElement.name);
9739        }
9740        getExtraParams() {
9741            const databaseFields = [];
9742            this.mapsvg.objectsRepository
9743                .getSchema()
9744                .getFields()
9745                .forEach(function (obj) {
9746                if (obj.type == "text" ||
9747                    obj.type == "region" ||
9748                    obj.type == "textarea" ||
9749                    obj.type == "post" ||
9750                    obj.type == "select" ||
9751                    obj.type == "radio" ||
9752                    obj.type == "checkbox") {
9753                    if (obj.type == "post") {
9754                        databaseFields.push("Object.post.post_title");
9755                    }
9756                    else {
9757                        databaseFields.push("Object." + obj.name);
9758                    }
9759                }
9760            });
9761            let databaseFieldsFilterableShort = [];
9762            databaseFieldsFilterableShort = this.mapsvg.objectsRepository
9763                .getSchema()
9764                .getFieldsAsArray()
9765                .filter(function (obj) {
9766                return obj.type == "select" || obj.type == "radio" || obj.type == "region";
9767            })
9768                .map(function (obj) {
9769                return obj.name;
9770            });
9771            let markerFieldsShort = [];
9772            markerFieldsShort = databaseFieldsFilterableShort.filter((o) => o.type === "select" || o.type === "radio");
9773            const regionFields = this.mapsvg.regionsRepository
9774                .getSchema()
9775                .getFieldsAsArray()
9776                .map(function (obj) {
9777                if (obj.type == "status" ||
9778                    obj.type == "text" ||
9779                    obj.type == "textarea" ||
9780                    obj.type == "post" ||
9781                    obj.type == "select" ||
9782                    obj.type == "radio" ||
9783                    obj.type == "checkbox") {
9784                    if (obj.type == "post") {
9785                        return "Region.post.post_title";
9786                    }
9787                    else {
9788                        return "Region." + obj.name;
9789                    }
9790                }
9791            });
9792            return {
9793                databaseFields: databaseFields,
9794                databaseFieldsFilterableShort: databaseFieldsFilterableShort,
9795                regionFields: regionFields,
9796                markerFieldsShort: markerFieldsShort,
9797            };
9798        }
9799        addField(formElement) {
9800            const _this = this;
9801            if (["region", "marker", "post", "status", "distance", "location", "search"].indexOf(formElement.type) != -1) {
9802                let repeat = false;
9803                _this.formElements.forEach(function (control) {
9804                    if (control.type == formElement.type)
9805                        repeat = true;
9806                });
9807                if (repeat) {
9808                    jQuery.growl.error({
9809                        title: "Error",
9810                        message: 'You can add only 1 "' + MapSVG.ucfirst(formElement.type) + '" field',
9811                    });
9812                    return;
9813                }
9814            }
9815            _this.formElements.push(formElement);
9816            _this.getForm().append(formElement.domElements.main);
9817            this.setFormElementEventHandlers(formElement);
9818            if (this.editMode) {
9819                if (formElement.protected) {
9820                    formElement.hide();
9821                }
9822                else {
9823                    this.edit(formElement);
9824                }
9825            }
9826            return formElement;
9827        }
9828        edit(formElement) {
9829            const _this = this;
9830            _this.currentlyEditing && _this.currentlyEditing.destroyEditor();
9831            this.getFormEditor().appendChild(formElement.getEditor());
9832            formElement.initEditor();
9833            _this.currentlyEditing = formElement;
9834            $$w(_this.getForm()).find(".form-group.active").removeClass("active");
9835            $$w(formElement.domElements.main).addClass("active");
9836        }
9837        get() {
9838        }
9839        getSchema() {
9840            return this.formElements.map(function (formElement) {
9841                return formElement.getSchema();
9842            });
9843        }
9844        close() {
9845            this.formElements.forEach((formElement) => formElement.destroy());
9846            MapSVG.formBuilder = null;
9847            this.events.trigger("close", this, [this]);
9848        }
9849        destroy() {
9850            $$w(this.view).empty().remove();
9851            this.sortable = null;
9852        }
9853        toJSON(addEmpty) {
9854            const obj = {};
9855            function add(obj, name, value) {
9856                if (!addEmpty && !value)
9857                    return false;
9858                if (name.length == 1) {
9859                    obj[name[0]] = value;
9860                }
9861                else {
9862                    if (obj[name[0]] == null) {
9863                        if (name[1] === "") {
9864                            obj[name[0]] = [];
9865                        }
9866                        else {
9867                            obj[name[0]] = {};
9868                        }
9869                    }
9870                    if (obj[name[0]].length !== undefined) {
9871                        obj[name[0]].push(value);
9872                    }
9873                    else {
9874                        add(obj[name[0]], name.slice(1), value);
9875                    }
9876                }
9877            }
9878            $$w(this.elements.containers.formView)
9879                .find("input, textarea, select")
9880                .each(function () {
9881                if (!$$w(this).data("skip") &&
9882                    !$$w(this).prop("disabled") &&
9883                    $$w(this).attr("name") &&
9884                    !(!addEmpty &&
9885                        $$w(this).attr("type") == "checkbox" &&
9886                        $$w(this).attr("checked") == undefined) &&
9887                    !($$w(this).attr("type") == "radio" && $$w(this).attr("checked") == undefined)) {
9888                    let value;
9889                    if ($$w(this).attr("type") == "checkbox") {
9890                        value = $$w(this).prop("checked");
9891                    }
9892                    else {
9893                        value = $$w(this).val();
9894                    }
9895                    add(obj, $$w(this).attr("name").replace(/]/g, "").split("["), value);
9896                }
9897            });
9898            return obj;
9899        }
9900        getRegionsList() {
9901            return this.mapsvg.regions.map(function (r) {
9902                return { id: r.id, title: r.title };
9903            });
9904        }
9905        getRegionsAsArray() {
9906            return this.mapsvg.regions;
9907        }
9908        setRegions(location) {
9909            const regionsFormElement = this.formElements.get("regions");
9910            if (this.mapsvg.options.source.indexOf("/geo-calibrated/us
9910a.svg") !== -1) {
9911                regionsFormElement.setValue(["US-" + location.address.state_short]);
9912            }
9913            else if (this.mapsvg.options.source.indexOf("/geo-calibrated/world.svg") !== -1) {
9914                if (location.address.country_short) {
9915                    regionsFormElement.setValue([location.address.country_short]);
9916                }
9917            }
9918            else {
9919                if (location.address.administrative_area_level_1) {
9920                    this.mapsvg.regions.forEach((_region) => {
9921                        if (_region.title === location.address.administrative_area_level_1 ||
9922                            _region.title === location.address.administrative_area_level_2 ||
9923                            _region.id ===
9924                                location.address.country_short +
9925                                    "-" +
9926                                    location.address.administrative_area_level_1_short) {
9927                            regionsFormElement.setValue([_region.id]);
9928                        }
9929                    });
9930                }
9931            }
9932        }
9933    }
9934
9935    const $$x = jQuery;
9936    class FiltersController extends DetailsController {
9937        constructor(options) {
9938            super(options);
9939            this.showButtonText = options.showButtonText;
9940            this.clearButton = options.clearButton;
9941            this.clearButtonText = options.clearButtonText;
9942            this.searchButton = options.searchButton;
9943            this.searchButtonText = options.searchButtonText;
9944            this.padding = options.padding;
9945            this.schema = options.schema;
9946            this.hideFilters = options.hide;
9947            this.query = options.query;
9948        }
9949        viewDidLoad() {
9950            super.viewDidLoad();
9951            const _this = this;
9952            this.formBuilder = new FormBuilder({
9953                container: this.containers.contentView,
9954                filtersMode: true,
9955                schema: this.schema,
9956                modal: this.modal,
9957                filtersHide: this.hideFilters,
9958                showButtonText: this.showButtonText,
9959                clearButton: this.clearButton,
9960                clearButtonText: this.clearButtonText,
9961                searchButton: this.searchButton,
9962                searchButtonText: this.searchButtonText,
9963                editMode: false,
9964                mapsvg: this.mapsvg,
9965                data: {},
9966                admin: false,
9967                events: {
9968                    "changed.field": (formElement, field, value) => {
9969                        const filters = {};
9970                        filters[field] = value;
9971                        this.query.setFilters(filters);
9972                        _this.events.trigger("changed.field", _this, [field, value]);
9973                        _this.events.trigger("changed.fields", _this, [field, value]);
9974                    },
9975                    "changed.search": (formElement, value) => {
9976                        this.query.setSearch(value);
9977                        _this.events.trigger("changed.search", _this, [value]);
9978                    },
9979                    cleared: (formBuilder) => {
9980                        this.query.clearFilters();
9981                        this.events.trigger("cleared.filters", _this, []);
9982                    },
9983                    loaded: (formBuilder) => {
9984                        $$x(formBuilder.container).find(".mapsvg-form-builder").css({
9985                            padding: _this.padding,
9986                        });
9987                        this.updateScroll();
9988                        this.events.trigger("loaded");
9989                    },
9990                },
9991            });
9992        }
9993        reset() {
9994            this.formBuilder && this.formBuilder.reset();
9995        }
9996        update(query) {
9997            this.formBuilder && this.formBuilder.update(query.filters);
9998        }
9999        setFiltersCounter() {
10000            if (this.hideFilters) {
10001                const filtersCounter = Object.keys(this.query.filters).length;
10002                const filtersCounterString = filtersCounter === 0 ? "" : f
10002iltersCounter.toString();
10003                this.formBuilder &&
10004                    this.formBuilder.showFiltersButton &&
10005                    $$x(this.formBuilder.showFiltersButton.domElements.main)
10006                        .find("button")
10007                        .html(this.showButtonText + " <b>" + filtersCounterString + "</b>");
10008            }
10009        }
10010        setEventHandlers() {
10011            super.setEventHandlers();
10012            const _this = this;
10013            $$x(this.containers.view).on("click", ".mapsvg-btn-show-filters", function () {
10014                _this.events.trigger("click.btn.showFilters");
10015            });
10016            $$x(this.containers.view).on("click", "#mapsvg-search-container", function () {
10017                _this.events.trigger("click.btn.searchButton");
10018            });
10019        }
10020    }
10021
10022    const $$y = jQuery;
10023    class PopoverController extends Controller {
10024        constructor(options) {
10025            super(options);
10026            options.autoresize = true;
10027            this.point = options.point;
10028            this.yShift = options.yShift;
10029            this.mapObject = options.mapObject;
10030            this.id = this.mapObject.id + "_" + Math.random();
10031            $$y(this.containers.main).data("popover-id", this.id);
10032        }
10033        setPoint(point) {
10034            this.point = point;
10035        }
10036        getToolbarTemplate() {
10037            if (this.withToolbar)
10038                return '<div class="mapsvg-popover-close"></div>';
10039            else
10040                return "";
10041        }
10042        viewDidLoad() {
10043            super.viewDidLoad.call(this);
10044            if (MapSVG.isPhone &&
10045                this.mapsvg.options.popovers.mobileFullscreen &&
10046                !this.mobileCloseBtn) {
10047                this.mobileCloseBtn = $$y('<button class="mapsvg-mobile-modal-close mapsvg-btn">' +
10048                    this.mapsvg.getData().options.mobileView.labelClose +
10049                    "</button>")[0];
10050                $$y(this.containers.view).append(this.mobileCloseBtn);
10051            }
10052            this.adjustScreenPosition();
10053            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", true);
10054            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", true);
10055            this.adjustHeight();
10056            this.updateScroll();
10057            this.autoresize && this.resizeSensor.setScroll();
10058            this.events.trigger("shown", this, [this]);
10059        }
10060        adjustHeight() {
10061            $$y(this.containers.main).height($$y(this.containers.main).find(".mapsvg-auto-height").outerHeight() +
10062                (this.containers.toolbar ? $$y(this.containers.toolbar).outerHeight() : 0));
10063        }
10064        adjustScreenPosition() {
10065            if (this.point) {
10066                const pos = this.mapsvg.converter.convertSVGToPixel(this.point);
10067                pos.y -= this.yShift;
10068                pos.x = Math.round(pos.x);
10069                pos.y = Math.round(pos.y);
10070                this.setScreenPosition(pos.x, pos.y);
10071            }
10072        }
10073        moveSrceenPositionBy(deltaX, deltaY) {
10074            const oldPos = this.screenPoint, x = oldPos.x - deltaX, y = oldPos.y - deltaY;
10075            this.setScreenPosition(x, y);
10076        }
10077        setScreenPosition(x, y) {
10078            this.screenPoint = new ScreenPoint(x, y);
10079            $$y(this.containers.main).css({
10080                transform: "translateX(-50%) translate(" + x + "px," + y + "px)",
10081            });
10082        }
10083        setEventHandlers() {
10084            $$y("body").off(".popover.mapsvg");
10085            $$y(this.containers.view).on("click touchend", ".mapsvg-popover-close, .mapsvg-mobile-modal-close", (e) => {
10086                e.stopImmediatePropagation();
10087                this.close();
10088            });
10089            $$y("body").on("mouseup.popover.mapsvg touchend.popover.mapsvg", (e) => {
10090                if (this.mapsvg.isScrolling ||
10091                    $$y(e.target).closest(".mapsvg-directory").length ||
10092                    $$y(e.target).closest(".mapsvg-popover").length ||
10093                    $$y(e.target).hasClass("mapsvg-btn-map"))
10094                    return;
10095                this.close();
10096            });
10097        }
10098        close() {
10099            if ($$y(this.containers.main).data("popover-id") != this.id ||
10100                !$$y(this.containers.main).is(":visible"))
10101                return;
10102            this.destroy();
10103            if (this.mapObject instanceof Region) {
10104                this.mapsvg.deselectRegion(this.mapObject);
10105            }
10106            if (this.mapObject instanceof Marker) {
10107                this.mapsvg.deselectAllMarkers();
10108            }
10109            this.events.trigger("closed", this, [this]);
10110        }
10111        destroy() {
10112            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", false);
10113            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", false);
10114            super.destroy.call(this);
10115        }
10116        show() {
10117            $$y(this.containers.main).toggleClass("mapsvg-popover-animate", true);
10118            $$y(this.containers.main).toggleClass("mapsvg-popover-visible", true);
10119        }
10120    }
10121
10122    const $$z = jQuery;
10123    class Tooltip extends Controller {
10124        constructor(options) {
10125            super(options);
10126            this.scrollable = false;
10127            this.withToolbar = false;
10128            this.autoresize = false;
10129            this.screenPoint = new ScreenPoint(0, 0);
10130            this.posOriginal = {};
10131            this.posShifted = {};
10132            this.posShiftedPrev = {};
10133            this.mirror = {};
10134            this.noPadding = true;
10135            this.setPosition(options.position);
10136            this.setSize(options.minWidth, options.maxWidth);
10137        }
10138        setSize(minWidth, maxWidth) {
10139            this.minWidth = minWidth;
10140            this.maxWidth = maxWidth;
10141            this.containers.main.style["min-width"] = this.minWidth + "px";
10142            this.containers.main.style["max-width"] = this.maxWidth + "px";
10143        }
10144        setPosition(position) {
10145            const ex = position.split("-");
10146            if (ex[0].indexOf("top") != -1 || ex[0].indexOf("bottom") != -1) {
10147                this.posOriginal.topbottom = ex[0];
10148            }
10149            if (ex[0].indexOf("left") != -1 || ex[0].indexOf("right") != -1) {
10150                this.posOriginal.leftright = ex[0];
10151            }
10152            if (ex[1]) {
10153                this.posOriginal.leftright = ex[1];
10154            }
10155            this.containers.main.className = this.containers.main.className.replace(/(^|\s)mapsvg-tt-\S+/g, "");
10156            this.containers.main.classList.add("mapsvg-tt-" + position);
10157        }
10158        setScreenPoint(x, y) {
10159            this.screenPoint.x = x;
10160            this.screenPoint.y = y;
10161        }
10162        viewDidLoad() {
10163            super.viewDidLoad.call(this);
10164        }
10165        viewDidAppear() {
10166            super.viewDidAppear();
10167            this.events.trigger("shown", this, [this]);
10168        }
10169        setScreenPosition(x, y) {
10170            this.setScreenPoint(x, y);
10171            this.containers.main.style.transform =
10172                "translateX(-50%) translate(" + x + "px," + y + "px)";
10173        }
10174        setEventHandlers() {
10175            const event = "mousemove.tooltip.mapsvg-" + this.mapsvg.id;
10176            $$z("body")
10177                .off(event)
10178                .on(event, (e) => {
10179                MapSVG.mouse = MapSVG.mouseCoords(e);
10180                this.containers.main.style.left =
10181                    e.clientX +
10182                        $$z(window).scrollLeft() -
10183                        $$z(this.mapsvg.containers.map).offset().left +
10184                        "px";
10185                this.containers.main.style.top =
10186                    e.clientY +
10187                        $$z(window).scrollTop() -
10188                        $$z(this.mapsvg.containers.map).offset().top +
10189                        "px";
10190                const m = new ScreenPoint(e.clientX + $$z(window).scrollLeft(), e.clientY + $$z(window).scrollTop());
10191                const _tbbox = this.containers.main.getBoundingClientRect();
10192                const _mbbox = this.mapsvg.containers.wrap.getBoundingClientRect();
10193                const tbbox = {
10194                    top: _tbbox.top + $$z(window).scrollTop(),
10195                    bottom: _tbbox.bottom + $$z(window).scrollTop(),
10196                    left: _tbbox.left + $$z(window).scrollLeft(),
10197                    right: _tbbox.right + $$z(window).scrollLeft(),
10198                    width: _tbbox.width,
10199                    height: _tbbox.height,
10200                };
10201                const mbbox = {
10202                    top: _mbbox.top + $$z(window).scrollTop(),
10203                    bottom: _mbbox.bottom + $$z(window).scrollTop(),
10204                    left: _mbbox.left + $$z(window).scrollLeft(),
10205                    right: _mbbox.right + $$z(window).scrollLeft(),
10206                    width: _mbbox.width,
10207                    height: _mbbox.height,
10208                };
10209                if (m.x > mbbox.right ||
10210                    m.y > mbbox.bottom ||
10211                    m.x < mbbox.left ||
10212                    m.y < mbbox.top) {
10213                    return;
10214                }
10215                if (this.mirror.top || this.mirror.bottom) {
10216                    if (this.mirror.top && m.y > this.mirror.top) {
10217                        this.mirror.top = 0;
10218                        delete this.posShifted.topbottom;
10219                    }
10220                    else if (this.mirror.bottom && m.y < this.mirror.bottom) {
10221                        this.mirror.bottom = 0;
10222                        delete this.posShifted.topbottom;
10223                    }
10224                }
10225                else {
10226                    if (tbbox.bottom < mbbox.top + tbbox.height) {
10227                        this.posShifted.topbottom = "bottom";
10228                        this.mirror.top = m.y;
10229                    }
10230                    else if (tbbox.top > mbbox.bottom - tbbox.height) {
10231                        this.posShifted.topbottom = "top";
10232                        this.mirror.bottom = m.y;
10233                    }
10234                }
10235                if (this.mirror.right || this.mirror.left) {
10236                    if (this.mirror.left && m.x > this.mirror.left) {
10237                        this.mirror.left = 0;
10238                        delete this.posShifted.leftright;
10239                    }
10240                    else if (this.mirror.right && m.x < this.mirror.right) {
10241                        this.mirror.right = 0;
10242                        delete this.posShifted.leftright;
10243                    }
10244                }
10245                else {
10246                    if (tbbox.right < mbbox.left + tbbox.width) {
10247                        this.posShifted.leftright = "right";
10248                        this.mirror.left = m.x;
10249                    }
10250                    else if (tbbox.left > mbbox.right - tbbox.width) {
10251                        this.posShifted.leftright = "left";
10252                        this.mirror.right = m.x;
10253                    }
10254                }
10255                let pos = $$z.extend({}, this.posOriginal, this.posShifted);
10256                const _pos = [];
10257                pos.topbottom && _pos.push(pos.topbottom);
10258                pos.leftright && _pos.push(pos.leftright);
10259                pos = _pos.join("-");
10260                if (this.posShifted.topbottom != this.posOriginal.topbottom ||
10261                    this.posShifted.leftright != this.posOriginal.leftright) {
10262                    this.containers.main.className = this.containers.main.className.replace(/(^|\s)mapsvg-tt-\S+/g, "");
10263                    this.containers.main.classList.add("mapsvg-tt-" + pos);
10264                    this.posShiftedPrev = pos;
10265                }
10266            });
10267        }
10268        setContent(template, data) {
10269            this.containers.main.innerHTML = template(data);
10270            return this;
10271        }
10272        show() {
10273            this.containers.main.classList.add("mapsvg-tooltip-visible");
10274            return this;
10275        }
10276        hide() {
10277            this.containers.main.classList.remove("mapsvg-tooltip-visible");
10278            return this;
10279        }
10280    }
10281
10282    const $$A = jQuery;
10283    class MapSVGMap {
10284        constructor(containerId, mapParams) {
10285            this.markerOptions = { src: MapSVG.urls.root + "markers/pin1_red.png" };
10286            const options = mapParams.options;
10287            this.updateOutdatedOptions(options);
10288            this.dirtyFields = [];
10289            this.containerId = containerId;
10290            this.options = $$A.extend(true, {}, DefaultOptions, options);
10291            this.options.source = this.urlToRelativePath(this.options.source);
10292            this.editMode = this.options.editMode;
10293            delete this.options.editMode;
10294            this.id = mapParams.id;
10295            this.svgFileLastChanged = mapParams.svgFileLastChanged;
10296            this.regions = new ArrayIndexed("id");
10297            this.objects = new ArrayIndexed("id");
10298            this.events = new Events(this);
10299            this.highlightedRegions = [];
10300            this.editRegions = { on: false };
10301            this.editMarkers = { on: false };
10302            this.editData = { on: false };
10303            this.controllers = {};
10304            this.containers = {
10305                map: document.getElementById(this.containerId),
10306                scrollpane: $$A('<div class="mapsvg-scrollpane"></div>')[0],
10307                layers: $$A('<div class="mapsvg-layers-wrap"></div>')[0],
10308            };
10309            this.containers.map.appendChild(this.containers.layers);
10310            this.containers.map.appendChild(this.containers.scrollpane);
10311            this.whRatio = 0;
10312            this.isScrolling = false;
10313            this.markerOptions = {};
10314            this.svgDefault = {};
10315            this.scale = 1;
10316            this._scale = 1;
10317            this.selected_id = [];
10318            this.regions = new ArrayIndexed("id");
10319            if (!this.options.database.regionsTableName) {
10320                this.options.database.regionsTableName = "regions_" + this.id;
10321            }
10322            if (!this.options.database.objectsTableName) {
10323                this.options.database.objectsTableName = "objects_" + this.id;
10324            }
10325            this.regionsRepository = new Repository("region", "regions/" + this.options.database.regionsTableName);
10326            this.regionsRepository.query.update({ perpage: 0 });
10327            this.objectsRepository = new Repository("object", "objects/" + this.options.database.objectsTableName);
10328            this.objectsRepository.query.update({ perpage: this.options.database.pagination.perpage });
10329            this.schemaRepository = new SchemaRepository();
10330            this.markers = new ArrayIndexed("id");
10331            this.markersClusters = new ArrayIndexed("id");
10332            this._viewBox = new ViewBox(0, 0, 0, 0);
10333            this.viewBox = new ViewBox(0, 0, 0, 0);
10334            this.zoomLevel = 0;
10335            this.scroll = {
10336                tx: 0,
10337                ty: 0,
10338                vxi: 0,
10339                vyi: 0,
10340                x: 0,
10341                y: 0,
10342                dx: 0,
10343                dy: 0,
10344                vx: 0,
10345                vy: 0,
10346                gx: 0,
10347                gy: 0,
10348                touchScrollStart: 0,
10349            };
10350            this.layers = {};
10351            this.geoCoordinates = false;
10352            this.geoViewBox = new GeoViewBox(new GeoPoint(0, 0), new GeoPoint(0, 0));
10353            this.eventsPreventList = {};
10354            this.googleMaps = {
10355                loaded: false,
10356                initialized: false,
10357                map: null,
10358                zoomLimit: true,
10359                maxZoomService: null,
10360            };
10361            this.init();
10362        }
10363        urlToRelativePath(url) {
10364            if (url.indexOf("//") === 0)
10365                url = url.replace(/^\/\/[^/]+/, "").replace("//", "/");
10366            else
10367                url = url.replace(/^.*:\/\/[^/]+/, "").replace("//", "/");
10368            return url;
10369        }
10370        setGroups(groups) {
10371            const _this = this;
10372            if (!this.groups) {
10373                _this.groups = new ArrayIndexed("id", _this.options.groups, {
10374                    autoId: true,
10375                    unique: true,
10376                });
10377            }
10378            else {
10379                this.options.groups = this.groups;
10380            }
10381            _this.groups.forEach(function (g) {
10382                g.objects &&
10383                    g.objects.length &&
10384                    g.objects.forEach(function (obj) {
10385                        _this.containers.svg
10386                            .querySelector("#" + obj.value)
10387                            .classList.toggle("mapsvg-hidden", !g.visible);
10388                    });
10389            });
10390        }
10391        getGroupSelectOptions() {
10392            const _this = this;
10393            const optionGroups = [];
10394            const options = [];
10395            const options2 = [];
10396            $$A(_this.containers.svg)
10397                .find("g")
10398                .each(function (index) {
10399                const id = $$A(this)[0].getAttribute("id");
10400                if (id) {
10401                    const title = $$A(this)[0].getAttribute("title");
10402                    options.push({ label: title, value: id });
10403                }
10404            });
10405            optionGroups.push({ title: "SVG Layers / Groups", options: options });
10406            $$A(_this.containers.svg)
10407                .find("path,ellipse,circle,polyline,polygon,rectangle,img,text")
10408                .each(function (index) {
10409                const id = $$A(this)[0].getAttribute("id");
10410                if (id) {
10411                    const title = $$A(this)[0].getAttribute("title");
10412                    options2.push({ label: title, value: id });
10413                }
10414            });
10415            optionGroups.push({ title: "Other SVG objects", options: options2 });
10416            return optionGroups;
10417        }
10418        setLayersControl(options) {
10419            const _this = this;
10420            if (options)
10421                $$A.extend(true, this.options.layersControl, options);
10422            if (this.options.layersControl.on) {
10423                if (!this.containers.layersControl) {
10424                    this.containers.layersControl = document.createElement("div");
10425                    this.containers.layersControl.classList.add("mapsvg-layers-control");
10426                    this.containers.layersControlLabel = document.createElement("div");
10427                    this.containers.layersControlLabel.classList.add("mapsvg-layers-label");
10428                    this.containers.layersControl.appendChild(this.containers.layersControlLabel);
10429                    const layersControlWrap = document.createElement("div");
10430                    layersControlWrap.classList.add("mapsvg-layers-list-wrap");
10431                    this.containers.layersControl.appendChild(layersControlWrap);
10432                    this.containers.layersControlListNano = document.createElement("div");
10433                    this.containers.layersControlListNano.classList.add("nano");
10434                    layersControlWrap.appendChild(this.containers.layersControlListNano);
10435                    this.containers.layersControlList = document.createElement("div");
10436                    this.containers.layersControlList.classList.add("mapsvg-layers-list");
10437                    this.containers.layersControlList.classList.add("nano-content");
10438                    this.containers.layersControlListNano.appendChild(this.containers.layersControlList);
10439                    this.containers.mapContainer.appendChild(this.containers.layersControl);
10440                }
10441                this.containers.layersControl.style.display = "block";
10442                this.containers.layersControlLabel.innerHTML = this.options.layersControl.label;
10443                this.containers.layersControlLabel.style.display = "block";
10444                this.containers.layersControlList.innerHTML = "";
10445                while (this.containers.layersControlList.firstChild) {
10446                    this.containers.layersControlList.removeChild(this.containers.layersControlList.firstChild);
10447                }
10448                this.containers.layersControl.classList.remove("mapsvg-top-left", "mapsvg-top-right", "mapsvg-bottom-left", "mapsvg-bottom-right");
10449                this.containers.layersControl.classList.add("mapsvg-" + this.options.layersControl.position);
10450                if (this.options.menu.on &&
10451                    !this.options.menu.customContainer &&
10452                    this.options.layersControl.position.indexOf("left") !== -1) {
10453                    this.containers.layersControl.style.left = this.options.menu.width;
10454                }
10455                this.containers.layersControl.style.maxHeight = this.options.layersControl.maxHeight;
10456                this.options.groups.forEach((g) => {
10457                    const item = document.createElement("div");
10458                    item.classList.add("mapsvg-layers-item");
10459                    item.setAttribute("data-group-id", g.id);
10460                    item.innerHTML =
10461                        '<input type="checkbox" class="ios8-switch ios8-switch-sm" ' +
10462                            (g.visible ? "checked" : "") +
10463                            " /><label>" +
10464                            g.title +
10465                            "</label>";
10466                    this.containers.layersControlList.appendChild(item);
10467                });
10468                $$A(this.containers.layersControlListNano).nanoScroller({
10469                    preventPageScrolling: true,
10470                    iOSNativeScrolling: true,
10471                });
10472                $$A(this.containers.layersControl).off();
10473                $$A(this.containers.layersControl).on("click", ".mapsvg-layers-item", function () {
10474                    const id = $$A(this).data("group-id");
10475                    const input = $$A(this).find("input");
10476                    input.prop("checked", !input.prop("checked"));
10477                    _this.groups.forEach(function (g) {
10478                        if (g.id === id)
10479                            g.visible = !g.visible;
10480                    });
10481                    _this.setGroups();
10482                });
10483                $$A(this.containers.layersControlLabel).off();
10484                $$A(this.containers.layersControlLabel).on("click", () => {
10485                    $$A(_this.containers.layersControl).toggleClass("closed");
10486                });
10487                $$A(this.containers.layersControl).toggleClass("closed", !this.options.layersControl.expanded);
10488            }
10489            else {
10490                if (this.containers.layersControl) {
10491                    this.containers.layersControl.style.display = "none";
10492                }
10493            }
10494        }
10495        loadDataObjects(params) {
10496            return this.objectsRepository.find(params);
10497        }
10498        loadDirectory() {
10499            if (!this.editMode &&
10500                this.options.menu.source === "database" &&
10501                this.objectsRepository.getLoaded().length === 0) {
10502                return;
10503            }
10504            if (this.options.menu.on) {
10505                this.controllers.directory.loadItemsToDirectory();
10506            }
10507            this.setPagination();
10508        }
10509        setPagination() {
10510            const _this = this;
10511            this.containers.pagerMap && $$A(this.containers.pagerMap).empty().remove();
10512            this.containers.pagerDir && $$A(this.containers.pagerDir).empty().remove();
10513            if (_this.options.database.pagination.on &&
10514                _this.options.database.pagination.perpage !== 0) {
10515                this.containers.directory.classList.toggle("mapsvg-with-pagination", ["directory", "both"].indexOf(_this.options.database.pagination.showIn) !== -1);
10516                this.containers.map.classList.toggle("mapsvg-with-pagination", ["map", "both"].indexOf(_this.options.database.pagination.showIn) !== -1);
10517                if (_this.options.menu.on) {
10518                    this.containers.pagerDir = _this.getPagination();
10519                    _this.controllers.directory.addPagination(this.containers.pagerDir);
10520                }
10521                this.containers.pagerMap = _this.getPagination();
10522                this.containers.map.appendChild(this.containers.pagerMap);
10523            }
10524        }
10525        getPagination(callback) {
10526            const _this = this;
10527            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; ' +
10528                _this.options.database.pagination.prev +
10529                " " +
10530                _this.options.database.pagination.perpage +
10531                '</a></li><li class="mapsvg-next"><a href="#">' +
10532                _this.options.database.pagination.next +
10533                " " +
10534                _this.options.database.pagination.perpage +
10535                ' &rarr;</a></li><!--<li class="mapsvg-last"><a href="#">Last</a></li>--></ul></nav>');
10536            if (this.objectsRepository.onFirstPage() && this.objectsRepository.onLastPage()) {
10537                pager.hide();
10538            }
10539            else {
10540                pager.find(".mapsvg-prev").removeClass("disabled");
10541                pager.find(".mapsvg-first").removeClass("disabled");
10542                pager.find(".mapsvg-last").removeClass("disabled");
10543                pager.find(".mapsvg-next").removeClass("disabled");
10544                this.objectsRepository.onLastPage() &&
10545                    pager.find(".mapsvg-next").addClass("disabled") &&
10546                    pager.find(".mapsvg-last").addClass("disabled");
10547                this.objectsRepository.onFirstPage() &&
10548                    pager.find(".mapsvg-prev").addClass("disabled") &&
10549                    pager.find(".mapsvg-first").addClass("disabled");
10550            }
10551            pager
10552                .on("click", ".mapsvg-next:not(.disabled)", (e) => {
10553                e.preventDefault();
10554                if (this.objectsRepository.onLastPage())
10555                    return;
10556                const query = new Query({ page: this.objectsRepository.query.page + 1 });
10557                this.objectsRepository.find(query).done(function () {
10558                    callback && callback();
10559                });
10560            })
10561                .on("click", ".mapsvg-prev:not(.disabled)", function (e) {
10562                e.preventDefault();
10563                if (_this.objectsRepository.onFirstPage())
10564                    return;
10565                const query = new Query({ page: _this.objectsRepository.query.page - 1 });
10566                _this.objectsRepository.find(query).done(function () {
10567                    callback && callback();
10568                });
10569            })
10570                .on("click", ".mapsvg-first:not(.disabled)", function (e) {
10571                e.preventDefault();
10572                if (_this.objectsRepository.onFirstPage())
10573                    return;
10574                const query = new Query({ page: 1 });
10575                _this.objectsRepository.find(query).done(function () {
10576                    callback && callback();
10577                });
10578            })
10579                .on("click", ".mapsvg-last:not(.disabled)", function (e) {
10580                e.preventDefault();
10581                if (_this.objectsRepository.onLastPage())
10582                    return;
10583                const query = new Query({ lastpage: true });
10584                _this.objectsRepository.find(query).done(function () {
10585                    callback && callback();
10586                });
10587            });
10588            return pager[0];
10589        }
10590        deleteMarkers() {
10591            while (this.markers.length) {
10592                this.markerDelete(this.markers[0]);
10593            }
10594        }
10595        deleteClusters() {
10596            if (this.markersClusters) {
10597                this.markersClusters.forEach(function (markerCluster) {
10598                    markerCluster.destroy();
10599                });
10600                this.markersClusters.clear();
10601            }
10602        }
10603        addLocations() {
10604            const _this = this;
10605            this.firstDataLoad = this.firstDataLoad === undefined;
10606            let locationField = this.objectsRepository.getSchema().getFieldByType("location");
10607            if (!locationField) {
10608                return;
10609            }
10610            locationField = locationField.name;
10611            if (locationField) {
10612                if (this.firstDataLoad) {
10613                    this.setMarkerImagesDependency();
10614                }
10615                _this.deleteMarkers();
10616                _this.deleteClusters();
10617                _this.clusters = {};
10618                _this.clustersByZoom = [];
10619                if (this.objectsRepository.getLoaded().length > 0) {
10620                    this.objectsRepository.getLoaded().forEach(function (object) {
10621                        if (object[locationField]) {
10622                            if (object[locationField].img &&
10623                                (object[locationField].geoPoint || object[locationField].svgPoint)) {
10624                                new Marker({
10625                                    location: object[locationField],
10626                                    object: object,
10627                                    mapsvg: _this,
10628                                });
10629                            }
10630                        }
10631                    });
10632                    if (_this.options.clustering.on) {
10633                        _this.startClusterizer();
10634                    }
10635                    else {
10636                        this.objectsRepository.getLoaded().forEach(function (object) {
10637                            if (object.location && object.location.marker) {
10638                                _this.markerAdd(object.location.marker);
10639                            }
10640                        });
10641                        _this.mayBeFitMarkers();
10642                    }
10643                }
10644            }
10645        }
10646        addClustersFromWorker(zoomLevel, clusters) {
10647            const _this = this;
10648            _this.clustersByZoom[zoomLevel] = [];
10649            for (const cell in clusters) {
10650                const markers = clusters[cell].markers.map(function (marker) {
10651                    return _this.objectsRepository.objects.findById(marker.id).location.marker;
10652                });
10653                _this.clustersByZoom[zoomLevel].push(new MarkerCluster({
10654                    markers: markers,
10655                    svgPoint: new SVGPoint(clusters[cell].x, clusters[cell].y),
10656                    cellX: clusters[cell].cellX,
10657                    cellY: clusters[cell].cellY,
10658                }, _this));
10659            }
10660            if (_this.zoomLevel === zoomLevel) {
10661                _this.clusterizeMarkers();
10662            }
10663        }
10664        startClusterizer() {
10665            if (!this.objectsRepository || this.objectsRepository.getLoaded().length === 0) {
10666                return;
10667            }
10668            const locationField = this.objectsRepository.getSchema().getFieldByType("location");
10669            if (!locationField) {
10670                return false;
10671            }
10672            if (!this.clusterizerWorker) {
10673                this.clusterizerWorker = new Worker(MapSVG.urls.root + "js/mapsvg/Core/clustering.js");
10674                this.clusterizerWorker.onmessage = (evt) => {
10675                    if (evt.data.clusters) {
10676                        this.addClustersFromWorker(evt.data.zoomLevel, evt.data.clusters);
10677                    }
10678                };
10679            }
10680            const objectsData = [];
10681            this.objectsRepository
10682                .getLoaded()
10683                .filter((o) => {
10684                return o.location && o.location.marker;
10685            })
10686                .forEach((o) => {
10687                objectsData.push({
10688                    id: o.id,
10689                    x: o.location.marker.svgPoint.x,
10690                    y: o.location.marker.svgPoint.y,
10691                });
10692            });
10693            this.clusterizerWorker.postMessage({
10694                objects: objectsData,
10695                cellSize: 50,
10696                mapWidth: this.containers.map.clientWidth,
10697                zoomLevels: this.zoomLevels,
10698                zoomLevel: this.zoomLevel,
10699                zoomDelta: this.zoomDelta,
10700                svgViewBox: this.svgDefault.viewBox,
10701            });
10702            this.events.on("zoom", () => {
10703                this.clusterizerWorker.postMessage({
10704                    message: "zoom",
10705                    zoomLevel: this.zoomLevel,
10706                });
10707            });
10708        }
10709        clusterizeMarkers(skipFitMarkers) {
10710            $$A(this.layers.markers)
10711                .children()
10712                .each((i, obj) => {
10713                $$A(obj).detach();
10714            });
10715            this.markers.clear();
10716            this.markersClusters.clear();
10717            this.clustersByZoom &&
10718                this.clustersByZoom[this.zoomLevel] &&
10719                this.clustersByZoom[this.zoomLevel].forEach((cluster) => {
10720                    if (this.options.googleMaps.on &&
10721                        this.googleMaps.map &&
10722                        this.googleMaps.map.getZoom() >= 17) {
10723                        this.markerAdd(cluster.markers[0]);
10724                    }
10725                    else {
10726                        if (cluster.markers.length > 1) {
10727                            this.markersClusterAdd(cluster);
10728                        }
10729                        else {
10730                            this.markerAdd(cluster.markers[0]);
10731                        }
10732                    }
10733                });
10734            if (this.editingMarker) {
10735                this.markerAdd(this.editingMarker);
10736            }
10737            if (!skipFitMarkers) {
10738                this.mayBeFitMarkers();
10739            }
10740            if (this.options.labelsMarkers.on) {
10741                this.setLabelsMarkers();
10742            }
10743        }
10744        getCssUrl() {
10745            return MapSVG.urls.root + "css/mapsvg.css";
10746        }
10747        isGeo() {
10748            return this.mapIsGeo;
10749        }
10750        functionFromString(string) {
10751            let func;
10752            let error;
10753            const fn = string.trim();
10754            if (fn.indexOf("{") == -1 || fn.indexOf("function") !== 0 || fn.indexOf("(") == -1) {
10755                return new SyntaxError("MapSVG user function error: no function body.");
10756            }
10757            const fnBody = fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"));
10758            const params = fn.substring(fn.indexOf("(") + 1, fn.indexOf(")"));
10759            try {
10760                func = new Function(params, fnBody);
10761            }
10762            catch (err) {
10763                error = err;
10764            }
10765            if (!error)
10766                return func;
10767            else
10768                return error;
10769        }
10770        getOptions(forTemplate, forWeb) {
10771            const options = $$A.extend(true, {}, this.options);
10772            function clearEmpties(o) {
10773                for (const k in o) {
10774                    if (!o[k] || typeof o[k] !== "object") {
10775                        continue;
10776                    }
10777                    clearEmpties(o[k]);
10778                    if (Object.keys(o[k]).length === 0) {
10779                        delete o[k];
10780                    }
10781                }
10782            }
10783            clearEmpties(options.regions);
10784            $$A.extend(true, options, this.optionsDelta);
10785            options.viewBox = this._viewBox.toArray();
10786            options.filtersSchema = this.filtersSchema.getFieldsAsArray();
10787            if (options.filtersSchema.length > 0) {
10788                options.filtersSchema.forEach((field) => {
10789                    if (field.type === "distance") {
10790                        field.value = "";
10791                    }
10792                });
10793            }
10794            delete options.markers;
10795            if (forTemplate) {
10796                options.svgFilename = options.source.split("/").pop();
10797                options.svgFiles = MapSVG.svgFiles;
10798            }
10799            if (forWeb)
10800                $$A.each(options, (key, val) => {
10801                    if (JSON.stringify(val) == JSON.stringify(this.defaults[key]))
10802                        delete options[key];
10803                });
10804            delete options.backend;
10805            return options;
10806        }
10807        restoreDeltaOptions() {
10808            this.update(this.optionsDelta);
10809            this.optionsDelta = {};
10810        }
10811        setEvents(functions) {
10812            let compiledFunction;
10813            for (const eventName in functions) {
10814                if (typeof functions[eventName] === "string") {
10815                    compiledFunction =
10816                        functions[eventName] != ""
10817                            ? this.functionFromString(functions[eventName])
10818                            : null;
10819                    if (!compiledFunction ||
10820                        compiledFunction.error ||
10821                        compiledFunction instanceof TypeError ||
10822                        compiledFunction instanceof SyntaxError) {
10823                        continue;
10824                    }
10825                }
10826                else if (typeof functions[eventName] === "function") {
10827                    compiledFunction = functions[eventName];
10828                }
10829                this.events.off(eventName);
10830                this.events.on(eventName, compiledFunction);
10831                if (eventName.indexOf("directory") !== -1) {
10832                    const event = eventName.split(".")[0];
10833                    if (this.controllers && this.controllers.directory) {
10834                        this.controllers.directory.events.off(event);
10835                        this.controllers.directory.events.on(event, compiledFunction);
10836                    }
10837                }
10838            }
10839            $$A.extend(true, this.options.events, functions);
10840        }
10841        setActions(options) {
10842            $$A.extend(true, this.options.actions, options);
10843        }
10844        setDetailsView(options) {
10845            options = options || this.options.detailsView || {};
10846            $$A.extend(true, this.options.detailsView, options);
10847            if (this.options.detailsView.location === "top" && this.options.menu.position === "left") {
10848                this.options.detailsView.location = "leftSidebar";
10849            }
10850            else if (this.options.detailsView.location === "top" &&
10851                this.options.menu.position === "right") {
10852                this.options.detailsView.location = "rightSidebar";
10853            }
10854            if (this.options.detailsView.location === "near" ||
10855                this.options.detailsView.location === "mapContainer") {
10856                this.options.detailsView.location = "map";
10857            }
10858            if (!this.containers.detailsView) {
10859                this.containers.detailsView = $$A('<div class="mapsvg-details-container"></div>')[0];
10860            }
10861            $$A(this.containers.detailsView).toggleClass("mapsvg-details-container-relative", !(MapSVG.isPhone && this.options.detailsView.mobileFullscreen) &&
10862                !this.shouldBeScrollable(this.options.detailsView.location));
10863            if (this.options.detailsView.location === "custom") {
10864                $$A("#" + this.options.detailsView.containerId).append($$A(this.containers.detailsView));
10865            }
10866            else {
10867                if (MapSVG.isPhone && this.options.detailsView.mobileFullscreen) {
10868                    $$A("body").append($$A(this.containers.detailsView));
10869                    $$A(this.containers.detailsView).addClass("mapsvg-container-fullscreen");
10870                }
10871                else {
10872                    this.containers[this.options.detailsView.location].append(this.containers.detailsView);
10873                }
10874                if (this.options.detailsView.margin) {
10875                    $$A(this.containers.detailsView).css("margin", this.options.detailsView.margin);
10876                }
10877                $$A(this.containers.detailsView).css("width", this.options.detailsView.width);
10878            }
10879        }
10880        setMobileView(options) {
10881            $$A.extend(true, this.options.mobileView, options);
10882        }
10883        attachDataToRegions(object) {
10884            this.regions.forEach(function (region) {
10885                region.objects = [];
10886            });
10887            this.objectsRepository.getLoaded().forEach((obj, index) => {
10888                const regions = obj.getRegionsForTable(this.regionsRepository.schema.name);
10889                if (regions && regions.length) {
10890                    regions.forEach((region) => {
10891                        const r = this.getRegion(region.id);
10892                        if (r)
10893                            r.objects.push(obj);
10894                    });
10895                }
10896            });
10897        }
10898        setTemplates(templates) {
10899            this.templates = this.templates || {};
10900            for (let name in templates) {
10901                if (name != undefined) {
10902                    this.options.templates[name] = templates[name];
10903                    let t = this.options.templates[name];
10904                    if (name == "directoryItem" || name == "directoryCategoryItem") {
10905                        const dirItemTemplate = this.options.templates.directoryItem;
10906                        t =
10907                            '{{#each items}}<div id="mapsvg-directory-item-{{id}}" class="mapsvg-directory-item" data-object-id="{{id}}">' +
10908                                dirItemTemplate +
10909                                "</div>{{/each}}";
10910                        if (this.options.menu.categories &&
10911                            this.options.menu.categories.on &&
10912                            this.options.menu.categories.groupBy) {
10913                            const t2 = this.options.templates["directoryCategoryItem"];
10914                            t =
10915                                '{{#each items}}{{#with category}}<div id="mapsvg-category-item-{{value}}" class="mapsvg-category-item" data-category-value="{{value}}">' +
10916                                    t2 +
10917                                    '</div><div class="mapsvg-category-block" data-category-id="{{value}}">{{/with}}' +
10918                                    t +
10919                                    "</div>{{/each}}";
10920                        }
10921                        name = "directory";
10922                    }
10923                    try {
10924                        this.options.templates[name] = t;
10925                        this.templates[name] = Handlebars.compile(t, { strict: false });
10926                    }
10927                    catch (err) {
10928                        console.error(err);
10929                        this.templates[name] = Handlebars.compile("", { strict: false });
10930                    }
10931                    if (this.editMode &&
10932                        (name == "directory" || name == "directoryCategoryItem") &&
10933                        this.controllers &&
10934                        this.controllers.directory) {
10935                        this.controllers.directory.templates.main = this.templates[name];
10936                        this.loadDirectory();
10937                    }
10938                }
10939            }
10940        }
10941        update(options) {
10942            for (const key in options) {
10943                if (key == "regions") {
10944                    for (const id in options.regions) {
10945                        const region = this.getRegion(id);
10946                        region && region.update(options.regions[id]);
10947                        if (options.regions[id].disabled != undefined) {
10948                            this.deselectRegion(region);
10949                            this.options.regions[id] = this.options.regions[id] || {};
10950                            this.options.regions[id].disabled = region.disabled;
10951                        }
10952                    }
10953                }
10954                else {
10955                    const setter = "set" + MapSVG.ucfirst(key);
10956                    if (typeof this[setter] == "function")
10957                        this[setter](options[key]);
10958                    else {
10959                        this.options[key] = options[key];
10960                    }
10961                }
10962            }
10963        }
10964        getDirtyFields() {
10965            return this.getData();
10966        }
10967        clearDirtyFields() {
10968            this.dirtyFields = [];
10969        }
10970        setTitle(title) {
10971            title && (this.options.title = title);
10972        }
10973        setExtension(extension) {
10974            if (extension) {
10975                this.options.extension = extension;
10976            }
10977            else {
10978                delete this.options.extension;
10979            }
10980        }
10981        setDisableLinks(on) {
10982            on = MapSVG.parseBoolean(on);
10983            if (on) {
10984                $$A(this.containers.map).on("click.a.mapsvg", "a", function (e) {
10985                    e.preventDefault();
10986                });
10987            }
10988            else {
10989                $$A(this.containers.map).off("click.a.mapsvg");
10990            }
10991            this.disableLinks = on;
10992        }
10993        setLoadingText(val) {
10994            this.options.loadingText = val;
10995        }
10996        setLockAspectRatio(onoff) {
10997            this.options.lockAspectRatio = MapSVG.parseBoolean(onoff);
10998        }
10999        setMarkerEditHandler(handler) {
11000            this.markerEditHandler = handler;
11001        }
11002        setChoroplethSourceField(field) {
11003            this.options.choropleth.sourceField = field;
11004            this.redrawChoropleth();
11005        }
11006        setRegionEditHandler(handler) {
11007            this.regionEditHandler = handler;
11008        }
11009        setDisableAll(on) {
11010            on = MapSVG.parseBoolean(on);
11011            $$A.extend(true, this.options, { disableAll: on });
11012            $$A(this.containers.map).toggleClass("mapsvg-disabled-regions", on);
11013        }
11014        setRegionStatuses(_statuses) {
11015            this.options.regionStatuses = {};
11016            const colors = {};
11017            _statuses.forEach((statusOptions) => {
11018                this.options.regionStatuses[statusOptions.value] = statusOptions;
11019                colors[statusOptions.value] = statusOptions.color.length
11020                    ? statusOptions.color
11021                    : undefined;
11022            });
11023            this.setColors({ status: colors });
11024        }
11025        setColorsIgnore(val) {
11026            this.options.colorsIgnore = MapSVG.parseBoolean(val);
11027            this.regionsRedrawColors();
11028        }
11029        setColors(colors) {
11030            for (const i in colors) {
11031                if (i === "status") {
11032                    for (const s in colors[i]) {
11033                        MapSVG.fixColorHash(colors[i][s]);
11034                    }
11035                }
11036                else {
11037                    if (typeof colors[i] == "string") {
11038                        MapSVG.fixColorHash(colors[i]);
11039                    }
11040                }
11041            }
11042            $$A.extend(true, this.options, { colors: colors });
11043            if (colors && colors.status)
11044                this.options.colors.status = colors.status;
11045            if (this.options.colors.markers) {
11046                for (const z in this.options.colors.markers) {
11047                    for (const x in this.options.colors.markers[z]) {
11048                        this.options.colors.markers[z][x] = parseInt(this.options.colors.markers[z][x]);
11049                    }
11050                }
11051            }
11052            if (this.options.colors.background)
11053                $$A(this.containers.map).css({ background: this.options.colors.background });
11054            if (this.options.colors.hover) {
11055                this.options.colors.hover = !isNaN(this.options.colors.hover)
11056                    ? parseInt(this.options.colors.hover + "")
11057                    : this.options.colors.hover;
11058            }
11059            if (this.options.colors.selected) {
11060                this.options.colors.selected = !isNaN(this.options.colors.selected)
11061                    ? parseInt(this.options.colors.selected + "")
11062                    : this.options.colors.selected;
11063            }
11064            $$A(this.containers.leftSidebar).css({
11065                "background-color": this.options.colors.leftSidebar,
11066            });
11067            $$A(this.containers.rightSidebar).css({
11068                "background-color": this.options.colors.rightSidebar,
11069            });
11070            $$A(this.containers.header).css({ "background-color": this.options.colors.header });
11071            $$A(this.containers.footer).css({ "background-color": this.options.colors.footer });
11072            if ($$A(this.containers.detailsView) && this.options.colors.detailsView !== undefined) {
11073                $$A(this.containers.detailsView).css({
11074                    "background-color": this.options.colors.detailsView,
11075                });
11076            }
11077            if ($$A(this.containers.directory) && this.options.colors.directory !== undefined) {
11078                $$A(this.containers.directory).css({
11079                    "background-color": this.options.colors.directory,
11080                });
11081            }
11082            if ($$A(this.containers.filtersModal) && this.options.colors.modalFilters !== undefined) {
11083                $$A(this.containers.filtersModal).css({
11084                    "background-color": this.options.colors.modalFilters,
11085                });
11086            }
11087            if ($$A(this.containers.filters) && this.options.colors.directorySearch) {
11088                $$A(this.containers.filters).css({
11089                    "background-color": this.options.colors.directorySearch,
11090                });
11091            }
11092            else if ($$A(this.containers.filters)) {
11093                $$A(this.containers.filters).css({
11094                    "background-color": "",
11095                });
11096            }
11097            if (!this.containers.clustersCss) {
11098                this.containers.clustersCss = ($$A("<style></style>").appendTo("body")[0]);
11099            }
11100            let css = "";
11101            if (this.options.colors.clusters) {
11102                css += "background-color: " + this.options.colors.clusters + ";";
11103            }
11104            if (this.options.colors.clustersBorders) {
11105                css += "border-color: " + this.options.colors.clustersBorders + ";";
11106            }
11107            if (this.options.colors.clustersText) {
11108                css += "color: " + this.options.colors.clustersText + ";";
11109            }
11110            $$A(this.containers.clustersCss).html(".mapsvg-marker-cluster {" + css + "}");
11111            if (!this.containers.clustersHoverCss) {
11112                this.containers.clustersHoverCss = ($$A("<style></style>").appendTo("body")[0]);
11113            }
11114            let cssHover = "";
11115            if (this.options.colors.clustersHover) {
11116                cssHover += "background-color: " + this.options.colors.clustersHover + ";";
11117            }
11118            if (this.options.colors.clustersHoverBorders) {
11119                cssHover += "border-color: " + this.options.colors.clustersHoverBorders + ";";
11120            }
11121            if (this.options.colors.clustersHoverText) {
11122                cssHover += "color: " + this.options.colors.clustersHoverText + ";";
11123            }
11124            $$A(this.containers.clustersHoverCss).html(".mapsvg-marker-cluster:hover {" + cssHover + "}");
11125            if (!this.containers.markersCss) {
11126                this.containers.markersCss = $$A("<style></style>").appendTo("head")[0];
11127            }
11128            const markerCssText = ".mapsvg-with-marker-active .mapsvg-marker {\n" +
11129                "  opacity: " +
11130                this.options.colors.markers.inactive.opacity / 100 +
11131                ";\n" +
11132                "  -webkit-filter: grayscale(" +
11133                (100 - this.options.colors.markers.inactive.saturation) +
11134                "%);\n" +
11135                "  filter: grayscale(" +
11136                (100 - this.options.colors.markers.inactive.saturation) +
11137                "%);\n" +
11138                "}\n" +
11139                ".mapsvg-with-marker-active .mapsvg-marker-active {\n" +
11140                "  opacity: " +
11141                this.options.colors.markers.active.opacity / 100 +
11142                ";\n" +
11143                "  -webkit-filter: grayscale(" +
11144                (100 - this.options.colors.markers.active.saturation) +
11145                "%);\n" +
11146                "  filter: grayscale(" +
11147                (100 - this.options.colors.markers.active.saturation) +
11148                "%);\n" +
11149                "}\n" +
11150                ".mapsvg-with-marker-hover .mapsvg-marker {\n" +
11151                "  opacity: " +
11152                this.options.colors.markers.unhovered.opacity / 100 +
11153                ";\n" +
11154                "  -webkit-filter: grayscale(" +
11155                (100 - this.options.colors.markers.unhovered.saturation) +
11156                "%);\n" +
11157                "  filter: grayscale(" +
11158                (100 - this.options.colors.markers.unhovered.saturation) +
11159                "%);\n" +
11160                "}\n" +
11161                ".mapsvg-with-marker-hover .mapsvg-marker-hover {\n" +
11162                "  opacity: " +
11163                this.options.colors.markers.hovered.opacity / 100 +
11164                ";\n" +
11165                "  -webkit-filter: grayscale(" +
11166                (100 - this.options.colors.markers.hovered.saturation) +
11167                "%);\n" +
11168                "  filter: grayscale(" +
11169                (100 - this.options.colors.markers.hovered.saturation) +
11170                "%);\n" +
11171                "}\n";
11172            $$A(this.containers.markersCss).html(markerCssText);
11173            $$A.each(this.options.colors, (key, color) => {
11174                if (color === null || color == "")
11175                    delete this.options.colors[key];
11176            });
11177            this.regionsRedrawColors();
11178        }
11179        setTooltips(options) {
11180            if (options.on !== undefined)
11181                options.on = MapSVG.parseBoolean(options.on);
11182            $$A.extend(true, this.options, { tooltips: options });
11183            if (!this.containers.tooltip) {
11184                this.containers.tooltip = $$A("<div />").addClass("mapsvg-tooltip")[0];
11185                $$A(this.containers.map).append(this.containers.tooltip);
11186                this.controllers.tooltip = new Tooltip({
11187                    mapsvg: this,
11188                    container: this.containers.tooltip,
11189                    position: this.options.tooltips.position,
11190                    maxWidth: this.options.tooltips.maxWidth,
11191                    minWidth: this.options.tooltips.minWidth,
11192                });
11193                this.controllers.tooltip._init();
11194            }
11195            if (typeof this.options.tooltips.position !== "undefined") {
11196                this.controllers.tooltip.setPosition(this.options.tooltips.position);
11197            }
11198            if (typeof this.options.tooltips.maxWidth !== "undefined" ||
11199                typeof this.options.tooltips.minWidth !== "undefined") {
11200                this.controllers.tooltip.setSize(this.options.tooltips.maxWidth, this.options.tooltips.minWidth);
11201            }
11202        }
11203        setPopovers(options) {
11204            if (options.on !== undefined)
11205                options.on = MapSVG.parseBoolean(options.on);
11206            $$A.extend(this.options.popovers, options);
11207            if (!this.containers.popover) {
11208                this.containers.popover = $$A("<div />").addClass("mapsvg-popover")[0];
11209                this.layers.popovers.append(this.containers.popover);
11210            }
11211            $$A(this.containers.popover).css({
11212                width: this.options.popovers.width + (this.options.popovers.width == "auto" ? "" : "px"),
11213                "max-width": this.options.popovers.maxWidth + "%",
11214                "max-height": (this.options.popovers.maxHeight * $$A(this.containers.wrap).outerHeight()) / 100 +
11215                    "px",
11216            });
11217            if (this.options.popovers.mobileFullscreen && MapSVG.
11217isPhone) {
11218                $$A("body").toggleClass("mapsvg-fullscreen-popovers", true);
11219                $$A(this.containers.popover).appendTo("body");
11220            }
11221        }
11222        setRegionPrefix(prefix) {
11223            this.options.regionPrefix = prefix;
11224        }
11225        setInitialViewBox(v) {
11226            if (typeof v == "string")
11227                v = v
11228                    .trim()
11229                    .split(" ")
11230                    .map(function (v) {
11231                    return parseFloat(v);
11232                });
11233            this._viewBox.update(new ViewBox(v));
11234            if (this.options.googleMaps.on) {
11235                this.options.googleMaps.center = this.googleMaps.map.getCenter().toJSON();
11236                this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
11237            }
11238            this.zoomLevel = 0;
11239            this.setZoomLevels();
11240        }
11241        setViewBoxOnStart() {
11242            this.viewBoxFull = this.svgDefault.viewBox;
11243            this.viewBoxFake = this.viewBox;
11244            this.whRatioFull = this.viewBoxFull.width / this.viewBox.width;
11245            this.containers.svg.setAttribute("viewBox", this.viewBoxFull.toString());
11246            if ((MapSVG.device.ios || MapSVG.device.android) && this.svgDefault.viewBox.width > 1500) {
11247                this.iosDownscaleFactor = this.svgDefault.viewBox.width > 9999 ? 100 : 10;
11248                this.containers.svg.style.width =
11249                    (this.svgDefault.viewBox.width / this.iosDownscaleFactor).toString() + "px";
11250            }
11251            else {
11252                this.containers.svg.style.width = this.svgDefault.viewBox.width + "px";
11253            }
11254            this.vbStart = true;
11255        }
11256        setViewBox(viewBox, adjustGoogleMap = true) {
11257            let initial = false;
11258            if (typeof viewBox === "undefined" || (viewBox.width === 0 && viewBox.height === 0)) {
11259                viewBox = this.svgDefault.viewBox;
11260                initial = true;
11261            }
11262            const isZooming = viewBox.width != this.viewBox.width || viewBox.height != this.viewBox.height;
11263            this.viewBox.update(viewBox);
11264            this.whRatio = this.viewBox.width / this.viewBox.height;
11265            !this.vbStart && this.setViewBoxOnStart();
11266            if (initial) {
11267                if (this._viewBox.width === 0 && this._viewBox.height === 0) {
11268                    this._viewBox.update(this.viewBox);
11269                }
11270                this._scale = 1;
11271            }
11272            this.scale = this.getScale();
11273            this.superScale = (this.whRatioFull * this.svgDefault.viewBox.width) / this.viewBox.width;
11274            const w = this.svgDefault.viewBox.width / this.containers.map.clientWidth;
11275            this.superScale = this.superScale / w;
11276            if ((MapSVG.device.ios || MapSVG.device.android) && this.svgDefault.viewBox.width > 1500) {
11277                this.superScale *= this.iosDownscaleFactor;
11278            }
11279            this.scroll.tx = Math.round((this.svgDefault.viewBox.x - this.viewBox.x) * this.scale);
11280            this.scroll.ty = Math.round((this.svgDefault.viewBox.y - this.viewBox.y) * this.scale);
11281            if (this.googleMaps.map && adjustGoogleMap !== false) {
11282                const googlePrevZoom = this.googleMaps.map.getZoom();
11283                this.googleMaps.map.setZoom(this.getZoomForGoogle());
11284                if (googlePrevZoom !== this.googleMaps.map.getZoom()) {
11285                    this.googleMaps.map.setCenter(this.getCenterGeoPoint());
11286                }
11287            }
11288            else {
11289                this.containers.scrollpane.style.transform =
11290                    "translate(" + this.scroll.tx + "px," + this.scroll.ty + "px)";
11291                this.containers.svg.style.transform = "scale(" + this.superScale + ")";
11292                this.syncZoomLevelWithGoogle();
11293            }
11294            this.movingItemsAdjustScreenPosition();
11295            if (isZooming) {
11296                this.mapAdjustStrokes();
11297                this.toggleSvgLayerOnZoom();
11298                if (this.options.clustering.on) {
11299                    this.throttle(this.clusterizeOnZoom, 400, this);
11300                }
11301                else {
11302                    this.events.trigger("zoom");
11303                }
11304            }
11305            return true;
11306        }
11307        syncZoomLevelWithGoogle() {
11308            if (this.googleMaps.map &&
11309                this.googleMaps.map.getZoom() !== this.getZoomForGoogle() &&
11310                typeof this.zoomDelta !== "undefined") {
11311                this.zoomLevel = this.googleMaps.map.getZoom() - this.zoomDelta;
11312            }
11313        }
11314        getCenterGeoPoint() {
11315            return this.converter.convertSVGToGeo(this.getCenterSvgPoint());
11316        }
11317        getCenterSvgPoint() {
11318            return new SVGPoint(this.viewBox.x + this.viewBox.width / 2, this.viewBox.y + this.viewBox.height / 2);
11319        }
11320        getZoomForGoogle() {
11321            return this.zoomLevel + this.zoomDelta;
11322        }
11323        getZoomRange() {
11324            const range = { min: 0, max: 0 };
11325            if (this.options.googleMaps.on) {
11326                range.min = Math.max(0, this.options.zoom.limit[0] + this.zoomDelta) - this.zoomDelta;
11327                range.max = Math.min(22, this.options.zoom.limit[1] + this.zoomDelta) - this.zoomDelta;
11328            }
11329            else {
11330                range.min = this.options.zoom.limit[0];
11331                range.max = this.options.zoom.limit[1];
11332            }
11333            return range;
11334        }
11335        enableMovingElementsAnimation() {
11336            $$A(this.containers.map).removeClass("no-transitions-markers no-transitions-labels no-transitions-bubbles");
11337        }
11338        disableMovingElementsAnimation() {
11339            $$A(this.containers.map).addClass("no-transitions-markers no-transitions-labels no-transitions-bubbles");
11340        }
11341        clusterizeOnZoom() {
11342            if (this.options.googleMaps.on && this.googleMaps.map && this.zoomDelta) {
11343                this.zoomLevel = this.googleMaps.map.getZoom() - this.zoomDelta;
11344            }
11345            this.events.trigger("zoom");
11346            this.clusterizeMarkers(true);
11347        }
11348        throttle(method, delay, scope, params) {
11349            clearTimeout(method._tId);
11350            method._tId = setTimeout(function () {
11351                method.apply(scope, params);
11352            }, delay);
11353        }
11354        setViewBoxByGoogleMapBounds() {
11355            const googleMapBounds = this.googleMaps.map.getBounds();
11356            if (!googleMapBounds)
11357                return;
11358            const googleMapBoundsJSON = googleMapBounds.toJSON();
11359            if (googleMapBoundsJSON.west == -180 && googleMapBoundsJSON.east == 180) {
11360                const center = this.googleMaps.map.getCenter().toJSON();
11361            }
11362            const ne = new GeoPoint(googleMapBounds.getNorthEast().lat(), googleMapBounds.getNorthEast().lng());
11363            const sw = new GeoPoint(googleMapBounds.getSouthWest().lat(), googleMapBounds.getSouthWest().lng());
11364            const xyNE = this.converter.convertGeoToSVG(ne);
11365            const xySW = this.converter.convertGeoToSVG(sw);
11366            if (xyNE.x < xySW.y) {
11367                const mapPointsWidth = (this.svgDefault.viewBox.width / this.mapLonDelta) * 360;
11368                xySW.x = -(mapPointsWidth - xySW.y);
11369            }
11370            const width = xyNE.x - xySW.x;
11371            const height = xySW.y - xyNE.y;
11372            const viewBox = new ViewBox(xySW.x, xyNE.y, width, height);
11373            this.setViewBox(viewBox);
11374        }
11375        redraw() {
11376            if (MapSVG.browser.ie) {
11377                $$A(this.containers.svg).css({ height: this.svgDefault.viewBox.height });
11378            }
11379            if (this.options.googleMaps.on && this.googleMaps.map) {
11380                google.maps.event.trigger(this.googleMaps.map, "resize");
11381            }
11382            else {
11383                this.setViewBox(this.viewBox);
11384            }
11385            $$A(this.containers.popover) &&
11386                $$A(this.containers.popover).css({
11387                    "max-height": (this.options.popovers.maxHeight * $$A(this.containers.wrap).outerHeight()) /
11388                        100 +
11389                        "px",
11390                });
11391            if (this.controllers && this.controllers.directory) {
11392                this.controllers.directory.updateTopShift();
11393                this.controllers.directory.updateScroll();
11394            }
11395            this.movingItemsAdjustScreenPosition();
11396            this.mapAdjustStrokes();
11397        }
11398        setSize(width, height, responsive) {
11399            this.options.width = width;
11400            this.options.height = height;
11401            this.options.responsive =
11402                responsive != null && responsive != undefined
11403                    ? MapSVG.parseBoolean(responsive)
11404                    : this.options.responsive;
11405            if (!this.options.width && !this.options.height) {
11406                this.options.width = this.svgDefault.width;
11407                this.options.height = this.svgDefault.height;
11408            }
11409            else if (!this.options.width && this.options.height) {
11410                this.options.width =
11411                    (this.options.height * this.svgDefault.width) / this.svgDefault.height;
11412            }
11413            else if (this.options.width && !this.options.height) {
11414                this.options.height =
11415                    (this.options.width * this.svgDefault.height) / this.svgDefault.width;
11416            }
11417            this.whRatio = this.options.width / this.options.height;
11418            this.scale = this.getScale();
11419            this.setResponsive(responsive);
11420            if (this.options.choropleth.on && this.options.choropleth.bubbleMode) {
11421                this.redrawBubbles();
11422            }
11423            this.movingItemsAdjustScreenPosition();
11424        }
11425        setResponsive(on) {
11426            on = on != undefined ? MapSVG.parseBoolean(on) : this.options.responsive;
11427            $$A(this.containers.map).css({
11428                width: "100%",
11429                height: "0",
11430                "padding-bottom": (this.viewBox.height * 100) / this.viewBox.width + "%",
11431            });
11432            if (on) {
11433                $$A(this.containers.wrap).css({
11434                    width: "100%",
11435                    height: "auto",
11436                });
11437            }
11438            else {
11439                $$A(this.containers.wrap).css({
11440                    width: this.options.width + "px",
11441                    height: this.options.height + "px",
11442                });
11443            }
11444            $$A.extend(true, this.options, { responsive: on });
11445            if (!this.resizeSensor) {
11446                this.resizeSensor = new ResizeSensor(this.containers.map, () => {
11447                    this.redraw();
11448                });
11449            }
11450            this.redraw();
11451        }
11452        setScroll(options, skipEvents) {
11453            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11454            options.limit != undefined && (options.limit = MapSVG.parseBoolean(options.limit));
11455            $$A.extend(true, this.options, { scroll: options });
11456            !skipEvents && this.setEventHandlers();
11457        }
11458        setZoom(options) {
11459            options = options || {};
11460            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11461            options.fingers != undefined && (options.fingers = MapSVG.parseBoolean(options.fingers));
11462            options.mousewheel != undefined &&
11463                (options.mousewheel = MapSVG.parseBoolean(options.mousewheel));
11464            options.delta = 2;
11465            if (options.limit) {
11466                if (typeof options.limit == "string")
11467                    options.limit = options.limit.split(";");
11468                options.limit = [parseInt(options.limit[0]), parseInt(options.limit[1])];
11469            }
11470            if (!this.zoomLevels) {
11471                this.setZoomLevels();
11472            }
11473            $$A.extend(true, this.options, { zoom: options });
11474            $$A(this.containers.map).off("wheel.mapsvg");
11475            if (this.options.zoom.mousewheel) {
11476                if (MapSVG.browser.firefox) {
11477                    this.firefoxScroll = { insideIframe: false, scrollX: 0, scrollY: 0 };
11478                    $$A(this.containers.map)
11479                        .on("mouseenter", () => {
11480                        this.firefoxScroll.insideIframe = true;
11481                        this.firefoxScroll.scrollX = window.scrollX;
11482                        this.firefoxScroll.scrollY = window.scrollY;
11483                    })
11484                        .on("mouseleave", () => {
11485                        this.firefoxScroll.insideIframe = false;
11486                    });
11487                    $$A(document).scroll(() => {
11488                        if (this.firefoxScroll.insideIframe)
11489                            window.scrollTo(this.firefoxScroll.scrollX, this.firefoxScroll.scrollY);
11490                    });
11491                }
11492                $$A(this.containers.map).on("wheel.mapsvg", (event) => {
11493                    this.throttle(this.mouseWheelZoom, 500, this, [event]);
11494                    return;
11495                });
11496            }
11497            this.canZoom = true;
11498        }
11499        mouseWheelZoom(event) {
11500            if ($$A(event.target).hasClass("mapsvg-popover") ||
11501                $$A(event.target).closest(".mapsvg-popover").length ||
11502                $$A(event.target).hasClass("mapsvg-details-container") ||
11503                $$A(event.target).closest(".mapsvg-details-container").length) {
11504                return;
11505            }
11506            event.preventDefault();
11507            const d = Math.sign(-event.originalEvent.deltaY);
11508            const center = this.getSvgPointAtClick(event.originalEvent);
11509            d > 0 ? this.zoomIn(center) : this.zoomOut(center);
11510        }
11511        setControls(options) {
11512            options = options || {};
11513            $$A.extend(true, this.options, { controls: options });
11514            this.options.controls.zoom = MapSVG.parseBoolean(this.options.controls.zoom);
11515            this.options.controls.zoomReset = MapSVG.parseBoolean(this.options.controls.zoomReset);
11516            this.options.controls.userLocation = MapSVG.parseBoolean(this.options.controls.userLocation);
11517            this.options.controls.previousMap = MapSVG.parseBoolean(this.options.controls.previousMap);
11518            const loc = this.options.controls.location || "right";
11519            if (!this.containers.controls) {
11520                const buttons = $$A("<div />").addClass("mapsvg-buttons");
11521                const zoomGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11522                const zoomIn = $$A("<div />").addClass("mapsvg-btn-map mapsvg-in");
11523                zoomIn.on("touchend click", (e) => {
11524                    if (e.cancelable) {
11525                        e.preventDefault();
11526                    }
11527                    e.stopPropagation();
11528                    this.zoomIn();
11529                });
11530                const zoomOut = $$A("<div />").addClass("mapsvg-btn-map mapsvg-out");
11531                zoomOut.on("touchend click", (e) => {
11532                    if (e.cancelable) {
11533                        e.preventDefault();
11534                    }
11535                    e.stopPropagation();
11536                    this.zoomOut();
11537                });
11538                zoomGroup.append(zoomIn).append(zoomOut);
11539                const location = $$A("<div />").addClass("mapsvg-btn-map mapsvg-btn-location");
11540                location.on("touchend click", (e) => {
11541                    if (e.cancelable) {
11542                        e.preventDefault();
11543                    }
11544                    e.stopPropagation();
11545                    this.showUserLocation((location) => {
11546                        if (this.options.scroll.on) {
11547                            this.centerOn(location.marker);
11548                        }
11549                    });
11550                });
11551                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>';
11552                location.html(userLocationIcon);
11553                const locationGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11554                locationGroup.append(location);
11555                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>';
11556                const zoomResetButton = $$A("<div />")
11557                    .html(zoomResetIcon)
11558                    .addClass("mapsvg-btn-map mapsvg-btn-zoom-reset");
11559                zoomResetButton.on("touchend click", (e) => {
11560                    if (e.cancelable) {
11561                        e.preventDefault();
11562                    }
11563                    e.stopPropagation();
11564                    this.viewBoxReset(true);
11565                });
11566                const zoomResetGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11567                zoomResetGroup.append(zoomResetButton);
11568                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="">' +
11569                    '<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)">' +
11570                    '<g id="g4">
11570<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" ' +
11571                    'id="path8" inkscape:connector-curvature="0" /></g></g></svg>';
11572                const previousMapButton = $$A("<div />")
11573                    .html(previousMapIcon)
11574                    .addClass("mapsvg-btn-map mapsvg-btn-previous-map");
11575                previousMapButton.on("touchend click", (e) => {
11576                    if (e.cancelable) {
11577                        e.preventDefault();
11578                    }
11579                    e.stopPropagation();
11580                    this.loadPreviousMap();
11581                });
11582                const previousMapGroup = $$A("<div />").addClass("mapsvg-btn-group").appendTo(buttons);
11583                previousMapGroup.append(previousMapButton);
11584                this.containers.controls = buttons[0];
11585                this.controls = {
11586                    zoom: zoomGroup[0],
11587                    userLocation: locationGroup[0],
11588                    zoomReset: zoomResetGroup[0],
11589                    previousMap: previousMapGroup[0],
11590                };
11591                $$A(this.containers.map).append($$A(this.containers.controls));
11592            }
11593            $$A(this.controls.zoom).toggle(this.options.controls.zoom);
11594            $$A(this.controls.userLocation).toggle(this.options.controls.userLocation);
11595            $$A(this.controls.zoomReset).toggle(this.options.controls.zoomReset);
11596            $$A(this.controls.previousMap).toggle(this.options.controls.previousMap && this.options.previousMapsIds.length > 0);
11597            $$A(this.containers.controls).removeClass("left");
11598            $$A(this.containers.controls).removeClass("right");
11599            (loc == "right" && $$A(this.containers.controls).addClass("right")) ||
11600                (loc == "left" && $$A(this.containers.controls).addClass("left"));
11601        }
11602        setZoomLevels() {
11603            if (!this.zoomLevels) {
11604                this.zoomLevels = new ArrayIndexed("zoomLevel");
11605            }
11606            else {
11607                this.zoomLevels.clear();
11608            }
11609            for (let i = -20; i < 0; i++) {
11610                const _scale = 1 / Math.pow(this.options.zoom.delta, Math.abs(i));
11611                this.zoomLevels.push({
11612                    zoomLevel: i,
11613                    _scale: _scale,
11614                    viewBox: new ViewBox(0, 0, this._viewBox.width / _scale, this._viewBox.height / _scale),
11615                });
11616            }
11617            for (let z = 0; z <= 20; z++) {
11618                const _scale = Math.pow(this.options.zoom.delta, Math.abs(z));
11619                this.zoomLevels.push({
11620                    zoomLevel: z,
11621                    _scale: _scale,
11622                    viewBox: new ViewBox(0, 0, this._viewBox.width / _scale, this._viewBox.height / _scale),
11623                });
11624            }
11625        }
11626        setCursor(type) {
11627            type = type == "pointer" ? "pointer" : "default";
11628            this.options.cursor = type;
11629            if (type == "pointer")
11630                $$A(this.containers.map).addClass("mapsvg-cursor-pointer");
11631            else
11632                $$A(this.containers.map).removeClass("mapsvg-cursor-pointer");
11633        }
11634        setMultiSelect(on, deselect) {
11635            this.options.multiSelect = MapSVG.parseBoolean(on);
11636            if (deselect !== false)
11637                this.deselectAllRegions();
11638        }
11639        _new_setChoropleth(options) {
11640            options = options || this.options.choropleth;
11641            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11642            if (typeof options.coloring === "undefined" ||
11643                typeof options.coloring.palette === "undefined" ||
11644                typeof options.coloring.palette.colors === "undefined") {
11645                if (typeof options.sourceFieldSelect === "undefined" ||
11646                    typeof options.sourceFieldSelect.variants === "undefined") {
11647                    $$A.extend(true, this.options.choropleth, options);
11648                }
11649                else {
11650                    this.options.choropleth.sourceFieldSelect.variants =
11651                        options.sourceFieldSelect.variants;
11652                }
11653            }
11654            else {
11655                const paletteColorsIndexes = Object.keys(options.coloring.palette.colors);
11656                if (paletteColorsIndexes.length > 1 ||
11657                    (paletteColorsIndexes[0] == "0" &&
11658                        Object.keys(options.coloring.palette.colors[0]).length > 1)) {
11659                    this.options.choropleth.coloring.palette.colors = options.coloring.palette.colors;
11660                }
11661                else {
11662                    const paletteColorIndex = Object.keys(options.coloring.palette.colors)[0];
11663                    $$A.extend(true, this.options.choropleth.coloring.palette.colors[paletteColorIndex], options.coloring.palette.colors[paletteColorIndex]);
11664                }
11665            }
11666            this.updateChoroplethMinMax();
11667            if (this.options.choropleth.on &&
11668                this.options.choropleth.sourceFieldSelect.on &&
11669                this.options.choropleth.sourceFieldSelect.variants) {
11670                if (!this.containers.choroplethSourceSelect) {
11671                    const sourceSelectOptions = [];
11672                    this.options.choropleth.sourceFieldSelect.variants.forEac
11672h((variant) => {
11673                        sourceSelectOptions.push($$A('<option value="' +
11674                            variant +
11675                            '" ' +
11676                            (variant === this.options.choropleth.sourceField
11677                                ? "selected"
11678                                : "") +
11679                            ">" +
11680                            variant +
11681                            "</option>"));
11682                    });
11683                    this.containers.choroplethSourceSelect = {
11684                        container: $$A('<div class="mapsvg-choropleth-source-field"></div>')[0],
11685                        select: $$A('<select id="mapsvg-choropleth-source-field-select" class="mapsvg-select2"></select>')[0],
11686                        options: sourceSelectOptions,
11687                    };
11688                    $$A(this.containers.choroplethSourceSelect.select).append(this.containers.choroplethSourceSelect.options);
11689                    $$A(this.containers.choroplethSourceSelect.container).append($$A(this.containers.choroplethSourceSelect.select));
11690                    $$A(this.containers.map).append($$A(this.containers.choroplethSourceSelect.container));
11691                    $$A(this.containers.choroplethSourceSelect.select).mselect2();
11692                    $$A(this.containers.choroplethSourceSelect.select)
11693                        .mselect2()
11694                        .on("select2:select select2:unselecting", (e) => {
11695                        if (e.cancelable) {
11696                            e.preventDefault();
11697                        }
11698                        e.stopPropagation();
11699                        this.setChoropleth({ sourceField: $$A(e.target).mselect2().val() });
11700                    });
11701                }
11702                else {
11703                    $$A(this.containers.choroplethSourceSelect.select).mselect2("destroy");
11704                    $$A(this.containers.choroplethSourceSelect.select).find("option").remove();
11705                    this.containers.choroplethSourceSelect.options = [];
11706                    this.options.choropleth.sourceFieldSelect.variants.forEac
11706h((variant) => {
11707                        this.containers.choroplethSourceSelect.options.push($$A('<option value="' +
11708                            variant +
11709                            '" ' +
11710                            (variant === this.options.choropleth.sourceField
11711                                ? "selected"
11712                                : "") +
11713                            ">" +
11714                            variant +
11715                            "</option>")[0]);
11716                    });
11717                    $$A(this.containers.choroplethSourceSelect.select).append(this.containers.choroplethSourceSelect.options);
11718                    $$A(this.containers.choroplethSourceSelect.select).mselect2({ width: "100%" });
11719                }
11720            }
11721            if ((!this.options.choropleth.on || !this.options.choropleth.sourceFieldSelect.on) &&
11722                this.containers.choroplethSourceSelect &&
11723                $$A(this.containers.choroplethSourceSelect.container).is(":visible")) {
11724                $$A(this.containers.choroplethSourceSelect.container).hide();
11725            }
11726            else if (this.options.choropleth.on &&
11727                this.options.choropleth.sourceFieldSelect.on &&
11728                this.containers.choroplethSourceSelect &&
11729                !$$A(this.containers.choroplethSourceSelect.container).is(":visible")) {
11730                $$A(this.containers.choroplethSourceSelect.container).show();
11731            }
11732            $$A(this.containers.map).find(".mapsvg-choropleth-legend").remove();
11733            if (this.options.choropleth.on && this.options.choropleth.coloring.legend.on) {
11734                const legend = this.options.choropleth.coloring.legend;
11735                let coloring = "";
11736                if (this.options.choropleth.coloring.mode === "gradient") {
11737                    coloring +=
11738                        '<div class="mapsvg-choropleth-legend-gradient-no-data">' +
11739                            this.options.choropleth.coloring.noData.description +
11740                            "</div>";
11741                    let legendGradient = "";
11742                    for (let chunkIdx = 1; chunkIdx < 5; chunkIdx++) {
11743                        legendGradient +=
11744                            '<div class="mapsvg-choropleth-legend-gradient-chunk">' +
11745                                ((this.options.choropleth.coloring.gradient.values.maxAdjusted * chunkIdx) /
11746                                    5 +
11747                                    this.options.choropleth.coloring.gradient.values.min) +
11748                                "</div>";
11749                    }
11750                    coloring +=
11751                        '<div class="mapsvg-choropleth-legend-gradient-colors">' +
11752                            legendGradient +
11753                            "</div>";
11754                }
11755                else {
11756                    coloring +=
11757                        '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="no-data">' +
11758                            '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
11759                            '<div class="mapsvg-choropleth-legend-palette-color-description">' +
11760                            this.options.choropleth.coloring.noData.description +
11761                            "</div>" +
11762                            "</div>";
11763                    coloring +=
11764                        '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="out-of-range">' +
11765                            '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
11766                            '<div class="mapsvg-choropleth-legend-palette-color-description">' +
11767                            this.options.choropleth.coloring.palette.outOfRange.description +
11768                            "</div>" +
11769                            "</div>";
11770                    const paletteColors = this.options.choropleth.coloring.palette.colors;
11771                    paletteColors.forEach((paletteColor, idx) => {
11772                        let paletteColorElementText = "";
11773                        if (paletteColor.description) {
11774                            paletteColorElementText = paletteColor.description;
11775                        }
11776                        else {
11777                            if (idx === 0 && !paletteColor.valueFrom && paletteColor.valueFrom !== 0) {
11778                                if (legend.layout === "vertical") {
11779                                    paletteColorElementText = "Less then " + paletteColor.valueTo;
11780                                }
11781                                else {
11782                                    paletteColorElementText = "< " + paletteColor.valueTo;
11783                                }
11784                            }
11785                            else if (idx === paletteColors.length - 1 && !paletteColor.valueTo) {
11786                                if (legend.layout === "vertical") {
11787                                    paletteColorElementText = paletteColor.valueFrom + " or more";
11788                                }
11789                                else {
11790                                    paletteColorElementText = paletteColor.valueFrom + " <";
11791                                }
11792                            }
11793                            else {
11794                                paletteColorElementText =
11795                                    paletteColor.valueFrom + " &#8804; " + paletteColor.valueTo;
11796                            }
11797                        }
11798                        coloring +=
11799                            '<div class="mapsvg-choropleth-legend-palette-color-wrap" data-idx="' +
11800                                idx +
11801                                '">' +
11802                                '<div class="mapsvg-choropleth-legend-palette-color"></div>' +
11803                                '<div class="mapsvg-choropleth-legend-palette-color-description">' +
11804                                paletteColorElementText +
11805                                "</div>" +
11806                                "</div>";
11807                    });
11808                }
11809                this.containers.legend = {
11810                    title: $$A('<div class="mapsvg-choropleth-legend-title">' + legend.title + "</div>")[0],
11811                    text: $$A('<div class="mapsvg-choropleth-legend-text">' + legend.text + "</div>")[0],
11812                    coloring: $$A('<div class="mapsvg-choropleth-legend-' +
11813                        this.options.choropleth.coloring.mode +
11814                        '">' +
11815                        coloring +
11816                        "</div>")[0],
11817                    description: $$A('<div class="mapsvg-choropleth-legend-description">' +
11818                        legend.description +
11819                        "</div>")[0],
11820                    container: $$A("<div />").addClass("mapsvg-choropleth-legend mapsvg-choropleth-legend-" +
11821                        legend.layout +
11822                        " mapsvg-choropleth-legend-container-" +
11823                        legend.container)[0],
11824                };
11825                $$A(this.containers.legend.container)
11826                    .append(this.containers.legend.title)
11827                    .append(this.containers.legend.text)
11828                    .append(this.containers.legend.coloring)
11829                    .append(this.containers.legend.description);
11830                $$A(this.containers.map).append(this.containers.legend.container);
11831                this.setChoroplethLegendCSS();
11832                this.regionsRepository.events.on("updated", () => {
11833                    this.redrawChoropleth();
11834                });
11835                this.objectsRepository.events.on("updated", () => {
11836                    this.redrawChoropleth();
11837                });
11838            }
11839            if (this.options.choropleth.on && this.options.choropleth.coloring.mode === "gradient") {
11840                const colors = this.options.choropleth.coloring.gradient.colors;
11841                if (colors) {
11842                    colors.lowRGB = tinycolor(colors.low).toRgb();
11843                    colors.highRGB = tinycolor(colors.high).toRgb();
11844                    colors.diffRGB = {
11845                        r: colors.highRGB.r - colors.lowRGB.r,
11846                        g: colors.highRGB.g - colors.lowRGB.g,
11847                        b: colors.highRGB.b - colors.lowRGB.b,
11848                        a: colors.highRGB.a - colors.lowRGB.a,
11849                    };
11850                    this.containers.legend && this.setChoroplethLegendCSS();
11851                }
11852            }
11853            this.redrawChoropleth();
11854        }
11855        redrawChoropleth() {
11856            this.updateChoroplethMinMax();
11857            this.redrawBubbles();
11858            this.regionsRedrawColors();
11859        }
11860        updateChoroplethMinMax() {
11861            if (this.options.choropleth.on) {
11862                const gradient = this.options.choropleth.coloring.gradient, values = [];
11863                gradient.values.min = 0;
11864                gradient.values.max = null;
11865                if (this.options.choropleth.source === "regions") {
11866                    this.regions.forEach((region) => {
11867                        const choropleth = region.data && region.data[this.options.choropleth.sourceField];
11868                        choropleth != undefined && choropleth !== "" && values.push(choropleth);
11869                    });
11870                }
11871                else {
11872                    this.objectsRepository.objects.forEach((object) => {
11873                        const choropleth = object[this.options.choropleth.sourceField];
11874                        choropleth != undefined && choropleth !== "" && values.push(choropleth);
11875                    });
11876                }
11877                if (values.length > 0) {
11878                    gradient.values.min = Math.min.apply(null, values);
11879                    gradient.values.max = Math.max.apply(null, values);
11880                    gradient.values.maxAdjusted = gradient.values.max - gradient.values.min;
11881                }
11882            }
11883        }
11884        setChoroplethLegendCSS() {
11885            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;
11886            $$A(".mapsvg-choropleth-legend").css({
11887                width: legend.width,
11888                height: legend.height,
11889            });
11890            if (this.options.choropleth.coloring.mode === "gradient") {
11891                if (legend.layout === "horizontal") {
11892                    $$A(".mapsvg-choropleth-legend-horizontal .mapsvg-choropleth-legend-gradient-colors").css({
11893                        background: "linear-gradient(to right," +
11894                            gradient.colors.low +
11895                            " 1%," +
11896                            gradient.colors.high +
11897                            " 100%)",
11898                    });
11899                }
11900                else {
11901                    $$A(".mapsvg-choropleth-legend-vertical .mapsvg-choropleth-legend-gradient-colors").css({
11902                        background: "linear-gradient(to bottom," +
11903                            gradient.colors.low +
11904                            " 1%," +
11905                            gradient.colors.high +
11906                            " 100%)",
11907                    });
11908                }
11909                $$A(".mapsvg-choropleth-legend-gradient-no-data").css({
11910                    "background-color": noData.color,
11911                });
11912            }
11913            else {
11914                const paletteColors = this.options.choropleth.coloring.palette.colors;
11915                paletteColors.forEach(function (paletteColor, idx) {
11916                    $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="' +
11917                        idx +
11918                        '"] .mapsvg-choropleth-legend-palette-color').css({
11919                        "background-color": paletteColor.color,
11920                    });
11921                });
11922                $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="no-data"] .mapsvg-choropleth-legend-palette-color').css({
11923                    "background-color": noData.color,
11924                });
11925                $$A('.mapsvg-choropleth-legend-palette-color-wrap[data-idx="out-of-range"] .mapsvg-choropleth-legend-palette-color').css({
11926                    "background-color": outOfRange.color,
11927                });
11928            }
11929        }
11930        setCss(css) {
11931            this.options.css =
11932                css || (this.options.css ? this.options.css.replace(/%id%/g, "" + this.id) : "");
11933            this.liveCss = this.liveCss || $$A("<style></style>").appendTo("head")[0];
11934            $$A(this.liveCss).html(this.options.css);
11935        }
11936        setFilters(options) {
11937            options = options || this.options.filters;
11938            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
11939            options.hide != undefined && (options.hide = MapSVG.parseBoolean(options.hide));
11940            $$A.extend(true, this.options, { filters: options });
11941            if (["leftSidebar", "rightSidebar", "header", "footer", "custom", "map"].indexOf(this.options.filters.location) === -1) {
11942                this.options.filters.location = "leftSidebar";
11943            }
11944            if (this.options.filters.on) {
11945                if (this.formBuilder) {
11946                    this.formBuilder.destroy();
11947                }
11948                if (!this.containers.filters) {
11949                    this.containers.filters = $$A('<div class="mapsvg-filters-wrap"></div>')[0];
11950                }
11951                else {
11952                    $$A(this.containers.filters).empty();
11953                    $$A(this.containers.filters).show();
11954                }
11955                $$A(this.containers.filters).css({
11956                    "background-color": this.options.colors.directorySearch,
11957                });
11958                if ($$A(this.containers.filtersModal)) {
11959                    $$A(this.containers.filtersModal).css({ width: this.options.filters.width });
11960                }
11961                if (this.options.filters.location === "custom") {
11962                    $$A(this.containers.filters)
11963                        .removeClass("mapsvg-filter-container-custom")
11964                        .addClass("mapsvg-filter-container-custom");
11965                    if ($$A("#" + this.options.filters.containerId).length) {
11966                        $$A("#" + this.options.filters.containerId).append(this.containers.filters);
11967                    }
11968                    else {
11969                        $$A(this.containers.filters).hide();
11970                        console.error("MapSVG: filter container #" +
11971                            this.options.filters.containerId +
11972                            " does not exists");
11973                    }
11974                }
11975                else {
11976                    if (MapSVG.isPhone) {
11977                        $$A(this.containers.header).append($$A(this.containers.filters));
11978                        this.setContainers({ header: { on: true } });
11979                    }
11980                    else {
11981                        const location = MapSVG.isPhone ? "header" : this.options.filters.location;
11982                        if (this.options.menu.on &&
11983                            this.controllers.directory &&
11984                            this.options.menu.location === this.options.filters.location) {
11985                            $$A(this.controllers.directory.containers.view)
11986                                .find(".mapsvg-directory-filter-wrap")
11987                                .append($$A(this.containers.filters));
11988                            this.controllers.directory.updateTopShift();
11989                        }
11990                        else {
11991                            $$A(this.containers[location]).append($$A(this.containers.filters));
11992                            this.controllers.directory && this.controllers.directory.updateTopShift();
11993                        }
11994                    }
11995                }
11996                this.loadFiltersController(this.containers.filters, false);
11997                this.updateFiltersState();
11998            }
11999            else {
12000                if ($$A(this.containers.filters)) {
12001                    $$A(this.containers.filters).empty();
12002                    $$A(this.containers.filters).hide();
12003                }
12004            }
12005            if (this.options.menu.on &&
12006                this.controllers.directory &&
12007                this.options.menu.location === this.options.filters.location) {
12008                this.controllers.directory.updateTopShift();
12009            }
12010        }
12011        updateFiltersState() {
12012            if (this.options.filters && this.options.filters.on && this.controllers.filters) {
12013                this.controllers.filters.update(this.objectsRepository.query);
12014                this.updateFilterTags();
12015            }
12016        }
12017        updateFilterTags() {
12018            $$A(this.containers.filterTags) && $$A(this.containers.filterTags).empty();
12019            for (const field_name in this.objectsRepository.query.filters) {
12020                let field_value = this.objectsRepository.query.filters[field_name];
12021                let _field_name = field_name;
12022                const filterField = this.filtersSchema.getField(_field_name);
12023                if (field_name == "regions") {
12024                    _field_name = "";
12025                    field_value = field_value.region_ids.map((id) => this.getRegion(id).title);
12026                }
12027                else {
12028                    _field_name = filterField && filterField.label;
12029                }
12030                if (field_name !== "distance") {
12031                    if (!this.containers.filterTags) {
12032                        this.containers.filterTags = $$A('<div class="mapsvg-filter-tags"></div>')[0];
12033                        if ($$A(this.containers.filters)) ;
12034                        else {
12035                            if (this.options.menu.on && this.controllers.directory) {
12036                                $$A(this.controllers.directory.containers.toolbar).append(this.containers.filterTags);
12037                                this.controllers.directory.updateTopShift();
12038                            }
12039                            else {
12040                                $$A(this.containers.map).append(this.containers.filterTags);
12041                                if (this.options.zoom.buttons.on) {
12042                                    if (this.options.layersControl.on) {
12043                                        if (this.options.layersControl.position == "top-left") {
12044                                            $$A(this.containers.filterTags).css({
12045                                                right: 0,
12046                                                bottom: 0,
12047                                            });
12048                                        }
12049                                        else {
12050                                            $$A(this.containers.filterTags).css({
12051                                                bottom: 0,
12052                                            });
12053                                        }
12054                                    }
12055                                    else {
12056                                        if (this.options.zoom.buttons.location == "left") {
12057                                            $$A(this.containers.filterTags).css({
12058                                                right: 0,
12059                                            });
12060                                        }
12061                                    }
12062                                }
12063                            }
12064                        }
12065                        $$A(this.containers.filterTags).on("click", ".mapsvg-filter-delete", (e) => {
12066                            const filterField = $$A(e.target).data("filter");
12067                            $$A(e.target).parent().remove();
12068                            this.objectsRepository.query.removeFilter(filterField);
12069                            this.deselectAllRegions();
12070                            this.loadDataObjects();
12071                        });
12072                    }
12073                    $$A(this.containers.filterTags).append('<div class="mapsvg-filter-tag">' +
12074                        (_field_name ? _field_name + ": " : "") +
12075                        field_value +
12076                        ' <span class="mapsvg-filter-delete" data-filter="' +
12077                        field_name +
12078                        '">
12078×</span></div>');
12079                }
12080            }
12081        }
12082        setContainers(options) {
12083            const _this = this;
12084            if (!this.containersCreated) {
12085                this.containers.wrapAll = document.createElement("div");
12086                this.containers.wrapAll.classList.add("mapsvg-wrap-all");
12087                this.containers.wrapAll.id = "mapsvg-map-" + this.id;
12088                this.containers.wrapAll.setAttribute("data-map-id", this.id ? this.id.toString() : "");
12089                this.containers.wrap = document.createElement("div");
12090                this.containers.wrap.classList.add("mapsvg-wrap");
12091                this.containers.mapContainer = document.createElement("div");
12092                this.containers.mapContainer.classList.add("mapsvg-map-container");
12093                this.containers.leftSidebar = document.createElement("div");
12094                this.containers.leftSidebar.className =
12095                    "mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-left";
12096                this.containers.rightSidebar = document.createElement("div");
12097                this.containers.rightSidebar.className =
12098                    "mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-right";
12099                this.containers.header = document.createElement("div");
12100                this.containers.header.className = "mapsvg-header mapsvg-top-container";
12101                this.containers.footer = document.createElement("div");
12102                this.containers.footer.className = "mapsvg-footer mapsvg-top-container";
12103                _this.containers.wrapAll = $$A('<div class="mapsvg-wrap-all"></div>')
12104                    .attr("id", "mapsvg-map-" + this.id)
12105                    .attr("data-map-id", this.id)[0];
12106                _this.containers.wrap = $$A('<div class="mapsvg-wrap"></div>')[0];
12107                _this.containers.mapContainer = $$A('<div class="mapsvg-map-container"></div>')[0];
12108                _this.containers.leftSidebar = $$A('<div class="mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-left"></div>')[0];
12109                _this.containers.rightSidebar = $$A('<div class="mapsvg-sidebar mapsvg-top-container mapsvg-sidebar-right"></div>')[0];
12110                _this.containers.header = $$A('<div class="mapsvg-header mapsvg-top-container"></div>')[0];
12111                _this.containers.footer = $$A('<div class="mapsvg-footer mapsvg-top-container"></div>')[0];
12112                $$A(_this.containers.wrapAll).insertBefore(_this.containers.map);
12113                $$A(_this.containers.wrapAll).append(_this.containers.header);
12114                $$A(_this.containers.wrapAll).append(_this.containers.wrap);
12115                $$A(_this.containers.wrapAll).append(_this.containers.footer);
12116                $$A(_this.containers.mapContainer).append(_this.containers.map);
12117                $$A(_this.containers.wrap).append(_this.containers.leftSidebar);
12118                $$A(_this.containers.wrap).append(_this.containers.mapContainer);
12119                $$A(_this.containers.wrap).append(_this.containers.rightSidebar);
12120                _this.containersCreated = true;
12121            }
12122            options = options || _this.options.containers || {};
12123            for (const contName in options) {
12124                if (options[contName].on !== undefined) {
12125                    options[contName].on = MapSVG.parseBoolean(options[contName].on);
12126                }
12127                if (options[contName].width) {
12128                    if (typeof options[contName].width != "string" ||
12129                        (options[contName].width.indexOf("px") === -1 &&
12130                            options[contName].width.indexOf("%") === -1 &&
12131                            options[contName].width !== "auto")) {
12132                        options[contName].width = options[contName].width + "px";
12133                    }
12134                    $$A(_this.containers[contName]).css({ "flex-basis": options[contName].width });
12135                }
12136                if (options[contName].height) {
12137                    if (typeof options[contName].height != "string" ||
12138                        (options[contName].height.indexOf("px") === -1 &&
12139                            options[contName].height.indexOf("%") === -1 &&
12140                            options[contName].height !== "auto")) {
12141                        options[contName].height = options[contName].height + "px";
12142                    }
12143                    $$A(_this.containers[contName]).css({
12144                        "flex-basis": options[contName].height,
12145                        height: options[contName].height,
12146                    });
12147                }
12148                $$A.extend(true, _this.options, { containers: options });
12149                let on = _this.options.containers[contName].on;
12150                if (MapSVG.isPhone &&
12151                    _this.options.menu.hideOnMobile &&
12152                    _this.options.menu.location === contName &&
12153                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12154                    on = false;
12155                }
12156                else if (MapSVG.isPhone &&
12157                    _this.options.menu.location === "custom" &&
12158                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12159                    on = false;
12160                    $$A(_this.containers.wrapAll).addClass("mapsvg-hide-map-list-buttons");
12161                }
12162                else if (MapSVG.isPhone &&
12163                    !_this.options.menu.hideOnMobile &&
12164                    _this.options.menu.location === contName &&
12165                    ["leftSidebar", "rightSidebar"].indexOf(contName) !== -1) {
12166                    $$A(_this.containers.wrapAll).addClass("mapsvg-hide-map-list-buttons");
12167                    $$A(_this.containers.wrapAll).addClass("mapsvg-directory-visible");
12168                }
12169                $$A(_this.containers[contName]).toggle(on);
12170            }
12171            _this.setDetailsView();
12172        }
12173        shouldBeScrollable(container) {
12174            const _this = this;
12175            switch (container) {
12176                case "map":
12177                case "leftSidebar":
12178                case "rightSidebar":
12179                    return true;
12180                case "custom":
12181                    return false;
12182                case "header":
12183                case "footer":
12184                    if (_this.options.containers[container].height &&
12185                        _this.options.containers[container].height !== "auto" &&
12186                        _this.options.containers[container].height !== "100%") {
12187                        return true;
12188                    }
12189                    else {
12190                        return false;
12191                    }
12192                default:
12193                    return false;
12194            }
12195        }
12196        setDirectory(options) {
12197            return this.setMenu(options);
12198        }
12199        setMenu(options) {
12200            options = options || this.options.menu;
12201            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12202            options.search != undefined && (options.search = MapSVG.parseBoolean(options.search));
12203            options.showMapOnClick != undefined &&
12204                (options.showMapOnClick = MapSVG.parseBoolean(options.showMapOnClick));
12205            options.searchFallback != undefined &&
12206                (options.searchFallback = MapSVG.parseBoolean(options.searchFallback));
12207            options.customContainer != undefined &&
12208                (options.customContainer = MapSVG.parseBoolean(options.customContainer));
12209            $$A.extend(true, this.options, { menu: options });
12210            this.controllers = this.controllers || {};
12211            if (!this.containers.directory) {
12212                this.containers.directory = $$A('<div class="mapsvg-directory"></div>')[0];
12213            }
12214            $$A(this.containers.directory).toggleClass("flex", this.shouldBeScrollable(this.options.menu.location));
12215            if (this.options.menu.on) {
12216                if (!this.controllers.directory) {
12217                    this.controllers.directory = new DirectoryController({
12218                        container: this.containers.directory,
12219                        template: this.options.templates.directory,
12220                        mapsvg: this,
12221                        repository: this.options.menu.source === "regions"
12222                            ? this.regionsRepository
12223                            : this.objectsRepository,
12224                        scrollable: this.shouldBeScrollable(this.options.menu.location),
12225                        events: {
12226                            click: (e, regionOrObject, mapsvg) => {
12227                                this.events.trigger("click.directoryItem", this, [
12228                                    e,
12229                                    regionOrObject,
12230                                    mapsvg,
12231                                ]);
12232                            },
12233                            mouseover: (e, regionOrObject, mapsvg) => {
12234                                this.events.trigger("mouseover.directoryItem", this, [
12235                                    e,
12236                                    regionOrObject,
12237                                    mapsvg,
12238                                ]);
12239                            },
12240                            mouseout: (e, regionOrObject, mapsvg) => {
12241                                this.events.trigger("mouseout.directoryItem", this, [
12242                                    e,
12243                                    regionOrObject,
12244                                    mapsvg,
12245                                ]);
12246                            },
12247                        },
12248                    });
12249                    this.controllers.directory._init();
12250                }
12251                else {
12252                    this.controllers.directory.repository =
12253                        this.options.menu.source === "regions"
12254                            ? this.regionsRepository
12255                            : this.objectsRepository;
12256                    this.controllers.directory.repository.query.update({
12257                        sort: [
12258                            {
12259                                field: this.options.menu.sortBy,
12260                                order: this.options.menu.sortDirection,
12261                            },
12262                        ],
12263                    });
12264                    if (options.filterout) {
12265                        const f = {};
12266                        f[this.options.menu.filterout.field] = this.options.menu.filterout.val;
12267                        this.controllers.directory.repository.query.setFilterOut(f);
12268                    }
12269                    this.controllers.directory.scrollable = this.shouldBeScrollable(this.options.menu.location);
12270                }
12271                let $container;
12272                if (MapSVG.isPhone && this.options.menu.hideOnMobile) {
12273                    $container = $$A(this.containers.leftSidebar);
12274                }
12275                else {
12276                    $container =
12277                        this.options.menu.location !== "custom"
12278                            ? $$A(this.containers[this.options.menu.location])
12279                            : $$A("#" + this.options.menu.containerId);
12280                }
12281                $container.append(this.containers.directory);
12282                if (this.options.colors.directory) {
12283                    $$A(this.containers.directory).css({
12284                        "background-color": this.options.colors.directory,
12285                    });
12286                }
12287                this.setFilters();
12288                this.setTemplates({ directoryItem: this.options.templates.directoryItem });
12289                if ((this.options.menu.source === "regions" && this.regionsRepository.loaded) ||
12290                    (this.options.menu.source === "database" && this.objectsRepository.loaded)) {
12291                    if (this.editMode &&
12292                        (options.sortBy || options.sortDirection || options.filterout)) {
12293                        this.controllers.directory.repository.reload();
12294                    }
12295                    this.loadDirectory();
12296                }
12297            }
12298            else {
12299                this.controllers.directory && this.controllers.directory.destroy();
12300                this.controllers.directory = null;
12301            }
12302        }
12303        setDatabase(options) {
12304            options = options || this.options.database;
12305            if (options.pagination) {
12306                if (options.pagination.on != undefined) {
12307                    options.pagination.on = MapSVG.parseBoolean(options.pagination.on);
12308                }
12309                if (options.pagination.perpage != undefined) {
12310                    options.pagination.perpage = parseInt(options.pagination.perpage);
12311                }
12312            }
12313            $$A.extend(true, this.options, { database: options });
12314            if (options.pagination) {
12315                if (options.pagination.on !== undefined || options.pagination.perpage) {
12316                    const query = new Query({
12317                        perpage: this.options.database.pagination.on
12318                            ? this.options.database.pagination.perpage
12319                            : 0,
12320                    });
12321                    this.objectsRepository.find(query);
12322                }
12323                else {
12324                    this.setPagination();
12325                }
12326            }
12327        }
12328        updateGoogleMapsMaxZoom(geoPoint) {
12329            this.googleMaps.maxZoomService.getMaxZoomAtLatLng(geoPoint, (result) => {
12330                if (result.status === "OK") {
12331                    this.googleMaps.currentMaxZoom = result.zoom;
12332                }
12333            });
12334        }
12335        setGoogleMaps(options) {
12336            options = options || this.options.googleMaps;
12337            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
12338            if (!this.googleMaps) {
12339                this.googleMaps = { loaded: false, initialized: false, map: null, overlay: null };
12340            }
12341            $$A.extend(true, this.options, { googleMaps: options });
12342            if (this.options.googleMaps.on) {
12343                $$A(this.containers.map).toggleClass("mapsvg-with-google-map", true);
12344                if (!MapSVG.googleMapsApiLoaded) {
12345                    this.events.on("googleMapsBoundsChanged", (bounds) => {
12346                        this.setViewBoxByGoogleMapsOverlay();
12347                    });
12348                    this.loadGoogleMapsAPI(() => {
12349                        this.setGoogleMaps();
12350                    }, () => {
12351                        this.setGoogleMaps({ on: false });
12352                    });
12353                }
12354                else {
12355                    if (!this.googleMaps.map) {
12356                        this.containers.googleMaps = $$A('<div class="mapsvg-layer mapsvg-layer-gm" id="mapsvg-google-maps-' +
12357                            this.id +
12358                            '"></div>').prependTo(this.containers.map)[0];
12359                        $$A(this.containers.googleMaps).css({
12360                            position: "absolute",
12361                            top: 0,
12362                            left: 0,
12363                            bottom: 0,
12364                            right: 0,
12365                            "z-index": "0",
12366                        });
12367                        this.googleMaps.map = new google.maps.Map(this.containers.googleMaps, {
12368                            mapTypeId: options.type,
12369                            fullscreenControl: false,
12370                            keyboardShortcuts: false,
12371                            mapTypeControl: false,
12372                            scaleControl: false,
12373                            scrollwheel: false,
12374                            streetViewControl: false,
12375                            zoomControl: false,
12376                            styles: options.styleJSON,
12377                        });
12378                        const southWest = new google.maps.LatLng(this.geoViewBox.sw.lat, this.geoViewBox.sw.lng);
12379                        const northEast = new google.maps.LatLng(this.geoViewBox.ne.lat, this.geoViewBox.ne.lng);
12380                        const bounds = new google.maps.LatLngBounds(southWest, northEast);
12381                        this.googleMaps.overlay = this.createGoogleMapOverlay(bounds, this.googleMaps.map);
12382                        if (!this.options.googleMaps.center || !this.options.googleMaps.zoom) {
12383                            this.googleMaps.map.fitBounds(bounds, 0);
12384                        }
12385                        else {
12386                            this.googleMaps.map.setZoom(this.options.googleMaps.zoom);
12387                            this.googleMaps.map.setCenter(this.options.googleMaps.center);
12388                        }
12389                        this.googleMaps.initialized = true;
12390                        this.googleMaps.maxZoomService = new google.maps.MaxZoomService();
12391                        this.googleMaps.map.addListener("idle", () => {
12392                            this.isZooming = false;
12393                        });
12394                        google.maps.event.addListenerOnce(this.googleMaps.map, "idle", () => {
12395                            setTimeout(() => {
12396                                $$A(this.containers.map).addClass("mapsvg-fade-in");
12397                                setTimeout(() => {
12398                                    $$A(this.containers.map).removeClass("mapsvg-google-map-loading");
12399                                    $$A(this.containers.map).removeClass("mapsvg-fade-in");
12400                                    if (!this.options.googleMaps.center ||
12401                                        !this.options.googleMaps.zoom) {
12402                                        this.options.googleMaps.center = this.googleMaps.map
12403                                            .getCenter()
12404                                            .toJSON();
12405                                        this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
12406                                    }
12407                                    this.zoomDelta = this.options.googleMaps.zoom - this.zoomLevel;
12408                                    this.updateGoogleMapsMaxZoom(this.options.googleMaps.center);
12409                                    this.setInitialViewBox(this.viewBox);
12410                                    this.toggleSvgLayerOnZoom();
12411                                    this.events.trigger("googleMapsLoaded");
12412                                }, 300);
12413                            }, 1);
12414                        });
12415                    }
12416                    else {
12417                        $$A(this.containers.map).toggleClass("mapsvg-with-google-map", true);
12418                        $$A(this.containers.googleMaps) && $$A(this.containers.googleMaps).show();
12419                        if (options.type) {
12420                            this.googleMaps.map.setMapTypeId(options.type);
12421                        }
12422                    }
12423                }
12424            }
12425            else {
12426                $$A(this.containers.map).toggleClass("mapsvg-with-google-map", false);
12427                $$A(this.containers.googleMaps) && $$A(this.containers.googleMaps).hide();
12428                this.googleMaps.initialized = false;
12429            }
12430            if (this.converter) {
12431                this.converter.setWorldShift(this.options.googleMaps.on);
12432            }
12433        }
12434        createGoogleMapOverlay(bounds, map) {
12435            class GoogleMapsOverlay extends google.maps.OverlayView {
12436                constructor(bounds, googleMapInstance, mapsvg) {
12437                    super();
12438                    this.bounds_ = bounds;
12439                    this.map_ = googleMapInstance;
12440                    this.mapsvg = mapsvg;
12441                    this.setMap(googleMapInstance);
12442                    this.prevCoords = {
12443                        sw: { x: 0, y: 0 },
12444                        sw2: { x: 0, y: 0 },
12445                        ne: { x: 0, y: 0 },
12446                        ne2: { x: 0, y: 0 },
12447                    };
12448                }
12449                draw() {
12450                    this.mapsvg.events.trigger("googleMapsBoundsChanged", this.map_, [
12451                        this.getPixelBounds(),
12452                        this.map_,
12453                    ]);
12454                }
12455                onAdd() {
12456                    this.element = document.createElement("div");
12457                    this.element.style.borderStyle = "none";
12458                    this.element.style.borderWidth = "0px";
12459                    this.element.style.position = "absolute";
12460                    const panes = this.getPanes();
12461                    panes.overlayLayer.appendChild(this.element);
12462                }
12463                getPixelBounds() {
12464                    const overlayProjection = this.getProjection();
12465                    if (!overlayProjection)
12466                        return;
12467                    const geoSW = this.bounds_.getSouthWest();
12468                    const geoNE = this.bounds_.getNorthEast();
12469                    const coords = {
12470                        sw: overlayProjection.fromLatLngToDivPixel(geoSW),
12471                        ne: overlayProjection.fromLatLngToDivPixel(geoNE),
12472                        sw2: overlayProjection.fromLatLngToContainerPixel(geoSW),
12473                        ne2: overlayProjection.fromLatLngToContainerPixel(geoNE),
12474                    };
12475                    const ww = overlayProjection.getWorldWidth();
12476                    if (this.prevCoords.sw) {
12477                        if (coords.ne.x < coords.sw.x) {
12478                            if (Math.abs(this.prevCoords.sw.x - coords.sw.x) >
12479                                Math.abs(this.prevCoords.ne.x - coords.ne.x)) {
12480                                coords.sw.x = coords.sw.x - ww;
12481                            }
12482                            else {
12483                                coords.ne.x = coords.ne.x + ww;
12484                            }
12485                            if (Math.abs(this.prevCoords.sw2.x - coords.sw2.x) >
12486                                Math.abs(this.prevCoords.ne2.x - coords.ne2.x)) {
12487                                coords.sw2.x = coords.sw2.x - ww;
12488                            }
12489                            else {
12490                                coords.ne2.x = coords.ne2.x + ww;
12491                            }
12492                        }
12493                    }
12494                    this.prevCoords = coords;
12495                    return { sw: coords.sw2, ne: coords.ne2 };
12496                }
12497            }
12498            return new GoogleMapsOverlay(bounds, map, this);
12499        }
12500        loadGoogleMapsAPI(callback, fail) {
12501            if (window.google !== undefined && google.maps) {
12502                MapSVG.googleMapsApiLoaded = true;
12503            }
12504            if (MapSVG.googleMapsApiLoaded) {
12505                if (typeof callback == "function") {
12506                    callback();
12507                }
12508                return;
12509            }
12510            MapSVG.googleMapsLoadCallbacks = MapSVG.googleMapsLoadCallbacks || [];
12511            if (typeof callback == "function") {
12512                MapSVG.googleMapsLoadCallbacks.push(callback);
12513            }
12514            if (MapSVG.googleMapsApiIsLoading) {
12515                return;
12516            }
12517            MapSVG.googleMapsApiIsLoading = true;
12518            window.gm_authFailure = () => {
12519                if (MapSVG.GoogleMapBadApiKey) {
12520                    MapSVG.GoogleMapBadApiKey();
12521                }
12522                else {
12523                    if (this.editMode) {
12524                        alert("Google maps API key is incorrect.");
12525                    }
12526                    else {
12527                        console.error("MapSVG: Google maps API key is incorrect.");
12528                    }
12529                }
12530            };
12531            this.googleMapsScript = document.createElement("script");
12532            this.googleMapsScript.onload = () => {
12533                MapSVG.googleMapsApiLoaded = true;
12534                MapSVG.googleMapsLoadCallbacks.forEach((_callback) => {
12535                    if (typeof callback == "function")
12536                        _callback();
12537                });
12538            };
12539            const gmLibraries = [];
12540            if (this.options.googleMaps.drawingTools) {
12541                gmLibraries.push("drawing");
12542            }
12543            if (this.options.googleMaps.geometry) {
12544                gmLibraries.push("geometry");
12545            }
12546            let libraries = "";
12547            if (gmLibraries.length > 0) {
12548                libraries = "&libraries=" + gmLibraries.join(",");
12549            }
12550            this.googleMapsScript.src =
12551                "https://maps.googleapis.com/maps/api/js?language=en&key=" +
12552                    this.options.googleMaps.apiKey +
12553                    libraries;
12554            document.head.appendChild(this.googleMapsScript);
12555        }
12556        loadDetailsView(obj) {
12557            this.controllers.popover && this.controllers.popover.close();
12558            if (this.controllers.detailsView)
12559                this.controllers.detailsView.destroy();
12560            this.controllers.detailsView = new DetailsController({
12561                autoresize: MapSVG.isPhone &&
12562                    this.options.detailsView.mobileFullscreen &&
12563                    this.options.detailsView.location !== "custom"
12564                    ? false
12565                    : this.options.detailsView.autoresize,
12566                container: this.containers.detailsView,
12567                template: obj instanceof Region
12568                    ? this.options.templates.detailsViewRegion
12569                    : this.options.templates.detailsView,
12570                mapsvg: this,
12571                data: obj.getData(),
12572                modal: MapSVG.isPhone &&
12573                    this.options.detailsView.mobileFullscreen &&
12574                    this.options.detailsView.location !== "custom",
12575                scrollable: (MapSVG.isPhone &&
12576                    this.options.detailsView.mobileFullscreen &&
12577                    this.options.detailsView.location !== "custom") ||
12578                    this.shouldBeScrollable(this.options.detailsView.location),
12579                withToolbar: !(MapSVG.isPhone &&
12580                    this.options.detailsView.mobileFullscreen &&
12581                    this.options.detailsView.location !== "custom") && this.shouldBeScrollable(this.options.detailsView.location),
12582                events: {
12583                    shown: (detailsController) => {
12584                        this.events.trigger("shown.detailsView", this, [this, detailsController]);
12585                        $$A(window).trigger("shown.detailsView", [this, detailsController]);
12586                    },
12587                    closed: (detailsController) => {
12588                        this.deselectAllRegions();
12589                        this.deselectAllMarkers();
12590                        this.controllers &&
12591                            this.controllers.directory &&
12592                            this.controllers.directory.deselectItems();
12593                        this.events.trigger("closed.detailsView", [this, detailsController]);
12594                    },
12595                },
12596            });
12597            this.controllers.detailsView._init();
12598        }
12599        loadFiltersModal() {
12600            if (this.options.filters.modalLocation != "custom") {
12601                if (!this.containers.filtersModal) {
12602                    this.containers.filtersModal = $$A('<div class="mapsvg-details-container mapsvg-filters-wrap"></div>')[0];
12603                }
12604                this.setColors();
12605                $$A(this.containers.filtersModal).css({ width: this.options.filters.width });
12606                if (MapSVG.isPhone) {
12607                    $$A("body").append($$A(this.containers.filtersModal));
12608                    $$A(this.containers.filtersModal).css({ width: "" });
12609                }
12610                else {
12611                    $$A(this.containers[this.options.filters.modalLocation]).append($$A(this.containers.filtersModal));
12612                }
12613            }
12614            else {
12615                this.containers.filtersModal = $$A("#" + this.options.filters.containerId)[0];
12616                $$A(this.containers.filtersModal).css({ width: "" });
12617            }
12618            this.loadFiltersController(this.containers.filtersModal, true);
12619        }
12620        loadFiltersController(container, modal = false) {
12621            if (this.filtersSchema.getFields().length === 0) {
12622                return;
12623            }
12624            let filtersInDirectory, filtersHide;
12625            if (MapSVG.isPhone) {
12626                filtersInDirectory = true;
12627                filtersHide = this.options.filters.hideOnMobile;
12628            }
12629            else {
12630                filtersInDirectory =
12631                    this.options.menu.on &&
12632                        this.controllers.directory &&
12633                        this.options.menu.location === this.options.filters.location;
12634                filtersHide = this.options.filters.hide;
12635            }
12636            const scrollable = modal ||
12637                (!filtersInDirectory &&
12638                    ["leftSidebar", "rightSidebar"].indexOf(this.options.filters.location) !== -1);
12639            this.filtersRepository =
12640                this.options.filters.source === "regions"
12641                    ? this.regionsRepository
12642                    : this.objectsRepository;
12643            if (this.options.filters.searchButton) {
12644                this.changedFields = null;
12645                this.changedSearch = null;
12646            }
12647            else {
12648                this.changedSearch = () => {
12649                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
12650                };
12651                this.changedFields = () => {
12652                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
12653                };
12654            }
12655            if (this.options.filters.searchButton) {
12656                this.changedFields = null;
12657                this.changedSearch = null;
12658            }
12659            else {
12660                this.changedSearch = () => {
12661                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
12662                };
12663                this.changedFields = () => {
12664                    this.throttle(this.filtersRepository.reload, 400, this.filtersRepository);
12665                };
12666            }
12667            this.controllers.filters = new FiltersController({
12668                container: container,
12669                query: this.filtersRepository.query,
12670                mapsvg: this,
12671                schema: this.filtersSchema,
12672                template: '<div class="mapsvg-filters-container"></div>',
12673                scrollable: scrollable,
12674                modal: modal,
12675                withToolbar: MapSVG.isPhone ? false : modal,
12676                width: $$A(container).hasClass("mapsvg-map-container")
12677                    ? this.options.filters.width
12678                    : "100%",
12679                hide: this.options.filters.hide,
12680                hideOnMobile: this.options.filters.hideOnMobile,
12681                showButtonText: this.options.filters.showButtonText,
12682                clearButton: this.options.filters.clearButton,
12683                clearButtonText: this.options.filters.clearButtonText,
12684                searchButton: this.options.filters.searchButton,
12685                searchButtonText: this.options.filters.searchButtonText,
12686                padding: this.options.filters.padding,
12687                events: {
12688                    "cleared.fields": () => {
12689                        this.deselectAllRegions();
12690                    },
12691                    "changed.fields": this.changedFields,
12692                    "changed.search": this.changedSearch,
12693                    "click.btn.searchButton": () => {
12694                        this.filtersRepository.reload();
12695                    },
12696                    loaded: () => {
12697                        this.controllers.directory && this.controllers.directory.updateTopShift();
12698                    },
12699                    "click.btn.showFilters": () => {
12700                        this.loadFiltersModal();
12701                    },
12702                },
12703            });
12704            this.controllers.filters._init();
12705        }
12706        textSearch(text, fallback = false) {
12707            const query = new Query({
12708                filters: { search: text },
12709                searchFallback: fallback,
12710            });
12711            this.filtersRepository.find(query);
12712        }
12713        getRegion(id) {
12714            return this.regions.findById(id);
12715        }
12716        getRegions() {
12717            return this.regions;
12718        }
12719        getMarker(id) {
12720            return this.markers.findById(id);
12721        }
12722        checkId(id) {
12723            if (this.getRegion(id))
12724                return { canUse: false, error: "This ID is already being used by a Region" };
12725            else if (this.getMarker(id))
12726                return { canUse: false, error: "This ID is already being used by another Marker" };
12727            else
12728                return { canUse: true, error: "" };
12729        }
12730        regionsRedrawColors() {
12731            this.regions.forEach((region) => {
12732                region.setFill();
12733            });
12734        }
12735        redrawBubbles() {
12736            $$A(this.containers.map).removeClass("bubbles-regions-on bubbles-database-on");
12737            if (this.options.choropleth.on && this.options.choropleth.bubbleMode) {
12738                $$A(this.containers.map).addClass("bubbles-" + this.options.choropleth.source + "-on");
12739            }
12740            this.regions.forEach(function (region) {
12741                region.drawBubble();
12742            });
12743            const markersBubbleMode = this.options.choropleth.on &&
12744                this.options.choropleth.source == "database" &&
12745                this.options.choropleth.bubbleMode;
12746            this.markers.forEach(function (marker) {
12747                marker.setBubbleMode(markersBubbleMode);
12748            });
12749        }
12750        destroy() {
12751            if (this.controllers && this.controllers.directory) {
12752                this.controllers.directory.mobileButtons.remove();
12753            }
12754            $$A(this.containers.map)
12755                .empty()
12756                .insertBefore($$A(this.containers.wrapAll))
12757                .attr("style", "")
12758                .removeClass("mapsvg mapsvg-responsive");
12759            this.controllers.popover && this.controllers.popover.close();
12760            if (this.controllers.detailsView)
12761                this.controllers.detailsView.destroy();
12762            $$A(this.containers.wrapAll).remove();
12763        }
12764        getData() {
12765            return {
12766                id: this.id,
12767                title: this.options.title,
12768                options: this.getOptions(false, false),
12769            };
12770        }
12771        mayBeFitMarkers() {
12772            if (!this.lastTimeFitWas) {
12773                this.lastTimeFitWas = Date.now() - 99999;
12774            }
12775            this.fitDelta = Date.now() - this.lastTimeFitWas;
12776            if (this.fitDelta > 1000 &&
12777                !this.firstDataLoad &&
12778                !this.fitOnDataLoadDone &&
12779                this.options.fitMarkers) {
12780                this.fitMarkers();
12781                this.fitOnDataLoadDone = true;
12782            }
12783            if (this.firstDataLoad &&
12784                (this.options.fitMarkersOnStart ||
12785                    (this.options.fitMarkers && this.options.database.loadOnStart === false))) {
12786                this.firstDataLoad = false;
12787                if (this.options.googleMaps.on && !this.googleMaps.map) {
12788                    this.events.on("googleMapsLoaded", () => {
12789                        this.fitMarkers();
12790                    });
12791                }
12792                else {
12793                    this.fitMarkers();
12794                }
12795            }
12796            this.lastTimeFitWas = Date.now();
12797        }
12798        fitMarkers() {
12799            const dbObjects = this.objectsRepository.getLoaded();
12800            if (!dbObjects || dbObjects.length === 0) {
12801                return;
12802            }
12803            if (this.options.googleMaps.on && typeof google !== "undefined") {
12804                const lats = [];
12805                const lngs = [];
12806                if (dbObjects.length > 1) {
12807                    dbObjects.forEach((object) => {
12808                        if (object.location && object.location.geoPoint) {
12809                            lats.push(object.location.geoPoint.lat);
12810                            lngs.push(object.location.geoPoint.lng);
12811                        }
12812                    });
12813                    const minlat = Math.min.apply(null, lats), maxlat = Math.max.apply(null, lats);
12814                    const minlng = Math.min.apply(null, lngs), maxlng = Math.max.apply(null, lngs);
12815                    const bbox = new google.maps.LatLngBounds({ lat: minlat, lng: minlng }, { lat: maxlat, lng: maxlng });
12816                    this.googleMaps.map.fitBounds(bbox, 0);
12817                }
12818                else {
12819                    if (dbObjects[0].location &&
12820                        dbObjects[0].location.geoPoint.lat &&
12821                        dbObjects[0].location.geoPoint.lng) {
12822                        const coords = {
12823                            lat: dbObjects[0].location.geoPoint.lat,
12824                            lng: dbObjects[0].location.geoPoint.lng,
12825                        };
12826                        if (this.googleMaps.map) {
12827                            this.googleMaps.map.setCenter(coords);
12828                            this.googleMaps.map.setZoom(this.options.fitSingleMarkerZoom);
12829                        }
12830                    }
12831                }
12832            }
12833            else {
12834                if (this.options.clustering.on) {
12835                    const arr = [];
12836                    this.markersClusters.forEach((c) => {
12837                        arr.push(c);
12838                    });
12839                    this.markers.forEach((m) => {
12840                        arr.push(m);
12841                    });
12842                    this.zoomTo(arr);
12843                    return;
12844                }
12845                else {
12846                    this.zoomTo(this.markers);
12847                    return;
12848                }
12849            }
12850        }
12851        setFitSingleMarkerZoom(zoom) {
12852            this.options.fitSingleMarkerZoom = parseInt(zoom);
12853        }
12854        showUserLocation(callback) {
12855            this.getUserLocation((geoPoint) => {
12856                this.userLocation = null;
12857                this.userLocation = new Location({
12858                    geoPoint: geoPoint,
12859                    img: MapSVG.urls.root + "/markers/user-location.svg",
12860                });
12861                this.userLocationMarker && this.userLocationMarker.delete();
12862                this.userLocationMarker = new Marker({
12863                    location: this.userLocation,
12864                    mapsvg: this,
12865                    width: 15,
12866                    height: 15,
12867                });
12868                $$A(this.userLocationMarker.element).addClass("mapsvg-user-location");
12869                this.userLocationMarker.centered = true;
12870                this.getLayer("markers").append(this.userLocationMarker.element);
12871                this.userLocationMarker.adjustScreenPosition();
12872                callback && callback(this.userLocation);
12873            });
12874        }
12875        getUserLocation(callback) {
12876            if (navigator.geolocation) {
12877                navigator.geolocation.getCurrentPosition(function (position) {
12878                    const pos = new GeoPoint(position.coords.latitude, position.coords.longitude);
12879                    callback && callback(pos);
12880                });
12881            }
12882            else {
12883                return false;
12884            }
12885        }
12886        getScale() {
12887            const scale2 = this.containers.map.clientWidth / this.viewBox.width;
12888            return scale2 || 1;
12889        }
12890        getViewBox() {
12891            return this.viewBox;
12892        }
12893        viewBoxSetBySize(width, height) {
12894            this.setSize(width, height);
12895            this._viewBox.update(this.viewBoxGetBySize(width, height));
12896            this.setViewBox(this._viewBox);
12897            $$A(window).trigger("resize");
12898            this.setSize(width, height);
12899            this.setZoomLevels();
12900            return this.viewBox;
12901        }
12902        viewBoxGetBySize(width, height) {
12903            const new_ratio = width / height;
12904            const old_ratio = this.svgDefault.viewBox.width / this.svgDefault.viewBox.height;
12905            const vb = $$A.extend([], this.svgDefault.viewBox);
12906            if (new_ratio != old_ratio) {
12907                if (new_ratio > old_ratio) {
12908                    vb[2] = this.svgDefault.viewBox.height * new_ratio;
12909                    vb[0] = this.svgDefault.viewBox.x - (vb[2] - this.svgDefault.viewBox.width) / 2;
12910                }
12911                else {
12912                    vb[3] = this.svgDefault.viewBox.width / new_ratio;
12913                    vb[1] = this.svgDefault.viewBox.y - (vb[3] - this.svgDefault.viewBox.height) / 2;
12914                }
12915            }
12916            return vb;
12917        }
12918        viewBoxReset(toInitial) {
12919            if (this.options.googleMaps.on && this.googleMaps.map) {
12920                if (!toInitial) {
12921                    this.options.googleMaps.center = null;
12922                    this.options.googleMaps.zoom = null;
12923                }
12924                if (!this.options.googleMaps.center || !this.options.googleMaps.zoom) {
12925                    const southWest = new google.maps.LatLng(this.geoViewBox.sw.lat, this.geoViewBox.sw.lng);
12926                    const northEast = new google.maps.LatLng(this.geoViewBox.ne.lat, this.geoViewBox.ne.lng);
12927                    const bounds = new google.maps.LatLngBounds(southWest, northEast);
12928                    this.googleMaps.map.fitBounds(bounds, 0);
12929                    this.options.googleMaps.center = this.googleMaps.map.getCenter().toJSON();
12930                    this.options.googleMaps.zoom = this.googleMaps.map.getZoom();
12931                }
12932                else {
12933                    this.googleMaps.map.setZoom(this.options.googleMaps.zoom);
12934                    this.googleMaps.map.setCenter(this.options.googleMaps.center);
12935                }
12936            }
12937            else {
12938                if (toInitial) {
12939                    const v = this._viewBox || this.svgDefault.viewBox;
12940                    this.zoomLevel = 0;
12941                    this._scale = 1;
12942                    this.setViewBox(v);
12943                }
12944                else {
12945                    this.setViewBox();
12946                }
12947            }
12948            return this.viewBox;
12949        }
12950        getGeoViewBox() {
12951            const v = this.viewBox;
12952            const p1 = new SVGPoint(v.x, v.y);
12953            const p2 = new SVGPoint(v.x + v.width, v.y);
12954            const p3 = new SVGPoint(v.x, v.y);
12955            const p4 = new SVGPoint(v.x, v.y + v.height);
12956            const leftLon = this.converter.convertSVGToGeo(p1).lng;
12957            const rightLon = this.converter.convertSVGToGeo(p2).lng;
12958            const topLat = this.converter.convertSVGToGeo(p3).lat;
12959            const bottomLat = this.converter.convertSVGToGeo(p4).lat;
12960            return [leftLon, topLat, rightLon, bottomLat];
12961        }
12962        mapAdjustStrokes() {
12963            this.regions.forEach((region) => region.adjustStroke(this.scale));
12964        }
12965        zoomIn(center) {
12966            if (this.canZoom) {
12967                this.isZooming = true;
12968                this.canZoom = false;
12969                setTimeout(() => {
12970                    this.isZooming = false;
12971                    this.canZoom = true;
12972                }, 700);
12973                this.zoom(1, center);
12974            }
12975        }
12976        zoomOut(center) {
12977            if (this.canZoom) {
12978                this.isZooming = true;
12979                this.canZoom = false;
12980                setTimeout(() => {
12981                    this.isZooming = false;
12982                    this.canZoom = true;
12983                }, 700);
12984                this.zoom(-1, center);
12985            }
12986        }
12987        zoomTo(mapObjects, zoomToLevel) {
12988            const convertedObjects = !Array.isArray(mapObjects) ? [mapObjects] : mapObjects;
12989            const bbox = this.getGroupBBox(convertedObjects);
12990            return this.fitViewBox(bbox, zoomToLevel);
12991        }
12992        getGroupBBox(mapObjects) {
12993            let _bbox;
12994            const xmax = [];
12995            const ymax = [];
12996            const xmin = [];
12997            const ymin = [];
12998            for (let i = 0; i < mapObjects.length; i++) {
12999                _bbox = mapObjects[i].getBBox();
13000                xmin.push(_bbox.x);
13001                ymin.push(_bbox.y);
13002                const _w = _bbox.x + _bbox.width;
13003                const _h = _bbox.y + _bbox.height;
13004                xmax.push(_w);
13005                ymax.push(_h);
13006            }
13007            const _xmin = Math.min(...xmin);
13008            const _ymin = Math.min(...ymin);
13009            const width = Math.max(...xmax) - _xmin;
13010            const height = Math.max(...ymax) - _ymin;
13011            let padding = 10;
13012            const point1 = new ScreenPoint(padding, 0);
13013            const point2 = new ScreenPoint(0, 0);
13014            padding =
13015                this.converter.convertPixelToSVG(point1).x - this.converter.convertPixelToSVG(point2).x;
13016            return new ViewBox(_xmin - padding, _ymin - padding, width + padding * 2, height + padding * 2);
13017        }
13018        fitViewBox(fitViewBox, forceZoomLevel) {
13019            let viewBoxPrev;
13020            let foundZoomLevelNumber = 0;
13021            let foundZoomLevel;
13022            let newViewBox;
13023            this.zoomLevels.forEach((zoomLevel) => {
13024                if (viewBoxPrev && viewBoxPrev.x !== undefined) {
13025                    if (fitViewBox.fitsInViewBox(viewBoxPrev) &&
13026                        zoomLevel.viewBox.fitsInViewBox(fitViewBox, true)) {
13027                        foundZoomLevelNumber = forceZoomLevel ? forceZoomLevel : zoomLevel.zoomLevel;
13028                        foundZoomLevel = this.zoomLevels.get(foundZoomLevelNumber);
13029                        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);
13030                    }
13031                }
13032                viewBoxPrev = zoomLevel && zoomLevel.viewBox;
13033            });
13034            if (foundZoomLevel) {
13035                if (this.canZoom) {
13036                    this.isZooming = true;
13037                    this.canZoom = false;
13038                    setTimeout(() => {
13039                        this.isZooming = false;
13040                        this.canZoom = true;
13041                    }, 700);
13042                    this.zoomLevel = foundZoomLevelNumber;
13043                    this._scale = foundZoomLevel._scale;
13044                    this.setViewBox(newViewBox);
13045                    return true;
13046                }
13047            }
13048            else {
13049                return false;
13050            }
13051        }
13052        zoomToRegion(region, zoomToLevel) {
13053            this.fitViewBox(region.getBBox(), zoomToLevel);
13054            return true;
13055        }
13056        zoomToMarkerOrCluster(mapObject, zoomToLevel) {
13057            this.zoomLevel = zoomToLevel || 1;
13058            const vb = this.zoomLevels.get(this.zoomLevel).viewBox;
13059            const newViewBox = new ViewBox(mapObject.svgPoint.x - vb.width / 2, mapObject.svgPoint.y - vb.height / 2, vb.width, vb.height);
13060            this.setViewBox(newViewBox);
13061            this._scale = this.zoomLevels.get(this.zoomLevel)._scale;
13062        }
13063        centerOn(region, yShift) {
13064            if (this.options.googleMaps.on) {
13065                yShift = yShift ? (yShift + 12) / this.getScale() : 0;
13066                $$A(this.containers.map).addClass("scrolling");
13067                const latLng = region.getCenterLatLng(yShift);
13068                this.googleMaps.map.panTo(latLng);
13069                setTimeout(() => {
13070                    $$A(this.containers.map).removeClass("scrolling");
13071                }, 100);
13072            }
13073            else {
13074                yShift = yShift ? (yShift + 12) / this.getScale() : 0;
13075                const bbox = region.getBBox();
13076                const vb = this.viewBox;
13077                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);
13078                this.setViewBox(newViewBox);
13079            }
13080        }
13081        zoom(delta, center) {
13082            let newViewBox = new ViewBox(0, 0, 0, 0);
13083            const d = delta > 0 ? 1 : -1;
13084            if (!this.zoomLevels.get(this.zoomLevel + d))
13085                return;
13086            const newZoomLevel = this.zoomLevel + d;
13087            const zoomIn = d > 0;
13088            const zoomOut = d < 0;
13089            const zoomRange = this.getZoomRange();
13090            const isInZoomRange = this.zoomLevel >= zoomRange.min && this.zoomLevel <= zoomRange.max;
13091            const goingOutOfZoomRange = isInZoomRange && (newZoomLevel > zoomRange.max || newZoomLevel < zoomRange.min);
13092            const outOfRangeAndMovingAway = !isInZoomRange &&
13093                ((zoomIn && newZoomLevel > zoomRange.max) || (zoomOut && newZoomLevel < zoomRange.min));
13094            if (goingOutOfZoomRange || outOfRangeAndMovingAway) {
13095                return;
13096            }
13097            this.zoomLevel = newZoomLevel;
13098            const z = this.zoomLevels.get(this.zoomLevel);
13099            this._scale = z._scale;
13100            newViewBox = z.viewBox;
13101            let shift = [];
13102            if (center) {
13103                const koef = zoomIn ? 0.5 : -1;
13104                newViewBox.x = this.viewBox.x + (center.x - this.viewBox.x) * koef;
13105                newViewBox.y = this.viewBox.y + (center.y - this.viewBox.y) * koef;
13106            }
13107            else {
13108                shift = [
13109                    (this.viewBox.width - newViewBox.width) / 2,
13110                    (this.viewBox.height - newViewBox.height) / 2,
13111                ];
13112                newViewBox.x = this.viewBox.x + shift[0];
13113                newViewBox.y = this.viewBox.y + shift[1];
13114            }
13115            this.shiftViewBoxToScrollBoundaries(newViewBox);
13116            this.setViewBox(newViewBox);
13117        }
13118        toggleSvgLayerOnZoom() {
13119            if (this.options.googleMaps.on &&
13120                this.googleMaps.map &&
13121                this.options.zoom.hideSvg &&
13122                this.googleMaps.map.getZoom() >= this.options.zoom.hideSvgZoomLevel) {
13123                if (!$$A(this.containers.svg).hasClass("mapsvg-invisible")) {
13124                    $$A(this.containers.svg).animate({ opacity: 0 }, 400, "linear", () => {
13125                        $$A(this.containers.svg).addClass("mapsvg-invisible");
13126                    });
13127                }
13128            }
13129            else {
13130                if ($$A(this.containers.svg).hasClass("mapsvg-invisible")) {
13131                    $$A(this.containers.svg).animate({ opacity: 1 }, 400, "linear", () => {
13132                        $$A(this.containers.svg).removeClass("mapsvg-invisible");
13133                    });
13134                }
13135            }
13136        }
13137        shiftViewBoxToScrollBoundaries(newViewBox) {
13138            if (this.options.scroll.limit) {
13139                if (newViewBox.x < this.svgDefault.viewBox.x)
13140                    newViewBox.x = this.svgDefault.viewBox.x;
13141                else if (newViewBox.x + newViewBox.width >
13142                    this.svgDefault.viewBox.x + this.svgDefault.viewBox.width)
13143                    newViewBox.x =
13144                        this.svgDefault.viewBox.x + this.svgDefault.viewBox.width - newViewBox.width;
13145                if (newViewBox.y < this.svgDefault.viewBox.y)
13146                    newViewBox.y = this.svgDefault.viewBox.y;
13147                else if (newViewBox.y + newViewBox.height >
13148                    this.svgDefault.viewBox.y + this.svgDefault.viewBox.height)
13149                    newViewBox.y =
13150                        this.svgDefault.viewBox.y + this.svgDefault.viewBox.height - newViewBox.height;
13151            }
13152            return newViewBox;
13153        }
13154        markerDelete(marker) {
13155            if (this.editingMarker && this.editingMarker.id == marker.id) {
13156                this.unsetEditingMarker();
13157            }
13158            if (this.markers.findById(marker.id)) {
13159                this.markers.delete(marker.id);
13160            }
13161            marker.delete();
13162            marker = null;
13163            if (this.markers.length === 0)
13164                this.options.markerLastID = 0;
13165        }
13166        markersClusterAdd(markersCluster) {
13167            this.layers.markers.append(markersCluster.elem);
13168            this.markersClusters.push(markersCluster);
13169            markersCluster.adjustScreenPosition();
13170        }
13171        markerAdd(marker) {
13172            $$A(marker.element).hide();
13173            marker.adjustScreenPosition();
13174            this.layers.markers.append(marker.element);
13175            this.markers.push(marker);
13176            marker.mapped = true;
13177            setTimeout(function () {
13178                $$A(marker.element).show();
13179            }, 100);
13180        }
13181        markerRemove(marker) {
13182            if (this.editingMarker && this.editingMarker.id == marker.id) {
13183                this.editingMarker = null;
13184                delete this.editingMarker;
13185            }
13186            if (this.markers.findById(marker.id)) {
13187                this.markers.findById(marker.id).element.remove();
13188                this.markers.delete(marker.id);
13189                marker = null;
13190            }
13191            if (this.markers.length === 0)
13192                this.options.markerLastID = 0;
13193        }
13194        markerId() {
13195            this.options.markerLastID = this.options.markerLastID + 1;
13196            const id = "marker_" + this.options.markerLastID;
13197            if (this.getMarker(id))
13198                return this.markerId();
13199            else
13200                return id;
13201        }
13202        movingItemsAdjustScreenPosition() {
13203            this.markersAdjustScreenPosition();
13204            this.popoverAdjustScreenPosition();
13205            this.bubblesRegionsAdjustScreenPosition();
13206            this.labelsRegionsAdjustScreenPosition();
13207        }
13208        movingItemsMoveScreenPositionBy(deltaX, deltaY) {
13209            this.markersMoveScreenPositionBy(deltaX, deltaY);
13210            this.popoverMoveScreenPositionBy(deltaX, deltaY);
13211            this.bubblesRegionsMoveScreenPositionBy(deltaX, deltaY);
13212            this.labelsRegionsMoveScreenPositionBy(deltaX, deltaY);
13213        }
13214        labelsRegionsAdjustScreenPosition() {
13215            if ($$A(this.containers.map).is(":visible")) {
13216                this.regions.forEach(function (region) {
13217                    region.adjustLabelScreenPosition();
13218                });
13219            }
13220        }
13221        bubblesRegionsAdjustScreenPosition() {
13222            if ($$A(this.containers.map).is(":visible")) {
13223                this.regions.forEach(function (region) {
13224                    region.adjustBubbleScreenPosition();
13225                });
13226            }
13227        }
13228        labelsRegionsMoveScreenPositionBy(deltaX, deltaY) {
13229            if ($$A(this.containers.map).is(":visible")) {
13230                this.regions.forEach(function (region) {
13231                    region.moveLabelScreenPositionBy(deltaX, deltaY);
13232                });
13233            }
13234        }
13235        bubblesRegionsMoveScreenPositionBy(deltaX, deltaY) {
13236            if ($$A(this.containers.map).is(":visible")) {
13237                this.regions.forEach((region) => {
13238                    region.moveBubbleScreenPositionBy(deltaX, deltaY);
13239                });
13240            }
13241        }
13242        markersAdjustScreenPosition() {
13243            this.markers.forEach((marker) => {
13244                marker.adjustScreenPosition();
13245            });
13246            this.markersClusters.forEach((cluster) => {
13247                cluster.adjustScreenPosition();
13248            });
13249            if (this.userLocationMarker) {
13250                this.userLocationMarker.adjustScreenPosition();
13251            }
13252        }
13253        markersMoveScreenPositionBy(deltaX, deltaY) {
13254            this.markers.forEach((marker) => {
13255                marker.moveSrceenPositionBy(deltaX, deltaY);
13256            });
13257            this.markersClusters.forEach((cluster) => {
13258                cluster.moveSrceenPositionBy(deltaX, deltaY);
13259            });
13260            if (this.userLocationMarker) {
13261                this.userLocationMarker.moveSrceenPositionBy(deltaX, deltaY);
13262            }
13263        }
13264        setEditingMarker(marker) {
13265            this.editingMarker = marker;
13266            if (!this.editingMarker.mapped) {
13267                this.editingMarker.needToRemove = true;
13268                this.markerAdd(this.editingMarker);
13269            }
13270        }
13271        unsetEditingMarker() {
13272            if (this.editingMarker && this.editingMarker.needToRemove) {
13273                this.markerRemove(this.editingMarker);
13274            }
13275            this.editingMarker = null;
13276        }
13277        getEditingMarker() {
13278            return this.editingMarker;
13279        }
13280        scrollStart(e, mapsvg) {
13281            if ($$A(e.target).hasClass("mapsvg-btn-map") ||
13282                $$A(e.target).closest(".mapsvg-choropleth").length)
13283                return;
13284            if (this.editMarkers.on && $$A(e.target).hasClass("mapsvg-marker"))
13285                return;
13286            e.preventDefault();
13287            $$A(this.containers.map).addClass("no-transitions");
13288            const ce = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]
13289                ? e.originalEvent.touches[0]
13290                : e;
13291            this.scrollStarted = true;
13292            this.scroll = {
13293                tx: this.scroll.tx || 0,
13294                ty: this.scroll.ty || 0,
13295                vxi: this.viewBox.x,
13296                vyi: this.viewBox.y,
13297                x: ce.clientX,
13298                y: ce.clientY,
13299                dx: 0,
13300                dy: 0,
13301                vx: 0,
13302                vy: 0,
13303                gx: ce.clientX,
13304                gy: ce.clientY,
13305                touchScrollStart: 0,
13306            };
13307            if (e.type.indexOf("mouse") === 0) {
13308                $$A(document).on("mousemove.scroll.mapsvg", (e) => {
13309                    this.scrollMove(e);
13310                });
13311                if (this.options.scroll.spacebar) {
13312                    $$A(document).on("keyup.scroll.mapsvg", (e) => {
13313                        if (e.keyCode == 32) {
13314                            this.scrollEnd(e, mapsvg);
13315                        }
13316                    });
13317                }
13318                else {
13319                    $$A(document).on("mouseup.scroll.mapsvg", (e) => {
13320                        this.scrollEnd(e, mapsvg);
13321                    });
13322                }
13323            }
13324        }
13325        scrollMove(e) {
13326            e.preventDefault();
13327            if (!this.isScrolling) {
13328                this.isScrolling = true;
13329                $$A(this.containers.map).addClass("scrolling");
13330            }
13331            const ce = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0]
13332                ? e.originalEvent.touches[0]
13333                : e;
13334            this.panBy(this.scroll.gx - ce.clientX, this.scroll.gy - ce.clientY);
13335            this.scroll.gx = ce.clientX;
13336            this.scroll.gy = ce.clientY;
13337            this.scroll.dx = this.scroll.x - ce.clientX;
13338            this.scroll.dy = this.scroll.y - ce.clientY;
13339            let vx = this.scroll.vxi + this.scroll.dx / this.scale;
13340            let vy = this.scroll.vyi + this.scroll.dy / this.scale;
13341            if (this.options.scroll.limit) {
13342                if (vx < this.svgDefault.viewBox.x)
13343                    vx = this.svgDefault.viewBox.x;
13344                else if (this.viewBox.width + vx >
13345                    this.svgDefault.viewBox.x + this.svgDefault.viewBox.width)
13346                    vx = this.svgDefault.viewBox.x + this.svgDefault.viewBox.width - this.viewBox.width;
13347                if (vy < this.svgDefault.viewBox.y)
13348                    vy = this.svgDefault.viewBox.y;
13349                else if (this.viewBox.height + vy >
13350                    this.svgDefault.viewBox.y + this.svgDefault.viewBox.height)
13351                    vy =
13352                        this.svgDefault.viewBox.y +
13353                            this.svgDefault.viewBox.height -
13354                            this.viewBox.height;
13355            }
13356            this.scroll.vx = vx;
13357            this.scroll.vy = vy;
13358        }
13359        scrollEnd(e, mapsvg, noClick) {
13360            setTimeout(() => {
13361                this.enableTransitions();
13362                this.scrollStarted = false;
13363                this.isScrolling = false;
13364            }, 100);
13365            if (this.googleMaps && this.googleMaps.overlay) {
13366                this.googleMaps.overlay.draw();
13367            }
13368            $$A(this.containers.map).removeClass("scrolling");
13369            $$A(document).off("keyup.scroll.mapsvg");
13370            $$A(document).off("mousemove.scroll.mapsvg");
13371            $$A(document).off("mouseup.scroll.mapsvg");
13372            if (noClick !== true && Math.abs(this.scroll.dx) < 5 && Math.abs(this.scroll.dy) < 5) {
13373                if (this.editMarkers.on)
13374                    this.clickAddsMarker && this.markerAddClickHandler(e);
13375                else if (this.objectClickedBeforeScroll)
13376                    if (this.objectClickedBeforeScroll instanceof Marker) {
13377                        this.markerClickHandler(e, this.objectClickedBeforeScroll);
13378                    }
13379                    else if (this.objectClickedBeforeScroll instanceof Region) {
13380                        this.regionClickHandler(e, this.objectClickedBeforeScroll);
13381                    }
13382                    else if (this.objectClickedBeforeScroll instanceof MarkerCluster) {
13383                        this.markerClusterClickHandler(e, this.objectClickedBeforeScroll);
13384                    }
13385            }
13386            this.viewBox.x = this.scroll.vx || this.viewBox.x;
13387            this.viewBox.y = this.scroll.vy || this.viewBox.y;
13388        }
13389        setViewBoxByGoogleMapsOverlay() {
13390            const bounds = this.googleMaps.overlay.getPixelBounds();
13391            const scale = (bounds.ne.x - bounds.sw.x) / this.svgDefault.viewBox.width;
13392            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);
13393            this.setViewBox(vb, false);
13394        }
13395        panBy(x, y) {
13396            let tx = this.scroll.tx - x;
13397            let ty = this.scroll.ty - y;
13398            const scrolled = { x: true, y: true };
13399            if (this.options.scroll.limit) {
13400                const svg = $$A(this.containers.svg)[0].getBoundingClientRect();
13401                const bounds = $$A(this.containers.map)[0].getBoundingClientRect();
13402                if ((svg.left - x > bounds.left && x < 0) || (svg.right - x < bounds.right && x > 0)) {
13403                    tx = this.scroll.tx;
13404                    scrolled.x = false;
13405                }
13406                if ((svg.top - y > bounds.top && y < 0) || (svg.bottom - y < bounds.bottom && y > 0)) {
13407                    ty = this.scroll.ty;
13408                    scrolled.y = false;
13409                }
13410            }
13411            $$A(this.containers.scrollpane).css({
13412                transform: "translate(" + tx + "px," + ty + "px)",
13413            });
13414            this.scroll.tx = tx;
13415            this.scroll.ty = ty;
13416            if (scrolled.x || scrolled.y) {
13417                const moveX = scrolled.x ? x : 0;
13418                const moveY = scrolled.y ? y : 0;
13419                this.movingItemsMoveScreenPositionBy(moveX, moveY);
13420                if (this.googleMaps.map) {
13421                    let point = this.googleMaps.map.getCenter();
13422                    const projection = this.googleMaps.overlay.getProjection();
13423                    const pixelpoint = projection.fromLatLngToDivPixel(point);
13424                    pixelpoint.x += moveX;
13425                    pixelpoint.y += moveY;
13426                    point = projection.fromDivPixelToLatLng(pixelpoint);
13427                    this.googleMaps.map.setCenter(point);
13428                }
13429            }
13430            return scrolled;
13431        }
13432        setObjectClickedBeforeScroll(object) {
13433            this.objectClickedBeforeScroll = object;
13434        }
13435        touchStart(_e, mapsvg) {
13436            _e.preventDefault();
13437            if (this.scrollStarted) {
13438                this.scrollEnd(_e, mapsvg, true);
13439            }
13440            const e = _e.originalEvent;
13441            if (this.options.zoom.fingers && e.touches && e.touches.length == 2) {
13442                this.touchZoomStart = true;
13443                this.scaleDistStart = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY);
13444            }
13445            else if (e.touches && e.touches.length == 1) {
13446                this.scrollStart(_e, mapsvg);
13447            }
13448            $$A(document)
13449                .on("touchmove.scroll.mapsvg", (e) => {
13450                e.preventDefault();
13451                this.touchMove(e, this);
13452            })
13453                .on("touchend.scroll.mapsvg", (e) => {
13454                e.preventDefault();
13455                this.touchEnd(e, this);
13456            });
13457        }
13458        touchMove(_e, mapsvg) {
13459            _e.preventDefault();
13460            const e = _e.originalEvent;
13461            if (this.options.zoom.fingers && e.touches && e.touches.length == 2) {
13462                if (!MapSVG.ios) {
13463                    e.scale =
13464                        Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY) / this.scaleDistStart;
13465                }
13466                if (e.scale != 1 && this.canZoom) {
13467                    const d = e.scale > 1 ? 1 : -1;
13468                    const cx = e.touches[0].pageX >= e.touches[1].pageX
13469                        ? e.touches[0].pageX -
13470                            (e.touches[0].pageX - e.touches[1].pageX) / 2 -
13471                            $$A(this.containers.map).offset().left
13472                        : e.touches[1].pageX -
13473                            (e.touches[1].pageX - e.touches[0].pageX) / 2 -
13474                            $$A(this.containers.map).offset().left;
13475                    const cy = e.touches[0].pageY >= e.touches[1].pageY
13476                        ? e.touches[0].pageY -
13477                            (e.touches[0].pageY - e.touches[1].pageY) -
13478                            $$A(this.containers.map).offset().top
13479                        : e.touches[1].pageY -
13480                            (e.touches[1].pageY - e.touches[0].pageY) -
13481                            $$A(this.containers.map).offset().top;
13482                    const center = this.converter.convertPixelToSVG(new ScreenPoint(cx, cy));
13483                    if (d > 0)
13484                        this.zoomIn(center);
13485                    else
13486                        this.zoomOut(center);
13487                }
13488            }
13489            else if (e.touches && e.touches.length == 1) {
13490                this.scrollMove(_e);
13491            }
13492        }
13493        touchEnd(_e, mapsvg) {
13494            _e.preventDefault();
13495            const e = _e.originalEvent;
13496            if (this.touchZoomStart) {
13497                this.touchZoomStart = false;
13498            }
13499            else if (this.scrollStarted) {
13500                this.scrollEnd(_e, mapsvg);
13501            }
13502            $$A(document).off("touchmove.scroll.mapsvg");
13503            $$A(document).off("touchend.scroll.mapsvg");
13504        }
13505        getSelected() {
13506            return this.selected_id;
13507        }
13508        selectRegion(id, skipDirectorySelection) {
13509            let region;
13510            if (typeof id == "string") {
13511                region = this.getRegion(id);
13512            }
13513            else {
13514                region = id;
13515            }
13516            if (!region)
13517                return;
13518            let ids;
13519            if (this.options.multiSelect && !this.editRegions.on) {
13520                if (region.selected) {
13521                    this.deselectRegion(region);
13522                    if (!skipDirectorySelection && this.options.menu.on) {
13523                        if (this.options.menu.source == "database") {
13524                            if (region.objects && region.objects.length) {
13525                                ids = region.objects.map((obj) => {
13526                                    return obj.id.toString();
13527                                });
13528                            }
13529                        }
13530                        else {
13531                            ids = [region.id];
13532                        }
13533                        this.controllers.directory.deselectItems();
13534                    }
13535                    return;
13536                }
13537            }
13538            else if (this.selected_id.length > 0) {
13539                this.deselectAllRegions();
13540                if (!skipDirectorySelection && this.options.menu.on) {
13541                    if (this.options.menu.source == "database") {
13542                        if (region.objects && region.objects.length) {
13543                            ids = region.objects.map((obj) => {
13544                                return obj.id.toString();
13545                            });
13546                        }
13547                    }
13548                    else {
13549                        ids = [region.id];
13550                    }
13551                    this.controllers.directory.deselectItems();
13552                }
13553            }
13554            this.selected_id.push(region.id);
13555            region.select();
13556            const skip = this.options.actions.region.click.filterDirectory;
13557            if (!skip &&
13558                !skipDirectorySelection &&
13559                this.options.menu.on &&
13560                this.controllers &&
13561                this.controllers.directory) {
13562                if (this.options.menu.source == "database") {
13563                    if (region.objects && region.objects.length) {
13564                        ids = region.objects.map((obj) => {
13565                            return obj.id.toString();
13566                        });
13567                    }
13568                    else {
13569                        ids = [region.id];
13570                    }
13571                }
13572                else {
13573                    ids = [region.id];
13574                }
13575                this.controllers.directory.selectItems(ids);
13576            }
13577            if (this.options.actions.region.click.addIdToUrl &&
13578                !this.options.actions.region.click.showAnotherMap) {
13579                window.location.hash = "/m/" + region.id;
13580            }
13581        }
13582        deselectAllRegions() {
13583            $$A.each(this.selected_id, (index, id) => {
13584                this.deselectRegion(this.getRegion(id));
13585            });
13586        }
13587        deselectRegion(region) {
13588            if (!region)
13589                region = this.getRegion(this.selected_id[0]);
13590            if (region) {
13591                region.deselect();
13592                const i = $$A.inArray(region.id, this.selected_id);
13593                this.selected_id.splice(i, 1);
13594            }
13595            if (this.options.actions.region.click.addIdToUrl) {
13596                if (window.location.hash.indexOf(region.id) !== -1) {
13597                    history.replaceState(null, null, " ");
13598                }
13599            }
13600        }
13601        highlightRegions(regions) {
13602            regions.forEach((region) => {
13603                if (region && !region.selected && !region.disabled) {
13604                    this.highlightedRegions.push(region);
13605                    region.highlight();
13606                }
13607            });
13608        }
13609        unhighlightRegions() {
13610            this.highlightedRegions.forEach((region) => {
13611                if (region && !region.selected && !region.disabled)
13612                    region.unhighlight();
13613            });
13614            this.highlightedRegions = [];
13615        }
13616        selectMarker(marker) {
13617            if (!(marker instanceof Marker))
13618                return;
13619            this.deselectAllMarkers();
13620            marker.select();
13621            this.selected_marker = marker;
13622            $$A(this.layers.markers).addClass("mapsvg-with-marker-active");
13623            if (this.options.menu.on && this.options.menu.source == "database") {
13624                this.controllers.directory.deselectItems();
13625                this.controllers.directory.selectItems(marker.object.id);
13626            }
13627        }
13628        deselectAllMarkers() {
13629            this.selected_marker && this.selected_marker.deselect();
13630            $$A(this.layers.markers).removeClass("mapsvg-with-marker-active");
13631        }
13632        deselectMarker(marker) {
13633            if (marker) {
13634                marker.deselect();
13635            }
13636        }
13637        highlightMarker(marker) {
13638            $$A(this.layers.markers).addClass("mapsvg-with-marker-hover");
13639            marker.highlight();
13640            this.highlighted_marker = marker;
13641        }
13642        unhighlightMarker() {
13643            $$A(this.layers.markers).removeClass("mapsvg-with-marker-hover");
13644            this.highlighted_marker && this.highlighted_marker.unhighlight();
13645        }
13646        convertMouseToSVG(e) {
13647            const mc = MapSVG.mouseCoords(e);
13648            const x = mc.x - $$A(this.containers.map).offset().left;
13649            const y = mc.y - $$A(this.containers.map).offset().top;
13650            const screenPoint = new ScreenPoint(x, y);
13651            return this.converter.convertPixelToSVG(screenPoint);
13652        }
13653        pickChoroplethColor(choroplethValue) {
13654            const w = (choroplethValue - this.options.choropleth.coloring.gradient.values.min) /
13655                this.options.choropleth.coloring.gradient.values.maxAdjusted;
13656            const rgba = {
13657                r: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.r * w +
13658                    this.options.choropleth.coloring.gradient.colors.lowRGB.r),
13659                g: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.g * w +
13660                    this.options.choropleth.coloring.gradient.colors.lowRGB.g),
13661                b: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.b * w +
13662                    this.options.choropleth.coloring.gradient.colors.lowRGB.b),
13663                a: Math.round(this.options.choropleth.coloring.gradient.colors.diffRGB.a * w +
13664                    this.options.choropleth.coloring.gradient.colors.lowRGB.a),
13665            };
13666            return rgba;
13667        }
13668        isRegionDisabled(id, svgfill) {
13669            if (this.options.regions[id] && (this.options.regions[id].disabled || svgfill == "none")) {
13670                return true;
13671            }
13672            else if ((this.options.regions[id] == undefined ||
13673                MapSVG.parseBoolean(this.options.regions[id].disabled)) &&
13674                (this.options.disableAll || svgfill == "none" || id == "labels" || id == "Labels")) {
13675                return true;
13676            }
13677            else {
13678                return false;
13679            }
13680        }
13681        loadMap(id, container) {
13682            if (!(container instanceof HTMLElement)) {
13683                console.error("Can't load a new map: container was not provided.");
13684                return;
13685            }
13686            const previousMapsIds = [...this.options.previousMapsIds];
13687            const currentMapId = this.id;
13688            if (previousMapsIds[previousMapsIds.length - 1] !== id) {
13689                previousMapsIds.push(currentMapId);
13690            }
13691            else {
13692                previousMapsIds.pop();
13693            }
13694            let showPreviousMapButton;
13695            if (this.options.actions.region.click.region.showAnotherMapContainerId !== "undefined") {
13696                showPreviousMapButton = false;
13697            }
13698            else {
13699                showPreviousMapButton = this.options.controls.previousMap;
13700            }
13701            const mapsRepo = new MapsRepository();
13702            mapsRepo.findById(id).done((map) => {
13703                this.destroy();
13704                const newMap = new MapSVGMap(container.getAttribute("id"), map);
13705                newMap.options.previousMapsIds = previousMapsIds;
13706                newMap.options.controls.previousMap = showPreviousMapButton;
13707                newMap.setControls(newMap.options.controls);
13708            });
13709        }
13710        loadPreviousMap() {
13711            const previousMapId = this.options.previousMapsIds[this.options.previousMapsIds.length - 1];
13712            const container = document.getElementById(this.containerId);
13713            this.loadMap(previousMapId, container);
13714        }
13715        markerClusterClickHandler(e, markerCluster) {
13716            this.objectClickedBeforeScroll = null;
13717            if (this.eventsPreventList["click"])
13718                return;
13719            this.zoomTo(markerCluster.markers);
13720            return;
13721        }
13722        regionClickHandler(e, region) {
13723            this.objectClickedBeforeScroll = null;
13724            if (this.eventsPreventList["click"])
13725                return;
13726            this.selectRegion(region.id);
13727            if (this.editRegions.on) {
13728                this.regionEditHandler.call(region);
13729                return;
13730            }
13731            const actions = this.options.actions;
13732            if (actions.region.click.zoom) {
13733                this.zoomTo(region, parseInt(actions.region.click.zoomToLevel));
13734            }
13735            if (actions.region.click.filterDirectory) {
13736                const query = new Query({
13737                    filters: {
13738                        regions: {
13739                            table_name: this.regionsRepository.getSchema().name,
13740                            region_ids: [region.id],
13741                        },
13742                    },
13743                });
13744                this.objectsRepository.find(query).done(() => {
13745                    if (this.controllers.popover) {
13746                        this.controllers.popover.redraw(region.forTemplate());
13747                    }
13748                    if (this.controllers.detailsView) {
13749                        this.controllers.detailsView.redraw(region.forTemplate());
13750                    }
13751                });
13752                this.updateFiltersState();
13753            }
13754            if (actions.region.click.showDetails) {
13755                this.loadDetailsView(region);
13756            }
13757            if (actions.region.click.showPopover) {
13758                if (actions.region.click.zoom) {
13759                    setTimeout(() => {
13760                        this.showPopover(region);
13761                    }, 400);
13762                }
13763                else {
13764                    this.showPopover(region);
13765                }
13766            }
13767            else if (e && e.type.indexOf("touch") !== -1 && actions.region.touch.showPopover) {
13768                if (actions.region.click.zoom) {
13769                    setTimeout(() => {
13770                        this.showPopover(region);
13771                    }, 400);
13772                }
13773                else {
13774                    this.showPopover(region);
13775                }
13776            }
13777            if (actions.region.click.goToLink) {
13778                const linkParts = actions.region.click.linkField.split(".");
13779                let url;
13780                if (linkParts.length > 1) {
13781                    const obj = linkParts.shift();
13782                    const attr = "." + linkParts.join(".");
13783                    if (obj == "Region") {
13784                        if (region.data) {
13785                            try {
13786                                url = eval("region.data" + attr);
13787                            }
13788                            catch (err) {
13789                                console.log("No such field as region.data" + attr);
13790                            }
13791                        }
13792                    }
13793                    else {
13794                        if (region.objects && region.objects[0]) {
13795                            try {
13796                                url = eval("region.objects[0]" + attr);
13797                            }
13798                            catch (err) {
13799                                console.log("No such field as region.objects[0]" + attr);
13800                            }
13801                        }
13802                    }
13803                    if (url && !this.disableLinks) {
13804                        if (this.editMode) {
13805                            alert("Redirect: " + url + "\nLinks are disabled in the preview.");
13806                            return;
13807                        }
13808                        if (actions.region.click.newTab) {
13809                            const win = window.open(url, "_blank");
13810                            win.focus();
13811                        }
13812                        else {
13813                            window.location.href = url;
13814                        }
13815                    }
13816                }
13817            }
13818            if (actions.region.click.showAnotherMap) {
13819                if (this.editMode) {
13820                    alert('"Show another map" action is disabled in the preview');
13821                    return;
13822                }
13823                const linkParts = actions.region.click.showAnotherMapField.split(".");
13824                if (linkParts.length > 1) {
13825                    const obj = linkParts.shift();
13826                    const attr = "." + linkParts.join(".");
13827                    let map_id;
13828                    if (obj == "Region") {
13829                        if (region.data)
13830                            map_id = eval("region.data" + attr);
13831                    }
13832                    else {
13833                        if (region.objects && region.objects[0])
13834                            map_id = eval("region.objects[0]" + attr);
13835                    }
13836                    if (map_id) {
13837                        const container = actions.region.click.showAnotherMapContainerId
13838                            ? $$A("#" + actions.region.click.showAnotherMapContainerId)[0]
13839                            : $$A(this.containers.map)[0];
13840                        this.loadMap(map_id, container);
13841                    }
13842                }
13843            }
13844            this.events.trigger("click.region", region, [e, region, this]);
13845        }
13846        markerClickHandler(e, marker) {
13847            this.objectClickedBeforeScroll = null;
13848            if (this.eventsPreventList["click"])
13849                return;
13850            const actions = this.options.actions;
13851            this.selectMarker(marker);
13852            const passingObject = marker.object;
13853            if (actions.marker.click.zoom) {
13854                this.zoomTo(marker, parseInt(actions.marker.click.zoomToLevel));
13855            }
13856            if (actions.marker.click.filterDirectory) {
13857                const query = new Query({ filters: { id: marker.object.id } });
13858                this.objectsRepository.find(query);
13859                this.updateFiltersState();
13860            }
13861            if (actions.marker.click.showDetails)
13862                this.loadDetailsView(passingObject);
13863            if (actions.marker.click.showPopover) {
13864                if (actions.marker.click.zoom) {
13865                    setTimeout(() => {
13866                        this.showPopover(passingObject);
13867                    }, 500);
13868                }
13869                else {
13870                    this.showPopover(passingObject);
13871                }
13872            }
13873            else if (e && e.type.indexOf("touch") !== -1 && actions.marker.touch.showPopover) {
13874                if (actions.marker.click.zoom) {
13875                    setTimeout(() => {
13876                        this.showPopover(passingObject);
13877                    }, 500);
13878                }
13879                else {
13880                    this.showPopover(passingObject);
13881                }
13882            }
13883            if (actions.marker.click.goToLink) {
13884                const linkParts = actions.marker.click.linkField.split(".");
13885                let url;
13886                if (linkParts.length > 1) {
13887                    const obj = linkParts.shift();
13888                    const attr = "." + linkParts.join(".");
13889                    try {
13890                        url = eval("passingObject" + attr);
13891                    }
13892                    catch (err) {
13893                        console.log("MapSVG: No such field as passingObject" + attr);
13894                    }
13895                    if (url && !this.disableLinks)
13896                        if (this.editMode) {
13897                            alert("Redirect: " + url + "\nLinks are disabled in the preview.");
13898                            return;
13899                        }
13900                    if (actions.marker.click.newTab) {
13901                        const win = window.open(url, "_blank");
13902                        win.focus();
13903                    }
13904                    else {
13905                        window.location.href = url;
13906                    }
13907                }
13908            }
13909            this.events.trigger("click.marker", marker, [e, marker, this]);
13910        }
13911        fileExists(url) {
13912            if (url.substr(0, 4) == "data")
13913                return true;
13914            const http = new XMLHttpRequest();
13915            http.open("HEAD", url, false);
13916            http.send();
13917            return http.status != 404;
13918        }
13919        hideMarkers() {
13920            this.markers.forEach(function (marker) {
13921                marker.hide();
13922            });
13923            $$A(this.containers.wrap).addClass("mapsvg-edit-marker-mode");
13924        }
13925        hideMarkersExceptOne(id) {
13926            this.markers.forEach(function (marker) {
13927                if (typeof id === "undefined" || (marker.object && id != marker.object.id)) {
13928                    marker.hide();
13929                }
13930            });
13931            $$A(this.containers.wrap).addClass("mapsvg-edit-marker-mode");
13932        }
13933        showMarkers() {
13934            this.markers.forEach(function (m) {
13935                m.show();
13936            });
13937            this.deselectAllMarkers();
13938            $$A(this.containers.wrap).removeClass("mapsvg-edit-marker-mode");
13939        }
13940        markerAddClickHandler(e) {
13941            if ($$A(e.target).hasClass("mapsvg-marker"))
13942                return;
13943            const svgPoint = this.getSvgPointAtClick(e);
13944            const geoPoint = this.isGeo() ? this.converter.convertSVGToGeo(svgPoint) : null;
13945            if (!$$A.isNumeric(svgPoint.x) || !$$A.isNumeric(svgPoint.y))
13946                return;
13947            if (this.editingMarker) {
13948                if (geoPoint) {
13949                    this.editingMarker.location.setGeoPoint(geoPoint);
13950                }
13951                else {
13952                    this.editingMarker.location.setSvgPoint(svgPoint);
13953                }
13954                return;
13955            }
13956            const location = new Location({
13957                svgPoint: svgPoint,
13958                geoPoint: geoPoint,
13959                img: this.options.defaultMarkerImage,
13960            });
13961            const marker = new Marker({
13962                location: location,
13963                mapsvg: this,
13964            });
13965            this.markerAdd(marker);
13966            this.markerEditHandler && this.markerEditHandler.call(location, location);
13967        }
13968        getSvgPointAtClick(e) {
13969            const mc = MapSVG.mouseCoords(e);
13970            const x = mc.x - $$A(this.containers.map).offset().left;
13971            const y = mc.y - $$A(this.containers.map).offset().top;
13972            const screenPoint = new ScreenPoint(x, y);
13973            return this.converter.convertPixelToSVG(screenPoint);
13974        }
13975        setDefaultMarkerImage(src) {
13976            this.options.defaultMarkerImage = src;
13977        }
13978        setMarkerImagesDependency() {
13979            this.locationField = this.objectsRepository.schema.getFieldByType("location");
13980            if (this.locationField.markersByFieldEnabled &&
13981                this.locationField.markerField &&
13982                Object.values(this.locationField.markersByField).length > 0) {
13983                this.setMarkersByField = true;
13984            }
13985            else {
13986                this.setMarkersByField = false;
13987            }
13988        }
13989        getMarkerImage(fieldValueOrObject, location) {
13990            let fieldValue;
13991            if (this.setMarkersByField) {
13992                if (typeof fieldValueOrObject === "object") {
13993                    fieldValue = fieldValueOrObject[this.locationField.markerField];
13994                }
13995                else {
13996                    fieldValue = fieldValueOrObject;
13997                }
13998                if (this.locationField.markersByField[fieldValue]) {
13999                    return this.locationField.markersByField[fieldValue];
14000                }
14001            }
14002            return location && location.img
14003                ? location.img
14004                : this.options.defaultMarkerImage
14005                    ? this.options.defaultMarkerImage
14006                    : MapSVG.urls.root + "markers/_pin_default.png";
14007        }
14008        setMarkersEditMode(on, clickAddsMarker) {
14009            this.editMarkers.on = MapSVG.parseBoolean(on);
14010            this.clickAddsMarker = this.editMarkers.on;
14011            this.setEventHandlers();
14012        }
14013        setRegionsEditMode(on) {
14014            this.editRegions.on = MapSVG.parseBoolean(on);
14015            this.deselectAllRegions();
14016            this.setEventHandlers();
14017        }
14018        setEditMode(on) {
14019            this.editMode = on;
14020        }
14021        setDataEditMode(on) {
14022            this.editData.on = MapSVG.parseBoolean(on);
14023            this.deselectAllRegions();
14024            this.setEventHandlers();
14025        }
14026        popoverAdjustScreenPosition() {
14027            if (this.controllers.popover instanceof PopoverController) {
14028                this.controllers.popover.adjustScreenPosition();
14029            }
14030        }
14031        popoverMoveScreenPositionBy(deltaX, deltaY) {
14032            if (this.controllers.popover instanceof PopoverController) {
14033                this.controllers.popover.moveSrceenPositionBy(deltaX, deltaY);
14034            }
14035        }
14036        showPopover(object) {
14037            const mapObject = object instanceof Region
14038                ? object
14039                : object.location && object.location.marker
14040                    ? object.location.marker
14041                    : null;
14042            if (!mapObject)
14043                return;
14044            let point;
14045            if (mapObject instanceof Marker) {
14046                point = mapObject.svgPoint;
14047            }
14048            else {
14049                point = mapObject.getCenterSVG();
14050            }
14051            this.controllers.popover && this.controllers.popover.destroy();
14052            this.controllers.popover = new PopoverController({
14053                container: this.containers.popover,
14054                point: point,
14055                yShift: mapObject instanceof Marker ? mapObject.height : 0,
14056                template: object instanceof Region
14057                    ? this.options.templates.popoverRegion
14058                    : this.options.templates.popoverMarker,
14059                mapsvg: this,
14060                data: object.getData(),
14061                mapObject: mapObject,
14062                scrollable: true,
14063                withToolbar: !(MapSVG.isPhone && this.options.popovers.mobileFullscreen),
14064                events: {
14065                    shown: (popover) => {
14066                        if (this.options.popovers.centerOn) {
14067                            const shift = popover.containers.main.offsetHeight / 2;
14068                            if (this.options.popovers.centerOn &&
14069                                !(MapSVG.isPhone && this.options.popovers.mobileFullscreen)) {
14070                                this.centerOn(mapObject, shift);
14071                            }
14072                        }
14073                        this.popoverShowingFor = mapObject;
14074                        this.events.trigger("shown.popover", this, [this, popover]);
14075                        $$A(window).trigger("shown.popover", [this, popover]);
14076                    },
14077                    closed: (popover) => {
14078                        this.options.popovers.resetViewboxOnClose && this.viewBoxReset(true);
14079                        this.popoverShowingFor = null;
14080                        this.events.trigger("closed.popover", this, [this, popover]);
14081                    },
14082                    resize: (popover) => {
14083                        if (this.options.popovers.centerOn) {
14084                            const shift = popover.containers.main.offsetHeight / 2;
14085                            if (this.options.popovers.centerOn &&
14086                                !(MapSVG.isPhone && this.options.popovers.mobileFullscreen)) {
14087                                this.centerOn(mapObject, shift);
14088                            }
14089                        }
14090                    },
14091                },
14092            });
14093            this.controllers.popover._init();
14094        }
14095        hidePopover() {
14096            this.controllers.popover && this.controllers.popover.close();
14097        }
14098        popoverOffHandler(e) {
14099            if (this.isScrolling ||
14100                $$A(e.target).closest(".mapsvg-popover").length ||
14101                $$A(e.target).hasClass("mapsvg-btn-map"))
14102                return;
14103            this.controllers.popover && this.controllers.popover.close();
14104        }
14105        mouseOverHandler(e, object) {
14106            if (this.eventsPreventList["mouseover"]) {
14107                return;
14108            }
14109            if (object instanceof Marker) {
14110                if (this.options.actions.marker.mouseover.showTooltip) {
14111                    this.showTooltip(object);
14112                }
14113            }
14114            if (object instanceof Region) {
14115                if (this.options.actions.region.mouseover.showTooltip) {
14116                    this.showTooltip(object);
14117                }
14118            }
14119            let ids;
14120            if (this.options.menu.on) {
14121                if (this.options.menu.source == "database") {
14122                    if (object instanceof Region && object.objects.length) {
14123                        ids = object.objects.map((obj) => {
14124                            return obj.id;
14125                        });
14126                    }
14127                    if (object instanceof Marker) {
14128                        ids = object.object ? [object.object.id] : [];
14129                    }
14130                }
14131                else {
14132                    if (object instanceof Region) {
14133                        ids = [object.id];
14134                    }
14135                    if (this instanceof Marker &&
14136                        object.object.regions &&
14137                        object.object.regions.length) {
14138                        ids = object.object.regions.map((obj) => {
14139                            return obj.id;
14140                        });
14141                    }
14142                }
14143                this.controllers.directory.highlightItems(ids);
14144            }
14145            if (object instanceof Region) {
14146                if (!object.selected)
14147                    object.highlight();
14148                this.events.trigger("mouseover.region", object, [e, this]);
14149            }
14150            else {
14151                this.highlightMarker(object);
14152                this.events.trigger("mouseover.marker", object, [e, this]);
14153            }
14154        }
14155        showTooltip(object) {
14156            let name, _object;
14157            if (object instanceof Region) {
14158                name = "tooltipRegion";
14159                _object = object;
14160            }
14161            else if (object instanceof Marker) {
14162                name = "tooltipMarker";
14163                _object = object.object;
14164            }
14165            else {
14166                name = "tooltipMarker";
14167                _object = object;
14168            }
14169            if (_object != null && this.popoverShowingFor !== object) {
14170                this.controllers.tooltip.setMainTemplate(this.options.templates[name]);
14171                this.controllers.tooltip.redraw(_object.getData());
14172                this.controllers.tooltip.show();
14173            }
14174        }
14175        mouseOutHandler(e, object) {
14176            if (this.eventsPreventList["mouseout"]) {
14177                return;
14178            }
14179            if (this.controllers.tooltip)
14180                this.controllers.tooltip.hide();
14181            if (object instanceof Region) {
14182                if (!object.selected)
14183                    object.unhighlight();
14184                this.events.trigger("mouseout.region", object, [e, this]);
14185            }
14186            else {
14187                this.unhighlightMarker();
14188                this.events.trigger("mouseout.marker", object, [e, this]);
14189            }
14190            let ids;
14191            if (this.options.menu.on) {
14192                if (this.options.menu.source == "database") {
14193                    if (object instanceof Marker) {
14194                        const marker = object;
14195                        ids = marker.object ? [marker.object.id] : [];
14196                    }
14197                }
14198                this.controllers.directory.unhighlightItems();
14199            }
14200        }
14201        eventsPrevent(event) {
14202            this.eventsPreventList[event] = true;
14203        }
14204        eventsRestore(event) {
14205            if (event) {
14206                this.eventsPreventList[event] = false;
14207            }
14208            else {
14209                this.eventsPreventList = {};
14210            }
14211        }
14212        setEventHandlers() {
14213            const _this = this;
14214            $$A(_this.containers.map).off(".common.mapsvg");
14215            $$A(_this.containers.scrollpane).off(".common.mapsvg");
14216            $$A(document).off("keydown.scroll.mapsvg");
14217            $$A(document).off("mousemove.scrollInit.mapsvg");
14218            $$A(document).off("mouseup.scrollInit.mapsvg");
14219            if (_this.editMarkers.on) {
14220                $$A(_this.containers.map).on("touchstart.common.mapsvg mousedown.common.mapsvg", ".mapsvg-marker", function (e) {
14221                    e.originalEvent.preventDefault();
14222                    const marker = _this.getMarker($$A(this).attr("id"));
14223                    const startCoords = MapSVG.mouseCoords(e);
14224                    marker.drag(startCoords, _this.scale);
14225                });
14226            }
14227            if (!_this.editMarkers.on) {
14228                $$A(_this.containers.map)
14229                    .on("mouseover.common.mapsvg", ".mapsvg-region", function (e) {
14230                    const id = $$A(this).attr("id");
14231                    _this.mouseOverHandler.call(_this, e, _this.getRegion(id));
14232                })
14233                    .on("mouseleave.common.mapsvg", ".mapsvg-region", function (e) {
14234                    const id = $$A(this).attr("id");
14235                    _this.mouseOutHandler.call(_this, e, _this.getRegion(id));
14236                });
14237            }
14238            if (!_this.editRegions.on) {
14239                $$A(_this.containers.map)
14240                    .on("mouseover.common.mapsvg", ".mapsvg-marker", function (e) {
14241                    const id = $$A(this).attr("id");
14242                    _this.mouseOverHandler.call(_this, e, _this.getMarker(id));
14243                })
14244                    .on("mouseleave.common.mapsvg", ".mapsvg-marker", function (e) {
14245                    const id = $$A(this).attr("id");
14246                    _this.mouseOutHandler.call(_this, e, _this.getMarker(id));
14247                });
14248            }
14249            if (_this.options.scroll.spacebar) {
14250                $$A(document).on("keydown.scroll.mapsvg", function (e) {
14251                    if (document.activeElement.tagName !== "INPUT" &&
14252                        !_this.isScrolling &&
14253                        e.keyCode == 32) {
14254                        e.preventDefault();
14255                        $$A(_this.containers.map).addClass("mapsvg-scrollable");
14256                        $$A(document)
14257                            .on("mousemove.scrollInit.mapsvg", function (e) {
14258                            _this.isScrolling = true;
14259                            $$A(document).off("mousemove.scrollInit.mapsvg");
14260                            _this.scrollStart(e, _this);
14261                        })
14262                            .on("keyup.scroll.mapsvg", function (e) {
14263                            if (e.keyCode == 32) {
14264                                $$A(document).off("mousemove.scrollInit.mapsvg");
14265                                $$A(_this.containers.map).removeClass("mapsvg-scrollable");
14266                            }
14267                        });
14268                    }
14269                });
14270            }
14271            else if (!_this.options.scroll.on) {
14272                if (!_this.editMarkers.on) {
14273                    $$A(_this.containers.map).on("touchstart.common.mapsvg", ".mapsvg-region", function (e) {
14274                        _this.scroll.touchScrollStart = $$A(window).scrollTop();
14275                    });
14276                    $$A(_this.containers.map).on("touchstart.common.mapsvg", ".mapsvg-marker", function (e) {
14277                        _this.scroll.touchScrollStart = $$A(window).scrollTop();
14278                    });
14279                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-region", function (e) {
14280                        if (e.cancelable) {
14281                            e.preventDefault();
14282                        }
14283                        if (!_this.scroll.touchScrollStart ||
14284                            _this.scroll.touchScrollStart === $$A(window).scrollTop()) {
14285                            _this.regionClickHandler(e, _this.getRegion($$A(this).attr("id")));
14286                        }
14287                    });
14288                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-marker", function (e) {
14289                        if (e.cancelable) {
14290                            e.preventDefault();
14291                        }
14292                        if (!_this.scroll.touchScrollStart ||
14293                            _this.scroll.touchScrollStart === $$A(window).scrollTop()) {
14294                            _this.markerClickHandler.call(_this, e, _this.getMarker($$A(this).attr("id")));
14295                        }
14296                    });
14297                    $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", ".mapsvg-marker-cluster", function (e) {
14298                        if (e.cancelable) {
14299                            e.preventDefault();
14300                        }
14301                        if (!_this.scroll.touchScrollStart ||
14302                            _this.scroll.touchScrollStart == $$A(window).scrollTop()) {
14303                            const cluster = $$A(this).data("cluster");
14304                            _this.zoomTo(cluster.markers);
14305                        }
14306                    });
14307                }
14308                else {
14309                    if (_this.clickAddsMarker)
14310                        $$A(_this.containers.map).on("touchend.common.mapsvg mouseup.common.mapsvg", function (e) {
14311                            if (e.cancelable) {
14312                                e.preventDefault();
14313                            }
14314                            _this.markerAddClickHandler(e);
14315                        });
14316                }
14317            }
14318            else {
14319                $$A(_this.containers.map).on("touchstart.common.mapsvg mousedown.common.mapsvg", function (e) {
14320                    if ($$A(e.target).hasClass("mapsvg-popover") ||
14321                        $$A(e.target).closest(".mapsvg-popover").length) {
14322                        if ($$A(e.target).hasClass("mapsvg-popover-close")) {
14323                            if (e.type == "touchstart") {
14324                                if (e.cancelable) {
14325                                    e.preventDefault();
14326                                }
14327                            }
14328                        }
14329                        return;
14330                    }
14331                    if (e.type == "touchstart") {
14332                        if (e.cancelable) {
14333                            e.preventDefault();
14334                        }
14335                    }
14336                    let obj;
14337                    if (e.target &&
14338                        $$A(e.target).attr("class") &&
14339                        $$A(e.target).attr("class").indexOf("mapsvg-region") != -1) {
14340                        obj = _this.getRegion($$A(e.target).attr("id"));
14341                        _this.setObjectClickedBeforeScroll(obj);
14342                    }
14343                    else if (e.target &&
14344                        $$A(e.target).attr("class") &&
14345                        $$A(e.target).attr("class").indexOf("mapsvg-marker") != -1 &&
14346                        $$A(e.target).attr("class").indexOf("mapsvg-marker-cluster") 
14346=== -1) {
14347                        if (_this.editMarkers.on) {
14348                            return;
14349                        }
14350                        obj = _this.getMarker($$A(e.target).attr("id"));
14351                        _this.setObjectClickedBeforeScroll(obj);
14352                    }
14353                    else if (e.target &&
14354                        $$A(e.target).attr("class") &&
14355                        $$A(e.target).attr("class").indexOf("mapsvg-marker-cluster") != -1) {
14356                        if (_this.editMarkers.on) {
14357                            return;
14358                        }
14359                        obj = $$A(e.target).data("cluster");
14360                        _this.setObjectClickedBeforeScroll(obj);
14361                    }
14362                    if (e.type == "mousedown") {
14363                        _this.scrollStart(e, _this);
14364                    }
14365                    else {
14366                        _this.touchStart(e, _this);
14367                    }
14368                });
14369            }
14370            $$A(_this.containers.map).on("mouseleave.common.mapsvg", ".mapsvg-choropleth-gradient-wrap", (e) => {
14371                this.controllers.tooltip.hide();
14372            });
14373        }
14374        setLabelsRegions(options) {
14375            options = options || this.options.labelsRegions;
14376            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14377            $$A.extend(true, this.options, { labelsRegions: options });
14378            if (this.options.labelsRegions.on) {
14379                this.regions.forEach((region) => {
14380                    if (!region.label) {
14381                        region.label = jQuery('<div class="mapsvg-region-label" />')[0];
14382                        $$A(this.layers.labels).append(region.label);
14383                    }
14384                    try {
14385                        $$A(region.label).html(this.templates.labelRegion(region.forTemplate()));
14386                    }
14387                    catch (err) {
14388                        console.error('MapSVG: Error in the "Region Label" template');
14389                    }
14390                });
14391                this.labelsRegionsAdjustScreenPosition();
14392            }
14393            else {
14394                this.regions.forEach((region) => {
14395                    if (region.label) {
14396                        $$A(region.label).remove();
14397                        region.label = null;
14398                        delete region.label;
14399                    }
14400                });
14401            }
14402        }
14403        setLabelsMarkers(options) {
14404            options = options || this.options.labelsMarkers;
14405            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14406            $$A.extend(true, this.options, { labelsMarkers: options });
14407            if (this.options.labelsMarkers.on) {
14408                this.markers.forEach((marker) => {
14409                    try {
14410                        marker.setLabel(this.templates.labelMarker(marker.object));
14411                    }
14412                    catch (err) {
14413                        console.error('MapSVG: Error in the "Marker Label" template');
14414                    }
14415                });
14416            }
14417        }
14418        addLayer(name) {
14419            this.layers[name] = $$A('<div class="mapsvg-layer mapsvg-layer-' + name + '"></div>')[0];
14420            this.containers.layers.appendChild(this.layers[name]);
14421            return this.layers[name];
14422        }
14423        getLayer(name) {
14424            return this.layers[name];
14425        }
14426        getDb() {
14427            return this.objectsRepository;
14428        }
14429        getDbRegions() {
14430            return this.regionsRepository;
14431        }
14432        regionAdd(svgObject) {
14433            const region = new Region(svgObject, this);
14434            region.setStatus(1);
14435            this.regions.push(region);
14436            this.regions.sort(function (a, b) {
14437                return a.id == b.id ? 0 : +(a.id > b.id) || -1;
14438            });
14439            return region;
14440        }
14441        regionDelete(id) {
14442            if (this.regions.findById(id)) {
14443                this.regions.findById(id).elem.remove();
14444                this.regions.delete(id);
14445            }
14446            else if ($$A("#" + id).length) {
14447                $$A("#" + id).remove();
14448            }
14449        }
14450        reloadRegions() {
14451            this.regions.clear();
14452            $$A(this.containers.svg).find(".mapsvg-region").removeClass("mapsvg-region");
14453            $$A(this.containers.svg)
14454                .find(".mapsvg-region-disabled")
14455                .removeClass("mapsvg-region-disabled");
14456            $$A(this.containers.svg)
14457                .find("path, polygon, circle, ellipse, rect")
14458                .each((index, element) => {
14459                const elem = element;
14460                if ($$A(elem).closest("defs").length)
14461                    return;
14462                if (elem.getAttribute("id")) {
14463                    if (!this.options.regionPrefix ||
14464                        (this.options.regionPrefix &&
14465                            elem.getAttribute("id").indexOf(this.options.regionPrefix) === 0)) {
14466                        const region = new Region(elem, this);
14467                        this.regions.push(region);
14468                    }
14469                }
14470            });
14471        }
14472        reloadRegionsFull() {
14473            const statuses = this.regionsRepository.getSchema().getFieldByType("status");
14474            this.regions.forEach((region) => {
14475                const _region = this.regionsRepository.getLoaded().findById(region.id);
14476                if (_region) {
14477                    region.setData(_region);
14478                    if (statuses && _region.status !== undefined && _region.status !== null) {
14479                        region.setStatus(_region.status);
14480                    }
14481                }
14482                else {
14483                    if (this.options.filters.filteredRegionsStatus ||
14484                        this.options.filters.filteredRegionsStatus === 0) {
14485                        region.setStatus(this.options.filters.filteredRegionsStatus);
14486                    }
14487                }
14488            });
14489            this.loadDirectory();
14490            this.setChoropleth();
14491            this.setLayersControl();
14492            this.setGroups();
14493            if (this.options.labelsRegions.on) {
14494                this.setLabelsRegions();
14495            }
14496        }
14497        fixMarkersWorldScreen() {
14498            if (this.googleMaps.map)
14499                setTimeout(() => {
14500                    const markers = { left: 0, right: 0 };
14501                    if (this.markers.length > 1) {
14502                        this.markers.forEach((m) => {
14503                            if (m.node.offset().left <
14504                                $$A(this.containers.map).offset().left +
14505                                    this.containers.map.clientWidth / 2) {
14506                                markers.left++;
14507                            }
14508                            else {
14509                                markers.right++;
14510                            }
14511                        });
14512                        if (markers.left === 0 || markers.right === 0) {
14513                            const k = markers.left === 0 ? 1 : -1;
14514                            const ww = (this.svgDefault.viewBox.width / this.mapLonDelta) *
14515                                360 *
14516                                this.getScale();
14517                            this.googleMaps.map.panBy(k * ww, 0);
14518                        }
14519                    }
14520                }, 600);
14521        }
14522        updateOutdatedOptions(options) {
14523            if (options.menu && (options.menu.position || options.menu.customContainer)) {
14524                if (options.menu.customContainer) {
14525                    options.menu.location = "custom";
14526                }
14527                else {
14528                    options.menu.position = options.menu.position === "left" ? "left" : "right";
14529                    options.menu.location =
14530                        options.menu.position === "left" ? "leftSidebar" : "rightSidebar";
14531                    if (!options.containers || !options.containers[options.menu.location]) {
14532                        options.containers = options.containers || {};
14533                        options.containers[options.menu.location] = { on: false, width: "200px" };
14534                    }
14535                    options.containers[options.menu.location].width = options.menu.width;
14536                    if (MapSVG.parseBoolean(options.menu.on)) {
14537                        options.containers[options.menu.location].on = true;
14538                    }
14539                }
14540                delete options.menu.position;
14541                delete options.menu.width;
14542                delete options.menu.customContainer;
14543            }
14544            if (options.detailsView &&
14545                (options.detailsView.location === "mapContainer" ||
14546                    options.detailsView.location === "near" ||
14547                    options.detailsView.location === "top")) {
14548                options.detailsView.location = "map";
14549            }
14550            if (!options.controls) {
14551                options.controls = {};
14552                options.controls.zoom =
14553                    options.zoom &&
14554                        options.zoom.on &&
14555                        (!options.zoom.buttons || options.zoom.buttons.location !== "hide");
14556                options.controls.location =
14557                    options.zoom && options.zoom.buttons && options.zoom.buttons.location !== "hide"
14558                        ? options.zoom.buttons.location
14559                        : "right";
14560            }
14561            if (options.colors && !options.colors.markers) {
14562                options.colors.markers = {
14563                    base: { opacity: 100, saturation: 100 },
14564                    hovered: { opacity: 100, saturation: 100 },
14565                    unhovered: { opacity: 100, saturation: 100 },
14566                    active: { opacity: 100, saturation: 100 },
14567                    inactive: { opacity: 100, saturation: 100 },
14568                };
14569            }
14570            if (options.tooltipsMode) {
14571                options.tooltips.mode = options.tooltipsMode;
14572                delete options.tooltipsMode;
14573            }
14574            if (options.popover) {
14575                options.popovers = options.popover;
14576                delete options.popover;
14577            }
14578        }
14579        init() {
14580            if (this.options.source === "") {
14581                throw new Error("MapSVG: please provide SVG file source.");
14582            }
14583            this.disableCssAnimations();
14584            this.setEvents(this.options.events);
14585            this.events.trigger("beforeLoad");
14586            this.containers.map.classList.add("mapsvg");
14587            this.setCss();
14588            if (this.options.colors && this.options.colors.background) {
14589                this.containers.map.style.background = this.options.colors.background;
14590            }
14591            this.setContainers(this.options.containers);
14592            this.setColors();
14593            this.addLoadingMessage();
14594            this.addLayer("markers");
14595            this.addLayer("labels");
14596            this.addLayer("bubbles");
14597            this.addLayer("popovers");
14598            this.addLayer("scrollpane");
14599            this.loadExtensions();
14600            $$A.ajax({ url: this.options.source + "?v=" + this.svgFileLastChanged })
14601                .fail((resp) => {
14602                this.svgLoadingFailed(resp);
14603            })
14604                .done((xmlData) => {
14605                this.renderSvgData(xmlData);
14606            });
14607            return this;
14608        }
14609        getContainer(name) {
14610            return this.containers[name];
14611        }
14612        renderSvgData(xmlData) {
14613            const svgTag = $$A(xmlData).find("svg");
14614            this.containers.svg = svgTag[0];
14615            if (svgTag.attr("width") && svgTag.attr("height")) {
14616                this.svgDefault.width = parseFloat(svgTag.attr("width").replace(/px/g, ""));
14617                this.svgDefault.height = parseFloat(svgTag.attr("height").replace(/px/g, ""));
14618                this.svgDefault.viewBox = svgTag.attr("viewBox")
14619                    ? new ViewBox(svgTag.attr("viewBox").split(" "))
14620                    : new ViewBox(0, 0, this.svgDefault.width, this.svgDefault.height);
14621            }
14622            else if (svgTag.attr("viewBox")) {
14623                this.svgDefault.viewBox = new ViewBox(svgTag.attr("viewBox").split(" "));
14624                this.svgDefault.width = this.svgDefault.viewBox.width;
14625                this.svgDefault.height = this.svgDefault.viewBox.height;
14626            }
14627            else {
14628                const msg = "MapSVG: width/height and viewBox are missing in the SVG file. Can't parse the file because of that.";
14629                if (this.editMode) {
14630                    alert(msg);
14631                }
14632                else {
14633                    console.error(msg);
14634                }
14635                return false;
14636            }
14637            this.geoViewBox = this.getGeoViewBoxFromSvgTag(this.containers.svg);
14638            if (this.options.viewBox && this.options.viewBox.length == 4) {
14639                this._viewBox = new ViewBox(this.options.viewBox);
14640            }
14641            else {
14642                this._viewBox = new ViewBox(this.svgDefault.viewBox);
14643            }
14644            svgTag.attr("preserveAspectRatio", "xMidYMid meet");
14645            svgTag.removeAttr("width");
14646            svgTag.removeAttr("height");
14647            $$A(this.containers.scrollpane).append(svgTag);
14648            this.reloadRegions();
14649            this.setSize(this.options.width, this.options.height, this.options.responsive);
14650            if (this.options.disableAll) {
14651                this.setDisableAll(true);
14652            }
14653            this.setViewBox(this._viewBox);
14654            this.converter = new Converter(this.containers.map, this.svgDefault.viewBox, this.viewBox);
14655            if (this.geoViewBox) {
14656                this.converter.setGeoViewBox(this.geoViewBox);
14657            }
14658            this.setResponsive(this.options.responsive);
14659            this.setScroll(this.options.scroll, true);
14660            this.setZoom(this.options.zoom);
14661            this.setControls(this.options.controls);
14662            this.setGoogleMaps();
14663            this.setTooltips(this.options.tooltips);
14664            this.setPopovers(this.options.popovers);
14665            if (this.options.cursor)
14666                this.setCursor(this.options.cursor);
14667            this.setTemplates(this.options.templates);
14668            this.loadExtensions();
14669            this.filtersSchema = new Schema({ fields: this.options.filtersSchema });
14670            this.objectsRepository.events.on("load", () => {
14671                this.showLoadingMessage();
14672            });
14673            this.objectsRepository.events.on("loaded", () => {
14674                this.fitOnDataLoadDone = false;
14675                this.addLocations();
14676                this.fixMarkersWorldScreen();
14677                this.attachDataToRegions();
14678                this.loadDirectory();
14679                if (this.options.labelsMarkers.on) {
14680                    this.setLabelsMarkers();
14681                }
14682                if (this.options.templates.labelRegion.indexOf("{{objects") !== -1) {
14683                    this.setLabelsRegions();
14684                }
14685                if (this.options.filters.on &&
14686                    this.options.filters.source === "database" &&
14687                    this.controllers.filters &&
14688                    this.controllers.filters.hideFilters) {
14689                    this.controllers.filters.setFiltersCounter();
14690                }
14691                this.hideLoadingMessage();
14692                this.events.trigger("dataLoaded");
14693                this.updateFiltersState();
14694                this.setChoropleth();
14695            });
14696            this.objectsRepository.events.on("schemaChanged", () => {
14697                this.objectsRepository.reload();
14698            });
14699            this.objectsRepository.events.on("updated", (obj) => {
14700                this.attachDataToRegions(obj);
14701                this.reloadRegionsFull();
14702            });
14703            this.objectsRepository.events.on("created", (obj) => {
14704                this.attachDataToRegions(obj);
14705                this.reloadRegionsFull();
14706            });
14707            this.objectsRepository.events.on("deleted", (id) => {
14708                this.attachDataToRegions();
14709                this.reloadRegionsFull();
14710            });
14711            this.regionsRepository.events.on("load", () => {
14712                this.showLoadingMessage();
14713            });
14714            this.regionsRepository.events.on("loaded", () => {
14715                this.hideLoadingMessage();
14716                this.reloadRegionsFull();
14717                if (this.options.filters.on &&
14718                    this.options.filters.source === "regions" &&
14719                    this.controllers.filters &&
14720                    this.controllers.filters.hideFilters) {
14721                    this.controllers.filters.setFiltersCounter();
14722                }
14723                this.events.trigger("regionsLoaded");
14724            });
14725            this.regionsRepository.events.on("updated", (regionData) => {
14726                this.reloadRegionsFull();
14727            });
14728            this.regionsRepository.events.on("created", (regionData) => {
14729                this.reloadRegionsFull();
14730            });
14731            this.regionsRepository.events.on("deleted", (regionData) => {
14732                this.reloadRegionsFull();
14733            });
14734            this.setMenu();
14735            this.setFilters();
14736            if (this.options.menu.filterout.field) {
14737                const f = {};
14738                f[this.options.menu.filterout.field] = this.options.menu.filterout.val;
14739                if (this.options.menu.source == "regions") ;
14740                else {
14741                    this.objectsRepository.query.setFilterOut(f);
14742                }
14743            }
14744            this.setEventHandlers();
14745            if (!this.id) {
14746                this.finalizeMapLoading();
14747                return;
14748            }
14749            if (!this.options.data_regions || !this.options.data_objects) {
14750                this.regionsRepository.find({ withSchema: true }).done((regions) => {
14751                    if (this.options.database.loadOnStart || this.editMode) {
14752                        this.objectsRepository.find({ withSchema: true }).done((data) => {
14753                            this.finalizeMapLoading();
14754                        });
14755                    }
14756                    else {
14757                        this.finalizeMapLoading();
14758                    }
14759                });
14760            }
14761            else {
14762                this.regionsRepository.loadDataFromResponse(this.options.data_regions);
14763                if (this.editMode || this.options.database.loadOnStart) {
14764                    this.objectsRepository.loadDataFromResponse(this.options.data_objects);
14765                }
14766                delete this.options.data_regions;
14767                delete this.options.data_objects;
14768            }
14769            this.finalizeMapLoading();
14770        }
14771        getGeoViewBoxFromSvgTag(svgTag) {
14772            const geo = $$A(svgTag).attr("mapsvg:geoViewBox") || $$A(svgTag).attr("mapsvg:geoviewbox");
14773            if (geo) {
14774                const geoParts = geo.split(" ").map((p) => parseFloat(p));
14775                if (geoParts.length == 4) {
14776                    this.mapIsGeo = true;
14777                    this.geoCoordinates = true;
14778                    const sw = new GeoPoint(geoParts[3], geoParts[0]);
14779                    const ne = new GeoPoint(geoParts[1], geoParts[2]);
14780                    return new GeoViewBox(sw, ne);
14781                }
14782            }
14783            else {
14784                return null;
14785            }
14786        }
14787        svgLoadingFailed(resp) {
14788            if (resp.status == 404) {
14789                let msg = "MapSVG: file not found - " +
14790                    this.options.source +
14791                    "\n\nIf you moved MapSVG from another server please read the following docs page: https://mapsvg.com/docs/installation/moving";
14792                if (this.editMode) {
14793                    msg +=
14794                        "\n\nIf you know the correct path for the SVG file, please write it and press OK:";
14795                    const oldSvgPath = this.options.source;
14796                    const userSvgPath = prompt(msg, oldSvgPath);
14797                    if (userSvgPath !== null) {
14798                        $$A.ajax({ url: userSvgPath + "?v=" + this.svgFileLastChanged })
14799                            .fail(function () {
14800                            location.reload();
14801                        })
14802                            .done((xmlData) => {
14803                            this.options.source = userSvgPath;
14804                            this.renderSvgData(xmlData);
14805                            const mapsRepo = new MapsRepository();
14806                            mapsRepo.update(this);
14807                        });
14808                    }
14809                    else {
14810                        location.reload();
14811                    }
14812                }
14813                else {
14814                    console.error(msg);
14815                }
14816            }
14817            else {
14818                const msg = "MapSVG: can't load SVG file for unknown reason. Please contact support: https://mapsvg.ticksy.com";
14819                if (this.editMode) {
14820                    alert(msg);
14821                }
14822                else {
14823                    console.error(msg);
14824                }
14825            }
14826        }
14827        addLoadingMessage() {
14828            this.containers.loading = document.createElement("div");
14829            this.containers.loading.className = "mapsvg-loading";
14830            const loadingTextBlock = document.createElement("div");
14831            loadingTextBlock.className = "mapsvg-loading-text";
14832            loadingTextBlock.innerHTML = this.options.loadingText;
14833            const spinner = document.createElement("div");
14834            spinner.className = "spinner-border spinner-border-sm";
14835            this.containers.loading.appendChild(spinner);
14836            this.containers.loading.appendChild(loadingTextBlock);
14837            this.containers.map.appendChild(this.containers.loading);
14838            if (this.options.googleMaps.on) {
14839                $$A(this.containers.map).addClass("mapsvg-google-map-loading");
14840            }
14841        }
14842        hideLoadingMessage() {
14843            $$A(this.containers.loading).hide();
14844        }
14845        showLoadingMessage() {
14846            $$A(this.containers.loading).show();
14847        }
14848        disableCssAnimations() {
14849            this.containers.map.classList.add("no-transitions");
14850        }
14851        enableTransitions() {
14852            $$A(this.containers.map).removeClass("no-transitions");
14853        }
14854        loadExtensions() {
14855            if (this.options.extension &&
14856                $$A().mapSvg.extensions &&
14857                $$A().mapSvg.extensions[_this.options.extension]) {
14858                const ext = $$A().mapSvg.extensions[_this.options.extension];
14859                ext && ext.common(this);
14860            }
14861        }
14862        finalizeMapLoading() {
14863            if (this.options.googleMaps.on && !this.googleMaps.map) {
14864                this.events.on("googleMapsLoaded", () => {
14865                    this.finalizeMapLoading();
14866                });
14867                return;
14868            }
14869            this.selectRegionByIdFromUrl();
14870            setTimeout(() => {
14871                this.movingItemsAdjustScreenPosition();
14872                this.mapAdjustStrokes();
14873                setTimeout(() => {
14874                    this.hideLoadingMessage();
14875                    $$A(this.containers.loading).find(".mapsvg-loading-text").hide();
14876                    this.enableTransitions();
14877                }, 200);
14878            }, 100);
14879            this.events.trigger("afterLoad");
14880            MapSVG.addInstance(this);
14881        }
14882        selectRegionByIdFromUrl() {
14883            const match = RegExp("[?&]mapsvg_select=([^&]*)").exec(window.location.search);
14884            if (match) {
14885                const select = decodeURIComponent(match[1].replace(/\+/g, " "));
14886                this.selectRegion(select);
14887            }
14888            if (window.location.hash) {
14889                const query = window.location.hash.replace("#/m/", "");
14890                const region = this.getRegion(query);
14891                if (region && this.options.actions.map.afterLoad.selectRegion) {
14892                    this.regionClickHandler(null, region);
14893                }
14894            }
14895        }
14896        createForm(options) {
14897            return new FormBuilder(options);
14898        }
14899        getApiUrl(path) {
14900            const server = new Server();
14901            return server.getUrl(path);
14902        }
14903        getConverter() {
14904            return this.converter;
14905        }
14906        setChoropleth(options) {
14907            const _this = this;
14908            options = options || _this.options.choropleth;
14909            options.on != undefined && (options.on = MapSVG.parseBoolean(options.on));
14910            $$A.extend(true, _this.options, { choropleth: options });
14911            let needsRedraw = false;
14912            if (!_this.$gauge) {
14913                _this.$gauge = {};
14914                _this.$gauge.gradient = $$A("<td>&nbsp;</td>").addClass("mapsvg-gauge-gradient");
14915                _this.setGaugeGradientCSS();
14916                _this.$gauge.container = $$A("<div />").addClass("mapsvg-gauge").hide();
14917                _this.$gauge.table = $$A("<table />");
14918                const tr = $$A("<tr />");
14919                _this.$gauge.labelLow = $$A("<td>" + _this.options.choropleth.labels.low + "</td>");
14920                _this.$gauge.labelHigh = $$A("<td>" + _this.options.choropleth.labels.high + "</td>");
14921                tr.append(_this.$gauge.labelLow);
14922                tr.append(_this.$gauge.gradient);
14923                tr.append(_this.$gauge.labelHigh);
14924                _this.$gauge.table.append(tr);
14925                _this.$gauge.container.append(_this.$gauge.table);
14926                $$A(_this.containers.map).append(_this.$gauge.container);
14927            }
14928            if (!_this.options.choropleth.on && _this.$gauge.container.is(":visible")) {
14929                _this.$gauge.container.hide();
14930                needsRedraw = true;
14931            }
14932            else if (_this.options.choropleth.on && !_this.$gauge.container.is(":visible")) {
14933                _this.$gauge.container.show();
14934                needsRedraw = true;
14935                _this.regionsRepository.events.on("change", function () {
14936                    _this.redrawGauge();
14937                });
14938            }
14939            if (options.colors) {
14940                _this.options.choropleth.colors.lowRGB = tinycolor(_this.options.choropleth.colors.low).toRgb();
14941                _this.options.choropleth.colors.highRGB = tinycolor(_this.options.choropleth.colors.high).toRgb();
14942                _this.options.choropleth.colors.diffRGB = {
14943                    r: _this.options.choropleth.colors.highRGB.r -
14944                        _this.options.choropleth.colors.lowRGB.r,
14945                    g: _this.options.choropleth.colors.highRGB.g -
14946                        _this.options.choropleth.colors.lowRGB.g,
14947                    b: _this.options.choropleth.colors.highRGB.b -
14948                        _this.options.choropleth.colors.lowRGB.b,
14949                    a: _this.options.choropleth.colors.highRGB.a -
14950                        _this.options.choropleth.colors.lowRGB.a,
14951                };
14952                needsRedraw = true;
14953                _this.$gauge && _this.setGaugeGradientCSS();
14954            }
14955            if (options.labels) {
14956                _this.$gauge.labelLow.html(_this.options.choropleth.labels.low);
14957                _this.$gauge.labelHigh.html(_this.options.choropleth.labels.high);
14958            }
14959            needsRedraw && _this.redrawGauge();
14960        }
14961        redrawGauge() {
14962            const _this = this;
14963            _this.updateGaugeMinMax();
14964            _this.regionsRedrawColors();
14965        }
14966        updateGaugeMinMax() {
14967            const _this = this;
14968            _this.options.choropleth.min = 0;
14969            _this.options.choropleth.max = false;
14970            const values = [];
14971            _this.regions.forEach(function (r) {
14972                const gauge = r.data && r.data[_this.options.regionChoroplethField];
14973                gauge != undefined && values.push(gauge);
14974            });
14975            if (values.length > 0) {
14976                _this.options.choropleth.min = values.length == 1 ? 0 : Math.min.apply(null, values);
14977                _this.options.choropleth.max = Math.max.apply(null, values);
14978                _this.options.choropleth.maxAdjusted =
14979                    _this.options.choropleth.max - _this.options.choropleth.min;
14980            }
14981        }
14982        setGaugeGradientCSS() {
14983            const _this = this;
14984            _this.$gauge.gradient.css({
14985                background: "linear-gradient(to right," +
14986                    _this.options.choropleth.colors.low +
14987                    " 1%," +
14988                    _this.options.choropleth.colors.high +
14989                    " 100%)",
14990                filter: 'progid:DXImageTransform.Microsoft.gradient( startColorstr="' +
14991                    _this.options.choropleth.colors.low +
14992                    '", endColorstr="' +
14993                    _this.options.choropleth.colors.high +
14994                    '",GradientType=1 )',
14995            });
14996        }
14997        get $map() {
14998            return $$A(this.getContainer("map"));
14999        }
15000        get $svg() {
15001            return $$A(this.getContainer("svg"));
15002        }
15003        get $popover() {
15004            return $$A(this.getContainer("popover"));
15005        }
15006        get $details() {
15007            return $$A(this.getContainer("detailsView"));
15008        }
15009        get $directory() {
15010            return $$A(this.getContainer("directory"));
15011        }
15012        get database() {
15013            return this.objectsRepository;
15014        }
15015        get regionsDatabase() {
15016            return this.regionsRepository;
15017        }
15018    }
15019
15020    exports.MapSVGMap = MapSVGMap;
15021    exports.arrayIndexed = ArrayIndexed;
15022    exports.formBuilder = FormBuilder;
15023    exports.geoPoint = GeoPoint;
15024    exports.globals = MapSVG;
15025    exports.location = Location;
15026    exports.map = MapSVGMap;
15027    exports.mapsRepository = MapsRepository;
15028    exports.mapsV2Repository = MapsV2Repository;
15029    exports.marker = Marker;
15030    exports.query = Query;
15031    exports.repository = Repository;
15032    exports.schema = Schema;
15033    exports.schemaRepository = SchemaRepository;
15034    exports.screenPoint = ScreenPoint;
15035    exports.server = Server;
15036    exports.svgPoint = SVGPoint;
15037
15038    Object.defineProperty(exports, '__esModule', { value: true });
15039
15040})));
15041//# 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.