{"version":3,"file":"listing_page_main-51aceea0e74209d51d04.js","mappings":"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","sources":["webpack://emmet/webpack/runtime/chunk loaded","webpack://emmet/webpack/runtime/create fake namespace object","webpack://emmet/./moderna_meteogrid/statix/js/base.mjs","webpack://emmet/./simmer/statix/simmer/js/simmerlayer.mjs","webpack://emmet/./simmer/statix/simmer/js/ol_control_searchES.js","webpack://emmet/./saver/statix/js/mapa_elementos.mjs","webpack://emmet/./simmer/statix/simmer/js/mapa.mjs","webpack://emmet/./saver/statix/js/saver_layers.mjs","webpack://emmet/./simmer/statix/simmer/js/GraphControl.mjs","webpack://emmet/./simmer/statix/simmer/js/timeline.mjs","webpack://emmet/./simmer/statix/simmer/js/simulaciones.mjs","webpack://emmet/./simmer/statix/simmer/js/informes.mjs","webpack://emmet/./simmer/statix/simmer/js/listing_page_main.mjs","webpack://emmet/webpack/bootstrap","webpack://emmet/webpack/runtime/define property getters","webpack://emmet/webpack/runtime/global","webpack://emmet/webpack/runtime/hasOwnProperty shorthand","webpack://emmet/webpack/runtime/make namespace object","webpack://emmet/webpack/runtime/node module decorator","webpack://emmet/webpack/runtime/runtimeId","webpack://emmet/webpack/runtime/jsonp chunk loading","webpack://emmet/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);\nvar leafPrototypes;\n// create a fake namespace object\n// mode & 1: value is a module id, require it\n// mode & 2: merge all properties of value into the ns\n// mode & 4: return value when already ns object\n// mode & 16: return value when it's Promise-like\n// mode & 8|1: behave like require\n__webpack_require__.t = function(value, mode) {\n\tif(mode & 1) value = this(value);\n\tif(mode & 8) return value;\n\tif(typeof value === 'object' && value) {\n\t\tif((mode & 4) && value.__esModule) return value;\n\t\tif((mode & 16) && typeof value.then === 'function') return value;\n\t}\n\tvar ns = Object.create(null);\n\t__webpack_require__.r(ns);\n\tvar def = {};\n\tleafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];\n\tfor(var current = mode & 2 && value; (typeof current == 'object' || typeof current == 'function') && !~leafPrototypes.indexOf(current); current = getProto(current)) {\n\t\tObject.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));\n\t}\n\tdef['default'] = () => (value);\n\t__webpack_require__.d(ns, def);\n\treturn ns;\n};","/*eslint no-implicit-globals: \"error\"*/\nimport $ from 'jquery';\nwindow.$ = window.jQuery = $;\nimport proj4 from 'proj4';\nimport flatpickr from 'flatpickr';\nimport dayjs from 'dayjs'\nimport customParseFormat from 'dayjs/plugin/customParseFormat'\ndayjs.extend(customParseFormat)\n\nimport utc from 'dayjs/plugin/utc'\nimport duration from 'dayjs/plugin/duration'\nimport pluralGetSet from 'dayjs/plugin/pluralGetSet'\nimport 'dayjs/locale/es'\nimport 'dayjs/locale/de'\nimport 'dayjs/locale/es'\nimport 'dayjs/locale/en'\n\nimport langMap_en from 'flatpickr/dist/l10n/default';\nimport langMap_es from 'flatpickr/dist/l10n/es';\nimport langMap_fr from 'flatpickr/dist/l10n/fr';\nimport langMap_cat from 'flatpickr/dist/l10n/cat';\n\nimport \"multiselect\";\nimport 'multiselect/css/multi-select.css';\nimport \"select2/dist/js/select2.min.js\"\nimport \"select2/dist/css/select2.min.css\"\n\nimport \"bootstrap\"\nimport \"bootstrap/dist/css/bootstrap.css\"\nimport 'flatpickr/dist/flatpickr.css';\n\nimport \"jquery-ui/ui/widgets/draggable\";\nimport \"jquery-ui/ui/widgets/resizable\";\nimport \"jquery-ui/ui/widgets/dialog\";\nimport \"jquery-ui/ui/widgets/tabs\";\nimport \"jquery-ui/ui/widgets/button\";\nimport \"jquery-ui/ui/widgets/spinner\";\nimport \"jquery-ui/ui/position\";\nimport \"jquery-ui/ui/widgets/menu\";\n\nimport \"jquery-ui/themes/base/all.css\";\nimport \"datatables.net-buttons-bs/css/buttons.bootstrap.css\"\n\nimport \"datatables.net/js/jquery.dataTables.mjs\"\nimport \"datatables.net-bs/js/dataTables.bootstrap.mjs\"\nimport \"datatables.net-buttons/js/dataTables.buttons.mjs\"\nimport \"datatables.net-buttons-bs/js/buttons.bootstrap.mjs\"\nimport \"datatables.net-buttons/js/buttons.html5.mjs\"\nimport \"datatables.net-buttons/js/buttons.colVis.mjs\"\nimport 'datatables.net-jqui/js/dataTables.jqueryui.js';\nimport 'datatables.net-scroller/js/dataTables.scroller.js';\nimport 'inspire-tree-dom/dist/inspire-tree-dark.min.css';\n\nimport \"../css/mezzanine.css\";\nimport '../css/datatables.css';\nimport '../css/checkbox.css';\nimport \"../css/style.css\";\nimport \"../css/meteogrid.css\";\n\nimport '../css/mapas.css';\nimport '../css/datatables2.css';\n\nimport '@fortawesome/fontawesome-pro/css/all.min.css'\n\nimport Cookies from 'js-cookie';\n\ndayjs.extend(utc);\ndayjs.extend(duration);\ndayjs.extend(pluralGetSet);\n\nconst _ = window.gettext;\n\nlet initialized = false;\n\nfunction global_init() {\n  if (initialized)\n    return;\n  initialized = true;\n  const csrftoken = Cookies.get('csrftoken');\n  function csrfSafeMethod(method) {\n    // these HTTP methods do not require CSRF protection\n    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));\n  }\n  $.ajaxSetup({\n    beforeSend: function (xhr, settings) {\n      if (!csrfSafeMethod(settings.type) && !this.crossDomain) {\n        xhr.setRequestHeader(\"X-CSRFToken\", csrftoken);\n      }\n    }\n  });\n  $(document).ajaxStart(function () {\n    $('body').addClass('wait');\n  }).ajaxComplete(function () {\n    $('body').removeClass('wait');\n  });\n  $('.draggable-panel').draggable();\n  $(\".draggable-panel\").click(function (e) { e.stopPropagation(); });\n  $('.resizable-panel').resizable({ handles: \"n, e, s, w\" });\n  $(\".resizable-panel\").click(function (e) { e.stopPropagation(); });\n  $(\".alert-dismissable.alert-info\").delay(2500).slideUp();\n  $(\".alert-dismissable.alert-success\").delay(2500).slideUp();\n  if (window.self != window.top) {\n    $(document.body).addClass(\"in-iframe\");\n  }\n  // /static/bootstrap-extras.js\n  // Form css tweaks.\n  $('.middle input:text, .middle input:password, textarea').not('[class]').addClass('input-xlarge');\n  $('.control-group label').addClass('control-label');\n  const $dropdowns = $('li.dropdown'); // Specifying the element is faster for older browsers\n  /**\n   * Mouse events\n   *\n   * @description Mimic hoverIntent plugin by waiting for the mouse to 'settle' within the target before triggering\n   */\n  $dropdowns\n    .on('mouseover', function () // Mouseenter (used with .hover()) does not trigger when user enters from outside document window\n    {\n      const $this = $(this);\n      if ($this.prop('hoverTimeout')) {\n        $this.prop('hoverTimeout', clearTimeout($this.prop('hoverTimeout')));\n      }\n      $this.prop('hoverIntent', setTimeout(function () {\n        $this.addClass('open');\n      }, 250));\n    })\n    .on('mouseleave', function () {\n      const $this = $(this);\n      if ($this.prop('hoverIntent')) {\n        $this.prop('hoverIntent', clearTimeout($this.prop('hoverIntent')));\n      }\n      $this.prop('hoverTimeout', setTimeout(function () {\n        $this.removeClass('open');\n      }, 250));\n    });\n  /**\n   * Touch events\n   *\n   * @description Support click to open if we're dealing with a touchscreen\n   */\n  if ('ontouchstart' in document.documentElement) {\n    $dropdowns.each(function () {\n      const $this = $(this);\n      this.addEventListener('touchstart', function (e) {\n        if (e.touches.length === 1) {\n          // Prevent touch events within dropdown bubbling down to document\n          e.stopPropagation();\n          // Toggle hover\n          if (!$this.hasClass('open')) {\n            // Prevent link on first touch\n            if (e.target === this || e.target.parentNode === this) {\n              e.preventDefault();\n            }\n            // Hide other open dropdowns\n            $dropdowns.removeClass('open');\n            $this.addClass('open');\n\n            // Hide dropdown on touch outside\n            const closeDropdown = function (e) {\n              e.stopPropagation();\n\n              $this.removeClass('open');\n              document.removeEventListener('touchstart', closeDropdown);\n            }\n            document.addEventListener('touchstart', closeDropdown);\n          }\n        }\n      }, false);\n    });\n  }\n  if (window.namespaces)\n    for (const ns of window.namespaces) {\n      ns.page = $(`#page-${ns.page_id}`);\n      ns.mapas = [];\n    }\n  const csrfmiddlewaretoken = Cookies.get('csrftoken');\n  document.getElementById('fileuploader').addEventListener(\"change\", function () {\n    const fileuploader = $(\"#fileuploader\")\n    const form = fileuploader.closest('form');\n    form.find('input[name=csrfmiddlewaretoken]').val(csrfmiddlewaretoken);\n    $.ajax({\n      type: \"POST\",\n      url: fileuploader.data('url'),\n      processData: false,\n      contentType: false,\n      data: new FormData(form[0]),\n      success: function (result) {\n        let text = 'Fichero subido correctamente';\n        let class_ = 'alert-success';\n        if (result.error) {\n          text = result.error;\n          class_ = 'alert-warning'\n        }\n        const ok = $(`\n            <div class=\"alert alert-dismissable ${class_}\" data-alert=\"alert\">\n            <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button> \n            ${_(text)}\n          </div>`);\n        const elem = ok.appendTo('#inner-headline');\n        elem.fadeIn(500).fadeOut(500).fadeIn(1000);\n        if (!result.error) elem.fadeOut(5000);\n        fileuploader.val('');\n      }\n    })\n  }, false);\n  $('.fileupload-link').on('click', function () {\n    const url = window.Urls.uploadFile($(this).data('page_id'))\n    const fileuploader = $(\"#fileuploader\")\n    fileuploader.data('url', url);\n    fileuploader.trigger('click');\n    return false;\n  })\n  setup_layer_tree_filter();\n}\n\nfunction setup_layer_tree_filter() {\n  const layerTree = $('#LAYER');\n  layerTree.on('search', 'input[name=filtrar-arbol]',\n    ev => {\n      const search = ev.currentTarget.value.toUpperCase();\n      if (search === '') {\n        layerTree.removeClass('filtered');\n        layerTree.find('.mostrar-capa.selector')\n          .removeClass('shown')\n          .removeClass('hidden');\n        return;\n      } else {\n        layerTree.addClass('filtered');\n      }\n      layerTree.find('.mostrar-capa.selector')\n        .each((idx, el) => {\n          const visible = el.textContent.toUpperCase()\n            .includes(search);\n          if (visible) {\n            el.classList.add('shown');\n            el.classList.remove('hidden');\n          } else {\n            el.classList.add('hidden');\n            el.classList.remove('shown');\n          }\n        })\n    }\n  )\n  layerTree.on('click', '.layers-collapse',\n    () => layerTree.find('.folder-toggler').removeClass('open')\n  )\n  layerTree.on('click', '.layers-expand',\n    () => layerTree.find('.folder-toggler').addClass('open')\n  )\n}\n\nfunction cargarCSS() {\n  const fileref = document.createElement(\"link\");\n  fileref.setAttribute(\"rel\", \"stylesheet\");\n  fileref.setAttribute(\"type\", \"text/css\");\n  fileref.setAttribute(\"href\", window.Urls.iconos_css());\n  document.getElementsByTagName(\"head\")[0].appendChild(fileref)\n}\nfunction getDTMessages() {\n  return {\n    \"sProcessing\": \"Procesando...\",\n    \"sLengthMenu\": \"Mostrar _MENU_ registros\",\n    \"sZeroRecords\": \"No se encontraron resultados\",\n    \"sEmptyTable\": \"Ningún dato disponible en esta tabla\",\n    \"sInfo\": \"_START_ - _END_ de _TOTAL_ coincidencias\",\n    \"sInfoEmpty\": \"No hay coincidencias\",\n    \"sInfoFiltered\": \"(total sin filtar: _MAX_)\",\n    \"sInfoPostFix\": \"\",\n    \"sSearch\": \"Buscar:\",\n    \"sUrl\": \"\",\n    \"sInfoThousands\": \",\",\n    \"sLoadingRecords\": \"Cargando...\",\n    \"oPaginate\": {\n      \"sFirst\": _(\"Primero\"),\n      \"sLast\": _(\"Último\"),\n      \"sNext\": _(\"Siguiente\"),\n      \"sPrevious\": _(\"Anterior\")\n    },\n    \"oAria\": {\n      \"sSortAscending\": _(\": Activar para ordenar la columna de manera ascendente\"),\n      \"sSortDescending\": _(\": Activar para ordenar la columna de manera descendente\")\n    }\n  }\n}\nfunction getFormData(form) {\n  const values = form.serializeArray();\n  for (const field of Object.values(values)) {\n    const input = form.find(`input[name=\"${field.name}\"][type=\"datetime-local\"]`);\n    if (input.length)\n      field.value = dayjs(field.value).toJSON();\n  }\n  return $.param(values);\n}\n\n/**\n* @param String name\n* @return String\n*/\nfunction getParameterByName(name) {\n  const url = new URL(window.location);\n  return url.searchParams.get(name) || '';\n}\nlet locale = null;\n\nconst langMap = {\n  en: langMap_en.default.en,\n  es: langMap_es.default.es,\n  fr: langMap_fr.default.fr,\n  ca: langMap_cat.default.ca,\n};\n\nfor (const lang of navigator.languages) {\n  const l = lang.split('-')[0];\n  if (l in langMap) {\n    locale = l;\n    dayjs.locale(l);\n    flatpickr.localize(langMap[l]);\n    break;\n  }\n}\nexport function multiselectOptions(headerLeft = '', headerRight = '') {\n  return {\n    selectableHeader: `${headerLeft}<div class=\"multiselect-botones\"><a href=\"#\" >\\u00BB</a></div><input type='text' class='search-input' autocomplete='off' placeholder='${_('Buscar')}...'>`,\n    selectionHeader: `${headerRight}<div class=\"multiselect-botones\"><a href=\"#\" >\\u00AB</a></div><input type='text' class='search-input' autocomplete='off' placeholder='${_('Buscar')}...'>`,\n    afterInit: function () {\n      const that = this,\n        $selectableSearch = that.$selectableUl.prev(),\n        $selectionSearch = that.$selectionUl.prev(),\n        selectableSearchString = '#' + that.$container.attr('id') + ' .ms-elem-selectable:not(.ms-selected)',\n        selectionSearchString = '#' + that.$container.attr('id') + ' .ms-elem-selection.ms-selected';\n      const select_all = $selectableSearch.prev().find('a');\n      const select_none = $selectionSearch.prev().find('a');\n      select_all.click(function () {\n        const lis_visible_selectable = that.$selectableContainer.find(that.elemsSelector)\n        lis_visible_selectable.click();\n        return false;\n      })\n      select_none.click(function () {\n        const lis_visible_selection = that.$selectionContainer.find(that.elemsSelector)\n        lis_visible_selection.click();\n        return false;\n      })\n      that.qs1 = $selectableSearch.quicksearch(selectableSearchString)\n        .on('keydown', function (e) {\n          that.qs1.cache();\n          if (e.which === 40) {\n            that.$selectableUl.focus();\n            return false;\n          }\n        });\n      that.qs2 = $selectionSearch.quicksearch(selectionSearchString)\n        .on('keydown', function (e) {\n          that.qs2.cache();\n          if (e.which == 40) {\n            that.$selectionUl.focus();\n            return false;\n          }\n        });\n    },\n    afterSelect: function () {\n      this.qs1.cache();\n      this.qs2.cache();\n    },\n    afterDeselect: function () {\n      this.qs1.cache();\n      this.qs2.cache();\n    }\n  }\n}\n// https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge\n/**\n * Simple object check.\n * @param item\n * @returns {boolean}\n */\nfunction isObject(item) {\n  return (item && typeof item === 'object' && !Array.isArray(item));\n}\n\n/**\n * Deep merge two objects.\n * @param target\n * @param ...sources\n */\nexport function mergeDeep(target, ...sources) {\n  if (!sources.length) return target;\n  const source = sources.shift();\n\n  if (isObject(target) && isObject(source)) {\n    for (const key in source) {\n      if (isObject(source[key])) {\n        if (!target[key]) Object.assign(target, { [key]: {} });\n        mergeDeep(target[key], source[key]);\n      } else {\n        Object.assign(target, { [key]: source[key] });\n      }\n    }\n  }\n\n  return mergeDeep(target, ...sources);\n}\n\nexport function transform_point(xy) {\n  const sourceProj = proj4('EPSG:4326');\n  const destProj = proj4(window.epsg);\n  return proj4(sourceProj, destProj, xy);\n}\n\n/*!\n * jQuery UI Touch Punch 0.2.3\n *\n * Copyright 2011–2014, Dave Furfero\n * Dual licensed under the MIT or GPL Version 2 licenses.\n *\n * Depends:\n *  jquery.ui.widget.js\n *  jquery.ui.mouse.js\n */\n!function (a) {\n  function f(a, b) {\n    if (!(a.originalEvent.touches.length > 1)) {\n      a.preventDefault(); const c = a.originalEvent.changedTouches[0], d = document.createEvent(\"MouseEvents\");\n      d.initMouseEvent(b, !0, !0, window, 1, c.screenX, c.screenY, c.clientX, c.clientY, !1, !1, !1, !1, 0, null),\n        a.target.dispatchEvent(d)\n    }\n  } if (a.support.touch = \"ontouchend\" in document, a.support.touch) {\n    let e, b = a.ui.mouse.prototype, c = b._mouseInit, d = b._mouseDestroy; b._touchStart = function (a) {\n      const b = this; !e && b._mouseCapture(a.originalEvent.changedTouches[0]) &&\n        (e = !0, b._touchMoved = !1, f(a, \"mouseover\"), f(a, \"mousemove\"), f(a, \"mousedown\"))\n    },\n      b._touchMove = function (a) { e && (this._touchMoved = !0, f(a, \"mousemove\")) }, b._touchEnd = function (a) { e && (f(a, \"mouseup\"), f(a, \"mouseout\"), this._touchMoved || f(a, \"click\"), e = !1) }, b._mouseInit = function () {\n        const b = this; b.element.bind({\n          touchstart: a.proxy(b, \"_touchStart\"), touchmove: a.proxy(b, \"_touchMove\"),\n          touchend: a.proxy(b, \"_touchEnd\")\n        }), c.call(b)\n      }, b._mouseDestroy = function () {\n        const b = this; b.element.unbind({\n          touchstart: a.proxy(b, \"_touchStart\"), touchmove: a.proxy(b, \"_touchMove\"), touchend: a.proxy(b, \"_touchEnd\")\n        }),\n          d.call(b)\n      }\n  }\n}($);\n\n// on window resize run function\n$(window).on('resize', () => fluidDialog());\n\n// catch dialog if opened within a viewport smaller than the dialog width\n$(document).on(\"dialogopen\", \".ui-dialog\", () => fluidDialog());\n\nfunction fluidDialog() {\n  const $visible = $(\".ui-dialog:visible\");\n  // each open dialog\n  $visible.each(function () {\n    const $this = $(this);\n    const dialog = $this.find(\".ui-dialog-content\").data(\"ui-dialog\");\n    if (!dialog)\n      return;\n    const wWidth = $(window).width();\n    // check window width against dialog width\n    if (wWidth < (parseInt(dialog.options.maxWidth || 1000) + 50)) {\n      // keep dialog from filling entire screen\n      $this.css(\"max-width\", \"90%\");\n    } else {\n      // fix maxWidth bug\n      $this.css(\"max-width\", dialog.options.maxWidth + \"px\");\n    }\n    const wHeight = $(window).height();\n    // check window width against dialog width\n    if (wHeight < (parseInt(dialog.options.maxHeight || 1000) + 50)) {\n      // keep dialog from filling entire screen\n      $this.css(\"max-height\", \"90%\");\n    } else {\n      // fix maxWidth bug\n      $this.css(\"max-height\", dialog.options.maxHeight + \"px\");\n    }\n    //reposition dialog\n    // dialog.option(\"width\", $this.width());\n    dialog.option(\"position\", dialog.options.position);\n    $(dialog).closest('.ui-dialog').draggable('option', dialog.option('appendTo'))\n  });\n\n}\nexport function get_horizon(dims) {\n  for (const v of Object.values(dims))\n    if (v.startsWith('HOR') || v.includes('HORIZON') || v.includes('YEAR_PERIOD ')) return v;\n}\nexport function getFormCoords(element) {\n  if (element.find('div#projection input').val() != ''\n    && element.find('input#xlong').val() != ''\n    && element.find('input#ylat').val() != '') return {\n      srcproj: element.find('div#projection input').attr(\"value\"),\n      xlong: Number(element.find('input#xlong').val()),\n      ylat: Number(element.find('input#ylat').val())\n    }\n  const lat_degrees = Number(element.find('div#lat input#degrees').val());\n  const lat_mins = Number(element.find('div#lat input#mins').val());\n  const lat_segs = Number(element.find('div#lat input#segs').val());\n  const lat_dir = element.find('div#lat div#direction input').val();\n  const long_degrees = Number(element.find('div#long input#degrees').val());\n  const long_mins = Number(element.find('div#long input#mins').val());\n  const long_segs = Number(element.find('div#long input#segs').val());\n  const long_dir = element.find('div#long div#direction input').val();\n  if (lat_degrees && long_degrees)\n    return {\n      ylat: ConvertDMSToDD(lat_degrees, lat_mins, lat_segs, lat_dir),\n      xlong: ConvertDMSToDD(long_degrees, long_mins, long_segs, long_dir),\n      srcproj: proj4('EPSG:4326')\n    }\n  return {\n    ylat: null,\n    xlong: null,\n    srcproj: null\n  }\n}\n\nfunction ConvertDMSToDD(degrees, minutes, seconds, direction) {\n  const dd = degrees + minutes / 60 + seconds / (60 * 60);\n  if (direction == \"S\" || direction == \"W\")\n    return -dd;\n  // Don't do anything for N or E\n  return dd;\n}\n\nexport function updateUnselectedHorizons(idx_hor_notsel) {\n  idx_hor_notsel = [...new Set(idx_hor_notsel)].sort()\n  if (idx_hor_notsel[0] === '')\n    idx_hor_notsel.splice(0, 1)\n  const oldUrl = window.location.href;\n  let newUrl = oldUrl;\n  if (oldUrl.includes('idx_hor_notsel')) {\n    newUrl = oldUrl.replace(/(idx_hor_notsel=)[^&]*(.*)/, '$1' + idx_hor_notsel + '$2');\n  } else {\n    const sep = oldUrl.includes('?') ? '&' : '?';\n    newUrl += sep + 'idx_hor_notsel=' + idx_hor_notsel;\n  }\n  if (oldUrl != newUrl)\n    window.history.replaceState(null, null, newUrl);\n}\nexport const LAYERTYPES = {};\n\nexport { $, dayjs, locale, flatpickr, global_init, cargarCSS, getDTMessages, getFormData, getParameterByName, proj4 };\n","import { $, dayjs, getParameterByName, mergeDeep } from '../../../../moderna_meteogrid/statix/js/base.mjs';\n\nimport GeoJSON from 'ol/format/GeoJSON';\nimport { optionsFromCapabilities } from 'ol/source/WMTS';\nimport WMTSCapabilities from 'ol/format/WMTSCapabilities';\nimport { WMTS, ImageWMS, OSM, Vector as VectorSource, BingMaps, TileWMS, XYZ } from 'ol/source';\nimport { Tile as TileLayer, Image as ImageLayer, Vector as VectorLayer } from 'ol/layer';\nimport { createForProjection } from 'ol/tilegrid';\nimport Flow from 'ol/layer/Flow.js';\nimport { get as getProjection } from 'ol/proj.js';\nimport DataTileSource from 'ol/source/DataTile.js';\nimport { createXYZ, wrapX } from 'ol/tilegrid.js';\n\nexport const sigym2 = 'https://sigym3.com/';\nconst tz = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\nlet dimension_controls = [];\nfunction getBigTileGrid(projectionObj) {\n  return createForProjection(projectionObj, undefined, [512, 512])\n}\nfunction repositionTooltips() {\n  $('button.layer-info').each(function (_, btn) {\n    $('#tt' + btn.id).position({\n      my: 'left top',\n      at: 'right top',\n      of: btn,\n      collision: 'flipfit',\n    });\n  });\n}\nconst uniqId = (function () {\n  let i = 0;\n  return function () {\n    return i++;\n  }\n})();\n\nlet id_counter = 0;\nclass Layer {\n  constructor(ns, pageLayer, time_delta, interactive_map) {\n    this.ns = ns;\n    this.id = 'simmer_layer_' + id_counter++;\n    this._pageLayer = pageLayer;\n    this._layer = pageLayer.layer;\n    this._layerTypeLocator = this._layer.layertype?.locator;\n    this._baseLayer = this._layerTypeLocator == \"BASELAYER\";\n    this._refLayer = this._layerTypeLocator == \"REFERENCE\";\n    this._varLayer = this._layerTypeLocator == \"LAYER\";\n    let extra = this._layer.extra;\n    extra.pageLayer = pageLayer.id;\n    if (pageLayer.extra)\n      mergeDeep(extra, pageLayer.extra)\n    if (pageLayer.extra_dim) {\n      extra = { ...extra, ...pageLayer.extra_dim }\n    }\n    this._extra = extra;\n    const title = extra.title;\n    this._title = title ? title : this._layer.name_and_unit;\n    if (this._layer.service) {\n      this._layer.service.url = this._layer.service.url\n        ? this._layer.service.url.replace('http://localhost/', '/')\n        : null;\n      this._url = this._layer.service.url;\n    }\n    if (this._layer.source_type)\n      this._serviceLayer = this._layer.source_type.locator;\n    else\n      this._serviceLayer = this._layer.servicelayer;\n    this._legend = this._layer.legend;\n    this._information = this._layer.information;\n    this._time_delta = time_delta;\n    this._interactive_map = interactive_map;\n    this._dynDate = null;\n    this._dynInfo = '';\n\n  }\n  get legend() {\n    return this._legend;\n  }\n  getTooltip() {\n    return `${this._information}${this._dynInfo}`;\n  }\n  get ol_factory() {\n    return TileLayer;\n  }\n  get zIndex() {\n    return 30000000 - this._pageLayer.weight * 1000 + this._pageLayer.order;\n  }\n  getLayerInfo(target, checkbox) {\n    const pageLayer = this._pageLayer;\n    const tooltipBtn = $(`<button class=\"layer-info fa fa-info\" type=\"button\" ></button>`);\n    const id = uniqId();\n    tooltipBtn.attr('id', 'layer-info' + id);\n    const tooltip = $('<div class=\"layer tooltip\"></div>').hide();\n    tooltip.attr('id', 'ttlayer-info' + id);\n    if (this._information) {\n      const self = this;\n      target.append(tooltipBtn);\n      this.ns.page.find('.map').append(tooltip);\n      tooltipBtn.on('click', function () {\n        const ishidden = tooltip.is(\":hidden\");\n        $('.layer.tooltip').hide();\n        const info = self.getTooltip();\n        tooltip.empty();\n        tooltip.append(info);\n        tooltip.toggle(ishidden);\n        repositionTooltips();\n      });\n      this.ns.page.find('.map').on('click', function (e) {\n        if (tooltipBtn[0] != e.target)\n          tooltip.hide();\n      });\n    }\n    tooltipBtn.toggle(pageLayer.shown);\n    checkbox.on('change', function () {\n      tooltipBtn.toggle(this.checked);\n      tooltip.toggle(false);\n    })\n  }\n  setSliderLayer(target, checkbox) {\n    const ol_layer = this._ol_layer;\n    const pageLayer = this._pageLayer;\n    const sliderCnt = $(`<div class=\"slidecontainer\">\n    <div class=\"etiqueta\" hidden=\"true\"></div>\n    <input type=\"range\" min=\"0\" max=\"1\" \n    step=\"0.1\" value=\"${ol_layer.get('opacity') || 1}\" class=\"slider\">\n    </div>`);\n    target.append(sliderCnt);\n    const inpt = sliderCnt.find('input')[0];\n    const etq = sliderCnt.find('div.etiqueta')[0];\n    inpt.onmouseover = function () {\n      const w = sliderCnt.width();\n      etq.innerHTML = parseFloat(this.value) * 100 + \"%\";\n      etq.style.left = String((parseFloat(this.value) * w)) + 'px';\n      etq.hidden = false;\n    }\n    inpt.onmouseout = function () {\n      etq.hidden = true;\n    }\n\n    inpt.oninput = function () {\n      ol_layer.setOpacity(parseFloat(this.value))\n      const w = sliderCnt.width();\n      etq.innerHTML = parseFloat(this.value) * 100 + \"%\";\n      etq.style.left = String((parseFloat(this.value) * w)) + 'px';\n\n    }\n    sliderCnt.toggle(pageLayer.shown);\n    checkbox.on('change', function () {\n      sliderCnt.toggle(this.checked);\n    })\n  }\n  setCalculatedDate(props) {\n    const STATIC_LAYER = 'static layer';\n    if (props)\n      try {\n        const dt = dayjs(props.base_time || props.time);\n        if (dt.year() === 9999)\n          throw new Error(STATIC_LAYER)\n        this._dynDate = dt;\n        this._dynInfo = `<br><b>${window.gettext('Cálculo')}</b>: ${dt.utc().format('DD-MM-YYYY HH[h UTC]')}`;\n      } catch (error) {\n        this._dynDate = null;\n        this._dynInfo = '';\n        if (error.message != STATIC_LAYER)\n          console.info(error);\n      }\n    else {\n      this._dynDate = null;\n      this._dynInfo = '';\n    }\n  }\n  registerInTree() {\n    const pageLayer = this._pageLayer;\n    const ol_layer = this._ol_layer;\n    const ol_map = this._ol_map;\n    const closedTree = ol_map.get('closed_tree');\n    const visible_layers = getParameterByName('visible_layers').split(',');\n    if (visible_layers[0] != '') {\n      pageLayer.shown = visible_layers.some((l) => l == pageLayer.id);\n      ol_layer.setVisible(pageLayer.shown);\n    }\n    const raiz = this.ns.page.find('div.sidebar-pane.arbol');\n    const arbol = raiz.find('#' + this._layerTypeLocator);\n    const existing_selector = arbol.find('#pageLayerSelector_' + pageLayer.id);\n    if (existing_selector.length) {\n      // reutilizamos checkbox para todas las capas en el caso de mosaico\n      const checkbox = existing_selector.find('input');\n      checkbox.on('change', function () {\n        ol_layer.setVisible(this.checked);\n        return false;\n      });\n      return;\n    }\n    const selector = raiz.find('div.model_selector').clone();\n    selector.attr('id', 'pageLayerSelector_' + pageLayer.id);\n    selector.attr('id_layer', pageLayer.id);\n    const leyenda = raiz.find('div.model_leyenda').clone();\n\n    selector.removeClass('model_selector');\n    leyenda.removeClass('model_leyenda');\n    selector.show();\n    let target = arbol;\n    if (pageLayer.folder) {\n      const orig_path = pageLayer.folder.split('/');\n      const path = [];\n      for (const component of orig_path) {\n        path.push(component);\n        const folder = path.join('/');\n        const carpeta_existente = arbol.find(`div.folder[folder=\"${folder}\"]`);\n        const carpetaDestino = carpeta_existente.length ? carpeta_existente : raiz.find('div.model_carpeta').clone();\n        target = carpetaDestino;\n        if (carpeta_existente.length == 0) {\n          carpetaDestino\n            .removeClass('model_carpeta')\n            .text(null)\n            .attr('folder', folder)\n            .show();\n          const thisPath = [...path];\n          const folderTitle = thisPath.pop();\n          const title = $(`<div class=\"folder-toggler${closedTree ? '' : ' open'}\">${folderTitle}</div>`);\n          title.on('click', () => title.toggleClass('open'));\n          carpetaDestino.append(title)\n          if (thisPath.length) {\n            const parentCarpet = raiz.find(`div.folder[folder=\"${thisPath.join('/')}\"]`);\n            parentCarpet.append(carpetaDestino);\n          }\n          else\n            arbol.append(carpetaDestino);\n        }\n      }\n    }\n    const checkbox = selector.find('input');\n    checkbox.prop('checked', pageLayer.shown && !pageLayer.disabled);\n    checkbox.prop('disabled', pageLayer.disabled);\n    if (pageLayer.disabled) {\n      selector.addClass('disabled');\n      selector.attr('title', 'Simulación pendiente de ejecución')\n    }\n    const layerTitle = selector.find('a').text(this._title);\n    this.getLayerInfo(layerTitle, checkbox);\n    if (this._interactive_map) {\n      const layers_opacity = ol_map.get('layers_opacity');\n      if (layers_opacity) {\n        const layer_opacity = layers_opacity.find((l) => l.id == String(this._pageLayer.id));\n        if (layer_opacity) ol_layer.set('opacity', parseFloat(layer_opacity.value))\n      }\n      this.setSliderLayer(layerTitle, checkbox);\n    }\n    target.append(selector);\n    let legend = this.legend;\n    if (this._interactive_map && legend) {\n      const elem_leyenda = leyenda.find('img');\n      elem_leyenda.attr('src', legend);\n      leyenda.attr('id', pageLayer.id)\n      leyenda.toggle(pageLayer.shown);\n      target.append(leyenda);\n      if (ol_map.get('floating_legend')) {\n        const legendDialog = showLegend(null, ol_map, this);\n        leyenda.addClass('hidden');\n        checkbox.on('change', function () {\n          legendDialog.dialog(this.checked ? 'open' : 'close');\n        })\n        if (!pageLayer.shown)\n          legendDialog.dialog('close');\n      }\n    }\n    const self = this;\n    checkbox.on('change', function () {\n      ol_layer.setVisible(this.checked);\n      for (const control of self.controls)\n        if (this.checked)\n          control.use();\n        else\n          control.unuse();\n      const info = ol_map ? ol_map.get('info') : null;\n      if (info) {\n        ol_map.unset('info', true); \n        ol_map.set('info', info);\n      }\n      setVisibleLayers_url(self.ns.page, ol_map, pageLayer.id, this.checked);\n      if ($('.mosaics').length) {\n        const value = $('input#iteration').val();\n        if (value)\n          $(`ul#iteration-list li[value=${value}]`).trigger('click');\n        else\n          // FIXME\n          window.location.reload();\n      }\n      if (legend) {\n        leyenda.toggle(this.checked);\n        repositionTooltips();\n        const legendDialog = $(`.legend-dialog img.legend[src=\"${legend}\"]`);\n        if (legendDialog.length)\n          if (this.checked) {\n            legendDialog.dialog('option', 'position', getPosDefault(ol_map.getTargetElement()));\n            legendDialog.dialog('open');\n          }\n          else legendDialog.dialog('close');\n      }\n      return false;\n    });\n    this.controls = [];\n    if (this._layer.source_type) {\n      dimension_controls = (this._ol_map) ? this._ol_map.get('dimension_controls') : dimension_controls;\n      for (const dim of this._layer.source_type.dimensions) {\n        if (dim.value_type == 'PERIODIC')\n          // De momento es especial; no hacemos nada\n          continue\n        if (pageLayer?.extra?.dimensions && dim.locator in pageLayer.extra.dimensions)\n          continue\n        if (this._layer?.extra?.dimensions && dim.locator in this._layer.extra.dimensions)\n          continue\n        const control = dimension_controls[dim.locator];\n        let dim_value = getParameterByName(dim.locator);\n        let control_empty = false;\n        if (dim_value.split(',').length > 1)\n          control_empty = true;\n        if (this._ol_map && this._ol_map.get(\"reloaded_dims\")) {\n          const reloaded_dims = this._ol_map.get(\"reloaded_dims\")\n          dim_value = (reloaded_dims[dim.locator]) ? reloaded_dims[dim.locator] : dim_value\n        }\n        if (!control_empty)\n          control.value = (dim_value) ? dim_value : dim.values[0][0];\n        this.source.updateParams({ [dim.locator]: control.value });\n        control.on('change:value',\n          () => this.source.updateParams({ [dim.locator]: control.value })\n        )\n        if (ol_layer.getVisible())\n          control.use();\n        this.controls.push(control);\n      }\n      this._layer.source_type._dimension_controls = dimension_controls;\n    }\n  }\n  async crearCapaOL(ol_map, extent_local) {\n    let src = this.source;\n    if (src == null)\n      src = await this.get_async_source();\n    const extraOpts = await this.getExtraOpts();\n    const ret = new this.ol_factory({\n      source: src,\n      title: this._title,\n      opacity: 1,\n      visible: this._pageLayer.shown && !this._pageLayer.disabled,\n      baseLayer: this._baseLayer,\n      displayInLayerSwitcher: this._baseLayer,\n      time_management: this._varLayer,\n      extra: this._extra,\n      simmer_id: this._pageLayer.id, // FIXME: está en extra\n      zIndex: this.zIndex,\n      ...extraOpts\n    });\n    const unit = this._pageLayer.layer.effective_unit;\n    ret.set('unit', unit ? unit : '-');\n    if (this._varLayer && !this._extra.unbound)\n      ret.setExtent(extent_local);\n    if (this._baseLayer)\n      ret.set('information', this._pageLayer.layer.information);\n    if (this._pageLayer.folder)\n      ret.set('folder', this._pageLayer.folder);\n    this._ol_layer = ret;\n    this._ol_map = ol_map;\n    if (ol_map)\n      ol_map.addLayer(ret);\n    if (this._varLayer || this._refLayer)\n      this.registerInTree();\n    return ret;\n  }\n  async getExtraOpts() {\n    return {};\n  }\n  get layerCaption() {\n    const dims = [];\n    if (this._layer.source_type?.dimensions)\n      for (const dim of this._layer.source_type.dimensions) {\n        if (dim.locator in dimension_controls) {\n          const control = dimension_controls[dim.locator];\n          dims.push(`${control.name}: ${control._caption}`)\n        }\n      }\n    let name = this._pageLayer.folder ?\n      this._pageLayer.folder + ' - ' + this._title :\n      this._title;\n    if (this._ol_map.get('graph_show_run_time') && this._dynDate)\n      name += ` ⏲ ${this._dynDate.utc().format('DD-MM-YYYY HH[h UTC]')}`\n    return `${name}${dims.length ? ' | ' + dims.join(' | ') : ''}`;\n  }\n}\nclass OSMLayer extends Layer {\n  get source() {\n    return new OSM();\n  }\n}\nclass BingLayer extends Layer {\n  get source() {\n    return new BingMaps({\n      key: this._url.split('#').pop(),\n      imagerySet: this._serviceLayer\n    });\n  }\n}\n\nclass WMTSLayer extends Layer {\n  get source() {\n    if (this._src)\n      return this._src;\n    return null;\n  }\n  async get_async_source() {\n    const projection = this._extra.epsg || window.epsg;\n    const matrixSet = this._extra.matrixSet || (projection == 'EPSG:3857' ? 'GoogleMapsCompatible' : projection);\n    const response = await fetch(this._url);\n    const text = await response.text();\n    const parser = new WMTSCapabilities();\n    const result = parser.read(text);\n    const options = optionsFromCapabilities(result, {\n      layer: this._serviceLayer,\n      matrixSet: matrixSet\n    });\n    const ret = new WMTS(options);\n    if (ret.urls[0].includes('http:'))\n      ret.setUrl(ret.urls[0].replace(/http:/, 'https:'))\n    this._src = ret;\n    return ret;\n  }\n\n}\nclass XYZLayer extends Layer {\n  get source() {\n    const src = new XYZ(\n      {\n        url: this._url.replace('{layer}', this._serviceLayer),\n        maxZoom: this._extra.maxZoom\n      }\n    );\n    src.set('time_delta', this._time_delta);\n    src.on('change:time', function () {\n      const time = this.get('time');\n      const effective_time = time.add(this.get('time_delta') || 0, 'hours');\n      this.set('effective_time', effective_time);\n      // const ISOstart = effective_time.format();\n      // FIXME casuística según servidor\n      //this.updateParams({TIME:ISOstart});\n    });\n    return src;\n  }\n}\n\nclass WMSLayer extends Layer {\n  async updateDynInfo() {\n    if (this._ol_map.get('animation'))\n      return;\n    const url = window.Urls.dyn_info(this._pageLayer.id)\n    $.ajax({\n      url: url,\n      dataType: 'json',\n      contentType: 'application/json',\n      data: { TIME: this.source.getParams().TIME }\n    })\n      .done(resp => {\n        try {\n          this.setCalculatedDate(resp);\n        }\n        catch {\n          console.debug(url);\n          this.setCalculatedDate(null);\n        }\n      })\n      .fail(() => this.setCalculatedDate(null));\n  }\n  get source() {\n    if (this._src)\n      return this._src;\n    let params = {\n      LAYERS: this._serviceLayer,\n      STYLES: ','.repeat(this._serviceLayer.split(',').length - 1)\n    };\n    if (this._extra.dimensions) {\n      params = {\n        ...params,\n        ...this._extra.dimensions\n      }\n    }\n    params = {\n      __tz: tz,\n      ...params,\n      ...this._extra\n    };\n    let tileGrid = null;\n    const projection = this._extra.epsg || window.epsg;\n    let url = this._url;\n    if (url.includes(sigym2)) {\n      url = url.replace(sigym2, '');\n      url = window.Urls.proxy_meteo2(url);\n      params.VERSION = '1.1.1';\n      params.AUTH_TYPE = 'basic';\n      tileGrid = getBigTileGrid(projection);\n    }\n    if (this._layer.source_type) {\n      tileGrid = getBigTileGrid(projection);\n    }\n    const [src_factory, ratio] = this._interactive_map && !this._extra.singleTile\n      ? [TileWMS, null]\n      : [ImageWMS, 1];\n    const src = new src_factory({\n      url,\n      params,\n      projection,\n      tileGrid,\n      ratio\n    });\n    const self = this;\n    let finalTime;\n    src.set('time_delta', this._time_delta);\n    const timeFormat = this._extra?.timeFormat;\n    const firstTime = this._extra?.firstTime;\n    const secondTime = this._extra?.secondTime;\n    src.on('change:time', function () {\n      const time = this.get('time');\n      const time_delta = this.get('time_delta') || 0;\n      const effective_time = typeof time_delta == 'number' ? time.add(time_delta, 'hours') : time_delta;\n      this.set('effective_time', effective_time);\n      if (firstTime && secondTime) {\n        const ISOstart = effective_time.add(...firstTime).format(timeFormat);\n        const ISOend = effective_time.add(...secondTime).format(timeFormat);\n        finalTime = ISOstart + '/' + ISOend;\n      } else if (firstTime) {\n        const ISOstart = effective_time.add(...firstTime).format(timeFormat);\n        const ISOend = effective_time.format(timeFormat);\n        finalTime = ISOstart + '/' + ISOend;\n      } else if (secondTime) {\n        const ISOstart = effective_time.format(timeFormat);\n        const ISOend = effective_time.add(...secondTime).format(timeFormat);\n        finalTime = ISOstart + '/' + ISOend;\n      } else {\n        const ISOstart = effective_time.format(timeFormat);\n        finalTime = ISOstart;\n      }\n      this.updateParams({ TIME: finalTime });\n      if ((self._interactive_map || self._time_delta === 0) &&\n        self._information &&\n        !self._pageLayer.disabled &&\n        !window.time_type?.locator.startsWith('ENUM'))\n        window.setTimeout(() => self.updateDynInfo(), self._ol_layer?.getVisible() ? 2000 : 5000 + Math.random() * 2000);\n    });\n    this._src = src;\n    return src;\n  }\n  get ol_factory() {\n    return this._interactive_map && !this._extra.singleTile ? TileLayer : ImageLayer;\n  }\n  get legend() {\n    let legend = this._legend;\n    if (!legend)\n      return legend;\n    if (legend.includes(sigym2)) {\n      legend = legend.replace(sigym2, '');\n      return window.Urls.proxy_meteo2(legend);\n    }\n    if (legend !== 'auto')\n      return legend;\n    const params = {\n      pageLayerId: this._pageLayer.id,\n      TRANSPARENT: 'TRUE'\n    };\n    return this.source.getLegendUrl(null, params);\n  }\n}\n\nclass WMSFlowLayer extends WMSLayer {\n  async getColorStops() {\n    const params = {\n      SERVICE: 'WMS',\n      VERSION: '1.3.0',\n      REQUEST: 'GetLegendGraphic',\n      FORMAT: 'application/json',\n      PAGELAYERID: this._pageLayer.id,\n      LAYERS: this._serviceLayer,\n      WIDTH: 256,\n      HEIGHT: 256,\n    };\n    const resp = await fetch(`${this._url}?${new URLSearchParams(params)}`);\n    const colorStops = await resp.json();\n    colorStops[0] = [0, 0, 0, 0];\n    return colorStops;\n  }\n  get legend() {\n    let legend = this._legend;\n    if (!legend || legend !== 'auto')\n      return legend;\n    const params = {\n      SERVICE: 'WMS',\n      VERSION: '1.3.0',\n      REQUEST: 'GetLegendGraphic',\n      FORMAT: 'image/png',\n      PAGELAYERID: this._pageLayer.id,\n      LAYERS: this._serviceLayer,\n      WIDTH: 150,\n      TRANSPARENT: 'TRUE'\n    };\n    return `${this._url}?${new URLSearchParams(params)}`;\n  }\n\n\n  async getExtraOpts() {\n    const jsonColors = await this.getColorStops();\n    const colorStops = [];\n    for (const [k, v] of Object.entries(jsonColors)) {\n      colorStops.push(parseFloat(k));\n      colorStops.push(v);\n    }\n    return {\n      maxSpeed: colorStops.at(-2),\n      style: {\n        color: [\n          'interpolate',\n          ['linear'],\n          ['get', 'speed'],\n          ...colorStops],\n      },\n    };\n  }\n\n  get ol_factory() {\n    return Flow;\n  }\n\n  get source() {\n    if (this._src)\n      return this._src;\n    const self = this;\n    const dataTileSize = 256;\n    const dataBands = 3;\n    const projection = this._extra.epsg || window.epsg;\n    const params = {\n      LAYERS: this._serviceLayer,\n      STYLES: ','.repeat(this._serviceLayer.split(',').length - 1)\n    };\n    if (this._extra.dimensions) {\n      Object.assign(params, this._extra.dimensions);\n    }\n    this.params = {\n      __tz: tz,\n      REQUEST: 'GetMap',\n      SERVICE: 'WMS',\n      VERSION: '1.3.0',\n      FORMAT: 'application/uv_particles',\n      STYLES: '',\n      TRANSPARENT: 'TRUE',\n      WIDTH: dataTileSize,\n      HEIGHT: dataTileSize,\n      CRS: projection,\n      ...params,\n      ...this._extra,\n    };\n    const dataTileGrid = createXYZ();\n    const dataTileProjection = getProjection('EPSG:3857');\n    const wind = new DataTileSource({\n      // transition must be 0, see https://github.com/openlayers/openlayers/issues/16119\n      transition: 0,\n      wrapX: true,\n      async loader(z, x, y) {\n        const tileCoord = wrapX(dataTileGrid, [z, x, y], dataTileProjection);\n        const params = { ...self.params, BBOX: dataTileGrid.getTileCoordExtent(tileCoord) };\n        const resp = await fetch(`${self._url}?${new URLSearchParams(params)}`);\n        if (!resp.ok) {\n          throw new Error(`tile ${z}/${x}/${y} failed`);\n        }\n        const { width, height, u, v } = await resp.json();\n        if (width != dataTileSize) {\n          console.warn('width != dataTileSize')\n        }\n        if (height != dataTileSize) {\n          console.warn('height != dataTileSize')\n        }\n        const data = new Float32Array(dataTileSize * dataTileSize * dataBands);\n        for (let row = 0; row < dataTileSize; ++row) {\n          let offset = row * dataTileSize * dataBands;\n          for (let col = 0; col < dataTileSize; ++col) {\n            data[offset] = u[row][col];\n            data[offset + 1] = v[row][col];\n            offset += dataBands;\n          }\n        }\n        return data;\n      },\n    });\n    wind.on('change:time', function () {\n      const time = this.get('time');\n      const effective_time = time.add(this.get('time_delta') || 0, 'hours');\n      this.set('effective_time', effective_time);\n      const ISOstart = effective_time.format();\n      self.params.TIME = ISOstart;\n      self._ol_layer.setSource(null);\n      self._ol_layer.setSource(this);\n    });\n    this._src = wind;\n    return wind;\n  }\n}\n\n\n\nfunction setVisibleLayers_url(page, ol_map, l_id, isVisible) {\n  let visible_layers = getParameterByName('visible_layers').split(',');\n  if (visible_layers[0] == '') {\n    const fondo = [];\n    for (const l of ol_map.getLayers().getArray()) {\n      if (l.get('baseLayer') && l.get('visible')) {\n        fondo.push(l.get('simmer_id'));\n        break;\n      }\n    }\n    const arbol = page.find('div.arbol');\n    const capas = arbol.find('#LAYER').find('div.mostrar-capa.selector:not(.cambios)').map((i, l) =>\n      ($(l).find('input.mostrar').prop('checked')) ? '' + $(l).attr('id_layer') : null).toArray();\n    const references = arbol.find('#REFERENCE').find('div.mostrar-capa.selector').map((i, l) =>\n      ($(l).find('input.mostrar').prop('checked')) ? '' + $(l).attr('id_layer') : null).toArray();\n    visible_layers = [...fondo, ...references, ...capas];\n  }\n  else {\n    visible_layers = visible_layers.filter(x => x != String(l_id));\n    if (isVisible)\n      visible_layers.push('' + l_id);\n  }\n  const oldUrl = window.location.href;\n  let newUrl = oldUrl.replace(/(visible_layers=)[^&]*(.*)/, '$1' + visible_layers + '$2');\n  if (!newUrl.includes('visible_layers')) {\n    const sep = oldUrl.includes('?') ? '&' : '?'\n    newUrl += sep + 'visible_layers=' + visible_layers;\n  }\n  window.history.replaceState(null, null, newUrl);\n}\nfunction showLegend(e, mapa, pl) {\n  let pageLayer;\n  pageLayer = pl;\n  if (!pageLayer)\n    return;\n  const lyr_name = pageLayer._layer.name_and_unit;\n  const target = mapa.getTargetElement();\n  const legendUrl = target.classList.contains('map') ?\n    $(`div#${pageLayer._pageLayer.id}.leyenda`).find('img').attr('src') :\n    $(`#${pageLayer._pageLayer.id}_legend`).attr('src');\n  if (!legendUrl) {\n    mapa.set('notification', window.gettext('No existe leyenda para la capa seleccionada'));\n    window.setTimeout(() => mapa.set('notification', null), 2500);\n    return;\n  }\n  const legend_element = $(`<img class=\"legend\" src =\"${legendUrl}\" />`);\n  let new_pos = getPosDefault(target);\n  if (e) {\n    const pixel = mapa.getPixelFromCoordinate(e.coordinate);\n    new_pos = {\n      my: 'left top',\n      at: 'left+' + pixel[0] + ' top+' + pixel[1],\n      of: target,\n      collision: 'fit'\n    };\n  }\n  else {\n    mapa.once('postrender', () => {\n      if (mapa.get(\"pos_legs\")) {\n        const pos = mapa.get(\"pos_legs\").find((l) => l.id == legend_element.attr('id'));\n        if (pos) {\n          new_pos = {\n            my: pos.my,\n            at: pos.at,\n            of: pos.mytarget ? target : window,\n            collision: 'fit'\n          };\n          legend_element.dialog('option', 'position', new_pos);\n        }\n        else legend_element.dialog('close')\n      }\n    })\n  }\n  const existing_legend_element = $(`.legend-dialog img.legend[src=\"${legendUrl}\"]`);\n  if (existing_legend_element.length) {\n    existing_legend_element.dialog('option', 'position', new_pos);\n    existing_legend_element.dialog('open');\n    return existing_legend_element;\n  }\n\n  legend_element.dialog({\n    appendTo: target,\n    classes: {\n      \"ui-dialog\": \"ui-corner-all legend-dialog\",\n      \"ui-dialog-titlebar\": \"ui-corner-all\",\n    },\n    position: new_pos,\n    width: \"auto\",\n    height: \"auto\",\n    title: lyr_name,\n    autoOpen: true,\n    resizable: false,\n    zIndex: 10000,\n    minHeight: 'none',\n    open: function () {\n      $('button.ui-dialog-titlebar-close').attr('title', `${window.gettext('Cerrar')}`)\n      legend_element.closest('div[role=dialog]').prop('title', lyr_name);\n    }\n  });\n  if (!mapa.get(\"pos_legs\"))\n    legend_element.one('load', () =>\n      legend_element.dialog('option', 'position', getPosDefault(target))\n    )\n  return legend_element;\n}\nfunction getPosDefault(target) {\n  let pixel = [-35, -35]\n  return {\n    my: 'right bottom',\n    at: 'right+' + pixel[0] + ' bottom+' + pixel[1],\n    of: target,\n    collision: 'fit'\n  };\n}\nexport { Layer, BingLayer, XYZLayer, WMSLayer, WMSFlowLayer, WMTSLayer, OSMLayer, repositionTooltips, setVisibleLayers_url, showLegend };\n","import { $ } from '../../../../moderna_meteogrid/statix/js/base.mjs';\n\nimport { transform as ol_proj_transform } from 'ol/proj'\nimport ol_control_SearchJSON from 'ol-ext/control/SearchJSON';\nimport Feature from 'ol/Feature';\nimport Point from 'ol/geom/Point'\nimport { Style, Icon } from 'ol/style';\nimport { Vector as VectorLayer } from 'ol/layer';\nimport { Vector as VectorSource } from 'ol/source';\nimport { containsCoordinate } from 'ol/extent';\n\n\n/**\n * Search places using the Nominatim geocoder from the OpenStreetmap project.\n *\n * @constructor\n * @extends {ol-ext.control.SearchNominatim}\n * @fires select\n * @param {Object=} Control options.\n *  @param {string} options.className control class name\n *  @param {boolean | undefined} options.polygon To get output geometry of results (in geojson format), default false.\n *  @param {Array<Number> | undefined} options.viewbox The preferred area to find search results. Any two corner points of the box are accepted in any order as long as they span a real box, default none.\n *  @param {boolean | undefined} options.bounded Restrict the results to only items contained with the bounding box. Restricting the results to the bounding box also enables searching by amenity only. default false\n *  @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport.\n *  @param {string | undefined} options.label Text label to use for the search button, default \"search\"\n *  @param {string | undefined} options.placeholder placeholder, default \"Search...\"\n *  @param {number | undefined} options.typing a delay on each typing to start searching (ms), default 500.\n *  @param {integer | undefined} options.minLength minimum length to start searching, default 3\n *  @param {integer | undefined} options.maxItems maximum number of items to display in the autocomplete list, default 10\n *\n *  @param {string|undefined} options.url URL to Nominatim API, default \"https://nominatim.openstreetmap.org/search\"\n * @see {@link https://wiki.openstreetmap.org/wiki/Nominatim}\n */\n\n\nclass ol_control_SearchES extends ol_control_SearchJSON {\n\n\n  constructor(options) {\n\n    options = options || {};\n    options.className = options.className || 'nominatim';\n    options.typing = options.typing || 500;\n    options.url = options.url || 'https://nominatim.openstreetmap.org/search';\n    super(options);\n    this.set('polygon', options.polygon);\n    this.set('viewbox', options.viewbox);\n    this.set('bounded', options.bounded);\n    this.set('alertmsg', options.alertmsg);\n  }\n\n  /** Returns the text to be displayed in the menu\n   *\t@param {ol.Feature} f the feature\n  *\t@return {string} the text to be displayed in the index\n  *\t@api\n  */\n  getTitle(f) {\n    return f.id.search('IGN') != -1 ?\n      f.title + ', ' + f.type :\n      f.address;\n  }\n\n  /** \n   * @param {string} s the search string\n   * @return {Object} request data (as key:value)\n   * @api\n   */\n  requestData_idee(s) {\n    var data = {\n      format: 'jsonp',\n      name_equals: s,\n      maxresults: 20,\n      polygon_geojson: this.get('polygon') ? 1 : 0,\n      bounded: this.get('bounded') ? 1 : 0,\n    };\n\n    if (this.get('viewbox')) data.viewbox = this.get('viewbox');\n    return data;\n  }\n  requestData_cc(s) {\n    var data = {\n      format: \"json\",\n      addressdetails: 1,\n      q: s,\n      polygon_geojson: this.get('polygon') ? 1 : 0,\n      bounded: this.get('bounded') ? 1 : 0,\n      limit: this.get('maxItems')\n    };\n\n    if (this.get('viewbox')) data.viewbox = this.get('viewbox');\n    return data;\n  }\n\n  /** A ligne has been clicked in the menu > dispatch event\n   *\t@param {any} f the feature, as passed in the autocomplete\n  *\t@api\n  */\n  select(f) {\n    var mapa = this.getMap();\n    var viewbox = this.get('viewbox');\n    var alertmsg = this.get('alertmsg');\n\n\n    if (f.id.search('IGN') != -1) {\n      $.ajax({\n        \"url\": 'https://www.idee.es/communicationsPoolServlet/Dispatcher',\n        \"dataType\": 'jsonp',\n        \"crossDomain\": true,\n        data: {\n          \"request\": 'OpenQuerySource',\n          \"query\": '<ogc:Filter><ogc:FeatureId fid=\"' + f.id + '\"/></ogc:Filter>',\n          \"sourcename\": 'http://www.idee.es/communicationsPoolServlet/sourceAccessWFS-INSPIRE-NGBE.rdf',\n          \"outputformat\": 'application/json'\n        },\n        success: function (cord) {\n          processData(cord.results[0].location, mapa, viewbox, alertmsg);\n        },\n        error: function (err) {\n          alert(err);\n        }\n      })\n\n    }\n    else {\n      var url = encodeURI('https://www.cartociudad.es/geocoder/api/geocoder/findJsonp');\n      var opt = {};\n      opt.dataType = 'jsonp';\n      var data = {\n        id: f.id,\n        type: f.type,\n        portal: f.portalNumber\n      }\n\n      this.ajax(url, data, function (resp) {\n        const response = JSON.parse(resp.slice(9, -1))\n        processData(response, mapa, viewbox, alertmsg);\n      }, opt);\n    }\n  }\n}\nfunction processData(result, mapa, viewbox, alertmsg) {\n  let lat = Number(result.lat);\n  let lng = Number(result.lng);\n  if (isNaN(lat) || isNaN(lng)) {\n    const cords = result.split(' ');\n    lat = parseFloat(cords[0]);\n    lng = parseFloat(cords[1]);\n\n  }\n  const olproj = mapa.getView().getProjection();\n  var c = ol_proj_transform([lng, lat], 'EPSG:4326', olproj);\n  if (containsCoordinate(viewbox, c)) {\n    mapa.getView().animate({\n      center: c,\n      zoom: Math.max(mapa.getView().getZoom(), 14)\n    }); mapa.addLayer(getMarkerVectorLayer(c));\n  }\n  else {\n    alertmsg.show('<div><p>' + window.gettext('La dirección seleccionada no se encuentra en la extensión del mapa...') + '</p></div>');\n    setTimeout(() => {\n      alertmsg.hide();\n    }, 5000)\n  }\n}\n\nfunction getMarkerVectorLayer(xy) {\n  var marker = new Feature({\n    geometry: new Point(xy),\n  });\n  const styles = getComputedStyle(document.body);\n  const color_marker = styles.getPropertyValue('--main-color').trim();\n  var iconStyle = new Style({\n    image: new Icon({\n      color: color_marker,\n      crossOrigin: 'anonymous',\n      anchorOrigin: 'bottom-left',\n      anchor: [0.5, 0],\n      anchorXUnits: 'fraction',\n      anchorYUnits: 'fraction',\n      src: '/media/uploads/site/location_pin.png',\n      scale: 0.5\n    })\n  });\n  marker.setStyle(iconStyle);\n  var vectorSource = new VectorSource({\n    features: [marker]\n  });\n  const markerVectorLayer = new VectorLayer({\n    source: vectorSource,\n    title: 'Marker',\n    displayInLayerSwitcher: false\n\n  });\n  markerVectorLayer.setZIndex(Infinity);\n  return markerVectorLayer;\n}\n\n\nol_control_SearchES.prototype.autocomplete = function (s, cback) {\n  this.cont = -1;\n  const url = window.location.protocol == 'https:'?\n     this.get('url').split(','):\n   this.get('url');\n\n  for (var i = 0; i < 2; i++) {\n    if (url[i].search('idee') != -1) {\n      const data = this.requestData_idee(s);\n      const opt = {};\n      opt.dataType = 'jsonp';\n      opt.data = data;\n      opt.url = url[i];\n      json(opt).then(function (res) {\n        ++this.cont;\n        cback(res.results)\n      }.bind(this))\n    }\n    else {\n      const data = this.requestData_cc(s);\n      const opt = {};\n      opt.dataType = 'jsonp';\n      opt.data = data;\n      opt.url = url[i];\n      this.ajax(opt.url, data, function (resp) {\n        ++this.cont;\n        if (typeof (cback) === 'function') cback(this.handleResponse(resp));\n      }, opt);\n    }\n  }\n}\n\n/** Draw the list\n* @param {Array} auto an array of search result\n* @private\n*/\nol_control_SearchES.prototype.drawList_ = function (auto) {\n  var self = this;\n  var ul = this.element.querySelector(\"ul.autocomplete\");\n  if (!auto) {\n    this.cont = -1;\n    var input = this.element.querySelector(\"input.search\");\n    var value = input.value;\n    auto = [];\n    if (!value) {\n      auto = this.get('history');\n    } else {\n      return;\n    }\n    ul.setAttribute('class', 'autocomplete history');\n  } else {\n    ul.setAttribute('class', 'autocomplete');\n  }\n  if (this.cont < 1) {\n    ul.innerHTML = '';\n    this._list = [];\n  }\n  var li, max = Math.min(self.get(\"maxItems\"), auto.length);\n  for (var i = 0; i < max; i++) {\n    if (auto[i]) {\n      if (!i || !self.equalFeatures(auto[i], auto[i - 1])) {\n        li = document.createElement(\"LI\");\n        li.setAttribute(\"data-search\", this._list.length);\n        this._list.push(auto[i]);\n        li.addEventListener(\"click\", function (e) {\n          self._handleSelect(self._list[e.currentTarget.getAttribute(\"data-search\")]);\n        });\n        var title = self.getTitle(auto[i]);\n        if (title instanceof Element) li.appendChild(title);\n        else li.innerHTML = title;\n        ul.appendChild(li);\n      }\n    }\n  }\n};\nfunction json(obj) {\n  return new Promise(function (resolve, reject) {\n    const url = encodeUrlXhr(obj.url, obj.data);\n    const config = {\n      method: 'GET',\n      mode: 'cors',\n\n    };\n\n    if (obj.dataType == 'jsonp') {\n      jsonp(url, 'callback', resolve);\n    } else {\n      fetch(url, config)\n        .then(function (r) { return r }).then(resolve)\n        .catch(reject);\n    }\n\n  });\n}\nfunction encodeUrlXhr(url, data) {\n  if (data && typeof data === 'object') {\n    url += (/\\?/.test(url) ? '&' : '?') + toQueryString(data);\n  }\n  return url;\n}\nfunction toQueryString(obj) {\n  return Object.keys(obj).reduce(function (a, k) {\n    a.push(\n      typeof obj[k] === 'object'\n        ? toQueryString(obj[k])\n        : ((encodeURIComponent(k)) + \"=\" + (encodeURIComponent(obj[k])))\n    );\n    return a;\n  }, []).join('&');\n}\n\nfunction jsonp(url, key, callback) {\n  // https://github.com/Fresheyeball/micro-jsonp/blob/master/src/jsonp.js\n  let head = document.head,\n    script = document.createElement('script'),\n    // generate minimally unique name for callback function\n    callbackName = 'f' + Math.round(Math.random() * Date.now());\n\n  // set request url\n  script.setAttribute('src',\n    /*  add callback parameter to the url\n          where key is the parameter key supplied\n          and callbackName is the parameter value */\n    (url + (url.indexOf('?') > 0 ? '&' : '?') + key + '=' + callbackName));\n\n  /*  place jsonp callback on window,\n      the script sent by the server should call this\n      function as it was passed as a url parameter */\n  window[callbackName] = function (data) {\n    window[callbackName] = undefined;\n\n    // clean up script tag created for request\n    setTimeout(function () { return head.removeChild(script); }, 0);\n\n    // hand data back to the user\n    callback(data);\n  };\n\n  // actually make the request\n  head.appendChild(script);\n}\nexport default ol_control_SearchES;\n","import { $, dayjs, flatpickr, getFormData, transform_point, get_horizon } from '../../../moderna_meteogrid/statix/js/base.mjs';\n\n\nimport WKT from 'ol/format/WKT';\nimport { getArea } from 'ol/sphere';\nimport { Polygon, MultiPolygon } from 'ol/geom';\n\nimport { numeric_lang_format, create_graph_control } from '../../../simmer/statix/simmer/js/mapa.mjs'\n\n\n\nlet mapa;  //  FIXME: objeto global un poco feo\n\nfunction initializeMapa(mapa_) { //  FIXME: objeto global un poco feo\n  mapa = mapa_;\n}\n\n\nfunction configureCalendar(calendar_element, enableTime) {\n  const options = {}\n  if (enableTime && window.timelinectl) {\n    try {\n      options.minDate = window.timelinectl.timeline.getCustomTime('Inicio').toISOString();\n      options.maxDate = window.timelinectl.timeline.getCustomTime('Fin').toISOString();\n    } catch {\n      null;\n    }\n  }\n  return flatpickr(calendar_element, {\n    wrap: true,\n    dateFormat: enableTime ? 'Y-m-dTH:i' : 'Y-m-d',\n    altInput: true,\n    altFormat: enableTime ? 'd-m-Y H:i' : 'd-m-Y',\n    allowInput: true,\n    //static: true,\n    clickOpens: true,\n    enableTime,\n    time_24hr: true,\n    minuteIncrement: 1,\n    appendTo: calendar_element.find('input.form-control')[0],\n    ...options\n  });\n}\n\nfunction elementValue(value) {\n  if (value == null) return '';\n  if (Array.isArray(value)) {\n    let ret = [];\n    for (const x of value)\n      ret.push(elementValue(x));\n    return ret.join(', ');\n  }\n  if (typeof value == 'object' && value.name) return value.name;\n  if (typeof value == 'object') return value.toString();\n  return value;\n}\n\nfunction crearSubCasilla(vdat, value, klass, readOnly) {\n  const format = vdat.type.format;\n  if (klass === 'parameter') {\n    const casilla = $('<select class=\"data_new\"></select>');\n    $.getJSON(window.window.Urls.parameter_options(vdat.type.parameter_type.locator), function (json) {\n      if (!vdat.fixed)\n        $('<option />')\n          .val(null)\n          .html('-')\n          .appendTo(casilla);\n      for (const opt of json) {\n        const selected = value ? value.id == opt.id : false;\n        $('<option ' + (selected ? 'selected=\"selected\"' : '') + '/>')\n          .val(opt.id)\n          .html(opt.name)\n          .appendTo(casilla);\n      }\n    });\n    return casilla;\n  }\n  if (klass === 'multiparameter') {\n    const casilla = $('<select class=\"data_new\" multiple></select>');\n    $.getJSON(window.Urls.parameter_options(vdat.type.parameter_type.locator), function (json) {\n      if (!vdat.fixed)\n        $('<option />')\n          .val(null)\n          .html('-')\n          .appendTo(casilla);\n      for (const k in json) {\n        const opt = json[k];\n        const selected = value && value.some(function (x) { return x.id == opt.id });\n        $('<option ' + (selected ? 'selected=\"selected\"' : '') + '/>')\n          .val(opt.id)\n          .html(opt.name)\n          .appendTo(casilla);\n      }\n    });\n    return casilla;\n  }\n  if (klass === 'date') {\n    const type = /[Hh]/.test(format) ? 'datetime-local' : 'date';\n    let dvalue = '';\n    if (value) {\n      const mvalue = dayjs(value);\n      if (type == 'date')\n        dvalue = mvalue.format('YYYY-MM-DD')\n      else\n        dvalue = mvalue.local().format('YYYY-MM-DD HH:mm');\n    }\n    if (readOnly) {\n      return dvalue;\n    } else {\n      const hasTime = type === 'datetime-local';\n      const placeholder = hasTime ? 'DD-MM-YYYY hh:mm' : 'DD-MM-YYYY';\n      const klass = hasTime ? 'hasTime' : 'hasNoTime';\n      const input_date = $(`\n          <span class=\"calendar-filter ${klass}\">\n          <input type=\"text\" value=\"${dvalue}\" placeholder=\"${placeholder}\" class=\"data_new\" data-input>\n          <a class=\"input-button\" title=\"${window.gettext('Abrir calendario')}\" data-toggle>\n            <i class=\"fa fa-calendar-alt\" id=\"calendar-icon\"></i>\n          </a>\n        </span>\n      `)\n      configureCalendar(input_date, hasTime);\n      return input_date;\n    }\n  }\n  if (klass === 'file') {\n    let ret = `<label name=\"upload\" title=\"${window.gettext(value ? 'Sustituir fichero existente' : 'Subir fichero')}\">\n          <input type=\"file\" class=\"data_new\" />\n          <i class=\"fa fa-cloud-upload\"></i>\n        </label>`\n    if (vdat.type.columns != 'file' && value?.url) // dato simple\n      ret += ` <a target=\"_blank\" href=\"${value.url}\"><i class=\"enlace-icono fa fa-book\" ></i>\n      ${value.url.split(/[\\\\/]/).pop()}</a> `;\n    return $(ret);\n  }\n  if (klass === 'integer')\n    return $('<input class=\"data_new\" type=\"number\">');\n  if (klass === 'float')\n    return $('<input class=\"data_new\" type=\"number\">');\n  if (klass === 'boolean')\n    return $(`<label>\n                  <input class=\"data_new\" value=\"True\" type=\"checkbox\" ${vdat.value ? 'checked=\"checked\"' : ''}>\n                  <a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>\n              </label>`);\n  if (klass === 'geom') {\n    const ret = $(`<span class=\"ui-dialog-buttonpane\">\n      <button class=\"geom-point\" title=\"${window.gettext('ubicación')}\"><i class=\"fa-solid fa-location-pin\"></i></button>\n      <textarea class=\"data_new hidden\"></textarea>\n    </span >`)\n    if (!readOnly) {\n      ret.append($(`<button class=\"geom-delete\" title=\"${window.gettext('eliminar ubicación')}\"><i class=\"fa-solid fa-x\"></i></button>\n      `))\n      ret.find('button.geom-point').on('click', function (evt) {\n        evt.preventDefault();\n        mapa.set('new_feature', 'Point');\n      });\n      ret.find('button.geom-delete').on('click', function (evt) {\n        evt.preventDefault();\n        ret.find('textarea').val('');\n      });\n    }\n    return ret;\n  }\n  return $('<textarea class=\"data_new\"></textarea>');\n}\nfunction crearCasilla(vdat, recuadro, order, readOnly) {\n  const name = `data_${vdat.type.id}_${order}`;\n  const klasses = vdat.type.klass.split(' ');\n  for (const [idx, klass] of klasses.entries()) {\n    const value = klasses.length === 1 ? vdat.value : vdat.value[idx];\n    const casilla = crearSubCasilla(vdat, value, klass, readOnly);\n    const cell = recuadro[idx];\n    cell.append(casilla);\n    if ((value !== null) && !['file', 'date'].includes(klass))\n      casilla.val(elementValue(value));\n    if (klass == 'file') {\n      const file_input = casilla.find('input');\n      new uploadFileReader(file_input, mapa, vdat?.type?.format);\n    }\n    cell.find('.data_new').attr('name', name);\n    cell.find('.form-control.data_new').attr('name', null);\n  }\n}\n\nclass uploadFileReader {\n  constructor(fileInput, mapa, format) {\n    this.input = fileInput[0];\n    this.mapa = mapa;\n    this.maxSize = format ? Number(format.slice(2, -2)) * 1024 : 10000000;\n    this.input.addEventListener('change', () => {\n      this.handleSelected();\n    });\n  }\n  handleEvent(event) {\n    this.mapa.set('notification', window.gettext(`${event.type}: ${Math.floor(event.loaded / event.total * 100)}% transferred\\n`));\n    if (event.type === \"loadend\") {\n      window.setTimeout(() => this.mapa.set('notification', ''), 1000);\n      const buttons = [\n        {\n          text: [window.gettext('Aceptar')],\n          click: function () {\n            $(this).dialog('close');\n          },\n        },\n      ]\n      showAlertDialog(window.gettext(\"Fichero cargado correctamente\"), buttons);\n      this.removeListeners(this.reader);\n    }\n  }\n\n  addListeners(reader) {\n    reader.addEventListener('progress', this.handleEvent.bind(this));\n    reader.addEventListener('loadend', this.handleEvent.bind(this));\n  }\n  removeListeners(reader) {\n    reader.removeEventListener('progress', this.handleEvent.bind(this));\n    reader.removeEventListener('loadend', this.handleEvent.bind(this));\n  }\n  handleSelected() {\n    const self = this;\n    self.reader = new FileReader();\n    $(self.input).parent().find('span').remove();\n    const selectedFile = this.input.files[0];\n    if (selectedFile) {\n      if (selectedFile.size >= self.maxSize) {\n        const buttons = [\n          {\n            text: [window.gettext('Aceptar')],\n            click: function () {\n              $(this).dialog('close');\n            },\n          },\n        ]\n        showAlertDialog(window.gettext(\"El fichero supera el tamaño máximo permitido, por favor, baje el tamaño o seleccione otro fichero\"), buttons)\n      }\n      else {\n        self.addListeners(self.reader);\n        self.reader.readAsDataURL(selectedFile);\n        $(self.input).parent().append($(`<span>${selectedFile.name}</span>`));\n      }\n    }\n  }\n}\n\nfunction showAlertDialog(msg, buttons) {\n  const div_error = $('<div id=\"error\"/>');\n  const error_element = $(`<p>${msg}</p>`);\n  div_error.append(error_element);\n  return div_error.dialog({\n    appendTo: self.ns.page.find('.map'),\n    position: {\n      my: 'center',\n      at: 'center',\n      collision: \"fit\"\n    },\n    width: \"auto\",\n    height: \"auto\",\n    minHeight: \"auto\",\n    autoOpen: true,\n    resizable: false,\n    modal: true,\n    buttons: buttons,\n    close: function () {\n      $(this).dialog('destroy');\n    }\n  })\n}\nfunction crearFilaData(tableId, old_data, new_data, element_id, poi_coords) {\n  const readOnly = tableId == \"#element-info\";\n  const old_vars = Object.groupBy(old_data, function (x) {\n    return x.type.name;\n  });\n  const calc_vars = Object.groupBy(\n    old_data.filter(x => x.dimension_values),\n    x => x.type.name);\n  const new_vars = Object.groupBy(new_data, x => x.type.name);\n  const all_vars = [...new Set(Object.keys(old_vars).concat(Object.keys(new_vars)))];\n  const map_dimensions = mapa.get('dimension_controls');\n  if (Object.keys(calc_vars).length > 0 && readOnly)\n    showCalcVars(tableId, all_vars, calc_vars, element_id, poi_coords);\n  for (const type of all_vars) {\n    //  rowspan y possibleVars difieren en los datos con dims\n    let rowspan = 1;\n    let possibleVars = 1;\n    if (type in old_vars)\n      possibleVars = rowspan = old_vars[type].length;\n    if (type in new_vars && new_vars[type].length > rowspan)\n      possibleVars = rowspan = new_vars[type].length;\n    let edTable;\n    if (old_vars && old_vars[type] && old_vars[type][0].dimension_values)\n      rowspan = 1;\n    for (let i = 0; i < possibleVars; i++) {\n      let cells;\n      const vdat_old = type in old_vars && old_vars[type][i];\n      const vdat_new = type in new_vars && new_vars[type][i];\n      const vdat = vdat_new ? vdat_new : vdat_old;\n      const existentes = $(tableId).find('.data_new_' + vdat.type.id);\n      if (!vdat.id && existentes.length && !vdat.multiple) {\n        existentes.fadeToggle(40).fadeToggle(40);\n        continue;\n      }\n      let order = null;\n      if (vdat_old?.order)\n        order = vdat_old.order;\n      else if (existentes.length == 0)\n        order = vdat.order;\n      if (vdat.type.calculation_id && !readOnly)\n        continue;\n      const dimensions = vdat.dimension_values;\n      if (dimensions && map_dimensions && map_dimensions.HORIZON) {\n        if (window.timelinectl) {\n          const currentYear = window.timelinectl.timeline.getCustomTime('current').getFullYear();\n          map_dimensions.HORIZON.value = currentYear;\n        }\n        let hasMapDimensions = true; //Se usa para filtrar los datos dimensionales que no corresponden con las dimensiones establecidas en el mapa\n        for (let [name, dat] of Object.entries(dimensions)) {\n          if (name.startsWith('HOR') || name.includes('HORIZON')) name = 'HORIZON';\n          if (!(map_dimensions[name] && (map_dimensions[name].value == dat))) {\n            hasMapDimensions = false //Si no coinciden las dimensiones\n            continue;\n          }\n        }\n        if (!hasMapDimensions) //Se filtran los datos dimensionalmente no coincidentes\n          continue;\n      }\n      const columns = vdat.type.columns.split(' ');\n      const simpleData = columns.length === 1;\n      const modelTR = $(tableId).find('.data').find('tr.model-row');\n      let tr;\n      if (simpleData || i === 0) {\n        tr = modelTR.clone();\n        tr.removeClass('model-row');\n        tr.insertBefore(modelTR);\n      } else {\n        tr = modelTR.prev();\n      }\n      const firstTD = tr.find('td').first();\n      if (simpleData && rowspan > 1)\n        if (i === 0)\n          firstTD.attr('rowspan', rowspan);\n        else\n          firstTD.addClass('hidden');\n      if (simpleData) {\n        tr.addClass('vardata simple');\n        const recuadro = tr.find('.data_new').parent();\n        tr.find('.data_new').remove();\n        cells = [recuadro];\n      } else {\n        if (i === 0) {\n          tr.addClass('vardata complex');\n          tr.find('.delete-td').remove();\n          tr.find('.datacomments_new').remove();\n          edTable = $('<table><thead></thead><tbody></tbody></table>');\n          if (tr.find('.data_new').length > 0) {\n            tr.find('.data_new').parent().attr('colspan', 2);\n            tr.find('.data_new').replaceWith(edTable);\n          } else {\n            tr.find('.data_old_').replaceWith(edTable);\n          }\n        }\n        const miscCell = modelTR.find('.delete-td').parent().clone();\n        miscCell.find('.data_new').remove();\n        const edRow = $('<tr class=\"vardata complex\"></tr>');\n        edTable.find('tbody').append(edRow);\n        cells = []\n        for (const col of columns) {\n          const cell = $(`<td class=\"${col}\"></td>`)\n          cells.push(cell);\n          edRow.append(cell);\n        }\n        edRow.append(miscCell);\n      }\n      tr.find('.caption').text(type);\n      crearCasilla(vdat, cells, order, readOnly);\n      const suffix = vdat.type.id + '_' + order;\n      if (vdat.id)\n        tr.find('input.delete').attr('name', 'delete_' + suffix);\n      else\n        tr.find('input.delete').parent().remove();\n      tr.find('.data_new').addClass('data_new_' + vdat.type.id);\n      tr.find('.datacomments_new').attr('name', 'datacomments_' + suffix);\n      tr.find('.datacomments_old').prop(\n        'title',\n        elementValue(vdat_old.comments)\n      );\n      // Rellenamos datos actuales en sólo lectura\n      if (simpleData && vdat_old) {\n        if (vdat_old.type.klass == 'file') {\n          tr.find('span.data_old').replaceWith($(`<a target=\"_blank\" href=\"${vdat_old.value.url}\">\n          <i class=\"enlace-icono fa fa-book\" ></i>${vdat_old.value.url.split(/[\\\\/]/).pop()\n            }</a>`));\n        } else {\n          if (vdat_old.type.klass === 'str' && vdat.value?.includes('\\r\\n'))\n            tr.find('span.data_old').replaceWith(\n              (vdat.value.split('\\r\\n').join('<br />'))\n            );\n          else if (vdat_old.type.klass === 'date' && vdat.value) {\n            const format = /[Hh]/.test(vdat_old.type.format) ?\n              'DD-MM-YYYY HH:mm' : 'DD-MM-YYYY';\n            tr.find('span.data_old').replaceWith(\n              dayjs(vdat.value).format(format)\n            );\n          }\n          else if (vdat_old.type.klass == 'boolean')\n            tr.find('span.data_old').text(vdat.value ? window.gettext('Sí') : window.gettext('No'));\n          else\n            tr.find('span.data_old').text(elementValue(vdat_old.value));\n        }\n      } else if (tr.find('.data_new').length === 0 && vdat_old) {\n        tr.find('span.data_old').text(elementValue(vdat_old.value));\n      } else {\n        tr.find('td.data_old_').remove();\n        if (readOnly) {\n          // Datos en solo lectura\n          edTable.find('.data_new').removeClass('data_new');\n          edTable.find('label:has(input[type=file])').remove();\n          edTable.find('input').attr('readonly', 'readonly');\n          edTable.find('textarea').attr('readonly', 'readonly');\n        }\n      }\n\n      tr.find('span.datacomments_new').prop(\n        'title',\n        elementValue(vdat.comments)\n      );\n      tr.find('textarea.datacomments_new').val(elementValue(vdat.comments));\n      tr.find('span.datacomments_new').on('click', function (evt) {\n        $(evt.target)\n          .next()\n          .toggle();\n      });\n      tr.find('textarea.datacomments_new').change(function (evt) {\n        const title = $(evt.currentTarget).val();\n        const bocadillo = $(evt.currentTarget).prev();\n        bocadillo.prop('title', title);\n        if (title) {\n          bocadillo.removeClass('fa-commenting');\n          bocadillo.addClass('fa-commenting-o');\n        } else {\n          bocadillo.removeClass('fa-commenting-o');\n          bocadillo.addClass('fa-commenting');\n        }\n      });\n\n      tr.find('.datacomments_new:not([title])').addClass('fa fa-commenting');\n      tr.find('.datacomments_new[title=\"\"]').addClass('fa fa-commenting');\n      tr.find('.datacomments_new[title!=\"\"]').addClass('fa fa-commenting-o');\n      tr.find('.datacomments_old[title!=\"\"]').addClass('fa fa-commenting-o');\n      modelTR.before(tr);\n    }\n  }\n}\nfunction fillElementTypes(tableId, currentTypeId, element_class) {\n  const table = $(tableId);\n  const selectElem = table.find('.data_new.element_element_type_id');\n  selectElem.empty();\n  const types = element_class ? ',' : currentTypeId;\n  element_class = element_class ? element_class : ',';\n  $.ajax({\n    url: window.Urls.element_types(element_class, types),\n    success: function (types) {\n      for (const opt of types) {\n        const selected = currentTypeId == opt.pk;\n        $(`<option ${selected ? 'selected=\"selected\"' : ''}/>`)\n          .val(opt.pk)\n          .html(opt.name)\n          .appendTo(selectElem);\n      }\n    }\n  });\n}\n\nfunction fillElementInfo(tableId, element_id, is_new, element_class) {\n  const table = $(tableId);\n  let elems, v;\n  const urlFunction = is_new ? window.Urls.element_change_info : window.Urls.element_info;\n  $.getJSON(urlFunction(element_id), function (json) {\n    if (is_new) json.pending_changes = json;\n    if (json.centroid && json.centroid.length) {\n      json.center_proj = transform_point(json.centroid)\n        .map(Math.floor)\n        .toString();\n      json.centroid = [\n        json.centroid[1].toFixed(6) + ',' + json.centroid[0].toFixed(6)\n      ];\n    }\n    table.find('.vardata').remove();\n    table.find('.related-row').remove();\n    table.find('.related-table').hide();\n    for (let [k, vv] of Object.entries(json)) {\n      if (k === 'related') {\n        const model_row = table.find('.related-model-row');\n        for (const related of vv) {\n          table.find('.related-table').show();\n          const new_row = model_row.clone();\n          new_row.appendTo(model_row.parent())\n          new_row.find('td.name').text(related.name)\n          new_row.removeClass('related-model-row');\n          new_row.addClass('related-row');\n          new_row.find('td.type')\n            .attr('title', related.element_type__name)\n            .attr('data-uid', 'et' + related.element_type_id)\n          new_row.attr('element_id', related.id)\n          new_row.attr('geom', related.geomx)\n        }\n      } else {\n        const elems = table.find('.data_old.element_' + k);\n        if (k == 'updated') {\n          json[k] = vv = dayjs(vv).format('DD-MM-YYYY');\n        }\n        elems.text(elementValue(vv));\n      }\n    }\n    const old_data = json.data;\n    let new_data = [];\n    if (json.pending_changes) {\n      new_data = json.pending_changes.data;\n      delete json.pending_changes.data;\n      for (const k in json.pending_changes) {\n        v = json.pending_changes[k];\n        elems = table.find('.data_new.element_' + k);\n        if (k == 'updated') {\n          json.pending_changes[k] = v; // = dayjs(v).format('DD-MM-YYYY');\n          if (json.pending_changes.parameter_change == 'DELETE_ELEMENT') {\n            elems = table.find('.data_old.element_updated.delete_change');\n            elems.text(elementValue(v));\n            continue;\n          }\n        }\n        elems.val(v);\n      }\n      fillElementTypes(tableId, json.pending_changes.element_type.pk, element_class);\n    } else {\n      // copiamos datos elemento existentes\n      for (const k in json) {\n        if (k !== 'element_type') {\n          v = elementValue(json[k]);\n          elems = table.find('.data_new.element_' + k);\n          elems.val(v);\n        }\n      }\n      fillElementTypes(tableId, json.element_type.pk, element_class);\n    }\n    const geom = table.find('.data_new.element_geometry').val();\n    if (tableId == '#element-info') {\n      const old_geom_data = table.find('.data_old.element_geometry');\n      old_geom_data.parent().addClass('hidden');\n      const wkt = old_geom_data.text();\n      if (wkt) {\n        const old_geom = new WKT().readGeometry(wkt, {\n          dataProjection: 'EPSG:4326',\n        });\n        if (old_geom instanceof Polygon || old_geom instanceof MultiPolygon) {\n          const formatArea = function (polygon) {\n            const area = getArea(polygon, { projection: 'EPSG:4326' });\n            if (area > 10000) {\n              old_geom_data.parent().find('td[name=\"title\"]').text(`${window.gettext('Superficie')} (km² - ha)`)\n              return `${numeric_lang_format((area / 1000000).toFixed(2))} - ${numeric_lang_format((area / 10000).toFixed(2))}`;\n            }\n            else {\n              old_geom_data.parent().find('td[name=\"title\"]').text(`${window.gettext('Superficie')} (m²)`)\n              return numeric_lang_format(area.toFixed(2));\n            }\n          };\n          const area_data = formatArea(old_geom);\n          old_geom_data.text(area_data);\n          old_geom_data.parent().removeClass('hidden');\n        }\n      }\n    }\n    crearFilaData(tableId, old_data, new_data, element_id, json.centroid ? json.centroid[0] : null);\n    if ($(tableId).find('.data_new').length > 1) {\n      if (geom && geom != 'POINT EMPTY') {\n        const feat = new WKT().readFeature(geom, {\n          dataProjection: 'EPSG:4326',\n          featureProjection: window.epsg\n        });\n        mapa.set('edit_feature', feat);\n      }\n      // Montamos lista de opciones para crear datos nuevos\n      const available_data = json.element_type.data;\n      $(tableId).find('.add-data').remove();\n      const data_menu = $('<ul class=\"add-data\"></ul>');\n      for (const [i, dat] of Object.entries(available_data)) {\n        if (dat.type.calculation_id)\n          continue;\n        if (!dat.multiple && old_data.some(elem => elem.type.id == dat.type.id))\n          continue;\n        data_menu.append($(\n          `<li idx_available_data=\"${i}\">${window.gettext('Añadir')} ${dat.type.name}</li>`\n        ));\n      }\n      const buttons = $(tableId).dialog('option', 'buttons');\n      const button = createAddDataButton(tableId, data_menu, available_data);\n      if (buttons[0].class == 'fa fa-female') {\n        buttons.splice(1, 0, button);\n      }\n      else {\n        buttons.unshift(button);\n      }\n      $(tableId).dialog('option', 'buttons', buttons);\n    }\n    $(tableId).dialog('open');\n  });\n}\n\nfunction showUserInfo(mapa, tableId, username) {\n  const table = $(tableId);\n  $.getJSON(window.Urls.user_info(username), function (json) {\n    for (const k in json) {\n      const v = elementValue(json[k]);\n      const elems = table.find('.' + k);\n      elems.text(v);\n    }\n  });\n  $(tableId).dialog({ appendTo: mapa.getTargetElement() });\n}\n\nfunction actOnElement(evt) {\n  const mapTarget = mapa.getTargetElement && mapa.getTargetElement();\n  if (mapTarget)\n    $(mapTarget).find('.dialog').dialog('close');\n  const appendTo = evt.appendTo ? evt.appendTo : mapTarget;\n  const op = evt.data;\n  const tr = $(this).closest('tr');\n  const element_id = this.id ? this.id.split('_')[1] : tr[0].attributes.element_id.value;\n\n  const element_class = 'element_class' in tr[0].attributes ? tr[0].attributes.element_class.value : null;\n  const lastElementPixel = mapa ? mapa.get('lastElementPixel') : null;\n  const width_edit = window.innerWidth;\n  const new_pos = evt.new_pos ? evt.new_pos :\n    {\n      my: 'right top',\n      at: 'right-10% top+5',\n      of: appendTo,\n      collision: 'none'\n    };\n  const width = 'auto';\n  const height = 'auto';\n  let minWidth_edit = 212;\n  if (op === 'url') {\n    const url = new URL(window.location);\n    url.searchParams.set('element_id', element_id);\n    navigator.clipboard.writeText(url.href);\n    mapa.set('notification', window.gettext('Enlace copiado al portapapeles'));\n    window.setTimeout(() => mapa.set('notification', ''), 1000);\n  } else if (op === 'info') {\n    const tableId = '#element-info';\n    mapa.set('lastInfoElem', this);\n    $(tableId)\n      .show()\n      .dialog({\n        appendTo: appendTo,\n        title: window.gettext('Información'),\n        width: width,\n        height: height,\n        maxHeight: window.innerHeight * 4 / 6,\n        maxWidth: window.innerWidth * 5 / 6,\n        buttons: [{\n          html: '<i class=\"fas fa-print\"></i>',\n          title: window.gettext('Imprimir información'),\n          click: () => window.open(window.Urls.print_element_info(element_id)),\n        }],\n        position: (lastElementPixel) ?\n          {\n            my: 'left top',\n            at: 'left+' + (lastElementPixel[0] + 50) + ' top+' + lastElementPixel[1],\n            of: appendTo,\n            collision: 'fit'\n          } :\n          new_pos,\n        autoOpen: false,\n        resizable: true,\n        open: function () {\n          $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'));\n          if (lastElementPixel)\n            $(this).parent().css('margin-top', '-25pt');\n          $(this).parent().css('margin-left', '-30pt');\n        },\n        close: function () {\n          $(this).parent().css('margin-left', 'unset');\n          $(this).parent().css('margin-top', 'unset');\n        }\n      });\n    fillElementInfo(tableId, element_id, false, element_class);\n  } else if (op === 'delete' || op === 'commit-delete') {\n    minWidth_edit -= 90;\n    const tableId = '#delete-dialog';\n    const table = $(tableId);\n    const buttons = [\n      {\n        text: window.gettext('Cancelar'),\n        click: function () {\n          $(this).dialog('close');\n        }\n      }\n    ];\n    minWidth_edit += 73;\n    buttons.unshift({\n      text: window.gettext('Eliminar'),\n      click: function () {\n        const dialog = this;\n        $.ajax({\n          url: window.Urls.element_delete(element_id),\n          type: 'POST',\n          success: function (json) {\n            $(dialog).dialog('close');\n            if (json.operation === 'DELETE') {\n              $('#delete-ok').dialog({\n                appendTo: appendTo,\n                position: new_pos\n              });\n              mapa.set('update_changes', true);\n              $('tr[element_id=\"' + element_id + '\"]').addClass(\n                'pending_delete'\n              );\n            } else if (json.operation === 'COMMIT-DELETE') {\n              mapa.set('update_changes', true);\n              mapa.set('update_elements', true);\n            }\n          }\n        });\n      }\n    });\n    if (op === 'commit-delete') {\n      minWidth_edit += 114;\n      buttons.unshift({\n        text: window.gettext('Confirmar'),\n        click: function () {\n          const dialog = this;\n          $.ajax({\n            url: window.Urls.element_commit_delete(element_id),\n            type: 'POST',\n            class: 'commit-edit',\n            success: function () {\n              $(dialog).dialog('close');\n              $('#commit-edit-ok').dialog({\n                appendTo: appendTo,\n                position: new_pos\n              });\n              mapa.set('update_changes', true);\n              mapa.set('update_elements', true);\n              $('tr[element_id=\"' + element_id + '\"]').remove();\n            }\n          });\n        }\n      });\n      buttons.unshift({\n        text: '',\n        class: 'fa fa-female',\n        click: function () {\n          showUserInfo(mapa, '#user-info', table.find('.element_user').val());\n        }\n      });\n    }\n    table.dialog({\n      appendTo: appendTo,\n      title: op === 'delete' ? window.gettext('Eliminar') : window.gettext('Confirmar eliminación'),\n      width: width,\n      height: height,\n      position: new_pos,\n      zIndex: 10000,\n      resizable: true,\n      autoOpen: false,\n      buttons: buttons,\n\n      maxHeight: window.innerHeight * 6 / 7,\n      maxWidth: minWidth_edit >= width_edit ? minWidth_edit : width_edit,\n      open: function () {\n        $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n      },\n      close: function () {\n        mapa.set('edit_feature', null);\n        $(this).hide();\n      },\n    });\n    fillElementInfo(tableId, element_id, false, element_class);\n  } else if (op === 'edit' || op === 'commit-edit') {\n    const tableId = '#edit-dialog';\n    const table = $(tableId);\n\n    const buttons = [\n      {\n        text: window.gettext('Cancelar'),\n        click: function () {\n          $(this).dialog('close');\n        }\n      }\n    ];\n    if (op === 'commit-edit') {\n      minWidth_edit += 114;\n      buttons.unshift({\n        text: window.gettext('Confirmar'),\n        click: function () {\n          const dialog = this;\n          const wkt = new WKT();\n          const feat = mapa.get('edit_feature');\n          const geom = feat ? wkt.writeFeature(feat, {\n            dataProjection: 'EPSG:4326',\n            featureProjection: window.epsg\n          }) : '';\n          table.find('form .element_geometry.data_new').val(geom);\n          $.ajax({\n            url: window.Urls.element_commit_edit(element_id),\n            data: getFormData(table.find('form')),\n            type: 'POST',\n            classes: 'commit-edit',\n            success: function () {\n              $(dialog).dialog('close');\n              $('#commit-edit-ok').dialog({\n                appendTo: appendTo,\n                position: new_pos\n              });\n              mapa.set('update_changes', true);\n              mapa.set('update_elements', true);\n              $('tr[element_id=\"' + element_id + '\"]').removeClass(\n                'pending_edit'\n              );\n              $('tr[element_id=\"' + element_id + '\"]').removeClass(\n                'pending_delete'\n              );\n            }\n          });\n        }\n      });\n    }\n    minWidth_edit += 78;\n    buttons.unshift({\n      text: window.gettext('Modificar'),\n      click: function () {\n        const dialog = this;\n        const wkt = new WKT();\n        const feat = mapa.get('edit_feature');\n        const geom = feat ? wkt.writeFeature(feat, {\n          dataProjection: 'EPSG:4326',\n          featureProjection: window.epsg\n        }) : '';\n        fixDates(table);\n        table.find('form .element_geometry.data_new').val(geom);\n        const data = new FormData(table.find('form')[0]);\n        for (const ipt of table.find('form input.data_new[type=\"checkbox\"]'))\n          data.set($(ipt).prop('name'), $(ipt).prop('checked') ? 'True' : 'False')\n        $.ajax({\n          url: window.Urls.element_edit(element_id),\n          type: 'POST',\n          data: data,\n          contentType: false,\n          processData: false,\n          success: function (json) {\n            $(dialog).dialog('close');\n            if (json.operation == 'EDIT') {\n              $('#edit-ok').dialog({\n                appendTo: appendTo,\n                position: new_pos\n              });\n              mapa.set('update_changes', true);\n              $('tr[element_id=\"' + element_id + '\"]').addClass('pending_edit');\n            } else {\n              mapa.set('update_changes', true);\n              mapa.set('update_elements', true);\n            }\n          }\n        });\n      }\n    });\n    if (op === 'commit-edit') {\n      buttons.unshift({\n        text: '',\n        class: 'fa fa-female',\n        click: function () {\n          showUserInfo(mapa, '#user-info', table.find('.element_user').val());\n        }\n      });\n    }\n    $(tableId).dialog({\n      width: width,\n      height: height,\n      appendTo: appendTo,\n      position: new_pos,\n      title: op === 'commit-edit' ? window.gettext('Confirmar modificación') : window.gettext('Modificar'),\n      zIndex: 10000,\n      resizable: true,\n      autoOpen: false,\n      maxHeight: window.innerHeight * 0.7,\n      maxWidth: window.innerWidth * 5 / 6,\n      buttons: buttons,\n      close: function () {\n        mapa.unset('edit_feature', null)\n        mapa.set('edit_feature', null);\n        $(this).hide();\n      },\n      open: function () {\n        $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n        const ww = $(this).outerWidth();\n        $('#' + this.id + ' td.data_old').css('max-width', (ww) / 2);\n        $('#' + this.id + ' td.data_old_').css('max-width', (ww) / 2);\n        $(this).find('.doble').css('height', 'auto');\n        $(this).parent().css('max-width', (minWidth_edit >= width_edit) ? minWidth_edit : width_edit);\n        $(this).css('max-width', (minWidth_edit >= width_edit) ? minWidth_edit : width_edit);\n        const doble_height = $(this).find('td.element_comments.data_old').height();\n        $(this).find('.doble').height(doble_height);\n        //$(this).find('.vardata .data_new').css('width', 'calc(100% - 45px)');\n      },\n      resize: function () {\n        $(this).css('width', 'auto');\n        const diff = String($(this).width() - $(this).find('table').width() - 2) + 'px';\n        if (diff > 0) {\n          $(this).find('.data_new').css('width', 'calc(100% + ' + diff + ')');\n          //$(this).find('.vardata .data_new').css('width', 'calc(100% - 45px + ' + diff + ')');\n          //$(this).find('input.vardata').css('width', 'calc(100% - 45px + ' + diff + ')');\n        }\n      },\n    });\n    fillElementInfo(tableId, element_id, false, element_class);\n  } else if (op === 'commit-create' || op === 'edit-new') {\n    const tableId = '#create-dialog';\n    const table = $(tableId);\n    const buttons = [\n      {\n        text: window.gettext('Cancelar'),\n        click: function () {\n          $(this).dialog('close');\n        }\n      }\n    ];\n    if (op === 'commit-create') {\n      minWidth_edit += 81;\n      buttons.unshift({\n        text: window.gettext('Confirmar'),\n        click: function () {\n          const dialog = this;\n          const wkt = new WKT();\n          const feat = mapa.get('edit_feature');\n          const geom = feat ? wkt.writeFeature(feat, {\n            dataProjection: 'EPSG:4326',\n            featureProjection: window.epsg\n          }) : '';\n          table.find('form .element_geometry.data_new').val(geom);\n          table.find('input.element_updated').val(dayjs().format('YYYY-MM-DD'));\n\n          $.ajax({\n            url: window.Urls.element_commit_create(element_id),\n            data: getFormData(table.find('form')),\n            type: 'POST',\n            success: function () {\n              $(dialog).dialog('close');\n              $('#commit-edit-ok').dialog({\n                appendTo: appendTo,\n                position: new_pos\n              });\n              mapa.set('update_changes', true);\n              mapa.set('update_elements', true);\n              $('.cambios tr[element_id=\"' + element_id + '\"]').remove();\n            }\n          });\n        }\n      });\n    }\n    if (op === 'edit-new') {\n      minWidth_edit += 78;\n      buttons.unshift({\n        text: window.gettext('Modificar'),\n        click: function () {\n          const dialog = this;\n          const wkt = new WKT();\n          const feat = mapa.get('edit_feature');\n          const geom = feat ? wkt.writeFeature(feat, {\n            dataProjection: 'EPSG:4326',\n            featureProjection: window.epsg\n          }) : '';\n          table.find('form .element_geometry.data_new').val(geom);\n          table.find('input.element_updated').val(dayjs().format('YYYY-MM-DD'));\n\n          $.ajax({\n            url: window.Urls.element_edit_new(element_id),\n            type: 'POST',\n            data: getFormData(table.find('form')),\n            success: function () {\n              $(dialog).dialog('close');\n              $(dialog).dialog('destroy');\n\n              $('#edit-ok').dialog({\n                appendTo: appendTo,\n                position: new_pos\n              });\n              mapa.set('update_changes', true);\n              $('tr[element_id=\"' + element_id + '\"]').addClass('pending_edit');\n            }\n          });\n        }\n      });\n    }\n    buttons.unshift({\n      text: '',\n      class: 'fa fa-female',\n      click: function () {\n        showUserInfo(mapa, '#user-info', table.find('.element_user').val());\n      }\n    });\n\n    table.dialog({\n      appendTo: appendTo,\n      width: width,\n      height: height,\n      position: new_pos,\n      title: op === 'edit-new' ? window.gettext('Modificar') : window.gettext('Confirmar creación'),\n      zIndex: 10000,\n      resizable: true,\n      autoOpen: false,\n      //maxHeight: window.innerHeight*2/3,\n      //maxWidth: window.innerWidth*2/5,\n      buttons: buttons,\n      open: function () {\n        $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n        $(this).parent().css('max-width', (minWidth_edit >= width_edit) ? minWidth_edit : width_edit);\n        $(this).css('max-width', (minWidth_edit >= width_edit) ? minWidth_edit : width_edit);\n      },\n      close: function () {\n        mapa.set('edit_feature', null);\n        $(this).hide();\n      },\n    });\n    fillElementInfo(tableId, element_id, true, element_class);\n  } else if (op === 'change-remove') {\n    minWidth_edit -= 90;\n    const tableId = '#change-remove-dialog';\n    const table = $(tableId);\n    const buttons = [\n      {\n        text: window.gettext('Cancelar'),\n        click: function () {\n          $(this).dialog('close');\n        }\n      }\n    ];\n    minWidth_edit += 79;\n    buttons.unshift({\n      text: window.gettext('Aceptar'),\n      click: function () {\n        const dialog = this;\n        const is_pending_create = $('tr[element_id=\"' + element_id + '\"]').hasClass('pending_create')\n        $.ajax({\n          url: (is_pending_create) ? window.Urls.element_cancel_create(element_id) : window.Urls.element_cancel_edit(element_id),\n          type: 'POST',\n          classes: 'cancel-edit',\n          success: function () {\n            $(dialog).dialog('close');\n            $('#cancel-edit-ok').dialog({\n              appendTo: appendTo,\n              position: new_pos\n            });\n            mapa.set('update_changes', true);\n            $('.cambios tr[element_id=\"' + element_id + '\"]').remove();\n          }\n        });\n      }\n    });\n\n    table.dialog({\n      appendTo: appendTo,\n      title: window.gettext('Descartar cambio pendiente'),\n      width: width,\n      height: height,\n      position: new_pos,\n      zIndex: 10000,\n      buttons: buttons,\n      maxHeight: window.innerHeight * 6 / 7,\n      maxWidth: minWidth_edit >= width_edit ? minWidth_edit : width_edit,\n      open: function () {\n        $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n      },\n      close: function () {\n        $(this).hide();\n      },\n    });\n  } else {\n    console.debug('Modificar - ' + op + ' ' + element_id);\n  }\n  return false;\n}\n\nfunction fixDates(table) {\n  table.find('form .vardata .form-control.input').each(function () {\n    const elem = $(this)\n    const pickr = elem.parent().find('input.flatpickr-input');\n    const datetime = dayjs(elem.val(), pickr.attr('placeholder'));\n    pickr.val(datetime.isValid() ? datetime.toISOString() : '');\n  });\n}\n\n\nfunction createAddDataButton(tableId, data_menu, available_data) {\n  const table = $(tableId);\n  return {\n    text: window.gettext('Añadir dato'),\n    disabled: data_menu.find('li').length == 0,\n    class: 'add-data',\n    click: function () {\n      $(this).append(data_menu);\n      data_menu.menu({\n        select: function (event, ui) {\n          const idx = ui.item[0].attributes.idx_available_data.value;\n          const dat = available_data[idx];\n          crearFilaData(tableId, [], [dat]);\n          if (!dat.multiple)\n            this.removeChild(ui.item[0]);\n          if (!$(this).find('li').length) {\n            table.parent().find('button.add-data').addClass('ui-button-disabled ui-state-disabled');\n          }\n        }\n      });\n    }\n  }\n}\n\nfunction showCalcVars(tableId, all_vars, calc_vars, element_id, poi_coords) {\n  const map_dimensions = mapa.get('dimension_controls');\n  const button = [{\n    html: '<i class=\"fas fa-table\"></i>',\n    class: 'info-dataTable',\n    click: function () {\n      $('#info-dataTable').dialog('destroy')\n      const model_table = $('#calculationData_table');\n      const total_table = $('<div id=\"info-dataTable\" class=\"static\"></div>');\n      total_table.append(`<h4>${$(tableId).find('td.element_element_type').text() + ' - ' + $(tableId).find('td.element_name').text()}</h4>`);\n      const table_one = $('<div ></div>');\n      const table_two = $('<div ></div>');\n      const table_n = $('<div ></div>');\n      const tabs = $('#tabs-Table').clone();\n      tabs.removeClass('hidden');\n      const horizon_opt = map_dimensions['HORIZON'].options;\n      all_vars.map((type) => {\n        if (calc_vars[type]) {\n          let table = model_table.clone();\n          table.removeClass('hidden');\n          const data = calc_vars[type];\n          const data_dim = Object.keys(data[0].dimension_values);\n          horizon_opt.forEach(opt => {\n            table.find('tbody').append(`<tr><td name=\"opt_h\">${opt}</td></tr>`)\n          })\n          const horizon_name = get_horizon(data_dim);\n          data_dim.splice(data_dim.indexOf(horizon_name), 1)\n          if (data_dim.length < 2) {\n            let dim = horizon_name;\n            const div_table = $(`<div id=\"tab\"></div>`);\n            div_table.append(`<h4>${type}</h4>`);\n            if (data_dim.length) {\n              dim = data_dim.pop();\n              table.find('tr[name =\"title_h1\"]').append(`<td width=\"100%\" colspan=\"${map_dimensions[dim].options.length}\">${map_dimensions[dim].name}</td>`)\n              map_dimensions[dim].options.map(dim_opt => {\n                const ordered_values = groupBy(data, function (x) {\n                  if (x.dimension_values[dim] == dim_opt[0])\n                    return x.dimension_values[horizon_name];\n                });\n                if (!(ordered_values[\"undefined\"] && ordered_values[\"undefined\"].length == data.length)) {\n                  table.find('tr[name =\"title_h2\"]').append(`<td>${dim_opt[1]}</td>`)\n                  table.find('tr td[name=\"opt_h\"]').map((i, td) => {\n                    const opt = ordered_values[td.innerText];\n                    if (opt)\n                      $(td.parentElement).append(`<td class=\"info-data\">${new Intl.NumberFormat($(window.document).find('html').attr('lang')\n                        , {\n                          maximumFractionDigits: 20\n                        }).format(opt[0].value)}</td>`)\n                    else\n                      $(td.parentElement).append(`<td class=\"info-data\"> - </td>`)\n                  });\n                }\n              })\n              if (table.find('tr[name =\"title_h2\"] td').length > 1) {\n                div_table.append(table);\n                table_two.append(div_table);\n              }\n            }\n            else {\n              table.find('tr[name =\"title_h2\"]').append(`<td>Valor</td>`)\n              table.find('tr td[name=\"opt_h\"]').map((i, td) => {\n                const ordered_values = groupBy(data, function (x) {\n                  return x.dimension_values[dim];\n                });\n                if (!(ordered_values[\"undefined\"] && ordered_values[\"undefined\"].length == data.length)) {\n                  const opt = ordered_values[td.innerText];\n                  if (opt)\n                    $(td.parentElement).append(`<td class=\"info-data\">${new Intl.NumberFormat($(window.document).find('html').attr('lang')\n                      , {\n                        maximumFractionDigits: 20\n                      }).format(opt[0].value)}</td>`)\n                  else\n                    $(td.parentElement).append(`<td class=\"info-data\"> - </td>`)\n                }\n              });\n              if (table.find('tr[name =\"title_h2\"] td').length > 1) {\n                div_table.append(table);\n                table_one.append(div_table);\n              }\n            }\n          }\n          else {\n            data_dim.map((dim, idx) => {\n              if (tabs.find('li').length < data_dim.length) {\n                tabs.find('ul').append(`<li><a href=\"#tabs_Table-${map_dimensions[dim].id}\"></a>${map_dimensions[dim].name}</li>`);\n                const div_tab = $(`<div id=\"tabs_Table-${map_dimensions[dim].id}\"></div>`);\n                tabs.append(div_tab);\n              }\n              const this_tab = tabs.find(`#tabs_Table-${map_dimensions[dim].id}`);\n              this_tab.append(`<h4>${type}</h4>`);\n              const other_dim = data_dim.slice();\n              other_dim.splice(idx, 1);\n              map_dimensions[dim].options.map(dim_opt => {\n                const tab = table.clone();\n                tab.find('tr[name =\"title_h1\"]').append(`<td width=\"100%\" colspan=\"${map_dimensions[other_dim[0]].options.length}\">${map_dimensions[other_dim[0]].name}</td>`)\n                map_dimensions[other_dim[0]].options.map(dim_opt2 => {\n                  const ordered_values = groupBy(data, function (x) {\n                    if ((x.dimension_values[dim] == dim_opt[0]) && (x.dimension_values[other_dim[0]] == dim_opt2[0]))\n                      return x.dimension_values[horizon_name];\n                  });\n                  if (!(ordered_values[\"undefined\"] && ordered_values[\"undefined\"].length == data.length)) {\n                    tab.find('tr[name =\"title_h2\"]').append(`<td>${dim_opt2[1]}</td>`)\n                    tab.find('tr td[name=\"opt_h\"]').map((i, td) => {\n                      const opt = ordered_values[td.innerText];\n                      if (opt)\n                        $(td.parentElement).append(`<td class=\"info-data\">${new Intl.NumberFormat($(window.document).find('html').attr('lang')\n                          , {\n                            maximumFractionDigits: 20\n                          }).format(opt[0].value)}</td>`)\n                      else\n                        $(td.parentElement).append(`<td class=\"info-data\"> - </td>`)\n                    });\n                  }\n                })\n                if (tab.find('tr[name =\"title_h2\"] td').length > 1) {\n                  this_tab.append(`<span>${map_dimensions[dim].name}: ${dim_opt[0]}</span>`);\n                  this_tab.append(tab);\n                }\n              })\n            })\n          }\n        }\n      })\n      table_n.append(tabs);\n      total_table.append(table_one);\n      total_table.append(table_two);\n      total_table.append(table_n);\n      tabs.tabs();\n      const buttons = [\n        {\n          html: '<i class=\"fas fa-print\"></i>',\n          click: function () {\n            window.open(\n              window.Urls.dimensionalTables2Pdf(element_id)\n            );\n          }\n        }\n      ]\n      total_table.dialog(\n        {\n          appendTo: this.ns.mapa.getTargetElement(),\n          title: window.gettext('Información dimensional'),\n          zIndex: 100000,\n          width: 'auto',\n          buttons: buttons,\n          open: function () {\n            $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n            $(this).scrollTop(0);\n            const hmax = $(this).height();\n            $(this).removeClass('static');\n            $(this).css('height', 'auto');\n            const hauto = $(this).height();\n            (hauto < hmax) ? null : $(this).css('height', String(hmax) + 'px');\n          },\n          close: function () {\n            $(this).dialog('destroy');\n          },\n        }\n      );\n    }\n  },\n  {\n    html: '<i class=\"fas fa-chart-area\"></i>',\n    class: 'info-dataGraph',\n    click: () => create_graph_control(mapa, { centroid: poi_coords.split(',').map(parseFloat), same_srid: false }, [element_id]),\n  }\n  ];\n  $(tableId).dialog('option', 'buttons', button);\n}\nexport {\n  actOnElement, crearFilaData, initializeMapa, configureCalendar,\n  fixDates, createAddDataButton\n};\n","/*eslint no-implicit-globals: \"error\"*/\nimport 'ol/ol.css';\nimport {\n  $, flatpickr, dayjs, getFormData, getParameterByName, multiselectOptions,\n  transform_point, getFormCoords, proj4, updateUnselectedHorizons,\n  LAYERTYPES\n} from '../../../../moderna_meteogrid/statix/js/base.mjs';\nimport { setVisibleLayers_url, showLegend } from './simmerlayer.mjs';\n\nimport 'ol-ext/control/Bar.css';\nimport ol_control_Bar from 'ol-ext/control/Bar';\nimport 'ol-ext/control/LayerPopup.css';\nimport ol_control_LayerPopup from 'ol-ext/control/LayerPopup';\nimport 'ol-ext/control/Notification.css';\nimport ol_control_Notification from 'ol-ext/control/Notification';\nimport 'ol-ext/control/Overlay.css';\nimport '../css/ol_ext_overlay_menu.css';\nimport ol_control_Overlay from 'ol-ext/control/Overlay';\nimport Geolocation from 'ol/Geolocation';\nimport 'ol-ext/control/LayerSwitcher.css';\nimport 'ol-ext/control/LayerSwitcherImage.css';\nimport '../../../../moderna_meteogrid/statix/css/mapas.css';\nimport '../../../../moderna_meteogrid/statix/css/checkbox.css';\n\nimport ol_control_Toggle from 'ol-ext/control/Toggle';\nimport searchNominatim from 'ol-ext/control/SearchNominatim'\nimport ol_control_SearchES from './ol_control_searchES'\nimport Style from 'ol/style/Style';\nimport Fill from 'ol/style/Fill';\nimport Circle from 'ol/style/Circle';\nimport Stroke from 'ol/style/Stroke';\nimport Modify from 'ol/interaction/Modify';\nimport Draw, { createBox } from 'ol/interaction/Draw';\nimport Transform from 'ol-ext/interaction/Transform';\nimport { transformExtent } from 'ol/proj';\n\nimport Map from 'ol/Map';\nimport View from 'ol/View';\nimport { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';\nimport { OSM, Vector as VectorSource } from 'ol/source';\nimport { createStringXY, toStringHDMS } from 'ol/coordinate';\nimport { Control } from 'ol/control';\nimport Collection from 'ol/Collection';\nimport MousePosition from 'ol/control/MousePosition';\nimport OverviewMap from 'ol/control/OverviewMap';\nimport ScaleLine from 'ol/control/ScaleLine';\nimport Zoom from 'ol/control/Zoom';\nimport ZoomToExtent from 'ol/control/ZoomToExtent';\nimport FullScreen from 'ol/control/FullScreen';\nimport Rotate from 'ol/control/Rotate';\nimport Button from 'ol-ext/control/Button';\nimport { containsCoordinate, getIntersection } from 'ol/extent';\nimport WKT from 'ol/format/WKT';\nimport { unByKey } from 'ol/Observable';\nimport { getArea, getLength } from 'ol/sphere';\nimport Overlay from 'ol/Overlay';\nimport { LineString, Polygon, Point, MultiPolygon, MultiLineString } from 'ol/geom';\nimport { fromExtent } from 'ol/geom/Polygon';\nimport KML from 'ol/format/KML';\nimport JSZip from 'jszip';\nimport Feature from 'ol/Feature';\nimport Icon from 'ol/style/Icon';\nimport { boundingExtent } from 'ol/extent';\nimport { register } from 'ol/proj/proj4';\nimport { defaults as defaultInteractions } from 'ol/interaction';\nimport { NewLaunchControl, ActControl, fillElementInfo, createProp_dialog } from './simulaciones.mjs';\nimport { BingLayer, XYZLayer, WMSLayer, WMSFlowLayer, WMTSLayer, OSMLayer, repositionTooltips, sigym2 } from './simmerlayer.mjs';\nimport { SaverElementsLayer } from '../../../../saver/statix/js/saver_layers.mjs';\nimport { GraphControl, crearControlesDimensiones } from './GraphControl.mjs';\nimport { TimelineControl, setCurrentValue, getFormatString, roundNextXMin } from './timeline.mjs'\nimport ContextMenu from 'ol-contextmenu'\nimport 'ol-contextmenu/ol-contextmenu.css'\nimport Measurer from './measurer.js'\nimport OLCesium from 'olcs'\n\nwindow.CESIUM_BASE_URL = '/CESIUM_BASE_URL/';\nimport { Cartesian3, createOsmBuildingsAsync, Ion, Math as CesiumMath, Terrain, Viewer } from 'cesium';\nimport \"cesium/Build/Cesium/Widgets/widgets.css\";\nimport * as Cesium from 'cesium'\nimport cartesian from 'cartesian';\nimport Cookies from 'js-cookie';\n\nwindow.Cesium = Cesium;\nIon.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJmYTc5NmUyOS0wZDM2LTQ2MzctYWMwNi01NmU3ZmRmNzEyNDYiLCJpZCI6MzEwODQ4LCJpYXQiOjE3NDk1NDYyNTZ9.gt1r2S3TxKIH3QUWL6TO0mDfa672i58DsrwI1IR1zSo';\n\nproj4.defs(\"EPSG:4083\", \"+proj=utm +zone=28 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\");\nproj4.defs(\"EPSG:25828\", \"+proj=utm +zone=28 +ellps=GRS80 +datum=ETRS89 +units=m +no_defs\");\nproj4.defs(\"EPSG:25829\", \"+proj=utm +zone=29 +ellps=GRS80 +datum=ETRS89 +units=m +no_defs\");\nproj4.defs(\"EPSG:25830\", \"+proj=utm +zone=30 +ellps=GRS80 +datum=ETRS89 +units=m +no_defs\");\nproj4.defs(\"EPSG:25831\", \"+proj=utm +zone=31 +ellps=GRS80 +datum=ETRS89 +units=m +no_defs\");\nproj4.defs(\"EPSG:32628\", \"+proj=utm +zone=28 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\");\nproj4.defs(\"EPSG:32613\", \"+proj=utm +zone=13 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\");\nproj4.defs(\"EPSG:32614\", \"+proj=utm +zone=14 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\");\nproj4.defs(\"EPSG:32616\", \"+proj=utm +zone=16 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\");\nproj4.defs(\"EPSG:32617\", \"+proj=utm +zone=17 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\");\nproj4.defs(\"EPSG:3035\", \"+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\");\nproj4.defs(\"EPSG:32715\", \"+proj=utm +zone=15 +south +datum=WGS84 +units=m +no_defs\");\nproj4.defs(\"EPSG:25833\", \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\");\nproj4.defs(\"EPSG:25836\", \"+proj=utm +zone=36 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\");\nproj4.defs(\"EPSG:23030\", \"+proj=utm +zone=30 +ellps=intl +towgs84=-87,-98,-121,0,0,0,0 +units=m +no_defs +type=crs\");\n\nregister(proj4);\n\nconst MAP_ACTIONS = {\n  GET_METEOCIEL_SOUNDING: function (evt) {\n    const coords = evt.coordinate;\n    let now = dayjs(window.timelinectl.timeline.getCurrentTime());\n    now = now.utc();\n    now = now.add(-6, 'hours');\n    now = now.startOf('day')\n    now = now.add(6, 'hours');\n    const selectedTime = dayjs(window.timelinectl.timeline.getCustomTime('current'));\n    selectedTime.utc();\n    const horizon = dayjs.duration(selectedTime.diff(now)).asHours();\n    const [lon, lat] = proj4(window.epsg, 'EPSG:4326', coords);\n    const url = `https://www.meteociel.fr/modeles/sondage2.php?mode=0&lon=${lon}&lat=${lat}&ech=${horizon}&map=10`\n    window.open(url, '_blank');\n  },\n  GET_VER_VAL_REPORT: async function (evt, map) {\n    const layers = map.get('layerObjects');\n    const REPORTS = window.namespaces[0].GET_VER_VAL_REPORT_LIST;\n    let availableReports = [];\n    let obs;\n    for (const obsType of Object.keys(REPORTS)) {\n      const obsLayer = layers.filter(lyr => lyr._pageLayer.extra?.GET_VER_VAL_REPORT == obsType)[0];\n      const url = obsLayer._ol_layer.getSource().getFeatureInfoUrl(\n        evt.coordinate,\n        map.getView().getResolution(), map.getView().getProjection(), {\n        INFO_FORMAT: 'application/vnd.meteogrid.emmet+json',\n        TOLERANCE: 7,\n      });\n      const response = await fetch(url);\n      const json = await response.json();\n      if (json.features.length) {\n        obs = json.features[0].properties;\n        availableReports = availableReports.concat(REPORTS[obsType]);\n      }\n    }\n    availableReports.sort(opt => opt[2]);\n    if (!obs) {\n      $('#report-list-empty').removeClass('hidden').dialog();\n      return;\n    }\n    const reportList = $('#report-list');\n    reportList.removeClass('hidden');\n    reportList.find('tr').not('.model').remove();\n    const modelRow = reportList.find('tr.model.report');\n    for (const opt of availableReports.toSorted((a, b) => a[2].localeCompare(b[2]))) {\n      const newRow = modelRow.clone();\n      newRow.removeClass('model');\n      const td = newRow.find('td.report-name');\n      const boton = newRow.find('td .boton');\n      boton.on('click', () => window.open(`${window.Urls.ad_hoc_report()}?report=${opt[0]}&pois=${obs.id}`));\n      td.data('report-id', opt[0]);\n      td.text(opt[2]);\n      modelRow.parent().append(newRow);\n    }\n    reportList.dialog({\n      appendTo: map.getTargetElement(),\n      title: window.gettext(obs.name),\n      width: 'auto',\n      height: 'auto',\n      open: () => {\n        reportList.parent().css('width', 'auto');\n        reportList.parent().css('height', 'auto');\n      }\n    })\n  },\n  SPECIES_ANALYSIS: async function (evt, map) {\n    const coords = evt.coordinate;\n    const [x, y] = coords\n    const srs = map.getView().getProjection();\n    const url = new URL(\n      window.Urls.analysis_forestecco(),\n      window.location);\n    url.searchParams.set('x', x);\n    url.searchParams.set('y', y);\n    url.searchParams.set('srs', srs.getCode());\n    url.searchParams.set('visible_srid', window.coordinates_epsg);\n    $('#species-dialog').removeClass('hidden');\n    const sel_species = $('#species');\n    const sel_scenarios = $('#scenarios');\n    const sel_periods = $('#periods');\n\n    if (sel_species.find('option').length == 0) {\n      const urlSpecs = new URL(\n        window.Urls.pois_json_by_st('FOREST_SPECIES'),\n        window.location);\n      urlSpecs.searchParams.set('no_geom', true);\n      const resp = await fetch(urlSpecs);\n      const specs = await resp.json();\n      for (const spec of specs)\n        sel_species.append($(`<option value=${spec.id}>${spec.name}</option>`));\n\n      const scenarios = map.get('dimension_controls').FIC_SCENARIO_FCC.options;\n      for (const scenario of scenarios)\n        if (scenario[0] != 'HISTORICAL')\n          sel_scenarios.append($(`<option selected value=${scenario[0]}>${scenario[1]}</option>`))\n\n      const periods = window.timelinectl.timeline.customTimes;\n      for (const period of periods)\n        if (period.options.id !== 'current' && period.customTime.getFullYear() > 2000)\n          sel_periods.append($(`<option selected value=${period.customTime.getFullYear()}>${period.options.title}</option>`))\n      sel_species.on('change', function () {\n        $('#btn_analysis').prop('disabled',\n          (sel_species.val().length && sel_scenarios.val().length && sel_periods.val().length) == 0);\n      })\n      sel_species.multiSelect(multiselectOptions(\n        '<div class=\"multiselect-header\">No incluir</div>',\n        '<div class=\"multiselect-header\">Incluir</div>')\n      );\n\n      sel_periods.multiSelect(multiselectOptions(\n        '<div class=\"multiselect-header\">No incluir</div>',\n        '<div class=\"multiselect-header\">Incluir</div>')\n      );\n\n      sel_scenarios.multiSelect(multiselectOptions(\n        '<div class=\"multiselect-header\">No incluir</div>',\n        '<div class=\"multiselect-header\">Incluir</div>')\n      );\n\n    }\n    sel_species.val([])\n    sel_species.multiSelect('deselect_all');\n    const downloadbusy = 'downloadbusy';\n    const buttons = [\n      {\n        id: 'btn_analysis',\n        text: window.gettext('Aceptar'),\n        disabled: true,\n        click: function () {\n          const iframe = $('<iframe>', { id: downloadbusy });\n          url.searchParams.set('elements', sel_species.val());\n          url.searchParams.set('periods', sel_periods.val());\n          url.searchParams.set('scenarios', sel_scenarios.val());\n          url.searchParams.set('order', $('input[name=\"order-by\"]:checked').val());\n          $('body').append(iframe);\n          Cookies.set(downloadbusy, true);\n          iframe.attr('src', url);\n          let timer = 0;\n          const timeOut = window.setInterval(\n            function () {\n              if (timer > 100 || !Cookies.get(downloadbusy)) {\n                $('body').remove(iframe);\n                map.set('notification', null)\n                window.clearInterval(timeOut)\n              }\n              else\n                map.set('notification', window.gettext('Generando... %s').replace(/[%]s/, Math.floor(timer++ / 10)));\n            },\n            500\n          )\n          $(this).dialog(\"close\");\n          $(this).dialog(\"destroy\");\n        },\n      },\n      {\n        text: window.gettext('Cancelar'),\n        click: function () {\n          $(this).dialog(\"close\");\n          $(this).dialog(\"destroy\");\n        }\n      }\n    ];\n    $('#species-dialog').dialog({\n      minWidth: 520,\n      buttons\n    })\n  }\n};\n\nfunction transform_extent(extent) {\n  const corners = [\n    transform_point([extent[0], extent[1]]),\n    transform_point([extent[2], extent[3]]),\n    transform_point([extent[0], extent[3]]),\n    transform_point([extent[2], extent[1]])\n  ];\n  return boundingExtent(corners);\n}\nasync function cargarMosaico(ns, cfg) {\n  let marks = [];\n  let diffs = [];\n  const string_extent = getParameterByName('extent');\n\n  if (cfg.page_type_locator == 'mappage') {\n    $.getJSON(window.Urls.page_json(ns.page_id), opt => cfg = opt);\n    cfg.extent = new Float64Array(string_extent.split(','));\n  }\n  //cfg.pagelayer_set.forEach(cargarArbol)\n  if (cfg.epsg)\n    ns.epsg = cfg.epsg.locator;\n\n  if (cfg.page_type_locator == 'mappage') {\n    window.document.title += ` - ${window.gettext(\"Mosaico\")}`;\n    $('ul.breadcrumb').find('li.active').parent().append(`<li>${window.gettext(\"Mosaico\")}</li>`);\n    $('ul.breadcrumb').find('li.active').remove();\n  }\n  let iter, interv, delta;\n  let iterations = cfg.iterations;\n  if (ns.time_type === undefined)\n    ns.time_type = cfg.time_type;\n  const extent_local_global = transformExtent(cfg.extent, 'EPSG:4326', window.epsg);\n\n  const view = new View({\n    center: extent_local_global,\n    projection: ns.epsg,\n    showFullExtent: true,\n    zoom: 10,\n  });\n  const emul_mapa = new Map({\n    _time_delta: null,\n    view: view,\n  });\n  emul_mapa.set('info', true);\n  const dimension_controls = {};\n  const activeDimensions = getParameterByName('activeDimensions');\n  if (!activeDimensions)\n    emul_mapa.set('activeDimensions', {}, true);\n  emul_mapa.set('simulatoin_id', ns.simulation_id);\n  emul_mapa.set('dimension_controls', dimension_controls, true);\n  emul_mapa.set('layerObjects', []);\n  crearControlesDimensiones(emul_mapa, dimension_controls, cfg.dimensions);\n  var $dim = $('#dimensions');\n  var hiddenDimsSel = (\n    $dim.length === 0 ||\n    $dim.is(':hidden') ||\n    $dim.width() === 0 ||\n    $dim.height() === 0\n  );\n  if (hiddenDimsSel)\n    $('#parameters').removeClass('hidden');\n  ns.mapas = [emul_mapa];\n  if (!cfg.time_type.locator.startsWith(\"ENUM\")) {\n    const iter_field = $('.iteration-field');\n    iter = iter_field.find('input');\n\n    const interv_field = $('.interval-field');\n    interv = interv_field.find('input');\n    iter_field.find('i').click(function () {\n      iter_field.toggleClass('listshown');\n    });\n    interv_field.find('i').click(function () {\n      interv_field.toggleClass('listshown');\n    });\n    let iter_list = [];\n    let interv_list = [];\n    delta = cfg.delta;\n    cfg.time_type.data.forEach((dat) => {\n      if (dat.type.locator == \"MOSAIC_DELTA\")\n        interv_list = JSON.parse(dat.value);\n      else if (dat.type.locator == \"MOSAIC_ITERATIONS\")\n        iter_list = JSON.parse(dat.value);\n      else if (dat.type.locator == \"DEFAULT_MOSAIC_DELTA\" && !delta)\n        delta = dat.value;\n      else if (dat.type.locator == \"DEFAULT_MOSAIC_ITERATIONS\" && !iterations)\n        iterations = dat.value;\n    })\n    if (!iter_list.includes(iterations))\n      iter_list.push(iterations)\n    iter.val(iterations);\n    interv.val(delta);\n\n    iter_list.forEach((ep) => {\n      const li = document.createElement('li')\n      li.innerText = ep;\n      li.value = ep;\n      li.addEventListener('click', async function () {\n        $(this).parent().find('li').removeClass('select');\n        $(this).addClass('select');\n        iter_field.removeClass('listshown');\n        $('.mosaics').empty();\n        iter.val($(this).val());\n        const string_extent = getParameterByName('extent');\n        const extent = string_extent ?\n          new Float64Array(string_extent.split(',')) :\n          cfg.extent;\n        ns.mapas = [emul_mapa];\n        const mapasM = await crearMosaicos(ns, { ...cfg, extent }, $(this).val(), false);\n        crearMapas_mosaico(ns, mapasM);\n      }, false);\n      $('ul#iteration-list').append(li);\n    })\n    interv_list.forEach((ep) => {\n      const li = document.createElement('li')\n      li.innerText = ep;\n      li.value = ep;\n      li.addEventListener('click', function () {\n        $(this).parent().find('li').removeClass('select');\n        $(this).addClass('select');\n        interv_field.removeClass('listshown');\n        interv.val($(this).val());\n        const self = this;\n        let resolution = 1;\n        if (cfg.time_type.locator == '1MO')\n          resolution = 720;\n        for (const [i, mapa] of ns.mapas.entries()) {\n          if (i == 0) continue;\n          const n_map = Number(mapa.getTargetElement().id.split('_')[1]);\n          mapa.getLayers().forEach(function (l) {\n            if (l.get('time_management')) {\n              const src = l.getSource();\n              src.set('time_delta', n_map * resolution * $(self).val());\n            }\n          });\n        }\n        setCurrentValue(dayjs(window.timelinectl.timeline.getCustomTime('current')));\n      }, false);\n      $('ul#interval-list').append(li);\n    });\n  }\n  else {\n    $('div.parameters').hide();\n    $('div.calendar').hide();\n    marks = cfg.time_type.locator\n      .split(':')[1]\n      .split('/')\n      .map(x => dayjs(x + '-01-01T00:00:00Z'));\n    diffs = marks;\n  }\n  let createTimeline = true;\n  const extent = string_extent ?\n    new Float64Array(string_extent.split(',')) :\n    cfg.extent;\n  if (!activeDimensions) {\n    const mapasM = await crearMosaicos(ns, { ...cfg, extent },\n      (diffs.length) ? diffs.length : iterations, createTimeline, diffs);\n    await crearMapas_mosaico(ns, mapasM);\n  }\n  else {\n    let newActiveDimensions = {};\n    for (const ctl of Object.values(dimension_controls)) {\n      if (!ctl.id) continue;\n      newActiveDimensions[ctl.id] = [];\n      const dim_values = getParameterByName(ctl.id);\n      for (const v of dim_values.split(',')) {\n        const option = ctl.options.find(o => o[0] == v);\n        if (option)\n          newActiveDimensions[ctl.id].push(option);\n      }\n    }\n    for (const k of Object.keys(newActiveDimensions))\n      if (newActiveDimensions[k].length > 1) {\n        dimension_controls[k].value = null;\n      }\n    emul_mapa.set(\"dimension_controls\", dimension_controls)\n    if (newActiveDimensions)\n      emul_mapa.set('activeDimensions', newActiveDimensions);\n    const combinations = !$.isEmptyObject(newActiveDimensions) ? cartesian(newActiveDimensions) : [{}];\n    const sortByValue = getParameterByName('sortByValue');\n    combinations.sort((a, b) => {\n      const valA = a[sortByValue]?.[0] ?? \"\";\n      const valB = b[sortByValue]?.[0] ?? \"\";\n      return valA.localeCompare(valB);\n    });\n    emul_mapa.set('sortByValue', sortByValue);\n    const mapasM = await crearMosaicos(ns, { ...cfg, extent, combinations, sortByValue },\n      diffs.length ? diffs.length : iterations, createTimeline, diffs);\n\n    await crearMapas_mosaico(ns, mapasM);\n  }\n  setTimeout(() => {\n    const idx_hor_notsel = getParameterByName('idx_hor_notsel').split(',');\n\n    ns.mapas.map(map => {\n      const elem = map.getTargetElement();\n      if (elem) {\n        const map_iter = elem.id.split('_')[1];\n        if (idx_hor_notsel.find(i => i == map_iter))\n          $(elem).parent().hide();\n      }\n    })\n  }, 200)\n  let drawBox;\n  const pagelayer_set = cfg?.pagelayer_set;\n  $('#seleccionar_bbox').on('click', function () {\n    const extentInicial = cfg.extent;\n    const { viewState, extent } = ns.mapas[1].getView().getViewStateAndExtent();\n\n    const extent_local_global = transformExtent(extent, viewState.projection, 'EPSG:3857');\n    const extentInicial3857 = transformExtent(extentInicial, 'EPSG:4326', 'EPSG:3857');\n    $('#selector-bbox').show().animate({ width: '300pt', height: '300pt' },\n      {\n        complete: async function () {\n          if ($('#selector-bbox div.ol-viewport').length > 0)\n            return;\n\n          const source = new VectorSource({ wrapX: false });\n          const feature = new Feature({\n            geometry: fromExtent(extent_local_global),\n          });\n\n          source.addFeature(feature);\n          const vector = new VectorLayer({\n            source: source,\n          });\n          const v = new View({\n            center: [0, 0],\n            showFullExtent: true,\n            extent: extentInicial3857,\n          });\n          v.fit(extentInicial3857);\n          const m = new Map({\n            layers: [\n              new TileLayer({\n                opacity: 0.5,\n                source: new OSM(),\n              }),\n              vector,\n            ],\n            target: 'selector-bbox',\n            view: v,\n          });\n          m.set('layerObjects', []);\n          for (const page_layer of cfg.pagelayer_set) {\n            if (page_layer.layer.layertype.locator == 'REFERENCE') {\n              await crearCapa(\n                ns,\n                m,\n                page_layer,\n                transform_extent(extentInicial),\n                false,\n                cfg.time_delta,\n                cfg.extra\n              );\n            }\n          }\n          drawBox = new Draw({\n            source: source,\n            type: 'Circle',\n            geometryFunction: createBox(),\n          });\n          /**\n   * The help tooltip element.\n   * @type {HTMLElement}\n   */\n          let helpTooltipElement;\n          /**\n           * Overlay to show the help messages.\n           * @type {Overlay}\n           */\n          let helpTooltip;\n          if (helpTooltipElement) {\n            helpTooltipElement.parentNode.removeChild(helpTooltipElement);\n          }\n          helpTooltipElement = document.createElement('div');\n          helpTooltipElement.className = 'ol-tooltip hidden';\n          helpTooltip = new Overlay({\n            element: helpTooltipElement,\n            offset: [15, 0],\n            positioning: 'center-left'\n          });\n          helpTooltipElement.innerHTML = window.gettext('Click para comenzar a dibujar');\n          m.addOverlay(helpTooltip);\n          const pointerMoveHandler = function (evt) {\n            if (evt.dragging) {\n              return;\n            }\n            helpTooltip.setPosition(evt.coordinate);\n            helpTooltipElement.classList.remove('hidden');\n          };\n          m.on('pointermove', pointerMoveHandler);\n          m.getViewport().addEventListener('mouseout', function () {\n            helpTooltipElement.classList.add('hidden');\n          });\n          drawBox.on('drawstart',\n            function () {\n              const f = this.source_.getFeatures().pop();\n              if (f)\n                this.source_.removeFeature(f)\n              helpTooltipElement.innerHTML = window.gettext('Click para terminar de dibujar');\n            });\n          drawBox.on('drawend',\n            function (evt) {\n              const feature = evt.feature;\n              if (feature) {\n                const oldUrl = window.location.href;\n                const extent3857 = feature.getGeometry().getExtent();\n                const extent4326 = transformExtent(extent3857, 'EPSG:3857', 'EPSG:4326');\n                let newUrl;\n                if (oldUrl.includes('extent'))\n                  newUrl = oldUrl.replace(/(extent=)[^&]*(.*)/, '$1' + extent4326 + '$2')\n                else {\n                  const sep = oldUrl.includes('?') ? '&' : '?'\n                  newUrl = oldUrl + sep + 'extent=' + extent4326;\n                }\n                window.history.replaceState(null, null, newUrl);\n                const value = $('input#iteration').val();\n                if (value)\n                  $(`ul#iteration-list li[value=${value}]`).trigger('click');\n                else\n                  // FIXME\n                  window.location.reload();\n              }\n              helpTooltipElement.innerHTML = window.gettext('Click para comenzar a dibujar');\n            })\n          m.addInteraction(drawBox);\n          $('#selector-bbox').find('.ol-attribution').addClass('ol');\n          setTimeout(() => {\n            $('#selector-bbox').find('.ol-attribution button').click();\n          }, 100);\n        },\n      })\n    $('#selector-bbox').dialog({\n      title: window.gettext('Seleccione el área a mostrar'),\n      width: 'auto',\n      height: 'auto',\n      open: () => {\n        $('#selector-bbox').parent().css('width', 'auto');\n        $('#selector-bbox').parent().css('height', 'auto');\n      },\n      close: () => {\n        $('#selector-bbox').empty();\n      }\n    });\n  });\n  $('#imprimir_mosaico').click(function () {\n    // FIXME: Es igual que exportar_tif\n    const string_extent = getParameterByName('extent');\n    const extent = string_extent ?\n      new Float64Array(string_extent.split(',')) :\n      cfg.extent;\n    const extent_mosaico = transformExtent(extent, 'EPSG:4326', ns.epsg);\n    const url = new URL(window.Urls.page_pdf(cfg.id), window.location.href);\n    url.searchParams.set(\n      'date', window.timelinectl.timeline.getCustomTime('current').toISOString());\n    url.searchParams.set(\n      'ITERATIONS', iter ? iter.val() : diffs.length);\n    url.searchParams.set(\n      'DELTA_TIME', interv ? interv.val() : 0);\n    url.searchParams.set(\n      'visible_layers', getParameterByName('visible_layers'));\n    url.searchParams.set('bbox', extent_mosaico);\n    if (emul_mapa.get('sortByValue'))\n      url.searchParams.set('sortByValue', emul_mapa.get('sortByValue'));\n    const activeDimensions = emul_mapa.get('activeDimensions');\n    let dimensions = {};\n    if (activeDimensions && Object.keys(activeDimensions).length) {\n      for (const [id, vals] of Object.entries(activeDimensions)) {\n        dimensions[id] = vals.map(d => d[0]).join(',');\n      }\n    } else {\n      dimensions = setDims(pagelayer_set);\n    }\n    for (const [k, v] of Object.entries(dimensions || {})) {\n      if (Array.isArray(v)) {\n        v.forEach(val => url.searchParams.append(k, val));\n      } else if (v != null) {\n        url.searchParams.set(k, v);\n      }\n    }\n    if (diffs && diffs.length) {\n      url.searchParams.set(\n        'DIFF_DELTA',\n        typeof diffs[0] === 'number'\n          ? diffs.join(',')\n          : diffs.map(d => d.toISOString()).join(',')\n      );\n    }\n    if (ns.simulation_id)\n      url.searchParams.set('simulation_id', ns.simulation_id);\n    const idx_hor_notsel = getParameterByName('idx_hor_notsel');\n    if (idx_hor_notsel.length)\n      url.searchParams.set('notsel_idxs', idx_hor_notsel);\n    window.open(url);\n  });\n  $('#exportar_tif').click(function () {\n    const string_extent = getParameterByName('extent');\n    const extent = string_extent ?\n      new Float64Array(string_extent.split(',')) :\n      cfg.extent;\n    const extent_mosaico = transformExtent(extent, 'EPSG:4326', ns.epsg);\n    const url = new URL(window.Urls.page_tif(cfg.id), window.location);\n    url.searchParams.set(\n      'date', window.timelinectl.timeline.getCustomTime('current').toISOString());\n    url.searchParams.set(\n      'ITERATIONS', iter ? iter.val() : marks.length);\n    url.searchParams.set(\n      'DELTA_TIME', interv ? interv.val() : 0);\n    url.searchParams.set(\n      'visible_layers', getParameterByName('visible_layers'));\n    url.searchParams.set('bbox', extent_mosaico);\n    if (ns.epsg)\n      url.searchParams.set('srid', ns.epsg);\n    const extra_dim = setDims(pagelayer_set);\n    if (extra_dim) {\n      for (const [k, v] of Object.entries(extra_dim)) {\n        if (Array.isArray(v)) {\n          v.forEach(val => url.searchParams.append(k, val));\n        } else if (v != null) {\n          url.searchParams.set(k, v);\n        }\n      }\n    }\n    if (ns.simulation_id)\n      url.searchParams.set('simulation_id', ns.simulation_id);\n    window.open(url);\n  });\n  $('#seleccionar_horizons').click(function () {\n    if ($('.dialog[name=\"sel_hor_dialog\"].ui-dialog-content').length)\n      $('.dialog[name=\"sel_hor_dialog\"].ui-dialog-content').dialog('destroy');\n    const selector_element = $('<div class=\"dialog\" id=\"select-horizons-dialog\" name=\"sel_hor_dialog\"><form><div class=\"multi flex\"><select multiple name=\"horizons\"></div></select></form></div>');\n    const sel = selector_element.find('select');\n    const { capas } = getVisibleLayers_set(pagelayer_set);\n    const default_layer = capas[0];\n    sel.empty();\n    const format_string = getFormatString(cfg.time_type.locator);\n    if (!cfg.time_type.locator.startsWith(\"ENUM\")) {\n      let init_date = $('div.calendar').find('input').val();\n      init_date = dayjs(init_date).startOf('hour');\n      const iter_value = Number(iter.val());\n      const delta_value = Number(interv.val());\n      const scale = cfg.time_type.locator == '1MO' ? 'months' : 'hours';\n      for (let iteracion = 0; iteracion < iter_value; iteracion++) {\n        const opt_val = dayjs(init_date).add(delta_value * iteracion, scale);\n        const hor_id = `${default_layer.id}_${iteracion}`;\n        const no_selected = $(`div#${hor_id}.mosaic_map`).is(':hidden');\n        sel.append($(`<option ${no_selected ? '' : 'selected=\"selected\"'} value=\"${opt_val.toISOString()}\" n_iter=\"${iteracion}\">${opt_val.format(format_string)}</option>`));\n      }\n    }\n    else {\n      const labelsj = cfg.time_type.data.find(x => x.locator == 'LABELS');\n      const labels = labelsj ? JSON.parse(labelsj.value) : null;\n      marks.map((mark, idx) => {\n        const k = labels ? labels[mark.format(format_string)] : mark.format(format_string);\n        const hor_id = `${default_layer.id}_${idx}`;\n        const no_selected = $(`div#${hor_id}.mosaic_map`).is(':hidden');\n        sel.append($(`<option ${no_selected ? '' : 'selected=\"selected\"'} n_iter=\"${idx}\">${k}</option>`));\n      })\n    }\n    const buttons = [\n      {\n        text: window.gettext('Guardar'),\n        click: function () {\n          const form = sel.closest('form');\n          const idx_hor_notsel = showHorizons(form);\n          updateUnselectedHorizons(idx_hor_notsel);\n          const dialog = this;\n          $(dialog).dialog(\"close\");\n          $(dialog).dialog(\"destroy\");\n        },\n      },\n      {\n        text: window.gettext('Cancelar'),\n        click: function () {\n          const dialog = this;\n          $(dialog).dialog(\"close\");\n          $(dialog).dialog(\"destroy\");\n        }\n      }\n    ];\n    sel.multiSelect(multiselectOptions(\n      '<div class=\"multiselect-header\">No mostrados</div>',\n      '<div class=\"multiselect-header\">Mostrados</div>')\n    );\n    sel.on('change', function () {\n      const form = sel.closest('form');\n      form.find('.ms-selection li').attr('title', window.gettext('Deseleccionar'))\n      form.find('.ms-selectable li').attr('title', window.gettext('Seleccionar'))\n\n    });\n    sel.trigger('change');\n    selector_element.attr('id', `select-horizons-dialog_${sel.attr('id')}`)\n    selector_element.show();\n    selector_element.dialog({\n      title: window.gettext('Seleccione los horizontes a mostrar:'),\n      width: 'auto',\n      height: 'auto',\n      buttons: buttons,\n      position: {\n        my: 'center',\n        at: 'center',\n        collision: \"fit\"\n      },\n      autoOpen: true,\n    });\n  });\n  setDims(pagelayer_set);\n  const hasSeriesComb =\n    pagelayer_set.some(pl => pl.shown &&\n      pl.extra_dim &&\n      Object.keys(pl.extra_dim).length > 0);\n  if (hasSeriesComb) {\n    const $container = $('.right-bar.ol-control');\n    let $btn = $('#show-dim-selector');\n    if (!$btn.length) {\n      $btn = $(`\n        <button id=\"show-dim-selector\"\n                class=\"fas fa-solid fa-cubes\"\n                title=\"${window.gettext('Seleccionar combinaciones de series')}\">\n        </button>\n      `).on('click', () => showDimSelector(emul_mapa));\n    }\n    $container.prepend($btn);\n  } else {\n    $('#show-dim-selector').remove();\n  }\n  emul_mapa.on('change:dimension_controls', function () {\n    if ($('#parameters').is(':hidden') && dimension_controls && Object.values(dimension_controls).length > 1) {\n      const oldUrl = window.location.href;\n      let restart = true;\n      let newUrl = new URL(oldUrl);\n      for (const ctl of Object.values(dimension_controls)) {\n        if (!ctl.id) continue;\n        if (ctl.value === null) {\n          restart = false;\n          continue\n        }\n        newUrl.searchParams.set(ctl.id, ctl.value);\n      }\n      if (restart) {\n        newUrl.searchParams.delete('activeDimensions');\n        newUrl.searchParams.delete('sortByValue');\n      }\n      window.history.replaceState(null, null, newUrl);\n      window.location.reload();\n    }\n  })\n}\n\nfunction showDimSelector(emul_mapa) {\n  const dimControls = emul_mapa.get('dimension_controls');\n  let $dialog = $('#dims-dialog');\n  if ($dialog.length === 0) {\n    $dialog = $('<div id=\"dims-dialog\"></div>').appendTo('body');\n\n    $dialog.dialog({\n      title: window.gettext('Seleccione dimensiones'),\n      autoOpen: false,\n      modal: true,\n      width: 'auto',\n      buttons: [{\n        text: window.gettext('Aceptar'),\n        click: function () {\n          const newActiveDimensions = {};\n          $('#dims-dialog .multi.flex:visible').each((idx, divSel) => {\n            const $divSel = $(divSel);\n            const sel = $divSel.find('select');\n            const val = sel.val() || [];\n\n            const id = sel.attr('id').split(' ')[1];\n            newActiveDimensions[id] = val.map(v => [v, captions[id][v]]);\n          });\n          const sortByValue = $('#sortSelect').val();\n          emul_mapa.set('sortByValue', sortByValue);\n          emul_mapa.set('activeDimensions', newActiveDimensions);\n          const oldUrl = window.location.href;\n          let newUrl = new URL(oldUrl);\n          if (newActiveDimensions) {\n            for (const [k, v] of Object.entries(newActiveDimensions)) {\n              if (Array.isArray(v)) {\n                const values = v.map(pair => pair[0]);\n                newUrl.searchParams.set(k, values.join(','));\n              } else if (v != null) {\n                newUrl.searchParams.set(k, v);\n              }\n            }\n            newUrl.searchParams.set(\"activeDimensions\", true);\n            newUrl.searchParams.set(\"sortByValue\", sortByValue);\n          }\n          else {\n            newUrl.searchParams.set(\"activeDimensions\", false);\n            newUrl.searchParams.set(\"sortByValue\", false);\n          }\n          window.history.replaceState(null, null, newUrl);\n          window.location.reload();\n          $dialog.dialog('close');\n        }\n      }\n      ]\n    });\n  } else {\n    $dialog.empty();\n  }\n  const captions = {};\n  const groupContainer = $(`\n    <div id=\"sortSelectContainer\" class=\"dim-control\">\n      <label for=\"sortSelect\">${window.gettext('Ordenar por:')}</label>\n      <select id=\"sortSelect\" class=\"custom-select\"></select>\n    </div>\n  `).appendTo($dialog);\n\n  const sortByValue = emul_mapa.get('sortByValue');\n\n  for (const ctl of Object.values(dimControls)) {\n    if (ctl.usage > 0) {\n      const selected = (ctl.id === sortByValue) ? 'selected' : '';\n      groupContainer.find('select').append(\n        `<option value=\"${ctl.id}\" ${selected}>${ctl.name}</option>`\n      );\n    }\n  }\n\n\n  for (const ctl of Object.values(dimControls)) {\n    if (!ctl.id) continue;\n    captions[ctl.id] = {};\n    const div = $(`<div class=\"multi flex\"></div>`).appendTo($dialog);\n    $(`<h4>${ctl.name}</h4>`).appendTo(div);\n\n    const sel = $(`<select id=\"dimensionSel ${ctl.id}\" multiple=\"multiple\"></select>`)\n      .appendTo(div);\n\n    for (const [value, name] of ctl.options) {\n      sel.append(`<option value=\"${value}\">${name}</option>`);\n      captions[ctl.id][value] = name;\n    }\n\n    sel.multiSelect(multiselectOptions(\n      '<div class=\"multiselect-header\">No mostrados</div>',\n      '<div class=\"multiselect-header\">Mostrados</div>'\n    ));\n  }\n\n  const activeDims = emul_mapa.get('activeDimensions') || {};\n  for (const ctl of Object.values(dimControls)) {\n    if (!ctl.id) continue;\n    const sel = $(`select[id=\"dimensionSel ${ctl.id}\"]`);\n    if (!sel.length) continue;\n    sel.multiSelect('deselect_all');\n    if (activeDims[ctl.id] && activeDims[ctl.id].length > 0) {\n      // usar lo guardado\n      sel.multiSelect('select', activeDims[ctl.id].map(v => '' + v[0]));\n    } else if (ctl.value) {\n      // si no había nada, usar el valor por defecto\n      sel.multiSelect('select', [ctl.value]);\n    }\n  }\n  $dialog.dialog('open');\n}\n\nfunction showHorizons(form) {\n  const lis_notsel = form.find('.ms-selectable li:not(.ms-selected)');\n  const lis_sel = form.find('.ms-selectable li.ms-selected');\n  const idx_hor_notsel = []\n  const maps = $('tr.fila_mapas .mosaic_map');\n  lis_notsel.map((idx_li, li) => {\n    idx_hor_notsel.push(li.getAttribute('n_iter'));\n    maps.map((i, map) => {\n      const map_iter = map.id.split('_')[1];\n      if (map_iter == li.getAttribute('n_iter'))\n        $('#' + map.id).parent().hide();\n    })\n  })\n  lis_sel.map((idx_li, li) => {\n    maps.map((i, map) => {\n      const map_iter = map.id.split('_')[1];\n      if (map_iter == li.getAttribute('n_iter'))\n        $('#' + map.id).parent().show();\n    })\n  })\n  return idx_hor_notsel;\n}\nasync function crearMapas_mosaico(ns, mapasM) {\n  Promise.allSettled(Object.entries(mapasM).map(kv => cargarMapa(ns, ns.page.find(`#${kv[0]}`), kv[1]))).then(\n    () => {\n      const dims = ns.mapas[0].get('dimension_controls');\n      const activeDimensions = getParameterByName('activeDimensions');\n      if (dims && !activeDimensions) {\n        for (const [i, mapa] of ns.mapas.entries()) {\n          if (i == 0) continue;\n          for (const dim_control of Object.values(dims)) {\n            for (const lyr of mapa.get('layerObjects')) {\n              const lyr_dims = lyr._layer?.source_type?.dimensions;\n              if (!lyr_dims || lyr_dims.length == 0)\n                continue;\n              if (!lyr_dims.find(d => d.locator == dim_control.id))\n                continue;\n              const l = lyr._ol_layer;\n              const src = l.getSource();\n              dim_control.on('change:value',\n                () => src.updateParams({ [dim_control.id]: dim_control.value })\n              );\n              src.updateParams({ [dim_control.id]: dim_control.value });\n            }\n          }\n        }\n      }\n      if (window.timelinectl)\n        setCurrentValue(dayjs(window.timelinectl.timeline.getCustomTime('current')))\n    });\n}\nfunction getVisibleLayers_set(pagelayer_set) {\n  let visible_layers = getParameterByName('visible_layers').split(',');\n  let baselayer = false;\n  if (visible_layers[0] == '') {\n    visible_layers = [];\n    pagelayer_set.forEach(l => {\n      if (l.shown)\n        if (l.layer.layertype.locator == 'BASELAYER' && !baselayer) {\n          baselayer = true;\n          visible_layers.push(String(l.id))\n        }\n        else if (l.layer.layertype.locator != 'BASELAYER')\n          visible_layers.push(String(l.id))\n    });\n  }\n  const referencias = [];\n  const fondos = [];\n  const capas = [];\n\n  let default_background = null;\n  for (const page_layer of pagelayer_set) {\n    if (!default_background && page_layer.layer.layertype.locator == 'BASELAYER' && page_layer.shown)\n      default_background = page_layer;\n    page_layer.shown = visible_layers.includes(String(page_layer.id));\n    if (page_layer.layer.layertype.locator == 'REFERENCE') referencias.push(page_layer);\n    if (page_layer.layer.layertype.locator == 'LAYER') capas.push(page_layer);\n    if (page_layer.layer.layertype.locator == 'BASELAYER') fondos.push(page_layer);\n  }\n  if (default_background && fondos.every(f => !f.shown))\n    window.setTimeout(() => { default_background.shown = true; })\n  return { referencias, fondos, capas };\n}\n\nasync function crearMosaicos(ns, cfg, iterations, createTimeline, diffs) {\n  const combinations = cfg.combinations || [{}];\n  const sortByValue = cfg.sortByValue || [{}];\n\n  setDims(cfg.pagelayer_set);\n  const mask_id = getParameterByName('trim_mask_id');\n  const { referencias, fondos, capas } = getVisibleLayers_set(cfg.pagelayer_set);\n  const capas_with = Object.groupBy(capas, (pl) => {\n    return pl.extra ? pl.extra.with : \"without\";\n  });\n  const mapasM = {};\n  for (const page_layer of capas) {\n    if (page_layer.extra && page_layer.extra.with)\n      continue;\n\n    const max_side = 170;\n    const order = page_layer.order;\n    const capas_pl = capas_with[order] ? capas_with[order] : [];\n    let height, width;\n\n    if (mask_id) {\n      page_layer.extra.mask_id = mask_id;\n    }\n    const layerObject = await crearCapa(ns, ns.mapas[0], page_layer, undefined, false, cfg.time_delta ?? 0, cfg.extra);\n    if (!page_layer.shown)\n      continue;\n\n    const extent_local = transform_extent(cfg.extent);\n    const aspect = (extent_local[3] - extent_local[1]) / (extent_local[2] - extent_local[0]);\n    if (aspect > 1) {\n      height = max_side;\n      width = max_side / aspect;\n    } else {\n      height = max_side * aspect;\n      width = max_side;\n    }\n\n    if (cfg.extra?.img_size) {\n      width = cfg.extra?.img_size * 40;\n      height = width * aspect;\n    }\n    if (page_layer.extra?.img_size) {\n      width = page_layer.extra.img_size * 40;\n      height = width * aspect;\n    }\n\n    if (layerObject.legend == 'auto') {\n      const params = { width: 150, pageLayerId: page_layer.id };\n      if (layerObject._layer.service.url.includes(sigym2))\n        params.height = 250;\n      layerObject._legend = layerObject.source.getLegendUrl(null, params);\n      layerObject._legend += '&TRANSPARENT=TRUE';\n    }\n\n    let titulo = getTitlePageLayer(page_layer);\n    for (const c of capas_pl) {\n      titulo += ' / ' + getTitlePageLayer(c);\n    }\n    const total_columnas = combinations.length * iterations + 1; // +1 por la celda de la leyenda\n    const fila_titulo = $(\n      `<tr class=\"fila_titulo\"><td class=\"titulo\" colspan=\"${total_columnas}\">${titulo}</td></tr>`\n    );\n    let fila = $('<tr class=\"fila_mapas\"/>');\n    let celda = $(\n      `<td><img \n        id=\"${page_layer.id}_legend\"\n        class=\"${layerObject.legend ? \"legend\" : \"no-legend\"}\"\n        src =\"${layerObject.legend || ''}\" />\n      </td>`\n    );\n    fila.append(celda);\n\n    for (const dimension_values of combinations) {\n      const dims_para_source = {};\n      for (const v of Object.entries(dimension_values))\n        dims_para_source[v[0]] = v[1][0];\n      const dims_para_id = Object.entries(dims_para_source).map(v => `${v[0]}-${v[1]}`).join('_');\n      for (let iteracion = 0; iteracion < iterations; iteracion++) {\n        const element_id = `${page_layer.id}_${iteracion}_${dims_para_id}`;\n        const sortedEntries = Object.entries(dimension_values)\n          .sort(([a], [b]) => (a === sortByValue ? -1 : b === sortByValue ? 1 : 0));\n        const dims_html = sortedEntries\n          .map(([k, v]) => `<div class=\"dim_label\">${v[1]}</div>`)\n          .join('');\n        let celda = $(`\n          <td>\n            <div class=\"time_info\" id=\"${element_id}_info\">...</div>\n            ${dims_html}\n            <div class=\"mosaic_map\" style=\"width:${width}pt; height:${height}pt;\" id=\"${element_id}\" class=\"celda\"></div>\n          </td>\n        `);\n        fila.append(celda);\n\n        let resolution = 1;\n        if (cfg.time_type.locator == '1MO') {\n          resolution = 720;\n          $('div.interval-field span#title').text(window.gettext('Intervalo (mes)'));\n          $('div.interval-field span#title').val('1MO');\n        }\n        const page_layer_with_dims = { ...page_layer };\n        page_layer_with_dims.extra = { ...page_layer_with_dims.extra, ...dims_para_source };\n        const map_cfg = {\n          pagelayer_set: [...referencias, ...fondos, ...capas_pl, page_layer_with_dims],\n          extent: cfg.extent,\n          time_delta: (diffs && diffs.length)\n            ? diffs[iteracion]\n            : iteracion * resolution * Number($('#interval').val()),\n        };\n        if (createTimeline) { // Sólo el primer mapa\n          createTimeline = false;\n          map_cfg.time_type = cfg.time_type;\n          map_cfg.initial_time = cfg.initial_time;\n        } else {\n          map_cfg.time_type = { locator: '0' };\n        }\n        mapasM[element_id] = map_cfg;\n      }\n    }\n\n    const tabla = $('<table><tbody></tbody></table>');\n    tabla.find('tbody').append(\n      fila_titulo,\n      fila,\n      '<tr class=\"fila_espacio\"><td colspan=\"99\">&nbsp;</td></tr>'\n    );\n    $('.mosaics').append(tabla);\n  }\n  return mapasM;\n}\n\nfunction getTitlePageLayer(page_layer) {\n  return (\n    page_layer.folder ?\n      page_layer.folder + ' - ' :\n      ''\n  ) + page_layer.layer.name_and_unit;\n}\nfunction setUpContextMenu(ns) {\n  const mapa = ns.mapa;\n  const items = [];\n  const hasSimulation = window.site_cfg.sim_type_locators.length;\n  if (hasSimulation && mapa.getTargetElement().classList.contains('interactive')) {\n    items.push({\n      text: `<i class=\"fab fa-gripfire fa-icon\"></i>&nbsp;&nbsp;${window.gettext('Propagación rápida')}`,\n      callback: createSimulation,\n      data: mapa,\n    });\n  }\n  for (const action of ns.parameters) {\n    if (action.type == 'MAP_ACTION')\n      items.push({\n        text: `<i class=\"${action.CLASS}\"></i>&nbsp;&nbsp;${window.gettext(action.name)}`,\n        callback: MAP_ACTIONS[action.parameter],\n      });\n  }\n  const contextMenu = new LegendContextMenu({\n    width: 'auto',\n    defaultItems: false,\n    items,\n  });\n  mapa.set('contextMenu', contextMenu);\n  mapa.addControl(contextMenu);\n}\nasync function cargarMapa(ns, element, cfg, dyn) {\n  if (cfg.epsg)\n    window.epsg = cfg.epsg.locator;\n  if (window.time_type === undefined)\n    window.time_type = cfg.time_type;\n  const destProj = proj4(window.epsg);\n  const oProj = destProj.oProj;\n  const deg = oProj.units == 'degrees';\n  const coordXY = createStringXY(deg ? 4 : 0);\n  const projDesc = `${window.epsg_name}`.toUpperCase();\n  if ('extent' in sessionStorage) {\n    const new_extent = sessionStorage.getItem('extent');\n    sessionStorage.removeItem('extent');\n    cfg.extent = new Float64Array(new_extent.split(','));\n  }\n  let extent = cfg.extent;\n  const extent_global = cfg.extent;\n  if (dyn && dyn.extent) extent = dyn.extent;\n  if (dyn) {\n    // FIXME: Debería ir con el modelo de\n    cfg.title = dyn.name;\n    for (let l of cfg.pagelayer_set) {\n      if (\n        l.layer.service.url &&\n        l.layer.service.url.includes('XXXsimulationXXX') &&\n        !dyn.reference\n      )\n        l.disabled = true;\n      l.layer.service.url = l.layer.service.url\n        ? l.layer.service.url.replace('XXXsimulation_idXXX', dyn.id)\n        : null;\n      l.layer.service.url = l.layer.service.url\n        ? l.layer.service.url.replace('XXXsimulationXXX', dyn.reference)\n        : null;\n      l.layer.extra = l.layer.extra || {};\n      if (dyn.relations.includes('READONLY'))\n        l.layer.extra.readonly = true;\n      if (l.extra?.affection_layer) {\n        l.layer.extra.affected_simulation_id = dyn.id;\n      }\n      for (const [k, extra_k] of Object.entries(l.layer.extra)) {\n        if (typeof extra_k === 'string') {\n          l.layer.extra[k] = l.layer.extra[k].replace(\n            'XXXsimulationXXX',\n            dyn.reference\n          ).replace(\n            'XXXsimulation_idXXX',\n            dyn.id\n          );\n        }\n      }\n    }\n  }\n  const interactive_map = element.hasClass('interactive');\n  const interactions = !interactive_map ? [] : defaultInteractions({ 'keyboard': false });\n  const extent_local = transform_extent(extent);\n  const extent_local_global = transform_extent(extent_global);\n\n  cfg.dyn = dyn;\n  let timeline_config;\n  if (cfg.time_type.locator != '0') {\n    if (cfg.time_type && window.timelinectl === undefined) {\n      if (interactive_map) {\n        $('.time-selector').appendTo(element);\n        $('.calendar').appendTo(element);\n      }\n      $('.time-selector').removeClass('hidden');\n      $('.time-selector-input').removeClass('hidden');\n      if (!cfg.time_type.locator.startsWith('ENUM')) {\n        $('.calendar').removeClass('hidden');\n      }\n      if ('date' in sessionStorage) {\n        const date = sessionStorage.getItem('date');\n        sessionStorage.removeItem('date');\n        cfg.new_initdate = date;\n      } else {\n        if (ns.time_travel)\n          cfg.new_initdate = dayjs(ns.time_travel);\n        else if (cfg.dyn?.initdate)\n          cfg.new_initdate = cfg.dyn.initdate;\n        else\n          cfg.new_initdate = new Date();\n        if (cfg.time_type.type.locator != '10M') {\n          cfg.new_initdate = dayjs(cfg.new_initdate).startOf('hour').toDate();\n        }\n      }\n    }\n    const timelineControl = window.timelinectl || new TimelineControl(cfg);\n    timeline_config = timelineControl.configure;\n    timeline_config.time_type = cfg.time_type.locator;\n  }\n\n  const geolocation = new Geolocation({\n    tracking: false\n  });\n\n  const mainbar_top = new ol_control_Bar({ className: 'ol-top ol-right' });\n  const infobar_bottom = new ol_control_Bar({ className: 'ol-bottom ol-right' });\n\n  const mousePosition = new MousePosition({\n    coordinateFormat: xy => coordXY(xy) + '<br>' + projDesc,\n    undefinedHTML: '&nbsp;'\n  });\n  const selectProjectionControl = new SelectProjectionControl(mousePosition);\n  const notification = new ol_control_Notification({});\n  let sidebar;\n  let sidebar_toggle;\n  if (interactive_map) {\n    const raiz = ns.page.find('div.arbol');\n    sidebar = new ol_control_Overlay({\n      className: \"slide-left menu\",\n      content: raiz[0]\n    });\n    sidebar_toggle = new ol_control_Toggle({\n      className: \"sb-capas\",\n      title: window.gettext(\"Capas\"),\n      html: `<i class=\"fa-solid fa-layer-group\"></i>`,\n      onToggle: function (value) {\n        sidebar.toggle();\n        mapa.set('sidebar_toggle', value, true);\n      }\n    });\n    raiz.attr('hidden', null);\n  }\n  const visibleLayerControl = new VisibleLayerControl();\n  const controls = !interactive_map\n    ? []\n    : new Collection([\n      sidebar,\n      sidebar_toggle,\n      new ScaleLine({\n        units: deg ? 'degrees' : 'metric'\n      }),\n      mousePosition,\n      selectProjectionControl,\n      infobar_bottom,\n      notification,\n      visibleLayerControl\n    ]);\n  const view = new View({\n    projection: window.epsg,\n    extent: extent_local_global,\n    showFullExtent: true,\n    //constrainResolution: true,\n  });\n  const srcElementEdit = new VectorSource();\n\n  const lyrElementEdit = new VectorLayer({\n    source: srcElementEdit,\n    displayInLayerSwitcher: false,\n    zIndex: Infinity,\n    style: new Style({\n      fill: new Fill({\n        color: 'rgba(255, 255, 255, 0.2)'\n      }),\n      stroke: new Stroke({\n        color: '#ffcc33',\n        width: 2\n      }),\n      image: new Circle({\n        radius: 7,\n        fill: new Fill({\n          color: '#ffcc33'\n        })\n      })\n    })\n  });\n  const modify = new Modify({ source: srcElementEdit });\n  const trans = new Transform({\n    source: srcElementEdit,\n    // translateFeature: true,\n    // scale: false,\n    // rotate: false,\n    // translate: true,\n    // stretch:false,\n    hitTolerance: 5,\n  });\n  let draw;\n  /**\n   * Overlay to show the measurement.\n   * @type {Overlay}\n   */\n  let measureTooltip, measureTooltipElement;\n  const mapa = new Map({\n    loadTilesWhileAnimating: true,\n    loadTilesWhileInteracting: true,\n    target: element[0],\n    view: view,\n    controls: controls,\n    interactions: interactions,\n    layers: [lyrElementEdit],\n    pixelRatio: Math.min(window.devicePixelRatio, 2)\n  });\n  mapa.set('layerObjects', []);\n  mapa.on('postrender', function () {\n    const layers = mapa.get('layerObjects');\n    const showableLegend = [];\n    for (const page_layer of layers) {\n      if (page_layer._ol_layer.getVisible() && page_layer._varLayer && page_layer._legend) {\n        showableLegend.push(page_layer);\n      }\n    }\n    this.get('contextMenu').set('showableLegend', showableLegend);\n    if (!cfg.extra?.hide_layers_caption) {\n      const captions = [];\n      for (const lyr of layers)\n        if (lyr._ol_layer.getVisible()\n          && lyr._varLayer\n          && lyr.layerCaption) {\n          captions.push([lyr._ol_layer.getZIndex(), lyr.layerCaption]);\n        }\n      visibleLayerControl.texts = captions.sort((a, b) => b[0] - a[0]);\n    }\n  })\n  mapa.set('sidebar_toggle', true, true);\n  mapa.set('dimension_controls', {}, true);\n  if (interactive_map) {\n    const infoContent = new ol_control_Overlay({\n      className: 'attribution',\n      content: infoElement()\n    });\n\n    const tb_controls_bottom = [\n      new OverviewMap({\n        collapseLabel: '\\u00BB',\n        label: '\\u00AB',\n        tipLabel: window.gettext('Vista de situación'),\n        layers: [\n          new TileLayer({\n            source: new OSM()\n          })\n        ],\n        view: new View({\n          projection: window.epsg,\n          //extent: extent_local_global\n        })\n      }),\n      new ol_control_Toggle({\n        className: \"ol-attribution\",\n        html: '<span>i</span>',\n        title: window.gettext('Atribución de fondo'),\n        onToggle: function () {\n          const active = this.getActive();\n          if (active) {\n            this.getMap().getLayers().getArray().forEach(ele => {\n              if (ele.getVisible() && ele.get('baseLayer'))\n                infoContent.element.getElementsByTagName('li')[0].innerHTML = ele.get('information') || 'n/a';\n            })\n          }\n          this.element.appendChild(infoContent.element);\n          infoContent.toggle();\n          this.setHtml(`<span>${active ? '»' : 'i'}</span>`)\n        }\n      }),\n    ]\n\n    const alertOverlay = new ol_control_Overlay({\n      className: 'alertmsg'\n    })\n    mapa.getTargetElement().append(alertOverlay.element);\n\n    const coordInput = new ol_control_Overlay({\n      className: 'coord-input',\n      content: coordInputElement()\n    });\n    const searcherBar = new ol_control_Bar({\n      toggleOne: true,\n      autoDeactivate: true,\n      controls: [\n        geosearch(extent, extent_local, alertOverlay),\n        new Button({\n          className: \"coordSearch\",\n          html: '<i class=\"fas fa-map-marker-alt\"></i>',\n          title: window.gettext('Ir a coordenadas'),\n          handleClick: function () {\n            coordSearchInput(this.coordInput, this.mapa, this.extent_local, this.alertOverlay)\n          }.bind({ coordInput, mapa, extent_local, alertOverlay })\n        }),\n        new ol_control_Toggle({\n          className: \"geolocation\",\n          html: '<i class=\"fa-solid fa-location-crosshairs\"></i>',\n          title: window.gettext('Mostrar posición actual'),\n          onToggle: function () { toggle_track(this, geolocation) }\n        }),\n      ]\n    })\n    searcherBar.getControls()[1].element.appendChild(coordInput.element);\n    const control_layer_popup = new ol_control_LayerPopup({ mouseover: false });\n    control_layer_popup.on('layer:visible', function (e) {\n      const fondo = e.layer;\n      const isVisible = fondo.get('visible');\n      setVisibleLayers_url(ns.page, mapa, fondo.get('simmer_id'), isVisible);\n    })\n    mapa.set('enableInfoGraph', 0)\n    const tb_controls_top = [\n      new Zoom({\n        zoomInTipLabel: window.gettext('Acercar'),\n        zoomOutTipLabel: window.gettext('Alejar')\n      }),\n      new Rotate({\n        tipLabel: window.gettext('Reiniciar rotación'),\n        label: \"⮝\"\n      }),\n      new ZoomToExtent({\n        extent: extent_local,\n        label: '',\n        tipLabel: window.gettext('Ver todo')\n      }),\n      control_layer_popup,\n      new FullScreen({\n        source: element.parent()[0],\n        tipLabel: window.gettext('Pantalla completa'),\n        label: $('<i class=\"fa fa-expand-alt\"></i>')[0]\n      }),\n      new ol_control_Toggle({\n        className: \"search-toggle\",\n        html: '<i class=\"fas fa-search-location\"></i>',\n        title: window.gettext('Buscar'),\n        bar: searcherBar\n      })\n    ];\n\n    const measurerBar = new ol_control_Bar({\n      toggleOne: true,\n      autoDeactivate: true,\n      controls: [\n        new Button({\n          html: `<i title=\"${window.gettext('Longitud')}\" >/</i>`,\n          handleClick: () => {\n            mapa.getInteractions().getArray().map((elm) => {\n              ((elm.type_ == 'Polygon') || (elm.type_ == 'LineString')) ?\n                mapa.removeInteraction(elm) :\n                null;\n            })\n            mapa.getOverlays().getArray().forEach(el => {\n\n              (el.getElement().getAttribute('class').search('ol-tooltip-static') == -1) ?\n                mapa.removeOverlay(el) : null;\n            })\n            Measurer(mapa, 'LineString')\n\n          }\n        }),\n        new Button({\n          className: 'area',\n          html: `<i title=\"${window.gettext('Superficie')}\">▟</i>`,\n          handleClick: () => {\n            mapa.getInteractions().getArray().map((elm) => {\n              ((elm.type_ == 'Polygon') || (elm.type_ == 'LineString')) ?\n                mapa.removeInteraction(elm) :\n                null;\n            })\n            mapa.getOverlays().getArray().forEach(el => {\n\n              (el.getElement().getAttribute('class').search('ol-tooltip-static') == -1) ?\n                mapa.removeOverlay(el) : null;\n            })\n            Measurer(mapa, 'area')\n          }\n\n        }),\n        new Button({\n          html: `<i title=\"${window.gettext('Eliminar')}\" class=\"fa fa-trash\"></i>`,\n          handleClick: () => {\n            deleteDrawing(mapa);\n          }\n        })\n      ]\n    });\n    tb_controls_top.push(\n      new ol_control_Toggle({\n        html: '<i class=\"fas fa-regular fa-ruler\"></i>',\n        title: window.gettext('Medir'),\n        bar: measurerBar\n      })\n    )\n    tb_controls_top.push(\n      new Button({\n        html: '<i class=\"fa fa-upload\"></i>',\n        title: window.gettext('Cargar KML/KMZ'),\n        handleClick: () => $('#fileElem').click(),\n      })\n    )\n    const handleKmlFiles = async function () {\n      const fileList = this.files;\n      const kml_layers = mapa.getLayers().getArray().filter(l => l.get('type_layer_locator') == 'kml_layer');\n      for (const kml_layer of kml_layers) {\n        mapa.removeLayer(kml_layer);\n      }\n      for (const file of fileList) {\n        let isKml = false;\n        const reader = new FileReader();\n        reader.onloadend = async function (e) {\n          const dataURL = e.target.result;\n          const encode_data = dataURL.split(',')[1];\n          if (file.name.includes('.kml')) {\n            isKml = true;\n            zip.file(file.name, encode_data, { base64: true });\n          }\n          const kmz_format = new KMZ({\n            extractStyles: true,\n            extractAttributes: true\n          });\n          const f = await kmz_format.readFeatures(encode_data, { dataProjection: 'EPSG:4326', featureProjection: window.epsg }, isKml)\n          const vectorSource = new VectorSource({ features: f });\n          const vectorLayer = new VectorLayer({\n            source: vectorSource,\n            zIndex: Infinity,\n            type_layer_locator: 'kml_layer',\n          })\n          mapa.addLayer(vectorLayer);\n        }\n        if (!file)\n          return;\n        reader.readAsDataURL(file);\n      }\n    }\n    $('#fileElem')[0].addEventListener(\"change\", handleKmlFiles, false);\n    if (window.site_cfg.extra?.cutting_mask) {\n      const recortarToggle = new ol_control_Toggle({\n        className: 'recortar-toggle', // clase CSS\n        title: window.gettext('Recortar'),\n        html: `<i class=\"fa-solid fa-scissors\"></i>`,\n        onToggle: value => mapa.set('recortar_activo', value),\n      })\n      tb_controls_top.push(recortarToggle);\n      mapa.on('change:recortar_activo', () => {\n        const { capas } = getVisibleLayers_set(cfg?.pagelayer_set);\n        const capas_id = capas.map(plyr => plyr.id);\n        const layerObjectVisible = mapa.get('layerObjects')\n          .filter(layerObject => capas_id.includes(layerObject._pageLayer.id));\n        const maskId = mapa.get('recortar_activo') ? window.site_cfg.extra.cutting_mask : null;\n        for (const layerObject of layerObjectVisible)\n          layerObject._ol_layer.getSource().updateParams({ mask_id: maskId });\n      })\n      mapa.set('recortar_activo', false);\n    }\n    if (cfg.time_type.locator !== '0') {\n      tb_controls_top.push(new MapAnimation({\n        fa: 'fa fa-play-circle',\n        config: timeline_config,\n        title: window.gettext('Animación'),\n        cfg: cfg,\n        mapa: mapa,\n      }))\n    }\n    if (dyn && dyn.simulationtype.locator) {\n      mapa.set('simulation_id', dyn.id);\n      const controls = [];\n      const ro = dyn.relations.includes('READONLY');\n      const rw = dyn.relations.includes('EDIT');\n      if (rw) controls.push(\n        new NewLaunchControl({\n          action: 'launch',\n          id: dyn.id,\n          fa: 'play',\n          title: window.gettext('Lanzar simulación')\n        }));\n      if (ro || rw) controls.push(new ActControl({\n        action: 'info',\n        id: dyn.id,\n        fa: 'fa fa-info',\n        title: window.gettext('Información')\n      }));\n      if (rw) controls.push(new ActControl({\n        action: 'edit',\n        id: dyn.id,\n        fa: 'fa fa-edit',\n        title: window.gettext('Editar')\n      }));\n      if (rw) controls.push(new ActControl({\n        action: 'share',\n        id: dyn.id,\n        fa: 'fa fa-user-plus',\n        title: window.gettext('Compartir')\n      }));\n      if (rw) controls.push(new ActControl({\n        action: 'lock',\n        id: dyn.id,\n        fa: 'fa fa-lock',\n        title: window.gettext('Bloquear')\n      }));\n      if ((cfg.extra.report_sim ?? true)\n        && (ro || rw)) controls.push(new ActControl({\n          action: 'report',\n          id: dyn.id,\n          fa: 'fas fa-book',\n          title: window.gettext('Informe')\n        }));\n      if (ro || rw) controls.push(new ActControl({\n        action: 'clone',\n        id: dyn.id,\n        fa: 'fas fa-copy',\n        title: window.gettext('Clonar')\n      }));\n      const sub1 = new ol_control_Bar({\n        toggleOne: true,\n        autoDeactivate: true,\n        controls: controls,\n      });\n      tb_controls_top.push(\n        new ol_control_Toggle({\n          title: window.gettext('Simulación'),\n          html: '<i class=\"fab fa-gripfire\"></i>',\n          bar: sub1\n        })\n      );\n    }\n    if (interactive_map && window.timelinectl) {\n      tb_controls_top.push(\n        new Button({\n          className: \"mosaico\",\n          html: '<i class=\"fas fa-grip-horizontal\"></i>',\n          title: window.gettext('Crear mosaico'),\n          handleClick: function () {\n            const bbox_map = transformExtent(mapa.getView().calculateExtent(), window.epsg, 'EPSG:4326');\n            const intersection = getIntersection(cfg.extent, bbox_map);\n            const page_opt = {\n              pagelayer_set: [],\n              extent: intersection,\n              content_model: cfg.page_type_locator,\n              time_type: cfg.time_type,\n              id: cfg.id\n            }\n            const visible_layers = getParameterByName('visible_layers');\n            const url = new URL(window.Urls.page_mosaic(cfg.id), window.location);\n            const sp = url.searchParams;\n            sp.set('extent', page_opt.extent.join(','))\n            sp.set('visible_layers', visible_layers)\n            sp.set('id', cfg.id)\n            if (mapa.get('recortar_activo')) {\n              const trim_mask_id = window.site_cfg.extra.cutting_mask;\n              sp.set('trim_mask_id', trim_mask_id);\n            }\n            const dimensions = mapa.get('dimension_controls');\n            if (dimensions) {\n              const { ...map_dimensions } = dimensions;\n              delete map_dimensions.HORIZON;\n              for (const [k, dim] of Object.entries(map_dimensions))\n                sp.set(k, dim.value);\n            }\n            const win = window.open(url);\n            win.opt = page_opt;\n          }\n        })\n      )\n    }\n    if (interactive_map) {\n      const sub1 = new ol_control_Bar({\n        toggleOne: true,\n        autoDeactivate: true,\n        controls: [\n          createExportButton(mapa, cfg, { icon: '<i class=\"fas fa-file-image\"></i>', title: 'Exportar a GeoTIFF/Gpkg', type: 'tif' }),\n          createExportButton(mapa, cfg, { icon: '<i class=\"fas fa-file\"></i>', title: 'Exportar a ASCII', toASCII: true, type: 'tif' }),\n          createExportButton(mapa, cfg, { icon: '<i class=\"fa fa-print\"></i>', title: 'Exportar a PDF', type: 'pdf' }),\n          createExportButton(mapa, cfg, { icon: '<i class=\"fa-solid fa-image\"></i>', title: 'Exportar a PNG', type: 'png' }),\n          createExportButton(mapa, cfg, { icon: '<i class=\"fa-solid fa-earth-africa\"></i>', title: 'Exportar a KML', type: 'kml' }),\n        ]\n      }\n      )\n      tb_controls_top.push(\n        new ol_control_Toggle({\n          title: window.gettext('Exportar'),\n          html: '<i class=\"fas fa-download\"></i>',\n          bar: sub1\n        })\n      );\n      tb_controls_top.push(\n        new Button({\n          html: '<i class=\"fa fa-arrows-rotate\"></i>',\n          title: window.gettext('Refrescar mapa'),\n          handleClick: () => {\n            const legs_visible = $(`.legend-dialog img.legend`).filter(\":visible\");\n            const slidecontainers = $('.mostrar-capa.selector .slidecontainer').filter(\":visible\")\n            const pos_legs = [], dims = {}, layers_opacity = []\n            const data = {\n              date: window.timelinectl.timeline.getCustomTime('current').toISOString(),\n              extent: transformExtent(mapa.getView().calculateExtent(), window.epsg, 'EPSG:4326'),\n            }\n            for (const l of legs_visible) {\n              const pos = $(l).dialog('option', 'position')\n              pos_legs.push({\n                id: l.id,\n                at: pos.at,\n                my: pos.my,\n                mytarget: mapa.get('target') == pos.of,\n              })\n            }\n            if (pos_legs.length)\n              data.pos_legs = JSON.stringify(pos_legs)\n            const { ...map_dimensions } = mapa.get('dimension_controls');\n            delete map_dimensions.HORIZON;\n            for (const [k, dim] of Object.entries(map_dimensions))\n              dims[k] = dim.value;\n            if (dims)\n              data.reloaded_dims = JSON.stringify(dims)\n            for (const slideCont of slidecontainers) {\n              layers_opacity.push({\n                id: $(slideCont).closest('.mostrar-capa.selector').attr('id_layer'),\n                value: $(slideCont).find('input').val()\n              })\n            }\n            if (layers_opacity.length)\n              data.layers_opacity = JSON.stringify(layers_opacity);\n            if (data.recortar_activo)\n              data.recortar_activo = JSON.stringify(mapa.get('recortar_activo'));\n            reloadWithParams(data)\n          }\n        })\n      )\n    }\n    tb_controls_top.push(\n      new ol_control_Toggle({\n        className: \"ol-3d\",\n        html: '<i class=\"fa-solid fa-cube\"></i>',\n        title: window.gettext('Vista 3D'),\n        onToggle: function () {\n          let ol3d = mapa.get('ol3d');\n          if (!ol3d) {\n            ol3d = new OLCesium({ map: mapa });\n            const scene = ol3d.getCesiumScene();\n            Cesium.createWorldTerrainAsync().then(tp => scene.terrainProvider = tp);\n            // truqui para que se vean los controles\n            // https://github.com/openlayers/ol-cesium/issues/1016\n            const olContainerDiv = document.querySelector(\".ol-overlaycontainer-stopevent\");\n            olContainerDiv.style.zIndex = 1;\n            mapa.set('ol3d', ol3d);\n          }\n          ol3d.setEnabled(this.getActive());\n        }\n      })\n    );\n    tb_controls_top.forEach(mainbar_top.addControl, mainbar_top);\n    tb_controls_bottom.forEach(infobar_bottom.addControl, infobar_bottom);\n    mapa.addControl(mainbar_top);\n    mapa.addControl(infobar_bottom);\n    tb_controls_top.map((control) => {\n      if (control instanceof ol_control_Toggle)\n        $(control.button_).on('click', () => control_layer_popup.hide())\n    })\n  }\n  ns.mapas.push(mapa);\n  ns.mapa = mapa;\n  view.fit(extent_local, { constrainResolution: interactive_map });\n  if (cfg.extra?.floating_legend)\n    mapa.set('floating_legend', true)\n  if (cfg.extra?.closed_tree)\n    mapa.set('closed_tree', true)\n  if (cfg.extra?.graph_show_run_time)\n    mapa.set('graph_show_run_time', true)\n  for (const attr of ['pos_legs', 'reloaded_dims', 'layers_opacity'])\n    if (attr in sessionStorage) {\n      const value = JSON.parse(sessionStorage.getItem(attr));\n      sessionStorage.removeItem(attr);\n      mapa.set(attr, value);\n    }\n  const map_dimensions = mapa.get('dimension_controls');\n  crearControlesDimensiones(mapa, map_dimensions, cfg.dimensions);\n  setUpContextMenu(ns);\n  for (const pagelayer of cfg.pagelayer_set) {\n    await crearCapa(\n      ns,\n      mapa,\n      pagelayer,\n      extent_local,\n      interactive_map,\n      cfg.time_delta,\n      cfg.extra\n    );\n  }\n\n  const attr = 'recortar_activo';\n  if (attr in sessionStorage) {\n    const jsValue = sessionStorage.getItem(attr);\n    sessionStorage.removeItem(attr);\n    if (jsValue !== 'undefined') {\n      const value = JSON.parse(jsValue);\n      mapa.set(attr, value);\n    }\n  }\n  if (interactive_map) {\n    document.getElementsByClassName('ol-attribution')[0].addEventListener('pointerdown', (e) => { e.preventDefault(); e.stopPropagation() }, false);\n    document.getElementsByClassName('ol-overviewmap')[0].getElementsByTagName('button')[0].addEventListener('pointerdown', function (evt) {\n      evt.preventDefault(); evt.stopPropagation()\n    }, false);\n    mapa.on('change:notification', function () {\n      const txt = this.get('notification');\n      if (txt) notification.show(txt, -1);\n      else notification.hide();\n    });\n\n    mapa.on('change:sidebar_toggle', function () {\n      sidebar_toggle.setActive(this.get('sidebar_toggle'));\n      this.get('sidebar_toggle') ? sidebar.show() : sidebar.hide();\n    });\n\n    mapa.on('singleclick', evt => evt.map.set('info', evt));\n    const info = $('#info');\n    const gc = new GraphControl(\n      info,\n      null,\n      cfg.extra?.groupGraphics,\n      cfg.extra?.print_pluma,\n    )\n    gc.threshold = cfg.extra?.threshold || 40;\n    mousePosition.on('change:coordStringFunction',\n      function () {\n        gc.coordXY = this.get('coordStringFunction');\n      })\n    mapa.on('change:dimension_controls',\n      function () {\n        const evt = this.get('dimension_controls');\n        if (evt === undefined)\n          return;\n        const info = $('#element-info');\n        if (info.is(':visible')) {\n          const this_ = mapa.get('lastInfoElem');\n          $(this_).click();\n        }\n        const newActiveDimensions = {};\n        for (const ctl of Object.values(evt)) {\n          newActiveDimensions[ctl.id] = [[ctl.value, ctl.caption]];\n        }\n        gc.set('activeDimensions', newActiveDimensions);\n      });\n    const buttons = [];\n    if (cfg.extra?.new_tab !== false)\n      buttons.push(\n        {\n          html: '<i class=\"fas fa-external-link-alt\"></i>',\n          title: window.gettext('Abrir en solapa'),\n          click: () => openNewWindow(gc, window.Urls.page_graph(ns.page_id))\n        }\n      )\n    if (cfg.extra?.graphic_pdf !== false)\n      buttons.push(\n        {\n          html: '<i class=\"fas fa-print\"></i>',\n          title: window.gettext('Imprimir informe'),\n          click: () => openNewWindow(gc, window.Urls.info_punto_pdf())\n        }\n      )\n    info.dialog({\n      appendTo: mapa.getTargetElement(),\n      autoOpen: false,\n      buttons: buttons,\n      maxHeight: window.innerHeight * 6 / 7,\n      width: 'auto',\n      close: function (event) {\n        if (event && event.originalEvent){\n          gc.unset('info', true);\n          gc.unset('activeDimensions');\n          gc.unset('type', true);\n        }\n      },\n    });\n    const marker_infoPunto = getMarkerVectorLayer([], '/media/uploads/site/map-marker-solid.svg');\n    info.on(\"dialogopen\", function () {\n      $(this).parent().css('width', 'auto');\n      mapa.addLayer(marker_infoPunto);\n    });\n    info.on(\"dialogclose\", function () {\n      mapa.removeLayer(marker_infoPunto);\n    });\n    mapa.addControl(gc);\n    gc.on('change:state', function () {\n      if (gc.get('state') == 'ok' && !info.dialog('isOpen')) {\n        const maxHeight = info.dialog('option', 'maxHeight');\n        const has_table = gc.info_tabla.length ? 1 : 0;\n        info.dialog('option', 'width', 'auto');\n        info.dialog('option', 'height',\n          Math.min(maxHeight,\n            gc.targets.length ? 300 * gc.targets.length + 50 * has_table\n              : 300));\n        info.dialog('open');\n      }\n    })\n\n    gc.on('change:can_be_grouped', function () {\n      const hasButton = $('#group').length > 0;\n      const mustHaveButton = gc.get('can_be_grouped');\n      if (hasButton === mustHaveButton)\n        return;\n      let buttons = info.dialog(\"option\", \"buttons\");\n      if (mustHaveButton) {\n        const groupButton = {\n          id: 'group',\n          html: '<i class=\"fa-kit fa-graph-multi\"></i>',\n          title: window.gettext('Agrupar/Desagrupar gráficas'),\n          click: function () {\n            info.dialog('close');\n            gc.group_by_unit = !gc.group_by_unit;\n            gc.redraw();\n          },\n        };\n        buttons.splice(0, 0, groupButton);\n      } else {\n        buttons = buttons.filter(b => b.id !== 'group');\n      }\n      info.dialog(\"option\", \"buttons\", buttons); // setter\n    })\n\n    gc.on('change:con_pluma', function () {\n      const hasButton = $('#show-dim-selector').length > 0;\n      const mustHaveButton = gc.get('con_pluma');\n      if (hasButton === mustHaveButton)\n        return;\n      let buttons = info.dialog(\"option\", \"buttons\");\n      if (mustHaveButton) {\n        /*\n        const groupButton = {\n          html: '<i id=\"con_pluma\" class=\"fas fa-feather\"></i>',\n          title: window.gettext('Mostrar plumas'),\n          click: () => create_graph_control(mapa, gc.poi),\n        };\n        buttons.splice(0, 0, groupButton);\n        */\n        const dimsButton = {\n          html: '<i id=\"show-dim-selector\" class=\"fas fa-solid fa-cubes\"></i>',\n          title: window.gettext('Seleccionar combinaciones de series'),\n          click: () => this.showDimSelector()\n        };\n        buttons.splice(0, 0, dimsButton);\n        const boxPlotButton = {\n          id: 'boxplot',\n          html: '<i class=\"fa-solid fa-chart-column\"></i>',\n          title: window.gettext('Mostrar boxplot (diagrama de caja)'),\n          click: function () {\n            const active = gc.get('type');\n            if (active) {\n              gc.unset('type');\n            } else {\n              gc.set('type', 'box');\n            }\n          }\n        };\n        gc.on('change:type', function () {\n          const active = gc.get('type');\n          const button = info.parent().find('#boxplot');\n          button.toggleClass('active', active)\n        })\n        const active = gc.get('type');\n        if (active)\n          boxPlotButton.classes = { \"ui-button\": \"ui-corner-all active\" };\n        buttons.splice(0, 0, boxPlotButton);\n      } else {\n        buttons = buttons.filter(b => !['show-dim-selector', 'boxplot'].includes(b.id));\n      }\n      info.dialog(\"option\", \"buttons\", buttons); // setter\n    })\n    gc.on('change:can_export2Excel', function () {\n      const can_export2Excel = this.get('can_export2Excel');\n      let buttons = info.dialog(\"option\", \"buttons\");\n      if (can_export2Excel) {\n        buttons.push({\n          id: 'can_export2Excel',\n          html: '<i class=\"fa fa-table\"></i>',\n          title: window.gettext('Exportar a Excel'),\n          click: () => gc.toExcel(),\n        });\n      }\n      else {\n        buttons = buttons.filter(b => b.id !== 'can_export2Excel');\n      }\n      info.dialog(\"option\", \"buttons\", buttons);\n    })\n    mapa.on('change:info',\n      function () {\n        if (this.get('isDrawing'))\n          return;\n        const evt = this.get('info');\n        ns.page.find('div.info_grafica').empty();\n        ns.page.find('div.info_tabla tbody').empty();\n        ns.page.find('div.info_elem').empty();\n        info.dialog({ autoOpen: false });\n        info.dialog('close');\n        mapa.set('info', evt, true);\n        if (evt) {\n          const marker_feature = marker_infoPunto.getSource().getFeatures()[0];\n          marker_feature.setGeometry(new Point(evt.coordinate));\n          requestInfo2(evt, gc);\n        }\n      });\n    /**\n     * Format length output.\n     * @param {LineString} line The line.\n     * @return {string} The formatted length.\n    */\n    const formatLength = function (line) {\n      const length = getLength(line, { projection: window.epsg });\n      return (length > 1000) ?\n        numeric_lang_format((length / 1000).toFixed(2)) + ' km' : numeric_lang_format(length.toFixed(2)) + ' m';\n    };\n    /**\n   * Format area output.\n   * @param {Polygon} polygon The polygon.\n   * @return {string} Formatted area.\n   */\n    const formatArea = function (polygon) {\n      const area = getArea(polygon, { projection: window.epsg, radius: 6371000 });\n      return (area > 100000) ?\n        `${numeric_lang_format((area / 1000000).toFixed(2))} km<sup>2</sup> - ${numeric_lang_format((area / 10000).toFixed(2))} ha`\n        : numeric_lang_format(area.toFixed(2)) + ' m<sup>2</sup>';\n    };\n    const refrescaEtiqueta = function (geom) {\n      let output, tooltipCoord;\n      if (!measureTooltip) {\n        measureTooltipElement = document.createElement('div');\n        measureTooltipElement.className = 'ol-tooltip ol-tooltip-static';\n        measureTooltip = new Overlay({\n          element: measureTooltipElement,\n          offset: [0, -7],\n          positioning: 'bottom-center'\n        });\n        mapa.addOverlay(measureTooltip);\n      }\n      if (!measureTooltip.getMap())\n        mapa.addOverlay(measureTooltip);\n      if (geom instanceof Polygon) {\n        output = formatArea(geom);\n        tooltipCoord = geom.getInteriorPoint().getCoordinates();\n      } else if (geom instanceof LineString) {\n        output = formatLength(geom);\n        tooltipCoord = geom.getLastCoordinate();\n      } else if (geom instanceof MultiLineString) {\n        output = formatLength(geom);\n        tooltipCoord = geom.getLastCoordinate();\n      } else if (geom instanceof MultiPolygon) {\n        output = formatArea(geom);\n        tooltipCoord = geom.getFlatInteriorPoints();\n        tooltipCoord = [tooltipCoord[0], tooltipCoord[1]];\n      }\n      measureTooltipElement.innerHTML = output;\n      measureTooltip.setPosition(tooltipCoord);\n    }\n    mapa.on('change:new_feature', function () {\n      mapa.set('edit_feature', null);\n      if (draw)\n        mapa.removeInteraction(draw);\n      draw = new Draw({\n        source: srcElementEdit,\n        type: mapa.get('new_feature'),\n        stopClick: true,\n      });\n      /**\n  * The measure tooltip element.\n  * @type {HTMLElement}\n  */\n      if (measureTooltipElement) {\n        measureTooltipElement.parentNode.removeChild(measureTooltipElement);\n      }\n      measureTooltipElement = document.createElement('div');\n      measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';\n      measureTooltip = new Overlay({\n        element: measureTooltipElement,\n        offset: [0, -15],\n        positioning: 'bottom-center'\n      });\n      mapa.addOverlay(measureTooltip);\n      draw.on('drawstart',\n        function (evt) {\n          // set sketch\n          let sketch = evt.feature;\n          /** @type {import(\"ol/coordinate.js\").Coordinate|undefined} */\n          let listener = sketch.getGeometry().on('change', function (evt) {\n            let geom = evt.target;\n            refrescaEtiqueta(geom);\n          });\n          draw.on('drawend', function (e) {\n            this.setActive(false);\n            mapa.set('edit_feature', e.feature);\n            measureTooltipElement.className = 'ol-tooltip ol-tooltip-static';\n            measureTooltip.setOffset([0, -7]);\n            unByKey(listener);\n          })\n        });\n      mapa.addInteraction(draw);\n      mapa.set('new_feature', null, true);\n    });\n    mapa.on('change:edit_feature', function (evt) {\n      if (this.get('edit_feature')) {\n        mapa.addInteraction(modify);\n        mapa.addInteraction(trans);\n        /** @type {import(\"ol/coordinate.js\").Coordinate|undefined} */\n        let sketch = this.get('edit_feature');\n        modify.on('modifystart', function (e) {\n          sketch = e.features.getArray()[0];\n          sketch.getGeometry().on('change', function (evt) {\n            let geom = evt.target;\n            refrescaEtiqueta(geom);\n          });\n        });\n        trans.on('rotateend', function (e) {\n          let geom = e.feature.getGeometry();\n          refrescaEtiqueta(geom);\n        });\n        trans.on('scaleend', function (e) {\n          let geom = e.feature.getGeometry();\n          refrescaEtiqueta(geom);\n        });\n        trans.on('translateend', function (e) {\n          let geom = e.feature.getGeometry();\n          refrescaEtiqueta(geom);\n        });\n      }\n      if (this.get('edit_feature') && !draw) {\n        srcElementEdit.addFeature(this.get('edit_feature'));\n      }\n      if (draw) {\n        draw.setActive(false);\n        mapa.removeInteraction(draw);\n        draw = null;\n      }\n      if (evt.oldValue) {\n        srcElementEdit.removeFeature(evt.oldValue);\n        mapa.removeOverlay(measureTooltip);\n        mapa.getOverlays().getArray().forEach(el => {\n          (el.getElement().getAttribute('class').search('ol-tooltip-static') != -1) ?\n            mapa.removeOverlay(el) : null;\n        })\n        mapa.removeInteraction(modify);\n        mapa.removeInteraction(trans);\n      }\n    });\n  }\n  if (interactive_map) {\n    $('.ol-overlay').on('scroll', repositionTooltips);\n  }\n  if (interactive_map && window.timelinectl)\n    setCurrentValue(dayjs(window.timelinectl.timeline.getCustomTime('current')));\n  if (window.timelinectl) {\n    if (map_dimensions && timeline_config && timeline_config.time_type.startsWith('ENUM'))\n      map_dimensions['HORIZON'] = { options: Object.keys(timeline_config.marks) };\n  }\n\n  return mapa;\n}\n\nfunction reloadWithParams(params) {\n  for (const key in params) {\n    sessionStorage.setItem(key, params[key]);\n  }\n  window.location.reload();\n}\n\nfunction coordSearchInput(coordInput, mapa, extent_local, alertOverlay) {\n\n  const this_ = {\n    mapa: mapa,\n    extent: extent_local,\n    overlay: alertOverlay,\n    element: coordInput\n  }\n  this_.getMarkerVectorLayer = getMarkerVectorLayer\n\n  coordInput.element.getElementsByClassName('goCoord').goCoord.addEventListener(\n    'click', function () {\n\n      const element = $(this.element.element);\n      const { srcproj, xlong, ylat } = getFormCoords(element);\n      const destProj = proj4(this.mapa.getView().getProjection().getCode());\n      const xy = proj4(srcproj, destProj, [xlong, ylat])\n      if (containsCoordinate(this.extent, xy)) {\n        this.mapa.addLayer(this.getMarkerVectorLayer(xy, '/media/uploads/site/location_pin.png'))\n        this.mapa.getView().animate({\n          center: xy,\n          zoom: Math.max(this.mapa.getView().getZoom(), 14)\n        })\n      }\n      else {\n        this.overlay.show(`<div><p>\n        ${window.gettext('La coordenada introducida no se encuentra en la extensión del mapa o no existe...')}\n        </p></div>`);\n        setTimeout(() => {\n          this.overlay.hide();\n        }, 5000)\n      }\n\n    }.bind(this_), false);\n\n  coordInput.element.getElementsByClassName('reset').reset.addEventListener('click', function () {\n    const element = $(this.element.element);\n    element.find('.combo-coord input').removeAttr(\"value\");\n    element.find('.combo-coord input').val('');\n    this.element.hide();\n    // FIXME: Esto es muy poco elegante\n    const mapa = this.mapa;\n    const len = mapa.getLayers().getLength();\n    for (let i = len - 1; i >= 0; i--) {\n      if (mapa.getLayers().getArray()[i].get('title') == 'Marker') {\n        mapa.removeLayer(mapa.getLayers().getArray()[i])\n      }\n    }\n  }.bind(this_), false)\n  coordInput.toggle();\n}\n\nfunction infoElement() {\n  const infoli = document.createElement('li');\n  infoli.innerHTML = '';\n  const infoul = document.createElement('ul');\n  infoul.appendChild(infoli);\n\n  return infoul;\n}\n\nfunction coordInputElement() {\n  let coordForm = $('<form/>');\n  coordForm.html(\n    `<div id=\"latlon\">\n    <div> <label for=\"xlong\">X|Long :</label> <input type=\"number\" id=\"xlong\" /></div>\n    <div><label for=\"ylat\">Y|Lat :</label><input type=\"number\" id=\"ylat\" /></div>\n    <div title=\"${window.gettext('Seleccionar proyección')}\" id=\"projection\" class=\"seleccionable combo-coord\"><input type=\"text\" data-input readonly=\"readonly\">\n    <i class=\"fas fa-sort-down\"></i>\n    <div class=\"chProj combo dropdown\">\n    <ul class=\"dropdown-content\" id=\"chProj\"></ul></div>\n    </div>\n    <button type=\"button\" title=\"${window.gettext('Ir')}\" class=\"goCoord\" id=\"goCoord\" ><i class=\"fa fa-caret-right\"></i></button>\n    <button type=\"reset\" title=\"${window.gettext('Borrar')}\" class=\"reset\" id=\"reset\" ><i class=\"fas fa-times\"></i></button>\n    </div>\n\n    <div id=\"DMS\">\n    <div id=\"lat\"><label for=\"lat\">Lat :</label>\n      <div><input type=\"number\" id=\"degrees\" /><label for=\"degrees\"> °</label></div>\n      <div><input type=\"number\" id=\"mins\" /><label for=\"mins\"> '</label></div>\n      <div><input type=\"number\" id=\"segs\" /><label for=\"segs\"> ''</label></div>\n      <div title=\"${window.gettext('Seleccionar dirección')}\" id=\"direction\" class=\"seleccionable combo-coord\"><input type=\"text\" data-input value=\"N\" readonly=\"readonly\">\n      <i class=\"fas fa-sort-down\"></i>\n      <div class=\"chProj combo dropdown\">\n      <ul class=\"dropdown-content\" id=\"chProj\">\n        <li value=\"N\" class=\"select\">N</li>\n        <li value=\"S\">S</li>\n      </ul></div>\n      </div>\n    </div>\n    <div id=\"long\"><label for=\"long\">Long :</label>\n      <div><input type=\"number\" id=\"degrees\" /><label for=\"degrees\"> °</label></div>\n      <div><input type=\"number\" id=\"mins\" /><label for=\"mins\"> '</label></div>\n      <div><input type=\"number\" id=\"segs\" /><label for=\"segs\"> ''</label></div>\n      <div title=\"${window.gettext('Seleccionar dirección')}\" id=\"direction\" class=\"seleccionable combo-coord\"><input type=\"text\" data-input value=\"W\" readonly=\"readonly\">\n      <i class=\"fas fa-sort-down\"></i>\n      <div class=\"chProj combo dropdown\">\n      <ul class=\"dropdown-content\" id=\"chProj\">\n        <li value=\"E\">E</li>\n        <li value=\"W\" class=\"select\">W</li>\n      </ul></div>\n      </div>\n    </div>\n    </div>`);\n  coordForm.find('div.combo-coord input').val();\n  for (const ep of window.site_cfg.site_epsgs) {\n    if (ep.code.endsWith(':DMS'))\n      continue;\n    const li = $(`<li value =\"${ep.code}\"></li>`)\n    li.text(ep.name + ' - ' + ep.code);\n    if (ep.code == window.epsg) {\n      li.addClass('select');\n      coordForm.find('div#projection input').val(li.text());\n      coordForm.find('div#projection input').attr('value', li.attr('value'));\n    }\n    coordForm.find('#latlon ul#chProj').append(li)\n  }\n  coordForm.find('div.combo-coord').click(function () {\n    $(this).find('div.dropdown').toggleClass('listshown');\n  })\n  coordForm.find('li').click(function () {\n    const input = $(this).parents('div.combo-coord').find('input');\n    input.val($(this).text());\n    input.attr('value', $(this).attr('value'))\n    $(this).parent().find('.select').removeClass('select')\n    $(this).addClass(\"select\");\n  })\n  return coordForm[0]\n}\n\nfunction geosearch(extent, extent_local, alertOverlay) {\n\n  let search;\n  if (window.geoservice == 'NOMINATIM') {\n    const viewbox = Array([extent[0], extent[1]], [extent[2], extent[3]]);\n\n    search = new searchNominatim(\n      {\n        label: window.gettext('Buscar lugar'),\n        placeholder: `${window.gettext('Buscar')}...`,\n        noCollapse: true,\n        bounded: true,\n        viewbox: viewbox\n      })\n\n  }\n  else {\n    search = new ol_control_SearchES(\n      {\n        label: window.gettext('Buscar lugar'),\n        placeholder: `${window.gettext('Buscar')}...`,\n        dataType: 'jsonp',\n        noCollapse: true,\n        viewbox: extent_local,\n        alertmsg: alertOverlay,\n        url: ['https://www.idee.es/communicationsPoolServlet/SearchAssistant',\n          'https://www.cartociudad.es/geocoder/api/geocoder/candidatesJsonp'],\n        handleResponse: function (response) {\n          return JSON.parse(response.slice(9, -1))\n        }\n      })\n  }\n\n  search.button.innerHTML = '<i class=\"fas fa-search\"></i>'\n  search.clearHistory();\n  reset(search);\n\n  search.on('select', function (e) {\n    if (containsCoordinate(extent_local, e.coordinate)) {\n      const mapa = this.getMap();\n      mapa.getView().animate({\n        center: e.coordinate,\n        zoom: Math.max(mapa.getView().getZoom(), 14)\n      });\n      mapa.addLayer(getMarkerVectorLayer(e.coordinate, '/media/uploads/site/location_pin.png'));\n    }\n    else {\n      e.target.setInput('');\n      e.target.cont = -1;\n      e.target.drawList_(e.target.getHistory());\n      alertOverlay.show('<div><p>' + window.gettext('La dirección seleccionada no se encuentra en la extensión del mapa...') + '</p></div>');\n      setTimeout(() => {\n        alertOverlay.hide();\n      }, 5000)\n    }\n  });\n\n  return search\n}\n\nfunction reset(search) {\n  const reset = document.createElement('button');\n  reset.className = 'reset-button';\n  reset.innerHTML = `<a title = \"${window.gettext('Borrar')}\" class=\"reset\"><i class=\"fas fa-times\"></i></a>`;\n  search.element.appendChild(reset);\n  reset.addEventListener('click', function (e) {\n    e.preventDefault();\n    e.stopPropagation();\n    if (!this.getInputField().value) {\n      this.element.classList.toggle(\"ol-collapsed\");\n    }\n    else {\n      this.setInput('');\n      this.cont = -1;\n      this.drawList_(this.getHistory())\n      // FIXME: poco elegante\n      const len = this.getMap().getLayers().getLength();\n      for (let i = len - 1; i >= 0; i--) {\n        if (this.getMap().getLayers().getArray()[i].get('title') == 'Marker') {\n          this.getMap().removeLayer(this.getMap().getLayers().getArray()[i])\n        }\n      }\n    }\n  }.bind(search), false)\n}\nfunction getMarkerVectorLayer(xy, src_path) {\n  const marker = new Feature({\n    geometry: new Point(xy),\n  });\n  const styles = getComputedStyle(document.body);\n  const color_marker = styles.getPropertyValue('--main-color').trim();\n  const iconStyle = new Style({\n    image: new Icon({\n      color: color_marker,\n      crossOrigin: 'anonymous',\n      anchorOrigin: 'bottom-left',\n      anchor: [0.5, 0],\n      anchorXUnits: 'fraction',\n      anchorYUnits: 'fraction',\n      src: src_path,\n      scale: 0.5\n    })\n  });\n  marker.setStyle(iconStyle);\n  const vectorSource = new VectorSource({\n    features: [marker]\n  });\n  const markerVectorLayer = new VectorLayer({\n    source: vectorSource,\n    title: 'Marker',\n    displayInLayerSwitcher: false\n  });\n  markerVectorLayer.setZIndex(Infinity);\n  return markerVectorLayer;\n}\n\n\nObject.assign(LAYERTYPES, {\n  SAVER: SaverElementsLayer,\n  OSM: OSMLayer,\n  WMS: WMSLayer,\n  WMSFLOW: WMSFlowLayer,\n  WMTS: WMTSLayer,\n  Bing: BingLayer,\n  XYZ: XYZLayer,\n});\n\n\nasync function crearCapa(ns, mapa, pageLayer, extent_local, interactive_map, time_delta, extra) {\n  let factory_name = pageLayer.layer.service.servicetype.name;\n  if (!(factory_name in LAYERTYPES)) {\n    console.warn('No hay factoría para capa:');\n    console.warn(pageLayer.layer);\n    factory_name = 'WMS'; // ficticio\n  }\n  const layerClass = LAYERTYPES[factory_name];\n  const layerObject = new layerClass(ns, pageLayer, time_delta, interactive_map);\n  if (extra?.closed_tree)\n    mapa.set('closed_tree', true)\n  await layerObject.crearCapaOL(mapa, extent_local);\n  if (mapa)\n    mapa.get('layerObjects').push(layerObject);\n  return layerObject;\n}\n\n\nfunction deleteDrawing(mapa) {\n  for (let i = (mapa.getLayers().getLength() - 1); i >= 0; i--) {\n    if (mapa.getLayers().getArray()[i].get('title') == 'Measure')\n      mapa.removeLayer(mapa.getLayers().getArray()[i]);\n  }\n  mapa.getInteractions().getArray().map((elm) => {\n    ((elm.type_ == 'Polygon') || (elm.type_ == 'LineString')) ?\n      mapa.removeInteraction(elm) :\n      null;\n  })\n  while (mapa.getOverlays().getLength()) {\n    mapa.getOverlays().getArray().forEach(el => { mapa.removeOverlay(el) });\n  }\n}\nfunction createOriginPoint(feat, mapa, prop_id, win) {\n  const tableId = '#create-origin';\n  const featProj = $('#fast-simulation-edit-dialog').find('select#projection').val();\n  $(tableId)\n    .find(\"textarea[name='simulation_id']\")\n    .val(prop_id);\n  const wkt = new WKT();\n  const geom = wkt.writeFeature(feat, {\n    dataProjection: 'EPSG:4326',\n    featureProjection: featProj\n  });\n  $(tableId + ' form .element_geometry.data_new').val(geom);\n  const formData = getFormData($(tableId + ' form'));\n  $.ajax({\n    url: window.Urls.element_create(133),\n    type: 'POST',\n    data: formData,\n    success: function () {\n      $.ajax({\n        url: window.Urls.simulation_launch(prop_id),\n        method: 'POST',\n        dataType: 'json',\n        contentType: 'application/json'\n      })\n        .done(function () {\n          win.location = window.Urls.simulation_page(prop_id);\n        })\n        .fail(function () {\n          alert('error');\n        });\n    }\n  });\n}\nasync function requestInfo2(evt, gc) {\n  gc.redraw(evt);\n}\n\nfunction toggle_track(self, geolocation) {\n  const mapa = self.getMap();\n\n  let geolocationLayer = mapa.get('geolocationLayer');\n\n  const styles = getComputedStyle(document.body);\n  const color_marker = styles.getPropertyValue('--main-color').trim();\n\n  const positionFeature = new Feature();\n  const iconStyle = new Style({\n    image: new Icon({\n      color: color_marker,\n      crossOrigin: 'anonymous',\n      anchorOrigin: 'bottom-left',\n      anchor: [0.5, 0],\n      anchorXUnits: 'fraction',\n      anchorYUnits: 'fraction',\n      src: '/media/uploads/site/location_pin.png',\n      scale: 0.5\n    })\n  });\n\n  positionFeature.setStyle(iconStyle);\n\n  geolocationLayer = new VectorLayer({\n    source: new VectorSource({\n      features: [positionFeature]\n    }),\n    title: 'geomarker',\n    zIndex: Infinity,\n    displayInLayerSwitcher: false,\n    visible: true\n  })\n\n  if (self.getActive()) {\n    geolocation.setProjection(mapa.getView().getProjection());\n    geolocation.setTracking(true);\n    geolocation.on('change:position', function () {\n      const coordinates = geolocation.getPosition();\n      positionFeature.setGeometry(coordinates ?\n        new Point(coordinates) : null);\n    });\n    mapa.addLayer(geolocationLayer);\n    if (geolocation.getPosition())\n      mapa.getView().setCenter(geolocation.getPosition());\n  }\n  else {\n    geolocation.setTracking(false);\n    mapa.getLayers().getArray().map(aux => {\n      (aux.get('title') == 'geomarker') ? mapa.removeLayer(aux) : null;\n    })\n  }\n\n}\n\nclass MapAnimation extends Control {\n  constructor(opt_options) {\n    const options = opt_options || {};\n    options.fa = options.fa || 'fa fa-play-circle';\n    options.action = options.action || 'play';\n    const element = document.createElement('div');\n    element.className = 'map-animation ol-unselectable ol-control';\n    const button = document.createElement('button');\n    button.innerHTML = `<i class=\"${options.fa}\"></i>`;\n    button.title = options.title;\n    element.appendChild(button);\n    super({\n      element: element,\n      target: options.target\n    });\n    this.diff = [];\n    this.enumTime = options.config.time_type.startsWith('ENUM');\n    this.start = options.config.start;\n    this.end = options.config.end;\n    this.scale = options.config.scale;\n    this.cfg = options.cfg;\n    this.mapa = options.mapa;\n    this.options = options;\n    this.intervalSeconds = 3; // s\n    button.addEventListener('click', e => this.handleMapAnimation(e), false);\n  }\n  get interval() {\n    return this.intervalSeconds * 1000;\n  }\n  handleMapAnimation(e) {\n    if (this.options.action === 'play') {\n      this.target = e.target;\n      this.createDialog();\n    } else {\n      this.pause();\n    }\n  }\n\n  play() {\n    this.options.action = 'pause';\n    this.target.className = 'fa fa-pause-circle';\n  }\n\n  pause() {\n    this.getMap().set('animation', false);\n    this.options.action = 'play';\n    this.target.className = 'fa fa-play-circle';\n    clearTimeout(this.timeoutID);\n  }\n\n  createDialog() {\n    const enableTime = this.scale === 'hour' || this.scale === 'minute';\n    if (this.enumTime) {\n      this.diff = [];\n      this.start_date_input = $('select#start-date').empty();\n      this.end_date_input = $('select#end-date').empty();\n      const years = this.options.config.years;\n      $('input#start-date')[0].style.display = 'none';\n      $('input#end-date')[0].style.display = 'none';\n      years.forEach((year, i) => {\n        const opIn = document.createElement('option');\n        opIn.innerText = year.format('YYYY');\n        this.start_date_input.append(opIn);\n        if (i > 0) {\n          const opOut = document.createElement('option');\n          opOut.innerText = year.format('YYYY');\n          this.end_date_input.append(opOut);\n          this.diff.push(year.diff(years[i - 1], 'y'));\n        }\n      })\n      this.start_date_input.on(\n        {\n          \"focus\": function () {\n            //console.log('clicked!', this, this.value);\n            //this.selectedIndex = -1;\n          }\n          , \"change\": function () {\n            const idx = this.selectedIndex;\n            this.end_date_input.empty();\n            this.diff = [];\n            //console.log('changed!', this, choice);\n            years.forEach((year, i) => {\n              if (i > idx) {\n                const op = document.createElement('option');\n                op.innerText = year.format('YYYY');\n                this.end_date_input.append(op);\n                this.diff.push(year.diff(years[i - 1], 'y'));\n              }\n            })\n          }\n        });\n    }\n    else {\n      if (this.start_date_input && this.end_date_input) {\n        this.start_date_input.destroy();\n        this.end_date_input.destroy();\n      }\n      this.start_date_input = this.configureCalendar(\n        $('input#start-date'),\n        dayjs(this.start),\n        enableTime\n      );\n      this.end_date_input = this.configureCalendar(\n        $('input#end-date'),\n        dayjs(this.end),\n        enableTime\n      );\n    }\n    this.showDialog();\n  }\n\n  showDialog() {\n    const self = this;\n    $('#interval').val(this.intervalSeconds);\n    $('#map-animation').dialog({\n      title: window.gettext('Animación'),\n      modal: true,\n      appendTo: this.getMap().getTargetElement(),\n      buttons: [\n        {\n          html: `<i class=\"fas fa-download\" title=\"${window.gettext(\"Exportar a gif\")}\"></i>`,\n          click: () => {\n            const visible_layers = [];\n            this.mapa.getLayers().getArray().forEach(l => {\n              if (l.getVisible() && l.get('simmer_id')) {\n                visible_layers.push(l.get('simmer_id'));\n              }\n            })\n            const bbox_max = transformExtent(this.cfg.extent, 'EPSG:4326', window.epsg);\n            const extent = this.mapa.getView().calculateExtent();\n            const intersection = getIntersection(extent, bbox_max);\n            const start = dayjs(this.start_date_input.latestSelectedDateObj);\n            const end = dayjs(this.end_date_input.latestSelectedDateObj);\n            const distance = end.diff(start, this.scale);\n            const time_type = window.timelinectl.configure.time_type;\n            const delta_time = time_type == '10M' ? 10 : 1;\n            let params = `?ITERATIONS=${Math.floor(distance / delta_time)}&DELTA_TIME=${delta_time}&SIZE=500` +\n              '&scale=' + this.scale + '&visible_layers=' + visible_layers.join(',') +\n              '&bbox=' + String(intersection) + '&INTERVAL=' + String($('#interval').val() * 1000);\n            if (window.timelinectl)\n              params += '&date=' + start.toISOString();\n            const { ...map_dimensions } = this.mapa.get('dimension_controls');\n            delete map_dimensions.HORIZON;\n            for (const [k, dim] of Object.entries(map_dimensions))\n              params += '&' + $.param({ [k]: dim.value });\n            if (this.getMap().get('simulation_id'))\n              params += '&simulation_id=' + this.getMap().get('simulation_id');\n            window.open(window.Urls.gif_export(this.cfg.id) + params);\n          },\n        },\n        {\n          text: [window.gettext('Aceptar')],\n          click: function () {\n            self.play();\n            $(this).dialog('close');\n            self.startAnimation();\n          },\n        },\n        {\n          text: [window.gettext('Cancelar')],\n          click: function () {\n            self.pause();\n            $(this).dialog('close');\n          }\n        },\n      ],\n      open: function () {\n        $('button.ui-dialog-titlebar-close').attr('title', `${window.gettext('Cerrar')}`)\n      },\n    });\n    if (!this.enumTime) {\n      $('#map-animation div select').hide();\n      $('#map-animation .start-date .form-control').on('click', () => {\n        this.start_date_input.toggle(!this.start_date_input.isOpen)\n      });\n      $('#map-animation .end-date .form-control').on('click', () => {\n        this.end_date_input.toggle(!this.end_date_input.isOpen)\n      });\n    }\n  }\n\n  configureCalendar(element, date, enableTime) {\n    return flatpickr(element, {\n      defaultDate: date.format('YYYY-M-D HH:mm'),\n      enableTime,\n      dateFormat: 'Y-m-dTH:i',\n      altInput: true,\n      altFormat: 'd-m-Y H:i',\n      allowInput: true,\n      time_24hr: true,\n      minuteIncrement: 60,\n      static: false,\n      clickOpens: false,\n      appendTo: $('#map-animation .' + element[0].id + ' input.form-control')[0],\n      onOpen: [\n        (selectedDates, dateStr, instance) =>\n          instance == this.start_date_input ? this.end_date_input.close() : this.start_date_input.close()\n      ]\n    });\n  }\n\n  getDateRanges(unit, start, end) {\n    let ranges = [start], pos = 0;\n    if (this.scale == 'year') {\n      while (start < end) {\n        start = start.add(this.diff[pos], unit);\n        ranges.push(start);\n        ++pos;\n      }\n    }\n    else {\n      while (start < end) {\n        start = start.add(1, unit);\n        ranges.push(start);\n      }\n    }\n    return ranges;\n  }\n\n  roundDates(start, end) {\n    const scale = this.scale;\n    if (scale == 'hour') {\n      start = start.startOf('hour');\n      end = end.startOf('hour');\n    } else if (scale == 'day') {\n      start = start.startOf('day').add(14, 'hours');\n      end = end.startOf('day').add(14, 'hours');\n    } else if (scale == 'minute') {\n      start = roundNextXMin(start, 10);\n      end = roundNextXMin(end, 10);\n    } else if (scale == 'month') {\n      start = start.startOf('month').add(15, 'days');\n      end = end.startOf('month').add(15, 'days');\n    }\n    return start, end;\n  }\n\n  startAnimation() {\n    const marks = this.options.config.marks;\n    let start_date, end_date, addMarks = [];\n    if (this.start_date_input.latestSelectedDateObj) {\n      start_date = dayjs(this.start_date_input.latestSelectedDateObj);\n      end_date = dayjs(this.end_date_input.latestSelectedDateObj);\n    }\n    else {\n      start_date = dayjs(this.start_date_input.val() + '-01-01T00:00:00Z');\n      end_date = dayjs(this.end_date_input.val() + '-01-01T00:00:00Z');\n    }\n    this.intervalSeconds = $('#interval').val() || this.intervalSeconds;\n\n    let unit = this.scale + 's';\n    start_date, end_date = this.roundDates(start_date, end_date);\n    const ranges = this.getDateRanges(unit, start_date, end_date);\n    addMarks.Inicio = start_date.toDate();\n    addMarks.Fin = end_date.toDate();\n    for (const [mark, dt] of Object.entries(addMarks)) {\n      if (marks[mark]) {\n        window.timelinectl.timeline.setCustomTime(dt, mark)\n      }\n      else {\n        window.timelinectl.timeline.addCustomTime(dt, mark);\n        window.timelinectl.timeline.setCustomTimeTitle(mark, mark);\n        marks[mark] = dt;\n      }\n      window.timelinectl.timeline.customTimes[\n        window.timelinectl.timeline.customTimes.length - 1\n      ].hammer.off('panstart panmove panend');\n    }\n    this.animate(ranges, -1);\n    $('.time-selector').on('click', () => this.pause());\n  }\n  animate(ranges, i) {\n    this.getMap().set('animation', true);\n    i = (i + 1) % ranges.length;\n    const date = ranges[i];\n    setCurrentValue(date);\n    if (!this.enumTime)\n      window.timelinectl.timeline.moveTo(date.toDate());\n    window.timelinectl.timeline.setCustomTime(date.toDate(), 'current');\n    this.timeoutID = setTimeout(() => this.animate(ranges, i), this.interval);\n  }\n}\n\nclass VisibleLayerControl extends Control {\n  constructor() {\n    const html = $(`<div class=\"ol-visible-layer-info\"></div>`)\n    super({\n      element: html[0]\n    });\n  }\n  /**\n   * @param {Array} texts\n   */\n  set texts(texts) {\n    this.element.innerHTML = texts.map((x, idx) => `<p class=\"first-${idx == 0}\">${x[1]}</p>`).join('');\n  }\n}\nclass SelectProjectionControl extends Control {\n  constructor(mousePosition) {\n    const html = $(`\n      <div title=\"${window.gettext('Seleccionar proyección')}\" class=\"chProj combo dropup \">\n      <i class=\"fas fa-sort-up\"></i>\n      <form class=\"dropup-content\">\n      <ul class=\"dropup-content\" id=\"chProj\">\n      </ul>\n      </form>\n      </div>\n      `)\n    html.on('click', () => html.toggleClass('listshown'))\n    html.on('mouseleave', () => html.removeClass('listshown'));\n    window.site_cfg.site_epsgs.forEach(ep => {\n      const li = $(`<li desc=\"${ep.name}\" value =\"${ep.code}\">${ep.name} - ${ep.code}</li>`);\n      html.find('ul').append(li);\n    });\n    super({\n      element: html[0]\n    });\n    html.find('li').on('click', function () {\n      html.find('.select').removeClass('select');\n      $(this).addClass(\"select\");\n      let projCode = this.getAttribute('value');\n      const projDesc = this.getAttribute('desc');\n      let coordStringFunction = null;\n      if (projCode.endsWith(':DMS')) {\n        projCode = projCode.split(':DMS')[0];\n        coordStringFunction = toStringHDMS\n      }\n      else {\n        const destProj = proj4(projCode);\n        const oProj = destProj.oProj;\n        coordStringFunction = createStringXY(oProj.units == 'degrees' ? 4 : 0);\n      }\n      mousePosition.setProjection(projCode);\n      mousePosition.setCoordinateFormat(xy => coordStringFunction(xy, 2) + '<br>' + projDesc);\n      mousePosition.set('coordStringFunction', coordStringFunction);\n      window.coordinates_epsg = projCode;\n      window.coordinates_epsg_name = projDesc;\n    });\n    html.find(`li[value=\"${window.site_cfg.site_epsgs[0].code}\"]`).trigger('click');\n    html.removeClass('listshown');\n\n  }\n}\n\nexport function format(x) {\n  if (x == null)\n    return 'n/a'\n  if (x == '')\n    return x\n  if (x.match && x.match(/\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z)/))\n    return new Date(x).toLocaleString()\n  if (isNaN(x))\n    return x\n  if (x > 100)\n    return Math.floor(x + .5)\n  else\n    return Math.floor(x * 1000 + .5) / 1000\n}\nfunction numeric_lang_format(x) {\n  const output = new Intl.NumberFormat($(window.document).find('html').attr('lang')\n    , { maximumFractionDigits: 20 }).format(x)\n  return output\n}\n\nfunction openNewWindow(gc, path) {\n  const element_ids = gc.elements.join(',');\n  const activeDimensions = gc.get('activeDimensions') || {};\n  const groupByValue = gc.get('groupByValue');\n  const boxplot = $('button#boxplot').hasClass('active');\n  const dimensions = {};\n  for (const [id, v] of Object.entries(activeDimensions)) {\n    if (id in activeDimensions)\n      dimensions[id] = activeDimensions[id].map(d => d[0]).join(',');\n    else if (!activeDimensions)\n      dimensions[id] = v.value;\n  }\n  let layers = gc.layers_loc;\n  if (dimensions) {\n    const set_layers = new Set(layers.split(','));\n    layers = [];\n    set_layers.forEach(s => layers.push(s));\n    layers = layers.join(',');\n  }\n  if ('mdt' in gc)\n    layers += `,${gc.mdt}`;\n  const url = new URL(path, window.location);\n  url.searchParams.set('srid', window.epsg);\n  url.searchParams.set('x', gc.poi.centroid[0]);\n  url.searchParams.set('y', gc.poi.centroid[1]);\n  url.searchParams.set('radius', gc.poi.radius || '');\n  url.searchParams.set('visible_srid', window.coordinates_epsg);\n  url.searchParams.set('visible_layers', layers);\n  url.searchParams.set('layers', layers);\n  url.searchParams.set('element_ids', element_ids);\n  url.searchParams.set('boxplot', boxplot);\n  url.searchParams.set('grouped', gc.group_by_unit);\n  url.searchParams.set('groupByDims', gc.print_pluma);\n  url.searchParams.set('groupByValue', groupByValue);\n  if (dimensions) {\n    for (const [k, v] of Object.entries(dimensions)) {\n      if (Array.isArray(v)) {\n        v.forEach(val => url.searchParams.append(k, val));\n      } else if (v != null) {\n        url.searchParams.set(k, v);\n      }\n    }\n  }\n  if (window.timelinectl)\n    url.searchParams.set('date', window.timelinectl.timeline.getCustomTime('current').toISOString());\n  window.open(url);\n}\n\nfunction create_graph_control(mapa, poi, elements) {\n  const target_graphs = $('#info-dataGraph');\n  const gc = new GraphControl(\n    target_graphs,\n    poi,\n    false,\n    true,\n    elements,\n  );\n  gc.on('change:state', function () {\n    if (gc.get('state') == 'ok' && !target_graphs.dialog('isOpen'))\n      target_graphs.dialog('open');\n  })\n  mapa.addControl(gc);\n  const buttons = [{\n    html: '<i class=\"fas fa-print\"></i>',\n    click: () => openNewWindow(gc, window.Urls.plumas_pdf()),\n  }];\n  target_graphs.dialog({\n    appendTo: mapa,\n    autoOpen: false,\n    buttons: buttons,\n    height: 'auto',\n  });\n  gc.redraw();\n}\n\nfunction setPropagation(element_type_id, point, mapa) {\n  const tableId = '#fast-simulation-edit-dialog';\n  const new_pos = {\n    my: 'center',\n    at: 'center',\n    collision: \"fit\"\n  };\n  const buttons = [\n    {\n      text: window.gettext('Cancelar'),\n      click: function () {\n        $(this).dialog(\"close\");\n      },\n    },\n  ];\n  $(tableId).find('select#projection').empty();\n  for (const ep of window.site_cfg.site_epsgs) {\n    if (ep.code.endsWith(':DMS'))\n      continue;\n    const op = document.createElement('option')\n    op.innerText = ep.name + ' - ' + ep.code;\n    op.value = ep.code;\n    op.selected = (op.value == window.coordinates_epsg);\n    $(tableId).find('select#projection').append(op);\n  }\n  const destProj = proj4(window.epsg);\n  const selectProj = proj4(window.coordinates_epsg);\n  const nDec = selectProj.oProj.units == 'm' ? 2 : 6;\n  const [sel_x, sel_y] = proj4(destProj, selectProj, point);\n  $(tableId).find('input#xlong').val(parseFloat(sel_x.toFixed(nDec)));\n  $(tableId).find('input#xlong').attr('step', 1 / Math.pow(10, nDec));\n  $(tableId).find('input#ylat').val(parseFloat(sel_y.toFixed(nDec)));\n  $(tableId).find('input#ylat').attr('step', 1 / Math.pow(10, nDec));\n\n  buttons.unshift({\n    text: window.gettext('Crear'),\n    click: function () {\n      const x = Number($(tableId).find('input#xlong').val());\n      const y = Number($(tableId).find('input#ylat').val());\n      const srcEpsg = $(tableId).find('select#projection').val();\n      const sourceProj = proj4(srcEpsg);\n      const [x2, y2] = proj4(sourceProj, destProj, [x, y]);\n      const p = new Point([x, y]);\n      const p2 = new Point([x2, y2]);\n      if (p2.intersectsExtent(mapa.getView().calculateExtent())) {\n        const form = $(tableId + ' form');\n        const formData = new FormData(form[0]);\n        formData.set('element_simulationtype', element_type_id);\n        let datetime = formData.get('element_initdate');\n        datetime = dayjs(datetime);\n        formData.set('element_initdate', datetime.toISOString());\n        const popup = window.open();\n        popup.document.write(window.gettext('Cargando nueva propagación...'));\n        const featPoint = new Feature({\n          geometry: p,\n        });\n        $.ajax({\n          url: window.Urls.simulation_edit_new(),\n          data: formData,\n          cache: false,\n          contentType: false,\n          processData: false,\n          method: 'POST',\n          success: function (json) {\n            createOriginPoint(featPoint, mapa, json.id, popup);\n            $(tableId).dialog('close');\n          },\n          error: function () {\n            if (popup)\n              popup.close();\n          }\n        });\n      } else {\n        alert('Las coordenadas no corresponden a un punto del mapa');\n      }\n    }\n  });\n\n  const createProp_element = createProp_dialog(tableId, buttons, 'create', new_pos);\n  const marker_fast_prop = getMarkerVectorLayer(point, '/media/uploads/site/map-marker-solid.svg');\n  mapa.addLayer(marker_fast_prop);\n  createProp_element.on(\"dialogclose\", function () {\n    mapa.removeLayer(marker_fast_prop);\n  });\n  fillElementInfo(createProp_element, null, false, element_type_id);\n}\nexport function showProblemDialog(source, url) {\n  const div_error = $('<div id=\"error\"/>');\n  const error_element = $(source.document.body.innerHTML);\n  div_error.append(error_element);\n  let buttons = [];\n  if (source.document.body.id === \"error\") {\n    buttons = [{\n      text: window.gettext('Aceptar'),\n      click: function () {\n        window.open(url + '&huge=ok');\n        $(this).dialog('close');\n      }\n    },\n    {\n      text: window.gettext('Cancelar'),\n      click: function () {\n        $(this).dialog('close');\n      }\n    }\n    ];\n  }\n  if (source.document.body.id === \"empty\") {\n    buttons = [{\n      text: window.gettext('Ok'),\n      click: function () {\n        $(this).dialog('close');\n      }\n    }]\n  }\n  div_error.dialog({\n    appendTo: '.map',\n    position: { my: 'center', at: 'center', collision: 'fit' },\n    width: 'auto',\n    height: 'auto',\n    autoOpen: true,\n    resizable: false,\n    modal: true,\n    buttons,\n  });\n  source.close();\n}\n\nfunction createExportButton(mapa, cfg, args) {\n  let url_func = window.Urls.page_tif;\n  let extra_params = '';\n  if (args.type == 'pdf') {\n    url_func = window.Urls.page_pdf;\n    extra_params = '&DELTA_TIME=1';\n  }\n  if (args.type == 'png') {\n    url_func = window.Urls.page_png;\n    extra_params = '&DELTA_TIME=1';\n  }\n  if (args.toASCII) extra_params += '&toASCII=true';\n  if (args.type == 'kml') {\n    url_func = window.Urls.page_kml;\n    extra_params = '&DELTA_TIME=1&ITERATIONS=1';\n  }\n\n  return new Button({\n    html: args.icon,\n    title: window.gettext(args.title),\n    handleClick: function () {\n      let visible_layers = [];\n      let visible_elements = [];\n      mapa.getLayers().getArray().forEach(l => {\n        if (l.getVisible() && l.get('simmer_id')) {\n          if (l.get('title') == 'elementsLayerGroup') {\n            if (l.getLayersArray()[0].getVisible()) {\n              visible_layers.push(l.get('simmer_id'));\n              visible_elements.push('types' + l.get('simmer_id') + '=' + l.getLayersArray()[0].getSource().getParams()['TYPES']);\n            }\n          }\n          else {\n            visible_layers.push(l.get('simmer_id'));\n          }\n        }\n      })\n      const bbox_max = transformExtent(cfg.extent, 'EPSG:4326', window.epsg);\n      const extent_mosaico = mapa.getView().calculateExtent();\n      const intersection = getIntersection(extent_mosaico, bbox_max);\n      let params = '?visible_layers=' +\n        visible_layers.join(',') +\n        '&bbox=' + String(intersection);\n      if (window.timelinectl)\n        params += '&date=' + window.timelinectl.timeline.getCustomTime('current').toISOString();\n      else\n        params += '&date=' + new Date().toISOString();\n      if (visible_elements.length)\n        params += '&' + visible_elements.join('&');\n      const { ...map_dimensions } = mapa.get('dimension_controls');\n      delete map_dimensions.HORIZON;\n      for (const [k, dim] of Object.entries(map_dimensions))\n        params += '&' + $.param({ [k]: dim.value });\n      if (mapa.get('simulation_id'))\n        params += '&simulation_id=' + mapa.get('simulation_id');\n      if (window.epsg)\n        params += '&srid=' + window.epsg;\n      const srid = $('#chProj').find('li.select').attr('value');\n      if (srid)\n        params += '&t_srid=' + srid;\n\n      if (mapa.get('recortar_activo')) {\n        const trim_mask_id = window.site_cfg.extra.cutting_mask;\n        params += '&' + $.param({ trim_mask_id });\n      }\n      params += extra_params;\n      const url = url_func(cfg.id) + params;\n      const foo = window.open(url);\n      if (args.type !== 'pdf' && args.type !== 'png') {\n        const onload_func = function () {\n          if (['error', 'empty'].includes(this.document.body.id))\n            showProblemDialog(this, url);\n        };\n        foo.addEventListener('load', onload_func);\n      }\n    }\n  });\n}\nfunction createSimulation(e) {\n  $('#simulation-element-type-dialog table tbody').empty()\n  $.ajax({\n    url: window.Urls.simulation_types(),\n    success: function (json) {\n\n      for (const elem_type of json) {\n        const row = $(`<tr element_type=\"${elem_type.id}\"><td>${elem_type.name}</td></tr>`);\n        $('#simulation-element-type-dialog table tbody').append(row);\n      }\n      $('#simulation-element-type-dialog tr').on('click', null, 'create', function () {\n        const element_type_id = $(this).attr('element_type');\n        setPropagation(element_type_id, e.coordinate, e.data);\n        $('#simulation-element-type-dialog').dialog(\"close\");\n      });\n      if (json.length == 1)\n        $('#simulation-element-type-dialog tr').trigger('click');\n    }\n  });\n  $('#simulation-element-type-dialog').dialog({\n    title: window.gettext('Seleccione tipo...'),\n    width: 180,\n    height: 'auto',\n    maxHeight: window.innerHeight,\n  });\n}\nfunction setDims(pagelayer_set) {\n  const extra_dim = {};\n  for (const page_layer of pagelayer_set) {\n    if (page_layer.layer.source_type && page_layer.layer.source_type._dimension_controls) {\n      for (const dim of page_layer.layer.source_type.dimensions) {\n        if (dim.value_type == 'PERIODIC')\n          continue;\n        if (!(dim.locator in page_layer.layer.source_type._dimension_controls))\n          continue;\n        const dim_control = page_layer.layer.source_type._dimension_controls[dim.locator];\n        extra_dim[dim.locator] = dim_control.value;\n      }\n      // OJO comprobar cambio porque creo que antes no tenía senido\n      page_layer.extra_dim = extra_dim;\n    }\n  }\n  return extra_dim;\n}\nconst zip = new JSZip();\n\nasync function getKMLData(buffer, isKml) {\n  let kml_data = zip\n  if (!isKml) {\n    zip.files = {};\n    kml_data = await zip.loadAsync(buffer, { base64: true });\n  }\n  const kmlFiles = kml_data.file(/.kml$/i);\n  const lastKml = kmlFiles.length - 1;\n  if (lastKml >= 0)\n    return await kmlFiles[lastKml].async(\"string\");\n  return kml_data\n}\n\nfunction getKMLImage(href) {\n  let url = href;\n  let path = window.location.href;\n  path = path.slice(0, path.lastIndexOf('/') + 1);\n  if (href.indexOf(path) === 0) {\n    const regexp = new RegExp(href.replace(path, '') + '$', 'i');\n    const kmlFile = zip.file(regexp)[0];\n    if (kmlFile) {\n      url = URL.createObjectURL(new Blob([kmlFile.async(\"arraybuffer\")]));\n    }\n  }\n  return url;\n}\n\n// Define a KMZ format class by subclassing ol/format/KML\n\nclass KMZ extends KML {\n  constructor(opt_options) {\n    const options = opt_options || {};\n    options.iconUrlFunction = getKMLImage;\n    super(options);\n  }\n\n  getType() {\n    return 'arraybuffer';\n  }\n\n  async readFeature(source, options) {\n    const kmlData = await getKMLData(source);\n    return super.readFeature(kmlData, options);\n  }\n\n  async readFeatures(source, options, isKml) {\n    const kmlData = await getKMLData(source, isKml);\n    return super.readFeatures(kmlData, options);\n  }\n}\n\nexport async function cargarMapaMain(ns, cfg) {\n  const mapa = await cargarMapa(ns, ns.page.find('.map'), cfg);\n  const element_id = getParameterByName('element_id');\n  if (element_id) {\n    const response = await fetch(window.Urls.element_info(element_id))\n    const json = await response.json();\n    const geom = json.geometry;\n    const wktFormat = new WKT();\n    const map_geom = wktFormat.readGeometry(geom, {\n      dataProjection: 'EPSG:4326',\n      featureProjection: window.epsg\n    });\n    const view = mapa.getView();\n    view.fit(map_geom, {\n      maxZoom: view.getMaxZoom() - 9,\n    });\n    const newUrl = window.location.href\n      .replace(`element_id=${element_id}`, '')\n      .replace(`?&`, '?')\n      .replace(`&#`, '#')\n      .replace(`&&`, '&');\n    window.history.replaceState(null, null, newUrl);\n  }\n}\n\nclass LegendContextMenu extends ContextMenu {\n  constructor(opt_options) {\n    super(opt_options);\n    this.set('showableLegend', []);\n    this.on('change:showableLegend',\n      function () {\n        if (this.isOpen())\n          this.updateLegendMenuItem()\n      }\n    );\n    this.on('open', function () {\n      this.updateLegendMenuItem();\n    });\n  }\n  updateLegendMenuItem() {\n    const visibles = this.get('showableLegend');\n    const mapa = this.getMap();\n    const cls = 'fa-elementor';\n    const idx = this.items.findIndex(i => i.text?.includes(cls));\n\n    if (visibles.length !== 0 && idx === -1) {\n      const legendItem = {\n        text: `<i class=\"fab ${cls} fa-icon\"></i>&nbsp;&nbsp;${window.gettext('Mostrar leyenda')}`,\n        callback: e => {\n          visibles.forEach(lyr => showLegend(e, mapa, lyr));\n        },\n      };\n      this.items.push(legendItem);\n    } else if (visibles.length === 0 && idx !== -1) {\n      this.items.splice(idx, 1);\n    }\n    this.clear();\n    this.extend(this.items);\n  }\n}\nexport { cargarMapa, crearCapa, cargarMosaico, numeric_lang_format, transform_extent, create_graph_control };\n","import { $, dayjs, cargarCSS, proj4, getParameterByName } from '../../../moderna_meteogrid/statix/js/base.mjs';\nimport { TileWMS as TileWMSSource } from 'ol/source';\nimport { Tile as TileLayer } from 'ol/layer';\nimport Point from 'ol/geom/Point';\nimport Feature from 'ol/Feature';\nimport { Layer, setVisibleLayers_url } from '../../../simmer/statix/simmer/js/simmerlayer.mjs';\nimport { transform_extent } from '../../../simmer/statix/simmer/js/mapa.mjs';\nimport InspireTree from 'inspire-tree'\nimport InspireTreeDOM from 'inspire-tree-dom'\nimport LayerGroup from 'ol/layer/Group';\nimport WKT from 'ol/format/WKT';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport { uniq } from 'underscore';\n\nimport {\n    configureCalendar, actOnElement, initializeMapa,\n    crearFilaData, fixDates, createAddDataButton\n} from './mapa_elementos.mjs';\nimport { fromExtent, circular } from 'ol/geom/Polygon';\n\nfunction updateStyles(tree, srcElements) {\n    const type_filters = $.map(tree.selected(), function (x) {\n        if (x.id.startsWith('et')) return x.id.substring(2);\n    });\n    type_filters.push(-1);\n    srcElements.updateParams({ TYPES: type_filters.join(',') });\n    srcElements.set('listado', true);\n}\n\n\nfunction zoomToPoint(evt) {\n    const mapa = evt.data;\n    const view = mapa.getView();\n    const element = (this.attributes.geom) ? this : $(this).closest('tr')[0];\n    mapa.set('lastElementPixel', undefined);\n    const geom = element.attributes.geom;\n    if (!geom.value)\n        return false;\n    const geojsonFormat = new GeoJSON()\n    const map_geom = geojsonFormat.readGeometry(geom.value, {\n        dataProjection: 'EPSG:4326',\n        featureProjection: window.epsg\n    });\n    view.fit(map_geom);\n    view.setZoom(view.getZoom() - 1);\n}\n\nclass SaverElementsLayer extends Layer {\n    constructor(ns, pageLayer, time_delta, interactive_map) {\n        super(ns, pageLayer, time_delta, interactive_map);\n        this.element_class = this._extra.element_class;\n        this.site = this._extra.site;\n        this.readonly = this._extra.readonly;\n        this.showElementsAffected = this._extra.showElementsAffected;\n        this.hideFilter = this._extra.hidefilter;\n        this.hideChanges = this._extra.hidechanges || this.readonly;\n        this.types = this._extra.types ? this._extra.types : [];\n        delete this._extra.types;\n        // No, no vale instanceof \n        // https://stackoverflow.com/questions/203739/why-does-instanceof-return-false-for-some-literals\n        if (this.types.constructor === String)\n            this.types = this.types.split(',');\n        if (!(this.types instanceof Array))\n            this.types = [this.types];\n        const type_locator = this?._layer?.source_type?.model_query?.filter?.element_type__locator\n        if (type_locator)\n            this.types = [type_locator];\n        const type_locator_in = this?._layer?.source_type?.model_query?.filter?.element_type__locator__in\n        if (type_locator_in)\n            this.types = type_locator_in;\n\n\n    }\n    registerGeomButtons(tableId) {\n        $(tableId).find('button.geom-point').on('click', evt => {\n            evt.preventDefault();\n            this.ns.mapa.set('new_feature', 'Point');\n        });\n        $(tableId).find('button.geom-line').on('click', evt => {\n            evt.preventDefault();\n            this.ns.mapa.set('new_feature', 'LineString');\n        });\n        $(tableId).find('button.geom-polygon').on('click', evt => {\n            evt.preventDefault();\n            this.ns.mapa.set('new_feature', 'Polygon');\n        });\n        $(tableId).find('button.geom-coords').on('click', evt => {\n            evt.preventDefault();\n            pointByCoords(this.ns.mapa);\n        });\n        $(tableId).find('button.geom-size').on('click', evt => {\n            evt.preventDefault();\n            this.polygonBySize();\n        });\n    }\n\n    polygonBySize() {\n        const mapa = this.ns.mapa;\n        const tableId = '#polygonbysize-dialog';\n        const form = $(tableId + ' form');\n        const buttons = [\n            {\n                text: window.gettext('Añadir polígono'),\n                click: function (evt) {\n                    evt.preventDefault();\n                    const w = parseFloat(form.find('[name=w]').val());\n                    const h = parseFloat(form.find('[name=h]').val());\n                    const center = mapa.getView().getCenter();\n                    const sourceProj = proj4(this.ns.epsg);\n                    const destProj = proj4(\"EPSG:4326\");\n                    const [x, y] = proj4(sourceProj, destProj, center);\n                    let polygon = getPolygonFromDistance(x, y, w, h, mapa.ns.epsg);\n\n                    if (polygon.intersectsExtent(mapa.getView().calculateExtent())) {\n                        const new_geom = new Feature(polygon);\n                        mapa.set('edit_feature', new_geom);\n                        $(tableId).dialog('close');\n                    } else {\n                        alert(window.gettext('Los datos no corresponden a un punto del mapa'));\n                    }\n                },\n            },\n        ];\n        $(tableId).show().dialog({\n            position: { my: \"right top\", at: \"right-5% top+150\", of: mapa.getTargetElement(), collision: 'fit' },\n            title: window.gettext('Dimensiones del polígono'),\n            width: 260,\n            buttons: buttons,\n            appendTo: mapa.getTargetElement(),\n        });\n        $(tableId).dialog(\"moveToTop\");\n    }\n    registerInTree() {\n        const self = this;\n        const raiz = this.ns.page.find('div.arbol');\n        raiz.show();\n        const arbol = raiz.find('#' + this._layerTypeLocator);\n\n        const modelo = $('.elementos.modelo');\n        const copia = modelo.clone();\n        copia.find('.fa.fa-chevron-right').parent().next().hide();\n        copia.removeClass('modelo')\n        if (this.hideChanges) {\n            copia.find('.cambios').remove();\n        }\n        if (this.hideFilter) {\n            copia.find('.filtro').hide();\n        }\n        copia.attr('id', this.id);\n        if (self._pageLayer.folder) {\n            const carpeta_existente = raiz.find(`div.folder[folder=\"${self._pageLayer.folder}\"]`);\n            if (carpeta_existente.length == 0) {\n                const carpeta_nueva = raiz.find('div.model_carpeta').clone();\n                carpeta_nueva.removeClass('model_carpeta');\n                carpeta_nueva.text(self._pageLayer.folder);\n                carpeta_nueva.attr('folder', self._pageLayer.folder);\n                carpeta_nueva.show();\n                arbol.append(carpeta_nueva);\n            }\n        }\n        arbol.append(copia);\n        copia.show();\n        activaAcordeones(copia);\n        const calendar_element_from = $('#' + this.id + ' div.calendar-filter[name=\"from\"]');\n        const calendar_element_to = $('#' + this.id + ' div.calendar-filter[name=\"to\"]');\n        configureCalendar(calendar_element_from);\n        configureCalendar(calendar_element_to);\n        const ol_map = this._ol_map;\n        const visible_layers = getParameterByName('visible_layers').split(',');\n        if (visible_layers[0] != '') {\n            this._pageLayer.shown = visible_layers.some((l) => l == this._pageLayer.id);\n            this.lyrElements.setVisible(this._pageLayer.shown);\n        }\n        $('#saver_dialogs').load(window.Urls.saver_dialogs(),\n            () => {\n                this.registerGeomButtons('#create-dialog');\n                this.registerGeomButtons('#edit-dialog');\n                $('#element-info').on('click', 'button.emmet-info', 'info',\n                    function (evt) {\n                        actOnElement.call(this, evt);\n                        $(this).parent().trigger('click');\n                    });\n                $('#element-info').on('click', 'tr.related-row', ol_map, zoomToPoint);\n            });\n        copia.find('.mostrar-capa').attr('id_layer', this._pageLayer.id);\n        copia.find('.clase_elementos').text(this._pageLayer.layer.name);\n        copia.find('.mostrar-elementos').prop('checked', this._pageLayer.shown);\n        copia.find('.mostrar-cambios').prop('checked', this._pageLayer.shown);\n        copia.find('.mostrar-elementos').on('change', function () {\n            self.lyrElements.setVisible(this.checked);\n            const info = ol_map.get('info');\n            if (info) {\n                ol_map.unset('info', true); \n                ol_map.set('info', info);\n            }\n            setVisibleLayers_url(self.ns.page, ol_map, self._pageLayer.id, this.checked);\n        });\n        copia.find('.mostrar-cambios').on('change', function () {\n            self.lyrElementChanges.setVisible(this.checked);\n        });\n        copia.find('.municipio select').on('change', async function () {\n            const srcElements = self.lyrElements.getSource();\n            if (this.value == '') {\n                srcElements.updateParams({ municipio: undefined });\n                srcElements.set('listado', true);\n                return;\n            }\n            srcElements.updateParams({ municipio: this.value });\n            srcElements.set('listado', true);\n            const response = await fetch(window.Urls.municipality(this.value));\n            const json = await response.json()\n            const extent = json.extent;\n            const view = this.ns.mapa.getView();\n            view.fit(transform_extent(extent));\n        });\n        copia.find('form').on('submit', function (event) {\n            event.preventDefault();\n            const from = $(this).find('input[name=\"from\"]').val();\n            const to = $(this).find('input[name=\"to\"]').val();\n            const contains = $(this).find('[name=\"contains\"]').val();\n            const srcElements = self.lyrElements.getSource();\n            srcElements.updateParams({ from: from, to: to, contains: contains });\n            srcElements.set('listado', true);\n        });\n        copia.find('form .reset-filter').on('click', function (event) {\n            event.preventDefault();\n            const from = this.form.elements.from.value = this.form.elements.from.defaultValue\n            const to = this.form.elements.to.value = this.form.elements.to.defaultValue\n            const contains = this.form.elements.contains.value = this.form.elements.contains.defaultValue\n            const srcElements = self.lyrElements.getSource();\n            srcElements.updateParams({ from: from, to: to, contains: contains });\n            srcElements.set('listado', true);\n        });\n        const target = copia.find('a.clase_elementos')\n        const cbx = copia.find('input.mostrar-elementos');\n        self.getLayerInfo(target, cbx);\n        if (self._interactive_map)\n            self.setSliderLayer(target, cbx);\n        const createElement = copia.find('.create-element');\n        if (!this.readonly) {\n            this.ns.mapa.get('contextMenu').push({\n                text: `<i class=\"fas fa-plus fa-left\"></i>\n                    <span>${window.gettext(\"Crear\")} ${self._pageLayer.layer.name}</span>`,\n                callback: () => self.createMapElement(),\n            });\n            createElement.on('click', () => this.createMapElement());\n        }\n        else createElement.hide();\n        const elementsAffected = copia.find('.elements-affected');\n        if (this.showElementsAffected)\n            elementsAffected.on('click', () => this.doElementsAffected());\n        else\n            elementsAffected.hide()\n    }\n\n    async crearCapaOL(olmap) {\n        const self = this;\n        this.ns.mapa = olmap;\n        initializeMapa(olmap);\n        this._ol_map = olmap;\n\n        const srcElements = new TileWMSSource({\n            url: window.Urls.wms(),\n            params: {\n                LAYERS: 'elements',\n                STYLES: '',\n                SIMULATION_ID: this._extra.simulation_id,\n                CLASE: this.element_class,\n                SRS: window.epsg,\n                MASK_SITE: true,\n                SITE: this.site,\n                TYPES: this.types,\n                ...this._extra\n            },\n        });\n        const timeFormat = this._extra?.timeFormat;\n        srcElements.on('change:time', function () {\n            const time = this.get('time');\n            const effective_time = time\n                .add(this.get('time_delta') || 0, 'hours');\n            this.set('effective_time', effective_time);\n            \n            this.updateParams({ TIME: effective_time.format(timeFormat) });\n        });\n\n        const lyrElements = new TileLayer({\n            source: srcElements,\n            title: 'null',\n            //maxResolution: 20,\n            name: 'elements',\n            visible: false,\n            displayInLayerSwitcher: false,\n            zIndex: this.zIndex,\n            time_management: 'affected_simulation_id' in this._extra,\n        });\n        this.lyrElements = lyrElements;\n        const srcElementChanges = new TileWMSSource({\n            url: window.Urls.wms(),\n            params: {\n                LAYERS: 'element_changes',\n                SIMULATION_ID: this._extra.simulation_id,\n                CLASE: this.element_class,\n                STYLES: '',\n                TYPES: this.types,\n                SRS: window.epsg,\n                MASK_SITE: true,\n                SITE: this._extra.site,\n                ...this._extra\n            },\n        });\n\n        const lyrElementChanges = this.hideChanges ? null : new TileLayer({\n            source: srcElementChanges,\n            title: null,\n            displayInLayerSwitcher: false,\n            zIndex: this.zIndex,\n            //maxResolution: 20,\n            name: 'element_changes',\n            visible: false\n        });\n        this.lyrElementChanges = lyrElementChanges;\n\n        const layers = this.readonly || this.hideChanges ?\n            [lyrElements] :\n            [lyrElements, lyrElementChanges];\n\n        const ret = new LayerGroup({\n            layers: layers,\n            displayInLayerSwitcher: false,\n            title: 'elementsLayerGroup',\n            simmer_id: this._pageLayer.id,\n            time_management: 'affected_simulation_id' in this._extra,\n        });\n        srcElements.on('change:listado', function () {\n            if (srcElements.get('listadoEnCurso')) {\n                window.clearTimeout(srcElements.get('listadoEnCurso'));\n                srcElements.set('listadoEnCurso', null);\n            }\n            srcElements.set('listado', false, true);\n            $('#' + this.id).find('.listado-elements').empty();\n            const layers = [lyrElements];\n            srcElements.set(\n                'listadoEnCurso',\n                window.setTimeout(function () {\n                    layers.forEach(requestList, self);\n                    srcElements.set('listadoEnCurso', null);\n                }, 1000)\n            );\n        });\n        if (!this.hideChanges)\n            olmap.on('change:update_changes', function () {\n                olmap.set('update_changes', false, true);\n                srcElementChanges.updateParams({ refresh: dayjs().format() });\n                const layers = [lyrElementChanges];\n                layers.forEach(requestList, self);\n            });\n        olmap.on('change:update_elements', function () {\n            olmap.set('update_elements', false, true);\n            srcElements.updateParams({ refresh: dayjs().format() });\n            const layers = [lyrElements];\n            layers.forEach(requestList, self);\n        });\n\n        olmap.on('change:info', function () {\n            if (this.get('isDrawing'))\n                return;\n            const evt = this.get('info');\n            if (evt) {\n                this.set('lastElementPixel', evt.pixel);\n                const layers = [];\n                if (self.lyrElements.getVisible())\n                    layers.push(lyrElements)\n                if (!self.hideChanges && self.lyrElementChanges.getVisible())\n                    layers.push(lyrElementChanges);\n                if (layers.length > 0)\n                    self.requestInfo(evt, layers);\n            }\n        });\n        cargarCSS();\n        this._ol_layer = ret;\n        if (this._ol_map)\n            this._ol_map.addLayer(ret);\n        this.registerInTree()\n        this.cargarArbol();\n        this.cargarMunicipios();\n        return ret;\n    }\n    async cargarMunicipios() {\n        const response = await fetch(window.Urls.municipalities());\n        const municipios = await response.json();\n        const select = $(`#${this.id} .municipio select`)\n        for (const m of municipios)\n            select.append($(`<option value=\"${m.id}\">${m.name}</option>`))\n    }\n    async cargarArbol() {\n        const self = this;\n        const lyrElements = this.lyrElements;\n        const lyrElementChanges = this.lyrElementChanges;\n        const mapa = this._ol_map;\n        const srcElements = lyrElements.getSource();\n        const response = await fetch(window.Urls.element_tree(this.element_class || ',', this.types?.length ? this.types : ',', this.site));\n        if (!response.ok)\n            throw new Error('Request Failed!');\n\n        const tree = new InspireTree({\n            selection: {\n                mode: 'checkbox'\n            },\n            data: await response.json(),\n        });\n        const target = $('#' + this.id).find('.arbol-elementos');\n        new InspireTreeDOM(tree, {\n            target: target\n        });\n        tree.on('model.loaded', function (nodes) {\n            mapa.set('update_changes', true);\n            lyrElements.setVisible(self._pageLayer.shown);\n            if (lyrElementChanges)\n                lyrElementChanges.setVisible(self._pageLayer.shown);\n            nodes.forEach(function (n) {\n                if (n.children)\n                    n.children.forEach(function (x) {\n                        x.refreshIndeterminateState();\n                    });\n                n.refreshIndeterminateState();\n            });\n            if (self.types.length) {\n                const et_ids = self.types.map(id => 'et' + id);\n                for (let n of nodes.slice()) {\n                    if (n.children)\n                        for (let x of n.children.slice()) { // FIXME: Recursivo\n                            if (x.children)\n                                for (let y of x.children.slice()) {\n                                    if (!et_ids.includes(y.id) && !y.indeterminate())\n                                        y.remove();\n                                }\n                            if (!et_ids.includes(x.id) && !x.indeterminate())\n                                x.remove();\n                        }\n                    if (!et_ids.includes(n.id) && !n.indeterminate())\n                        n.remove();\n                }\n            }\n            updateStyles(this, srcElements);\n            tree.on('node.checked', function () {\n                updateStyles(this, srcElements);\n            });\n            tree.on('node.unchecked', function () {\n                updateStyles(this, srcElements);\n            });\n        });\n        const tooltip = $('<div id=\"saver-tooltip\" class=\"layer tooltip\"></div>').hide();\n        const mapDiv = $(this._ol_map.getTargetElement());\n        mapDiv.append(tooltip);\n        let old_img = null;\n        $('[custom_legend=true]').on('mouseover',\n            function (event) {\n                if (tooltip.is(\":visible\"))\n                    return;\n                const offset = mapDiv.offset();\n                const left = event.pageX + 1;\n                const top = event.pageY - offset.top + 1;\n                const et_id = this.dataset.uid.replace(/et/, '');\n                const params = { width: 200, pageLayerId: self._pageLayer.id, types: et_id };\n                const img = `<img src=\"${self._ol_layer.getLayersArray()[0].getSource().getLegendUrl(null, params)}\"></img>`\n                if (img !== old_img) {\n                    old_img = img;\n                    tooltip.empty();\n                    tooltip.append($(img))\n                }\n                tooltip.css({ top, left }).show();\n            }\n        );\n        $('[custom_legend=true]').on('mouseleave', () => tooltip.hide());\n        return tree;\n    }\n    elementRow(tableId, v) {\n        if (v.name === 'elements') {\n            const tt = v.properties.comments || '';\n            const buttons =\n                '<button type=\"button\" class=\"fa fa-link emmet-url\"></button>' +\n                '<button type=\"button\" class=\"fa fa-info emmet-info\"></button>' +\n                '<button type=\"button\" class=\"fa fa-edit emmet-edit\"></button>' +\n                '<button type=\"button\" class=\"fa fa-trash emmet-delete\"></button>';\n            const tr = $(\n                '<tr geom=\"' +\n                JSON.stringify(v.geometry).replace(/\"/g, '&quot;') +\n                '\" element_id=\"' +\n                v.properties.id +\n                '\" element_class=\"' +\n                v.properties.element_type__element_class +\n                '\"><td title=\"' +\n                v.properties.element_type__name +\n                '\" data-uid=\"et' +\n                v.properties.element_type_id +\n                '\"></td><td title=\"' +\n                tt +\n                '\">' +\n                (v.properties.name\n                    ? v.properties.name\n                    : v.properties.element_type__name) +\n                buttons +\n                '</td></tr>'\n            );\n            if (!this.readonly && (\n                (window.change_municipal_element && v.properties.element_type__municipal) ||\n                window.validate_element_changes ||\n                window.change_site_element\n            ))\n                tr.addClass('can-edit');\n            if (v.properties.elementchange__parameter_change__locator === 'DELETE_ELEMENT')\n                tr.addClass('pending_delete');\n            if (v.properties.elementchange__parameter_change__locator === 'UPDATE_ELEMENT')\n                tr.addClass('pending_edit');\n            $(tableId + ' tr:last').after(tr);\n        } else if (v.name === 'element_changes') {\n            const tt = v.properties.comments || '';\n            let buttons =\n                '<button type=\"button\" class=\"fa fa-check emmet-commit-create\"></button>' +\n                '<button type=\"button\" class=\"fa fa-edit emmet-edit-new\"></button>' +\n                '<button type=\"button\" class=\"fa fa-check emmet-commit-edit\"></button>' +\n                '<button type=\"button\" class=\"fa fa-check emmet-commit-delete\"></button>' +\n                '<button type=\"button\" class=\"fa fa-link emmet-url\"></button>';\n            if (window.change_municipal_element && v.properties.element_type__municipal)\n                buttons += '<button type=\"button\" class=\"fa fa-xmark emmet-change-remove\"></button>'\n            const element_id = v.properties.references__id || v.properties.id;\n            const tr = $(\n                '<tr geom=\"' +\n                JSON.stringify(v.geometry).replace(/\"/g, '&quot;') +\n                '\" element_id=\"' +\n                element_id +\n                '\" element_class=\"' +\n                v.properties.element_type__element_class +\n                '\"><td title=\"' +\n                v.properties.element_type__name +\n                '\" data-uid=\"et' +\n                v.properties.element_type_id +\n                '\"></td><td title=\"' +\n                tt +\n                '\">' +\n                (v.properties.name\n                    ? v.properties.name\n                    : v.properties.element_type__name) +\n                buttons +\n                '</td></tr>'\n            );\n            if (v.properties.parameter_change__locator === 'INSERT_ELEMENT')\n                tr.addClass('pending_create');\n            if (v.properties.parameter_change__locator === 'DELETE_ELEMENT')\n                tr.addClass('pending_delete');\n            if (v.properties.parameter_change__locator === 'UPDATE_ELEMENT')\n                tr.addClass('pending_edit');\n            if (!this.readonly && (\n                (window.change_municipal_element && v.properties.element_type__municipal) ||\n                window.validate_element_changes ||\n                window.change_site_element\n            ))\n                tr.addClass('can-edit-new');\n            if (window.validate_element_changes) tr.addClass('can-commit');\n            $(tableId + ' tr:last').after(tr);\n        }\n    }\n    elementTable(tableId, features, mapa) {\n        const self = this;\n        const newDiv = $('<div><table><tr><td/><td/></tr></table></div>');\n        $(tableId).append(newDiv);\n        $.each(features, function (_, v) {\n            self.elementRow(tableId, v);\n        });\n        newDiv.find('tr:first').remove();\n        newDiv.on('click', 'tr', mapa, zoomToPoint);\n        newDiv.find('button.emmet-url').prop('title', window.gettext('Generar enlace'));\n        newDiv.on('click', 'button.emmet-url', 'url', actOnElement);\n        newDiv.on('click', 'button.emmet-edit', 'edit', actOnElement);\n        newDiv.find('button.emmet-edit').prop('title', window.gettext('Modificar'));\n        newDiv.on('click', 'button.emmet-edit-new', 'edit-new', actOnElement);\n        newDiv.find('button.emmet-edit-new').prop('title', window.gettext('Modificar'));\n        newDiv.on('click', 'button.emmet-delete', 'delete', actOnElement);\n        newDiv.find('button.emmet-delete').prop('title', window.gettext('Eliminar'));\n        newDiv.on('click', 'button.emmet-info', 'info', actOnElement);\n        newDiv.find('button.emmet-info').prop('title', window.gettext('Información'));\n        newDiv.on('click', 'button.emmet-commit-create', 'commit-create', actOnElement);\n        newDiv.find('button.commit-create').prop('title', window.gettext('Confirmar/descartar cambio'));\n        newDiv.on('click', 'button.emmet-commit-edit', 'commit-edit', actOnElement);\n        newDiv.find('button.emmet-commit-edit').prop('title', window.gettext('Confirmar/descartar cambio'));\n        newDiv.on('click', 'button.emmet-commit-delete', 'commit-delete', actOnElement);\n        newDiv.find('button.emmet-commit-delete').prop('title', window.gettext('Confirmar/descartar cambio'));\n        newDiv.on('click', 'button.emmet-change-remove', 'change-remove', actOnElement);\n        newDiv.find('button.emmet-change-remove').prop('title', window.gettext('Descartar cambio'));\n        if (tableId != '.info_elem') {\n            newDiv.on('click', 'button.emmet-edit', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-edit-new', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-delete', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-info', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-commit-create', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-commit-edit', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-commit-delete', mapa, zoomToPoint);\n            newDiv.on('click', 'button.emmet-change-remove', mapa, zoomToPoint);\n        }\n    }\n    requestInfo(evt, layers) {\n        const self = this;\n        const view = evt.map.getView();\n        const viewResolution = view.getResolution();\n        const viewProjection = view.getProjection();\n        const urls = [];\n        for (let i = 0; i < layers.length; i++) {\n            urls[i] = layers[i]\n                .getSource()\n                .getFeatureInfoUrl(evt.coordinate, viewResolution, viewProjection, {\n                    INFO_FORMAT: 'application/vnd.meteogrid.emmet+json',\n                    TOLERANCE: 7,\n                });\n        }\n        const tableId = '.info_elem';\n        const ajax = urls.map(url => $.ajax(url));\n        const simple = urls.length == 1;\n        $.when(...ajax).done(function (...jsons) {\n            if (simple)\n                jsons = [jsons];\n            let features = [];\n            for (const json of jsons)\n                features = features.concat(json[0].features);\n            self.elementTable(tableId, features, evt.map);\n            const containerId = '#info';\n            if (features.length > 0) {\n                if ($(tableId).is(':hidden')) $(tableId).show();\n                if ($(containerId).is(':hidden')) $(containerId).show();\n                if (!$(containerId).dialog('isOpen'))\n                    $(containerId).dialog('open');\n                else\n                    $('.ui-dialog').trigger(\"dialogopen\");\n            }\n        });\n    }\n\n    createMapElement() {\n        const self = this;\n        const new_pos = {\n            my: 'right top',\n            at: 'right-5% top+5',\n            of: this.ns.mapa.getTargetElement(),\n            collision: 'fit'\n        };\n        this.ns.mapa.set('sidebar_toggle', false);\n        $('#element-type-dialog table tbody').empty();\n        $.ajax({\n            url: window.Urls.element_types(this.element_class, this.types?.length ? this.types : ','),\n            success: function (json) {\n                const element_types = json;\n                for (const elem_type of json) {\n                    const row = $(\n                        '<tr element_type=\"' +\n                        elem_type.pk +\n                        '\"><td data-uid=\"et' +\n                        elem_type.pk +\n                        '\"></td><td>' +\n                        elem_type.name +\n                        '</td></tr>'\n                    );\n                    $('#element-type-dialog table tbody').append(row);\n                }\n                $('#element-type-dialog tr').on('click', function (evt) {\n                    const tableId = '#create-dialog';\n                    const table = $(tableId);\n                    table.find('input.element_updated')\n                        .val(dayjs().format('DD-MM-YYYY'));\n                    const element_type_id = $(evt.target)\n                        .closest('tr')\n                        .attr('element_type');\n                    // Montamos lista de opciones para crear datos nuevos\n                    const element_type = element_types.filter(function (elem) {\n                        return elem.pk == element_type_id;\n                    })[0];\n                    const available_data = element_type.data\n                    table.find('.vardata').remove();\n                    table\n                        .find(\"textarea[name='simulation_id']\")\n                        .val(self._extra.simulation_id ? self._extra.simulation_id : '');\n\n                    table.find('.add-data').remove();\n                    const data_menu = $('<ul class=\"add-data\"></ul>');\n                    for (const [i, dat] of Object.entries(available_data)) {\n                        if (!dat.type.calculation_id) {\n                            if (dat.fixed) {\n                                crearFilaData(tableId, [], [dat]);\n                            }\n                            else {\n                                const it = $(\n                                    '<li idx_available_data=\"' + i + '\">Añadir ' + dat.type.name + '</li>'\n                                );\n                                data_menu.append(it);\n                            }\n                        }\n                    }\n\n                    const buttons = [\n                        {\n                            text: window.gettext('Guardar'),\n                            click: function () {\n                                const dialog = this;\n                                if (element_type.locatable) {\n                                    const feat = self.ns.mapa.get('edit_feature');\n                                    if (!feat) {\n                                        $('button.geometry').fadeTo('fast', 0).fadeTo('fast', 1);\n                                        return;\n                                    }\n                                    const geometry = feat.getGeometry();\n                                    geometry.transform(window.epsg, 'EPSG:4326');\n                                    const wkt = new WKT();\n                                    const geom = wkt.writeGeometry(geometry, {\n                                        dataProjection: 'EPSG:4326',\n                                    });\n                                    table.find('form .element_geometry.data_new').val(geom);\n                                }\n                                table.find('input.element_updated').val(dayjs().format('YYYY-MM-DD'));\n                                fixDates(table);\n                                $.ajax({\n                                    url: window.Urls.element_create(element_type_id),\n                                    type: 'POST',\n                                    cache: false,\n                                    contentType: false,\n                                    processData: false,\n                                    data: new FormData(table.find('form')[0]),\n                                    success: function () {\n                                        $(dialog).dialog('close');\n                                        $(dialog).dialog('destroy');\n                                        $('#create-ok').dialog();\n                                        self.ns.mapa.set('update_elements', true);\n                                        self.ns.mapa.set('update_changes', true);\n                                    }\n                                });\n                            }\n                        },\n                        {\n                            text: window.gettext('Cancelar'),\n                            click: function () {\n                                $(this).dialog('close');\n                            }\n                        },\n                    ];\n                    buttons.unshift(createAddDataButton(tableId, data_menu, available_data));\n                    table\n                        .find('textarea.data_new')\n                        .val('');\n                    table.dialog({\n                        width: (window.innerWidth * 2 / 5 <= 475) ? 475 : 'auto',\n                        height: 'auto',\n                        maxHeight: window.innerHeight * 0.7,\n                        appendTo: self.ns.mapa.getTargetElement(),\n                        title: `${window.gettext(\"Crear\")} ${this.textContent}`,\n                        zIndex: 10000,\n                        resizable: true,\n                        buttons: buttons,\n                        position: new_pos,\n                        open: function () {\n                            $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n                            $(this).parent().css('max-width', (window.innerWidth * 2 / 5 <= 475) ? 475 : 'auto');\n                            $(this).css('max-width', (window.innerWidth * 2 / 5 <= 475) ? 475 : 'auto');\n                            self.ns.mapa.set('isDrawing', true)\n                        },\n                        close: function () {\n                            self.ns.mapa.set('isDrawing', false)\n                            // Forzamos refresco de edit_feature\n                            self.ns.mapa.unset('edit_feature');\n                            $(this).hide();\n                        },\n                        autoOpen: false,\n                    });\n                    table.dialog('open');\n                    $('#element-type-dialog').dialog('close');\n                });\n                if (json.length == 1)\n                    $('#element-type-dialog tr').click();\n            }\n        });\n        const height = $(window).height();\n        $('#element-type-dialog').dialog({\n            title: window.gettext('Seleccione tipo...'),\n            appendTo: this.ns.mapa.getTargetElement(),\n            width: 'auto',\n            height: 'auto',\n            maxHeight: height * .6,\n            position: {\n                my: 'center top',\n                at: 'center top+19%',\n                of: this.ns.mapa.getTargetElement(),\n                collision: 'fit'\n            },\n        });\n    }\n    async doElementsAffected() {\n        const self = this;\n        $('body').addClass('wait');\n        const response = await fetch(window.Urls.simul_affected_elements(this.ns.simulation_id, this._pageLayer.id));\n        $('body').removeClass('wait');\n        const json = await response.json()\n        const elements_by_minutes = {};\n        const abs_time_for_time = {};\n        const elements_by_type = {};\n        const elements = {};\n        const all_features = [];\n        for (const [minutes, features, abs_time_iso] of json) {\n            const abs_time = dayjs(abs_time_iso);\n            abs_time_for_time[minutes] = abs_time.format('HH:mm');\n            all_features.push(...features);\n            elements_by_minutes[minutes] = [];\n            for (const elem of features) {\n                elements_by_type[elem.element_type__name] = [];\n                if (!elements[elem.element_type__name])\n                    elements[elem.element_type__name] = {};\n                elements[elem.element_type__name][minutes] = [];\n            }\n        }\n        const uniq_features = uniq(all_features, v => v.id);\n        const layer_features = uniq_features.map(f => ({\n            name: 'elements',\n            geometry: f.geom,\n            properties: f,\n        }))\n        for (const [minutes, features] of json) {\n            for (const elem of features) {\n                elements_by_minutes[minutes].push(elem.id);\n                elements_by_type[elem.element_type__name].push(elem.id);\n                elements[elem.element_type__name][minutes].push(elem.id);\n            }\n        }\n        const ret = $('#affected-elements');\n        ret.find('.delenda').remove();\n        ret.find('.increase-colspan').attr('colspan', 1 + Object.keys(elements_by_minutes).length)\n        const col = ret.find('.minutes.model');\n        const col_abs = ret.find('.time-for-minutes.model');\n\n        const total_col = ret.find('.model.total-count-by-minutes');\n        const row = ret.find('.model.element-type');\n        for (const [minutes, ids] of Object.entries(elements_by_minutes)) {\n            col.clone().removeClass('model').addClass('delenda').text(minutes).insertBefore(col);\n            col_abs.clone().removeClass('model').addClass('delenda').text(abs_time_for_time[minutes]).insertBefore(col_abs);\n            const new_total_col = total_col.clone().removeClass('model').addClass('delenda').insertBefore(total_col).data('ids', ids);\n            new_total_col.find('a').text(ids.length).data('ids', ids);\n        }\n        ret.find('.total-count a').text(uniq_features.length).data('ids', '*');\n        for (const [element_type, ids_by_type] of Object.entries(elements_by_type)) {\n            const uniq_ids_by_type = uniq(ids_by_type);\n            const new_row = row.clone().removeClass('model').addClass('delenda').insertBefore(row);\n            new_row.find('.type').text(element_type);\n            new_row.find('.total-count-by-type a').text(uniq_ids_by_type.length).data('ids', uniq_ids_by_type);\n            const count_model = new_row.find('.count');\n            for (const minutes of Object.keys(elements_by_minutes)) {\n                const ids = elements[element_type][minutes]\n                const new_count = count_model.clone().removeClass('model').addClass('delenda').insertBefore(count_model);\n                new_count.find('a').text(ids && ids.length).data('ids', ids)\n            }\n        }\n        ret.off('click', 'a');\n        ret.on('click', 'a', function (evt) {\n            const ids = $(this).data('ids');\n            const features = layer_features.filter(v => ids === '*' || ids.includes(v.properties.id));\n            const tableId = '.info_elem';\n            $(tableId).empty();\n            self.elementTable(tableId, features, self._ol_map);\n            const containerId = '#info'\n            if ($(containerId).dialog('isOpen'))\n                $(containerId).dialog('close')\n            if (features.length > 0) {\n                if ($(tableId).is(':hidden')) $(tableId).show();\n                if ($(containerId).is(':hidden')) $(containerId).show();\n                const new_pos = evt.new_pos ? evt.new_pos :\n                    {\n                        my: 'right top',\n                        at: 'right-10% top+5',\n                        of: self.ns.mapa.getTargetElement(),\n                        collision: 'none'\n                    };\n                $(containerId).dialog({\n                    position: new_pos,\n                })\n                $(containerId).dialog('open');\n            }\n            evt.stopPropagation();\n            return false;\n        })\n        ret.dialog({\n            title: window.gettext('Elementos afectados'),\n            width: 'auto',\n            maxWidth: 2048,\n            classes: {\n                \"ui-dialog\": \"ui-front-ma-non-troppo\"\n            }\n\n        });\n    }\n}\nfunction getPolygonFromDistance(x, y, w, h) {\n    // w y h en ms\n    let pol_extent;\n    w = w / 2;\n    h = h / 2;\n    if (w == h) {\n        pol_extent = circular([x, y], w, 4).getExtent();\n    }\n    else {\n        const pol_extent_w = circular([x, y], w, 4).getExtent();\n        const pol_extent_h = circular([x, y], h, 4).getExtent();\n        pol_extent = [pol_extent_w[0], pol_extent_h[1], pol_extent_w[2], pol_extent_h[3]]\n    }\n    let polygon = fromExtent(pol_extent);\n    polygon.transform('EPSG:4326', window.epsg);\n    return polygon;\n}\n\nfunction requestList(layer) {\n    const self = this;\n    const mapa = this._ol_map;\n    const view = mapa.getView();\n    const viewResolution = view.getResolution();\n    const viewProjection = view.getProjection();\n    const src = layer.getSource();\n    const url = src.getFeatureInfoUrl(\n        view.getCenter(),\n        viewResolution,\n        viewProjection,\n        { INFO_FORMAT: 'application/vnd.meteogrid.emmet+json' }\n    );\n    const id = '#' + this.id;\n    $.getJSON(\n        url.replace(/&I=/, '&II='), // TODO hacerlo más elegante\n        function (json) {\n            const tableId = id + ' .listado-' + layer.get('name');\n            $(tableId).empty();\n            self.elementTable(tableId, json.features, mapa);\n        }\n    );\n}\n\nexport { SaverElementsLayer, initializeMapa };\nfunction activaAcordeones(id) {\n    id.find('.accordion').click(function () {\n        $(this)\n            .children('span')\n            .toggleClass(\n                'fa-chevron-right',\n                $(this)\n                    .next()\n                    .is(':visible')\n            );\n        $(this)\n            .children('span')\n            .toggleClass(\n                'fa-chevron-down',\n                !$(this)\n                    .next()\n                    .is(':visible')\n            );\n        $(this)\n            .next()\n            .toggle('slow');\n        return false;\n    });\n}\n$(function () {\n    $('.accordion2').click(function () {\n        $(this)\n            .children('span')\n            .toggleClass(\n                'fa-plus-square',\n                $(this)\n                    .parent()\n                    .next()\n                    .is(':visible')\n            );\n        $(this)\n            .children('span')\n            .toggleClass(\n                'fa-minus-square',\n                !$(this)\n                    .parent()\n                    .next()\n                    .is(':visible')\n            );\n        $(this)\n            .parent()\n            .next()\n            .toggle('slow');\n        return false;\n    });\n});\n\nfunction pointByCoords(mapa) {\n    const tableId = '#pointbycoords-dialog';\n    const form = $(tableId + ' form');\n    const buttons = [\n        {\n            text: window.gettext('Añadir punto'),\n            click: function (evt) {\n                evt.preventDefault();\n                const x = parseFloat(form.find('[name=x]').val());\n                const y = parseFloat(form.find('[name=y]').val());\n                const srcEpsg = form.find('[name=epsg]').val();\n                const destProj = proj4(window.epsg);\n                const sourceProj = proj4(srcEpsg);\n                const [x2, y2] = proj4(sourceProj, destProj, [x, y]);\n                const p = new Point([x2, y2]);\n                if (p.intersectsExtent(mapa.getView().calculateExtent())) {\n                    const new_geom = new Feature(p);\n                    mapa.set('edit_feature', new_geom);\n                    $(tableId).dialog('close');\n\n                } else {\n                    alert('Las coordenadas no corresponden a un punto del mapa');\n                }\n            },\n        },\n    ];\n    const epsgSelect = $(tableId).find('select[name=\"epsg\"]');\n    if (epsgSelect.find('option').length === 0)\n        window.site_cfg.site_epsgs.forEach(ep => {\n            const projName = ep.name;\n            const text = projName + ' - ' + ep.code;\n            const op = $(`<option value =\"${ep.code}\">${text}</option>`);\n            epsgSelect.append(op);\n        });\n    $(tableId).show().dialog({\n        position: { my: \"right top\", at: \"right-5% top+150\", of: mapa.getTargetElement(), collision: 'fit' },\n        title: window.gettext('Coordenadas'),\n        width: 'auto',\n        buttons: buttons,\n        appendTo: mapa.getTargetElement(),\n    });\n    $(tableId).dialog(\"moveToTop\");\n}\n","/*eslint no-implicit-globals: \"error\"*/\nimport { $, dayjs, locale, mergeDeep, multiselectOptions, transform_point, getParameterByName, get_horizon, proj4 } from '../../../../moderna_meteogrid/statix/js/base.mjs';\nimport { createStringXY } from 'ol/coordinate';\nimport Plotly from 'plotly.js-cartesian-dist-min'\nimport locale_es from 'plotly.js-locales/es'\nimport { Control } from 'ol/control'\nimport { format } from './mapa.mjs'\nimport cartesian from 'cartesian';\nimport * as Excel from \"exceljs\";\nimport { saveAs } from \"file-saver\";\nimport { template } from 'underscore';\nPlotly.register(locale_es);\n\nfunction getColor(i) {\n  // coordinar con simmer/plugins.py\n  const colors = [\n    'red', 'lime', 'blue', 'orange', 'black',\n    'purple', 'pink', 'skyblue', 'silver'];\n  return colors[i % colors.length];\n}\n\nexport class GraphControl extends Control {\n  constructor(target, poi, group_by_unit, print_pluma, elements) {\n    const html = $(`\n        <div>\n          <div class=\"info_elem listado\"></div>\n          <div class=\"info_tabla\"><table class=\"tabla_datos\"><tbody></tbody></table></div>\n          <div id=\"threshold\" class=\"hidden negrita-main-color\">${(window.gettext('Umbral'))}: <input type=\"number\" min=\"0\" max=\"100\" step=\"5\" name=\"threshold\" value=\"\" ></div>\n        </div>\n    `);\n    super({\n      element: html[0],\n      target: target[0]\n    });\n    const self = this;\n    $(html.find('#threshold input')).on('change', function () {\n      self.redraw();\n    })\n    this.isDialog = target.hasClass('dialog');\n    this.target = target;\n    this.info_tabla = html.find('.info_tabla');\n    this.poi = poi;\n    this.elements = elements || [];\n    this.group_by_unit = group_by_unit || false;\n    this.print_pluma = print_pluma || false;\n    this.destProj = proj4(window.coordinates_epsg);\n    this.oProj = this.destProj.oProj;\n    const deg = this.oProj.units == 'degrees';\n    this.coordXY = createStringXY(deg ? 4 : 0);\n    this.projDesc = `${window.epsg_name}`.toUpperCase();\n    this.on('change:type', function () {\n      const new_type = this.get('type');\n      let idx = 0;\n      for (const target of this.targets) {\n        const data = target.base_data;\n        const new_data_groups = {};\n        const allgroupedDimValues = new Set();\n        let groupedDim = '';\n        let infoDims = {};\n        if (new_type === 'box') {\n          const groupColumns = Object.keys(data[0]?.dimensions) || [];\n          infoDims = data[0]?.infoDims || {};\n          let groupByValue = data[0]?.groupByValue;\n          const dimsName = {};\n          data.forEach(entry => {\n            Object.values(entry.dimensions).forEach((values) => {\n              if (values.length >= 2 && !Object.prototype.hasOwnProperty.call(dimsName, values[0])) {\n                dimsName[values[0]] = values[1];\n              }\n            });\n          });\n          const uniqueValues = groupColumns.reduce((acc, col) => {\n            acc[col] = new Set(data.map(item => item.dimensions[col][0])).size;\n            return acc;\n          }, {});\n          const columnsWithMultipleValues = groupColumns.filter(col => uniqueValues[col] > 1);\n          if (columnsWithMultipleValues.includes(groupByValue)) {\n            // Si está presente, moverlo al principio del array\n            const index = columnsWithMultipleValues.indexOf(groupByValue);\n            const valueToMove = columnsWithMultipleValues.splice(index, 1)[0];\n            columnsWithMultipleValues.unshift(valueToMove);\n          }\n          for (let i = 0; i < data.length; i++) {\n            const orig_serie = data[i];\n            const dims = Object.fromEntries(\n              Object.entries(orig_serie.dimensions).map(([k, vv]) => [k, vv[0]])\n            );\n            let dimsLabel = {};\n            // dimensiones únicas\n            const columnControl = [];\n            for (const uniqueColumn of groupColumns.filter(\n              col => uniqueValues[col] < 2)) {\n              let name = dimsName[dims[uniqueColumn]];\n              dimsLabel[infoDims[uniqueColumn]] = name;\n              columnControl.push(uniqueColumn);\n            }\n            // las multiplevalues las combinamos todas menos la última\n            for (let i = 0; i < columnsWithMultipleValues.length - 1; i++) {\n              const multiColumn = columnsWithMultipleValues[i]\n              let name = dimsName[dims[multiColumn]];\n              dimsLabel[infoDims[multiColumn]] = name;\n              columnControl.push(multiColumn)\n            }\n            let groupLabel = Object.entries(dimsLabel)\n              .map(([k, v]) => `${k}=${v}`)\n              .join(\" | \");\n            groupedDim = groupColumns.filter(key => !columnControl.includes(key));\n            allgroupedDimValues.add(dimsName[dims[groupedDim]]);\n            if (!(groupLabel in new_data_groups)) {\n              new_data_groups[groupLabel] = {\n                x: [],\n                y: [],\n                dims: dimsLabel,\n                name: orig_serie.layer_name,\n                type: 'box',\n                boxmean: 'true',\n                line: { color: getColor(idx++), width: 1.5 }\n              };\n            }\n            const serie = new_data_groups[groupLabel];\n            for (let j = 0; j < orig_serie.x.length; j++) {\n              serie.x.push(orig_serie.x[j]); // Fecha en el eje X\n              serie.y.push(orig_serie.y[j]); // Valores en el eje Y\n            }\n          }\n        }\n\n        const new_values = Object.values(new_data_groups);\n        const groupedString = Array.from(allgroupedDimValues).join(\", \");\n        if (groupedString.length > 0) {\n          for (const newValue of new_values) {\n            let dimsnewValue = newValue.dims;\n            dimsnewValue[infoDims[groupedDim]] = groupedString;\n            newValue.name = `${newValue.name} | ${Object.entries(dimsnewValue)\n              .map(([k, v]) => `${k}: ${v}`)\n              .join(\" | \")}`;\n          }\n        }\n        const delenda = [];\n        for (let idx = 0; idx < target.data.length; idx++)\n          delenda.push(idx)\n        Plotly.deleteTraces(target, delenda);\n        if (new_type == 'box') {\n          target.old_layout = target.layout;\n          target.layout = {\n            xaxis: target.old_layout.xaxis,\n            yaxis: target.old_layout.yaxis,\n            //hovermode: target.old_layout.hovermode,\n            hoverlabel: {\n              namelength: 999\n            },\n            legend: target.old_layout.legend,\n            hovermode: 'x unified',\n            font: target.old_layout.font,\n            margin: target.old_layout.margin,\n            showlegend: target.old_layout.showlegend,\n          }\n        } else {\n          target.layout = target.old_layout;\n        }\n        if (new_values.length > 1) {\n          target.layout.boxmode = \"group\"\n          for (let idx = 0; idx < new_values.length; idx++) {\n            new_values[idx].offsetgroup = `group${idx}`;\n            new_values[idx].hoverinfo = 'y';\n          }\n        }\n        if (new_values.length) {\n          Plotly.addTraces(target, new_values);\n        } else {\n          Plotly.addTraces(target, target.base_data);\n        }\n      }\n    })\n  }\n  get threshold() {\n    return $(this.element).find('#threshold input').val();\n  }\n  set threshold(value) {\n    $(this.element).find('#threshold input').val(value);\n  }\n  purge() {\n    for (const target of this.targets) {\n      this.observer.unobserve(target);\n      Plotly.purge(target);\n    }\n    this.target.remove();\n  }\n  async redraw(evt) {\n    this.targets = [];\n    this.set('state', 'busy');\n    if (evt) {\n      this.poi = {\n        centroid: evt.coordinate,\n        same_srid: true,\n      };\n      this.analyers = evt.analyers;\n      const pixelSize = evt.frameState?.pixelToCoordinateTransform[0];\n      if (pixelSize)\n        this.poi.radius = pixelSize * 3;\n    }\n    $(this.element).find('#threshold').toggleClass('hidden', !this.analyers);\n    const point = this.poi && this.poi.same_srid ? this.poi.centroid : transform_point(this.poi.centroid);\n    const mapa = this.getMap();\n    const view = mapa.getView();\n    let con_pluma = false;\n    const map_dimensions = mapa.get('dimension_controls') || {};\n    if (Object.values(map_dimensions).some(x => x.options.length)) {\n      if (!this.get('activeDimensions')) {\n        this.set('activeDimensions', {}, true);\n        const newActiveDimensions = {}\n        Object.values(map_dimensions).map(dc => {\n          if (dc.id) {\n            newActiveDimensions[dc.id] = [];\n            const dim_values = getParameterByName(dc.id);\n            if (dim_values) {\n              for (const dval of dim_values.split(',')) {\n                const option = dc.options.find(o => o[0] == dval);\n                if (option)\n                  newActiveDimensions[dc.id].push(option);\n              }\n            }\n            else\n              newActiveDimensions[dc.id] = [[dc.value, dc.caption]]\n          }\n        });\n        this.set('activeDimensions', newActiveDimensions);\n      } else {\n        const activeDimensions = this.get('activeDimensions');\n        this.unset('activeDimensions', activeDimensions);\n        this.set('activeDimensions', activeDimensions);\n      }\n    }\n    if (!mapa.getTarget()) {\n      mapa.setSize([100, 100]);\n      view.setResolution(1000);\n      view.setCenter(point);\n    }\n    mapa.set('elements', this.elements);\n    let [layers, urls, data_plumas_mapping, dimDataByLayer] = this.getQueryLayers(\n      evt ? evt.coordinate : point,\n      this.get('activeDimensions'));\n    for (const lyr of layers){\n      for (const dim of lyr._layer.source_type.dimensions){\n        if (dim.locator in map_dimensions){\n          con_pluma = true;\n          break;\n        }\n      }\n    }\n    this.set('con_pluma', con_pluma);\n    this.layers_loc = layers.map(x => x._pageLayer.id).join(',');\n    this.layers = layers;\n    this.dimDataByLayer = dimDataByLayer;\n    const urls_plumas = []\n    const group_dims = !$.isEmptyObject(this.get('activeDimensions'));\n    const tabs = $('#tabs-Graph').clone();\n    tabs.removeClass('hidden');\n    if (this.print_pluma) {\n      this.target.empty();\n      this.target.append(tabs);\n      let layers_by_graphs = []\n      for (const layer of layers.values()) {\n        const src = layer?.source;\n        let this_url = urls.splice(1, 1)[0];\n        if (src) {\n          const dim_mapping = {};\n          for (const [i, v] of Object.entries(map_dimensions)) {\n            if (i.includes('HOR'))\n              continue;\n            if (src && i in src.getParams())\n              dim_mapping[i] = v.options;\n          }\n          getCombinatedDims(dim_mapping, tabs, map_dimensions, this_url, data_plumas_mapping, urls_plumas, layers_by_graphs, layer);\n        }\n        else {\n          urls_plumas.push(this_url);\n          layers_by_graphs.push(layer);\n        }\n      }\n      urls.push(...urls_plumas);\n      layers = layers_by_graphs;\n    }\n    let numUrls = urls.length;\n    if (numUrls > 1)\n      this.getMap().set('notification', window.gettext('Quedan %s consultas...').replace(/[%]s/, numUrls));\n    const calls = urls.map(async url => {\n      const response = await fetch(url);\n      if (--numUrls > 1)\n        this.getMap().set('notification', window.gettext('Quedan %s consultas...').replace(/[%]s/, numUrls));\n      return await response.json();\n    });\n    this.graphs = await Promise.allSettled(calls).then(\n      jsons => {\n        if (this.getMap() == null)\n          return;\n        this.getMap().set('notification', null);\n        this.jsons = jsons;\n        this.loadGraphs(jsons, layers, data_plumas_mapping, group_dims, tabs)\n      })\n    this.observer = new ResizeObserver(entries => {\n      for (const entry of entries) {\n        const style = getComputedStyle(entry.target);\n\n        const paddingLeft = parseFloat(style.paddingLeft);\n        const paddingRight = parseFloat(style.paddingRight);\n        const paddingTop = parseFloat(style.paddingTop);\n        const paddingBottom = parseFloat(style.paddingBottom);\n        const width = entry.target.clientWidth - paddingLeft - paddingRight;\n        const origHeight = entry.target.layout?.height;\n        const height = origHeight || entry.target.clientHeight - paddingTop - paddingBottom;\n        const newLayout = {\n          width: width,\n          height: height || undefined,\n        }\n        Plotly.relayout(entry.target, newLayout);\n        entry.target.layout.height = origHeight;\n        const infolayer = $(entry.target).find('g.infolayer');\n        // Leyendas transparentes\n        infolayer.attr('pointer-events', 'none');\n        infolayer.find('[pointer-events]').attr('pointer-events', 'none');\n      }\n    });\n    for (const target of this.targets)\n      this.observer.observe(target);\n    if (this.get('type')) {\n      this.unset('type', true);\n      this.set('type', 'box');\n    }\n    if (this.targets.length || this.info_tabla.find('tr').length)\n      this.set('state', 'ok');\n  }\n  getQueryLayers(coordinate, dimensionValues) {\n    const mapa = this.getMap();\n    const poi = this.poi;\n    const layers = this.analyers ?\n      this.analyers\n      : mapa.get('layerObjects');\n    if (this.analyers)\n      this.group_by_unit = true;\n    const elements = mapa.get('elements');\n    const map_dimensions = mapa.get('dimension_controls') || {};\n    const view = mapa.getView();\n    const viewResolution = view.getResolution();\n    const viewProjection = view.getProjection();\n    const graph_layers = [];\n    const dimDataByLayer = []\n    const data_plumas_mapping = [];\n    const urls = [window.Urls.info_punto_json(window.epsg.split(':')[1], ...coordinate, window.coordinates_epsg.split(':')[1], 'None')];\n    for (const layerObj of layers) {\n      const layer = layerObj._ol_layer;\n      if (!('mdt' in layerObj._extra && layerObj._extra['mdt'])) {\n        if (!this.analyers && !layer.getVisible())\n          continue;\n        if (!layer.get('time_management') && layer.get('title') != 'elementsLayerGroup') {\n          if (!layerObj._extra)\n            continue;\n          if (layerObj._extra.queryable !== true) {\n            continue;\n          }\n        }\n      }\n      const layerDimensions = layerObj._layer.source_type ? layerObj._layer.source_type.dimensions.map(x => x.locator) : [];\n      const layerDimensionValues = {};\n      if (dimensionValues)\n        for (const [k, v] of Object.entries(dimensionValues))\n          if (layerDimensions.includes(k))\n            layerDimensionValues[k] = v;\n      const combinations = !$.isEmptyObject(layerDimensionValues) ? cartesian(layerDimensionValues) : [{}];\n      if (layer.get('title') == 'elementsLayerGroup') {\n        for (const elem of elements) {\n          urls.push(window.Urls.element_info(elem))\n          graph_layers.push(layerObj);\n        }\n        continue;\n      }\n      if (layerObj._extra &&\n        layerObj._extra.queryable === false)\n        continue;\n      if ('mdt' in layerObj._extra) {\n        urls.shift()\n        urls.unshift(window.Urls.info_punto_json(window.epsg.split(':')[1], ...coordinate, window.coordinates_epsg.split(':')[1], layerObj._pageLayer.id))\n        continue;\n      }\n      layer.set('addFolderName', false);\n      if (graph_layers.some(graph_layer => graph_layer._ol_layer.get('title') == layer.get('title')))\n        layer.set('addFolderName', true);\n      const params = getTimeParams(layer);\n      if (this.analyers)\n        params.HORIZON = undefined;\n      if (poi && poi.type == 'element')\n        params.element = poi.id;\n      const src = layer.getSource();\n      const infoDims = {};\n      for (const combination of combinations) {\n        dimDataByLayer.push(combination);\n        const title_dims = [];\n        let dims_names = '';\n        const saved_params = { ...src.getParams() };\n        for (const [k, vv] of Object.entries(combination)) {\n          const dim_name = map_dimensions[k]?.name\n          src.updateParams({ [k]: vv[0] });\n          dims_names += ` | ${dim_name}: ${vv[1]}`;\n          // title_dims.push(`${}: ${vv[1]}`);\n          title_dims.push(`${vv[1]}`);\n          infoDims[k] = dim_name;\n        }\n        data_plumas_mapping.push({\n          title_dims: title_dims.join(' / '),\n          dimensions: combination,\n          infoDims,\n          dims_names\n        })\n        urls.push(\n          src.getFeatureInfoUrl(coordinate, viewResolution, viewProjection, {\n            INFO_FORMAT: 'application/json',\n            TOLERANCE: 3,\n            ...params\n          })\n        );\n        graph_layers.push(layerObj);\n        src.updateParams(saved_params);\n      }\n    }\n    return [graph_layers, urls, data_plumas_mapping, dimDataByLayer];\n  }\n  showDimSelector() {\n    const dimsDialogExistente = $('#dims-dialog');\n    const dimControls = this.getMap().get('dimension_controls');\n    if (dimsDialogExistente.length === 0) {\n      const self = this;\n      const captions = {};\n      const dialog = $(`<div id=\"dims-dialog\"></div>`)\n        .appendTo(this.target)\n        .dialog({\n          title: window.gettext('Seleccione dimensiones'),\n          autoOpen: false,\n          width: 'auto',\n          buttons: [{\n            text: window.gettext('Aceptar'), click: function () {\n              const newActiveDimensions = {};\n              $(this).find('.multi.flex:visible').each((idx, divSel) => {\n                const $divSel = $(divSel);\n                const sel = $divSel.find('select');\n                const val = sel.val();\n                const id = sel.attr('id').split(' ')[1];\n                if (val.length == 0)\n                  $divSel.fadeOut().fadeIn();\n                newActiveDimensions[id] = val.map(v => [v, captions[id][v]]);\n              });\n              const groupByValue = $('#sortSelect').val();\n              if (Object.values(newActiveDimensions).some(x => x.length == 0))\n                return;\n              if (self.isDialog) {\n                const keepType = self.get('type');\n                self.target.dialog('close');\n                self.set('type', keepType);\n              }\n              self.set('groupByValue', groupByValue);\n              self.set('activeDimensions', newActiveDimensions);\n              self.redraw();\n              dialog.dialog('close');\n            }\n          }]\n        });\n      for (const ctl of Object.values(dimControls)) {\n        if (!ctl.id)\n          continue\n        captions[ctl.id] = {};\n        const div = $(`<div class=\"multi flex\"></div>`).appendTo(dialog);\n        $(`<h4>${ctl.name}</h4>`).appendTo(div)\n        const sel = $(`<select id=\"dimensionSel ${ctl.id}\" multiple=\"multiple\"></select>`).appendTo(div);\n        for (const [value, name] of ctl.options) {\n          sel.append($(`<option value=\"${value}\">${name}</option>`))\n          captions[ctl.id][value] = name;\n        }\n        sel.multiSelect(multiselectOptions());\n      }\n    }\n    for (const [k, vv] of Object.entries(this.get('activeDimensions'))) {\n      const sel = $(`select[id=\"dimensionSel ${k}\"]`);\n      sel.multiSelect('deselect_all');\n      sel.multiSelect('select', vv.map(v => '' + v[0]));\n    }\n    for (const ctl of Object.values(dimControls)) {\n      $(`select[id=\"dimensionSel ${ctl.id}\"]`).closest('div').toggle(ctl.usage > 0);\n    }\n    const dimsDialog = $('#dims-dialog');\n    if ($('#sortSelectContainer').length === 0) {\n      const selectHTML = `\n        <div id=\"sortSelectContainer\" class=\"dim-control\">\n          <label for=\"sortSelect\">${window.gettext('Agrupar por')}:</label>\n          <select id=\"sortSelect\" class=\"custom-select\">\n            ${Object.values(dimControls)\n          .filter(ctl => ctl.usage > 0)\n          .map(ctl => `<option value=\"${ctl.id}\">${ctl.name}</option>`)\n          .join('')}\n          </select>\n        </div>\n      `;\n      dimsDialog.prepend(selectHTML);\n    }\n    dimsDialog.dialog('open');\n  }\n  loadGraphs(jsons, layers, data_plumas_mapping, group_dims, tabs) {\n    let tzFunction = 'local';\n    const info = jsons[0].value;\n    let title = this.poi.name;\n    if (!title) {\n      title = info.success ? info.name + ' ' : '';\n      title += '(' + this.coordXY(info.pt) + ')';\n      if ('mdt' in info) {\n        title += ` ${info.mdt.title}: ${info.mdt.value}`;\n        this.mdt = info.mdt.id_mdt;\n      }\n    }\n    this.title = title;\n    jsons.shift();\n    this.target.find('h3').remove();\n    this.target.find('h5').remove();\n    this.target.find('h6').remove();\n    this.target.find('div.graph').addClass('delenda');\n    this.target.find('div.info_tabla').empty();\n    const all_data = [];\n    const subplots = [];\n    const yaxises = {};\n    const unit_mapping = {};\n    const order_mapping = {};\n    const var_mapping = {};\n    let can_be_grouped = false;\n    this.set('can_export2Excel', jsons.length > 0);\n    let y_idx = this.group_by_unit || this.print_pluma || group_dims ? -1 : 0;\n    for (const [idx, json] of jsons.entries()) {\n      if (json.status == 'rejected')\n        continue\n      const lyr = layers[idx];\n      [y_idx, can_be_grouped] = this.carga_serie(lyr, all_data, subplots, yaxises, json, data_plumas_mapping, idx, group_dims, can_be_grouped, tzFunction, unit_mapping, var_mapping, order_mapping, y_idx, tabs);\n    }\n    for (const idx of [1, 2, 3])\n      this.target.removeClass(`subplots_${idx}`)\n    for (const idx of [1, 2, 3])\n      this.target.removeClass(`subplots_info_${idx}`)\n    this.target.addClass(`subplots_info_${this.info_tabla.find('tr').length}`);\n    this.target.addClass(`subplots_${y_idx + 1}`);\n    if (this.isDialog) {\n      this.target.dialog('option', 'title', this.title);\n    }\n    else {\n      const jqTitle = $(`<h3>${this.title}</h3>`);\n      this.target.append(jqTitle);\n    }\n    this.set('can_be_grouped', can_be_grouped);\n    for (const subplot of new Set(subplots)) {\n      const data = all_data.filter(d => 'x' + d.yaxis == subplot);\n      for (const datum of data)\n        if ('serie' in datum)\n          for (const [k, v] of Object.entries(datum.serie))\n            datum[k] = v;\n      const jqTarget = $('<div class=\"graph\"></div>');\n      const target = jqTarget[0];\n      this.targets.push(target);\n      const titles = {};\n      if (this.analyers) {\n        const legend = data[0].fixed_times[0] + data[0].legend_title;\n        const new_data = data.map(d => [d.layer_name, d.y[0], d.short_name]);\n        new_data.sort((d1, d2) => d2[1] - d1[1]);\n        new_data.splice(0, new_data.length, ...new_data.filter(d => d[1] >= parseFloat(this.threshold)));\n        if (new_data.length === 0) {\n          return;\n        }\n        data.splice(0);\n        data.push({\n          x: new_data.map(x => x[2]),\n          y: new_data.map(x => x[1]),\n          hovertext: new_data.map(x => x[0]),\n          hoverinfo: 'text+y',\n          fixed_times: [],\n          layout: {\n            xaxis: {\n              type: 'category',\n              automargin: true,\n            },\n            yaxis: {\n              range: [0, 100],\n            }\n          },\n          name: legend,\n          type: 'bar'\n        })\n        this.target.append(jqTarget);\n      } else if (this.print_pluma) {\n        // if (data[0]?.dim_name != data[0]?.dim_title) {\n        const target_tab = tabs.find(`#tabs_Graph-${data[0]?.dim_id}`);\n        if (!target_tab.find(`h4#${data[0]?.layer_loc}`).length)\n          target_tab.append(`<h4 id=\"${data[0]?.layer_loc}\">${data[0]?.layer_name}</h4>`);\n        if (data[0]?.obj_name && !target_tab.find(`h4#object_${data[0]?.obj_count}`).length)\n          target_tab.append(`<h4 id=\"object_${data[0]?.obj_count}\">${data[0]?.obj_name}</h4>`);\n        if (data[0]?.dim_title_opt != data[0]?.name) {\n          target_tab.append(`<h5>${data[0]?.dim_title}: ${data[0]?.dim_title_opt}</h5>`);\n          target_tab.append(`<h6>${data[0]?.dim_name}</h6>`);\n        }\n        target_tab.append(jqTarget);\n        // }\n      } else {\n        let idx = 0;\n        for (const v of data) {\n          if (group_dims && v.name != v.layer_name) {\n            v.legendgroup = v.layer_name;\n            v.hovertemplate = `${v.name} %{customdata:.2f}`;\n            if (!titles[v.layer_name]) {\n              titles[v.layer_name] = {};\n            } else {\n              if (v?.marker?.color) {\n                v.marker = {};\n                v.marker.color = getColor(idx++);\n              }\n            }\n            v.name = `${v.layer_name} ${v.legend_title}`;\n          }\n          if (v.dynDate)\n            v.name += ` <br>⏲ ${v.dynDate.utc().format('DD-MM-YYYY HH')}h UTC`;\n        }\n        this.target.append(jqTarget);\n      }\n      tabs.tabs();\n      data[0].layout = data[0].layout || {};\n      if (Object.keys(titles).length) {\n        data[0].layout.margin = {\n          l: 50,\n          r: 0,\n          b: 50,\n          t: 55,\n          pad: 4\n        };\n        data[0].layout.xlegend = {\n          title: {\n            text: data[0].legend_title,\n            font: { family: \"'Alegreya Sans', Arial, sans-serif\", size: 12 },\n          },\n          xanchor: 'left',\n          x: 0,\n          yanchor: 'bottom',\n          y: 1,\n          orientation: \"h\",\n          bgcolor: 'rgba(255,255,255,.5)',\n        };\n      }\n      this.create_graph(target, data, tzFunction, yaxises[subplot]);\n    }\n    this.target.find('div.graph.delenda').remove();\n    if (this.analyers) {\n      return;\n    }\n    if (this.targets.length) {\n      const target = this.targets[0];\n      window.setTimeout(() => target.dispatchEvent(new Event('mouseleave')), 200);\n      if (this.targets.length > 1) {\n        let [mrange0, mrange1] = target.layout.xaxis.range;\n        for (const target of this.targets) {\n          const [range0, range1] = target.layout.xaxis.range;\n          if (range0 < mrange0)\n            mrange0 = range0\n          if (range1 > mrange1)\n            mrange1 = range1\n        }\n        const range = {\n          \"xaxis.range[0]\": mrange0,\n          \"xaxis.range[1]\": mrange1,\n        }\n        target.emit('plotly_relayout', range);\n      }\n    }\n  }\n  carga_serie(lyr, all_data, subplots, yaxises, json, data_plumas_mapping, idx, group_dims, can_be_grouped, tzFunction, unit_mapping, var_mapping, order_mapping, y_idx, tabs) {\n    const { listOfDates, listOfValues, listOfTable, listOfFixed_times, listOfDimMapping } = (json.value?.features) ? layerdataFromJson(json.value, lyr) : elementdataFromJson(json.value, this.getMap(), lyr, tabs);\n    let count_obj = -1;\n    for (const [name_obj, arrayOfValues] of Object.entries(listOfValues)) {\n      const arrayOfDates = listOfDates[name_obj];\n      const arrayOfTable = listOfTable[name_obj];\n      const arrayOfFixed_times = listOfFixed_times[name_obj];\n      const arrayOfDimMapping = listOfDimMapping[name_obj];\n      ++count_obj;\n      for (const [i_serie, values] of arrayOfValues.entries()) {\n        const dates = arrayOfDates[i_serie];\n        const table = arrayOfTable[i_serie] || [];\n        const fixed_times = arrayOfFixed_times[i_serie] || [];\n        const extra = lyr._extra;\n        const unit = lyr._layer.effective_unit;\n        const order = lyr.order || lyr._pageLayer.order;\n        let data_pluma = data_plumas_mapping[idx] || [];\n        if (arrayOfDimMapping.length) {\n          idx = i_serie;\n          data_pluma = arrayOfDimMapping[idx];\n        }\n        if (this.group_by_unit) {\n          if (unit in unit_mapping) {\n            y_idx = unit_mapping[unit];\n            can_be_grouped = true;\n          } else {\n            y_idx++;\n            unit_mapping[unit] = y_idx;\n          }\n        } else if (extra.with) {\n          y_idx = order_mapping[extra.with];\n        } else if (group_dims) {\n          const v = data_pluma?.title_opt == data_pluma?.name_opt ?\n            lyr._layer.id + '-' + data_pluma?.id + '-' + String(count_obj) :\n            lyr._layer.id + '-' + data_pluma?.title_opt + '-' + String(count_obj);\n          if (v in var_mapping) {\n            y_idx = var_mapping[v];\n          } else {\n            var_mapping[v] = ++y_idx;\n          }\n        } else {\n          y_idx = idx;\n        }\n        order_mapping[order] = y_idx;\n        if (unit in unit_mapping)\n          can_be_grouped = true;\n        else\n          unit_mapping[unit] = true;\n        if (!$.isEmptyObject(table)) {\n          let columns = extra.info;\n          let label_columns = extra.columns;\n          const table_info = extra.table_info;\n          const nexttotitle = extra.nexttotitle;\n          if (typeof columns === 'string')\n            columns = [columns];\n          if (Array.isArray(columns)) {\n            const columnsObject = {};\n            for (const [i, k] of columns.entries())\n              if (typeof k === 'string')\n                columnsObject[' '.repeat(i)] = `<%= ${k} %>`;\n              else\n                mergeDeep(columnsObject, k);\n            columns = columnsObject;\n          }\n          const tr_title = $(`<tr><td class=\"negrita-main-color\">${lyr._layer.name_and_unit}:</td></tr>`)\n          this.info_tabla.append(tr_title);\n          if (table_info) {\n            const table_info_element = $('<table><thead><tr></tr></thead><tbody></tbody></table>');\n            for (const [it, t] of Object.entries(table)) {\n              const row = $('<tr></tr>');\n              if (label_columns) {\n                const colspan = label_columns.length || 0;\n                for (const col of Object.values(label_columns)) {\n                  if (it == \"0\")\n                    table_info_element.find('thead tr').append(\n                      $(`<th colspan=${colspan} class=\"negrita-main-color\">${col.alias}</th>`)\n                    )\n                  row.append($(`<td colspan=${colspan}>${t[col.id] || '---'}</td>`))\n                }\n                table_info_element.find('tbody').append(row);\n              }\n              else {\n                if (columns) {\n                  const colspan = Object.entries(columns).length || 0;\n                  for (const templateIn of Object.values(columns)) {\n                    const _template = template(templateIn);\n                    let content;\n                    try {\n                      content = _template(t);\n                    } catch {\n                      content = null;\n                    }\n                    row.append($(`<td colspan=${colspan}>${content || '---'}</td>`))\n                  }\n                  table_info_element.find('tbody').append(row);\n                }\n                else {\n                  for (const [k, vvv] of Object.entries(t)) {\n                    if (vvv !== null && vvv !== '')\n                      this.info_tabla.append($(`<tr><td>${k}</td><td>${vvv != null ? vvv : 'n/a'}</td></tr>`));\n                  }\n                }\n              }\n            }\n            this.info_tabla.append(table_info_element);\n          }\n          else\n            for (const [it, t] of Object.entries(table)) {\n              if (columns) {\n                let row = tr_title;\n                if (!nexttotitle) {\n                  row = $('<tr></tr>')\n                  this.info_tabla.append(row);\n                }\n\n                for (const [title, templateIn] of Object.entries(columns)) {\n                  const _template = template(templateIn);\n                  try {\n                    title ? row.append($(`<td>${title}</td><td>${_template(t)}</td>`))\n                      : row.append($(`<td>${_template(t)}</td>`));\n                  }\n                  catch {\n                    row.append($(`<td>${title}</td><td>---</td>`));\n                  }\n                }\n                if (nexttotitle && table.length != Number(it) + 1)\n                  row.append(', ');\n              }\n              else\n                for (const [k, vvv] of Object.entries(t)) {\n                  if (vvv !== null && vvv !== '')\n                    this.info_tabla.append($(`<tr><td>${k}</td><td>${vvv != null ? vvv : 'n/a'}</td></tr>`));\n                }\n            }\n        }\n        if ($.isEmptyObject(dates))\n          continue;\n        if (fixed_times.length > 0 || window.time_type?.locator == '1D')\n          tzFunction = 'utc';\n        const text = extra.text;\n        const y = text ? values.map(() => 1) : values;\n        let name = lyr._pageLayer.folder ?\n          lyr._pageLayer.folder + ' - ' + lyr._title :\n          lyr._title;\n        const data = {\n          x: dates,\n          y: y.length ? y : [0],\n          line: { color: getColor(idx), width: 1.5 },\n          customdata: values.length ? values : [NaN],\n          name: data_pluma?.title_opt ? data_pluma?.name_opt || data_pluma?.title_opt : data_pluma?.title_dims ? data_pluma?.title_dims : name,\n          layer_name: data_pluma?.element_name ? data_pluma?.element_name : name,\n          legend_title: data_pluma.dims_names,\n          obj_name: name_obj,\n          obj_count: count_obj,\n          layer_loc: lyr._layer?.source_type?.locator || lyr._layer.servicelayer,\n          yaxis: `y${y_idx == 0 ? '' : y_idx + 1}`,\n          hovertemplate: '%{customdata:.2f}',\n          hoverinfo: 'x+y',\n          hoverlabel: {\n            namelength: 0,\n          },\n          dim_name: data_pluma?.name,\n          dim_title: data_pluma?.title,\n          dim_title_opt: data_pluma?.title_opt,\n          dim_id: data_pluma?.id,\n          dimensions: data_pluma?.dimensions,\n          infoDims: data_pluma?.infoDims,\n          groupByValue: this.get('groupByValue'),\n          fixed_times,\n          ...extra\n        };\n        if (this.getMap().get('graph_show_run_time'))\n          data.dynDate = lyr._dynDate;\n        if (extra?.marker?.color)\n          data.line.color = extra.marker.color\n        all_data.push(data);\n        subplots.push(`x${data.yaxis}`)\n        yaxises[`xy${y_idx == 0 ? '' : y_idx + 1}`] = text ? {\n          zeroline: false, showgrid: false, showline: false,\n          ticks: '',\n          showticklabels: false,\n        } : {};\n      }\n    }\n    return [y_idx, can_be_grouped];\n  }\n  create_graph(target, data, tzFunction, yaxis) {\n    const self = this;\n    const layout_extra = 'layout' in data[0] ? data[0].layout : {};\n    let minx = '9999', maxx = '0000';\n    delete data[0].layout;\n    let range;\n    if (layout_extra?.xaxis?.type !== 'category') {\n      for (const datum of data) {\n        minx = minx < datum.x[0] ? minx : datum.x[0];\n        maxx = maxx > datum.x.slice(-1)[0] ? maxx : datum.x.slice(-1)[0];\n        delete datum.yaxis;\n        datum.x = datum.x.map(x => dayjs(x)[tzFunction]().format());\n      }\n      range = [minx, maxx];\n      range = range.map(x => dayjs(x))\n      const xmargin = dayjs.duration((range[1] - range[0]) / 10);\n      range[0] = range[0].subtract(xmargin);\n      range[1] = range[1].add(xmargin);\n      range = range.map(x => x[tzFunction]().format())\n    }\n    let fixed_times = [];\n    if (data[0].fixed_times.length > 0) {\n      // ordenamos los valores, y nos aseguramos que para cada x haya un valor y\n      const data_sorted = Array.from(\n        new Map(\n          data.flatMap(datum =>\n            datum.x.map((xValue, index) =>\n              [`${xValue}-${datum.fixed_times[index]}`, { x: xValue, fixed_times: datum.fixed_times[index] }]\n            )\n          )\n        ).values()\n      ).sort((a, b) => new Date(a.x) - new Date(b.x));\n\n      fixed_times = data_sorted.map(item => item.fixed_times);\n      const new_x = [];\n      const new_y = [];\n      for (const ft of fixed_times) {\n        const item = data[0].fixed_times.find(fixedTime => fixedTime === ft);\n        if (item) {\n          const index = data[0].fixed_times.indexOf(ft);\n          new_x.push(data[0].x[index]);\n          new_y.push(data[0].y[index]);\n        } else {\n          new_x.push(data_sorted.find(item => item.fixed_times === ft)?.x || null);\n          new_y.push(null);\n        }\n      }\n      data[0].fixed_times = fixed_times;\n      data[0].x = new_x;\n      data[0].y = new_y;\n    }\n    else {\n      fixed_times = data[0].fixed_times;\n    }\n    const layout = {\n      font: { family: \"'Alegreya Sans', Arial, sans-serif\", size: 12 },\n      margin: {\n        l: 50,\n        r: 0,\n        t: 30,\n        pad: 4\n      },\n      hoverlabel: {\n        bordercolor: 'transparent',\n        bgcolor: 'rgba(255,255,255,.9)',\n      },\n      legend: {\n        xanchor: 'left',\n        x: 0,\n        yanchor: 'bottom',\n        y: 1,\n        orientation: \"h\",\n        bgcolor: 'rgba(255,255,255,.5)',\n      },\n      showlegend: true,\n\n      hovermode: 'x unified',\n      xaxis: {\n        showgrid: true,\n        gridcolor: 'silver',\n        tickformat: '%Hh\\n%d-%m-%Y',\n        range,\n        automargin: true,\n      },\n      yaxis:  {\n        ...yaxis,\n        fixedrange: true // bloquea zoom y pan vertical\n      },\n      ...layout_extra\n    };\n    if (fixed_times.length > 0) {\n      layout.xaxis = {\n        ...layout.xaxis,\n        ticktext: fixed_times,\n        tickmode: \"array\",\n        tickvals: data[0].x,\n        type: 'category',\n      }\n    } else if (window.time_type?.locator == '1MO') {\n      layout.xaxis.tickformat = '%B\\n%Y';\n      layout.xaxis.tickvals = data[0].x;\n    } else if (window.time_type?.locator == '1D') {\n      layout.xaxis.tickformat = '%a %d\\n%m-%Y';\n    } else if (['1H', '1D_1H', 'TIME'].includes(\n      window.time_type?.locator) &&\n      // (diez)minutales\n      !data[0].x.every(x => x.match(/00:00[+-]/))) {\n      layout.xaxis.tickformat = '%H:%M\\n%d-%m-%Y';\n    }\n    if (window.innerWidth < 700 - 100)\n      layout.width = window.innerWidth - 100;\n    Plotly.newPlot(target, data, layout, {\n      locale: locale,\n      displayModeBar: false,\n    }).then(function (g) {\n      for (const trace of g.data) {\n        if (trace.text && !self.analyers) {// Hay que rotar las etiquetas esta dirección\n          const flechas = $(g).find('svg g.textpoint text')\n          for (let i = 0; i < trace.customdata.length; i++) {\n            const angle = trace.customdata[i];\n            const flecha = flechas[i];\n            flecha.setAttribute(\"style\",\n              flecha.getAttribute(\"style\") +\n              `transform:rotate(${angle}deg);\n                 transform-box:fill-box;\n                 transform-origin:center;`);\n          }\n        }\n      }\n    });\n    target.on('plotly_legendclick', () => false);\n    target.base_data = [...data];\n    if (fixed_times.length == 0 && !this.analyers)\n      target.addEventListener('mouseleave', () => {\n        let currentTime = dayjs(window.timelinectl.timeline.getCustomTime('current'))[tzFunction]();\n        for (const other_target of this.targets) {\n          for (let numSeries = 0; numSeries < other_target.data.length; numSeries++) {\n            const xx = other_target.data[numSeries].x;\n            if (xx.length === 0)\n              continue\n            for (const [ix, xxx] of Object.entries(xx)) {\n              const m_xxx = dayjs(xxx);\n              if (m_xxx.isAfter(currentTime)) {\n                if (ix == 0) break;\n                currentTime = dayjs(xx[ix - 1])[tzFunction]();\n                break;\n              }\n            }\n            const layout = other_target.layout;\n            const range = layout.xaxis.range.map(x => dayjs(x));\n            const dx = (currentTime - range[0]) / (range[1] - range[0]);\n            const xpx = (layout.width - layout.margin.l - layout.margin.r) * dx;\n            Plotly.Fx.hover(other_target, { xpx }, undefined, true);\n            break;\n          }\n        }\n      });\n\n    target.on('plotly_hover', eventdata => {\n      if (self.analyers)\n        return;\n      for (const other_target of this.targets) {\n        if (target != other_target)\n          Plotly.Fx.hover(other_target, eventdata.event, undefined, true);\n      }\n    });\n    target.on(\"plotly_relayout\", ed => {\n      if (!('xaxis.range[0]' in ed || 'xaxis.range[1]' in ed))\n        return;\n      this.targets.forEach(div => {\n        const x = div.layout.xaxis;\n        if (x.range[0] != ed[\"xaxis.range[0]\"] || x.range[1] != ed[\"xaxis.range[1]\"])\n          Plotly.relayout(div, ed);\n      });\n    });\n  }\n  async toExcel(zip) {\n    const headers_dimensions = [];\n    const data_rows = [];\n    for (const [idx, json] of this.jsons.entries()) {\n      if (json.status == 'rejected')\n        continue\n      const lyr = this.layers[idx];\n      const layer = lyr._layer;\n      const { listOfDates, listOfValues, listOfTable, listOfFixed_times } = layerdataFromJson(json.value, lyr);\n      const dates = listOfDates[''][0];\n      const values = listOfValues[''][0];\n      const table = listOfTable[''][0];\n      const fixed_times = listOfFixed_times[''][0];\n      const dimensions = layer?.source_type && layer?.source_type?._dimension_controls;\n      if (dimensions)\n        for (const [k, dim] of Object.entries(dimensions)) {\n          if (headers_dimensions.some((h) => h.key == dim.id) || k.includes('HOR'))\n            continue;\n          headers_dimensions.push({ header: dim.name, key: dim.id, width: 15 })\n        }\n      const layerActualDims = layer?.source_type?.dimensions.map(d => d.locator);\n      for (let [i_value, value] of values.entries()) {\n        let full_name = layer?.name_and_unit;\n        const json_dimensions = {};\n        if (dimensions) {\n          const dimData = this.dimDataByLayer[idx];\n          for (const [k, dim] of Object.entries(dimensions)) {\n            if (k.includes('HOR'))\n              continue;\n            if (!layerActualDims.includes(k))\n              continue;\n            json_dimensions[dim.id] = dimData[k][1] || dim.value;\n          }\n          full_name += ' ' + Object.values(json_dimensions).map(x => x).join('/');\n        }\n        const effective_time = fixed_times.length ? fixed_times[i_value] : dayjs(dates[i_value])\n        const unit = layer?.locator_unit ? layer.locator_unit : layer?.effective_unit;\n        if (value != null)\n          value = parseFloat(value.toFixed(2));\n        data_rows.push({ 'name': full_name, 'var': lyr?._serviceLayer, 'u': unit, ...json_dimensions, 'hor': fixed_times.length ? effective_time : new Date(effective_time.utcOffset(0, true).toDate()), 'val': value });\n      }\n      for (const row of table.values()) {\n        let name = layer?._title;\n        let effective_time, val;\n        for (const [col, value] of Object.entries(row)) {\n          if (col == 'datetime') {\n            let dt = value.replaceAll(',', '');\n            if (!dt.includes('Z')) dt = dt.concat('Z');\n            effective_time = dayjs(dt, 'DD-M-YYYY HH:mm:ss');\n            effective_time.$x ??= {};\n          }\n          if (col == 'name') name = (value == '-') ? name : value;\n          if (col == 'value') val = value;\n        }\n        const unit = layer?.locator_unit ? layer.locator_unit : layer?.effective_unit;\n        data_rows.push({ 'name': name, 'var': lyr?._serviceLayer, 'u': unit, 'hor': new Date(effective_time?.utcOffset(0, true).toDate()), 'val': val });\n      }\n    }\n    const headers = [\n      { header: window.gettext('Nombre'), key: 'name', width: 15 },\n      { header: window.gettext('Variable'), key: 'var', width: 15 },\n      { header: window.gettext('Unidad'), key: 'u', width: 15 },\n      ...headers_dimensions,\n      { header: window.gettext('Horizonte'), key: 'hor', width: 25, style: { numFmt: 'DD-MM-YYYY HH:mm' } },\n      { header: window.gettext('Valor'), key: 'val', width: 15 },\n    ]\n    const wb = new Excel.Workbook();\n    const ws = wb.addWorksheet('My Sheet');\n    const fileName = this.title.replace(/\\s+/g, '');\n    ws.columns = headers;\n    ws.addRows(data_rows);\n    const buffer = await wb.xlsx.writeBuffer();\n    const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';\n    const fileExtension = '.xlsx';\n    const blob = new Blob([buffer], { type: fileType });\n    if (zip)\n      zip.file(fileName + fileExtension, blob);\n    else\n      saveAs(blob, fileName + fileExtension);\n  }\n}\n\nfunction layerdataFromJson(features, lyr) {\n  const values = [];\n  const dates = [];\n  const table = [];\n  let fixed_times = [];\n  const listOfValues = { '': [values] };\n  const listOfDates = { '': [dates] }\n  const listOfTable = { '': [table] }\n  const listOfFixed_times = { '': [fixed_times] }\n  const listOfDimMapping = { '': [] }\n  if (features.features.length == 0) return { listOfDates, listOfValues, listOfTable, listOfFixed_times, listOfDimMapping };\n  const variable = features.features[0];\n  if (features.features.length == 1 &&\n    variable.type == \"FeatureCollection\" &&\n    variable.features.length == 0)\n    return { listOfDates, listOfValues, listOfTable, listOfFixed_times, listOfDimMapping };\n  if (variable.type === 'FeatureCollection') {\n    const v = variable.features[0];\n    if (v && v.properties.data_history) {\n      const arrayFeatures = v.properties.data_history.features[0].features;\n      for (const h of arrayFeatures) {\n        const tab = {};\n        const prop = h.properties;\n        const time_prop = 'time' in prop ? prop['time'] : prop['timestamp'];\n        dates.push(time_prop);\n        values.push(h.value);\n        for (const k in prop) {\n          const vv = format(prop[k]);\n          tab[k] = vv;\n        }\n        table.push(tab);\n      }\n    } else if (!variable.has_time) {\n      for (const v of variable.features) {\n        const single_table = {}\n        if (v.properties.value === null)\n          continue\n        for (const [k, vvv] of Object.entries(v.properties)) {\n          if (vvv !== null && vvv !== '')\n            single_table[k] = format(vvv);\n        }\n        table.push(single_table);\n      }\n    } else { // gráfica de raster\n      for (const [i_v, v] of variable.features.entries()) {\n        const prop = v.properties;\n        if (i_v == 0)\n          lyr.setCalculatedDate(prop);\n        const value = prop.value;\n        if (prop.fixed_times)\n          fixed_times.push(prop.fixed_times);\n        const time_prop = 'time' in prop ? prop['time'] : prop['timestamp'];\n        values.push(value);\n        dates.push(time_prop);\n      }\n    }\n    return { listOfDates, listOfValues, listOfTable, listOfFixed_times, listOfDimMapping };\n  }\n}\n\nfunction elementdataFromJson(json, mapa, lyr, tabs) {\n  const calc_vars = Object.groupBy(json.data, function (x) {\n    if (x.dimension_values)\n      return x.type.name;\n  });\n  const name_vars = Object.groupBy(json.data, function (x) {\n    return x.type.name;\n  });\n  const map_dimensions = mapa.get('dimension_controls') || {};\n  const listOfDates = {};\n  const listOfValues = {};\n  const listOfTable = {};\n  const listOfFixed_times = {};\n  const listOfDimMapping = {};\n  for (const [type, data] of Object.entries(calc_vars)) {\n    const arrayOfDates = [];\n    const arrayOfValues = [];\n    const arrayOfTable = [];\n    const arrayOfFixed_times = [];\n    const arrayOfDimMapping = [];\n    if (!(type in name_vars))\n      continue;\n    const dim_mapping = {};\n    let horizon_dim;\n    const data_dim = Object.keys(data[0].dimension_values);\n    const horizon_name = get_horizon(data_dim);\n    for (const [i, v] of Object.entries(map_dimensions)) {\n      if (i.includes('HOR')) {\n        horizon_dim = v;\n        continue;\n      }\n      if (i in data[0].dimension_values)\n        dim_mapping[i] = v.options;\n    }\n    const ret = getCombinatedDims(dim_mapping, tabs, map_dimensions, null, [], [], [], lyr);\n    let info_dim_data = ret['data_plumas_mapping']\n    info_dim_data = Object.groupBy(info_dim_data, function (x) {\n      return x.title_opt;\n    });\n    for (const [n_opt, info_dim_series] of Object.entries(info_dim_data)) {\n      for (const info_dim_serie of info_dim_series) {\n        const id = info_dim_serie['id'];\n        let id2 = info_dim_serie['id2'];\n        if (!id2) id2 = id;\n        const ordered = Object.groupBy(data, function (x) {\n          if (x.dimension_values[id] == n_opt && x.dimension_values[id2] == info_dim_serie['name_opt'])\n            return x.dimension_values[horizon_name]\n        })\n        const { dates, values, fixed_dates } = createItems(ordered, horizon_dim.options, info_dim_serie);\n        info_dim_serie['element_name'] = json.element_type.name + ': ' + json.name;\n        if (dates.length) {\n          arrayOfDates.push(dates);\n          arrayOfValues.push(values);\n          arrayOfFixed_times.push(fixed_dates);\n          arrayOfDimMapping.push(info_dim_serie);\n        }\n      }\n    }\n    listOfDates[type] = arrayOfDates;\n    listOfValues[type] = arrayOfValues;\n    listOfTable[type] = arrayOfTable;\n    listOfFixed_times[type] = arrayOfFixed_times;\n    listOfDimMapping[type] = arrayOfDimMapping;\n  }\n  return { listOfDates, listOfValues, listOfTable, listOfFixed_times, listOfDimMapping }\n}\n\nfunction createItems(ordered_values, horizon_opt) {\n  const values = [];\n  const dates = [];\n  const fixed_dates = [];\n  for (const opt of horizon_opt) {\n    if (!(opt in ordered_values)) continue;\n    for (const data of ordered_values[opt].values()) {\n      let fixedYears = true;\n      const ef_time = opt.length == 4 ? opt + '-01-01T00:00Z' : opt;\n      if (opt.length != 4)\n        fixedYears = false;\n      if (data) {\n        values.push(data.value);\n        dates.push(dayjs(ef_time).toDate());\n        if (fixedYears)\n          fixed_dates.push(opt);\n      }\n    }\n  }\n  return { dates, values, fixed_dates };\n}\n\nfunction getCombinatedDims(dim_mapping, tabs, map_dimensions, this_url, data_plumas_mapping, urls_plumas, layers_by_graphs, layer) {\n  const combinations = cartesian(dim_mapping);\n  const dim_mapping_length = Object.keys(dim_mapping).length;\n  for (const i of Object.keys(dim_mapping)) {\n    let id_dim2;\n    id_dim2 = Object.keys(dim_mapping).filter(d => d != i);\n    if (tabs.find('li').length < dim_mapping_length) {\n      tabs.find('ul').append(`<li><a href=\"#tabs_Graph-${map_dimensions[i].id}\"></a>${map_dimensions[i].name}</li>`);\n      tabs.append($(`<div id=\"tabs_Graph-${map_dimensions[i].id}\"></div>`));\n    }\n    const grouped_combinations = Object.groupBy(combinations, (c) => {\n      return c[i];\n    });\n    for (const cbx of Object.values(grouped_combinations)) {\n      for (const dim of Object.values(cbx)) {\n        const data = { 'id': map_dimensions[i].id, 'title': map_dimensions[i].name, 'title_opt': dim[i][0], 'name': '', 'name_opt': '', }\n        if (id_dim2) data['id2'] = id_dim2[0];\n        for (const [n_op, dim_op] of Object.entries(dim)) {\n          if (this_url)\n            this_url = this_url.replace(new RegExp(`(${n_op}=)[^&]*(.*)`), '$1' + dim_op[0] + '$2');\n          if (!(dim_mapping_length > 1 && i == n_op)) {\n            data['name'] = map_dimensions[n_op].name;\n            data['name_opt'] = String(dim_op[0]);\n          }\n        }\n        urls_plumas.push(this_url);\n        data_plumas_mapping.push(data);\n        layers_by_graphs.push(layer);\n      }\n    }\n  }\n  return { data_plumas_mapping, layers_by_graphs, urls_plumas }\n}\nfunction getTimeParams(layer) {\n  const params = {};\n  const days_back = layer.get('extra').days_back;\n  const days_forward = layer.get('extra').days_forward;\n  const round_to_days = days_back || days_forward;\n  const t1_iso = layer.getSource().getParams()['TIME'];\n  const t1p = dayjs(t1_iso).utc();\n  const t1 = round_to_days ? t1p.startOf('date') : t1p;\n  if (days_back && days_forward) {\n    const t2 = t1.subtract(days_back, 'days');\n    const t3 = t1.add(days_forward, 'days');\n    params.TIME = t2.format() + '/' + t3.format();\n  } else if (days_forward) {\n    const t2 = t1;\n    const t3 = t1.add(days_forward, 'days');\n    params.TIME = t2.format() + '/' + t3.format();\n  } else if (days_back) {\n    const t2 = t1.subtract(days_back, 'days')\n    const t3 = t1.add(1)\n    params.TIME = t2.format() + '/' + t3.format();\n  } else {\n    params.TIME = t1_iso;\n    params.HORIZON = '__all__';\n  }\n  return params;\n}\nexport function crearControlesDimensiones(ol_map, dimension_controls, dimensions) {\n  if (!dimensions)\n    return;\n  for (const dim of dimensions) {\n    if (dim.value_type == 'PERIODIC')\n      continue;\n    const alreadyExists = dim.locator in dimension_controls;\n    const control = alreadyExists ? dimension_controls[dim.locator] : new DimensionControl(dim);\n    if (!alreadyExists) {\n      if (ol_map) {\n        ol_map.addControl(control);\n      } else {\n        $('#dimensions').append(control.element);\n        $('#dimensions').removeClass('hidden');\n      }\n      dimension_controls[dim.locator] = control;\n    }\n  }\n}\nclass DimensionControl extends Control {\n  constructor(dim) {\n    const html = $(`\n          <div id=\"${dim.locator}\" title=\"${dim.name}\" class=\"chProj combo dropdown \">\n          <span class='dim_title'></span>\n          <span class='dim_value'>...</span>\n          <i class=\"fas fa-sort-down\"></i>\n          <form class=\"dropdown-content\">\n          <ul class=\"dropdown-content\" id=\"${dim.locator}\">\n          </ul>\n          </form>\n          </div>\n          `)\n    html.on('click', function () {\n      html.toggleClass('listshown');\n    });\n    html.on('mouseleave', () => html.removeClass('listshown'));\n    dim.values.forEach((dimv) => {\n      const li = $(`<li value =\"${dimv[0]}\">${dimv[1]}</li>`);\n      html.find('ul').append(li);\n    });\n    const target = $('#dimensions');\n    target.removeClass('hidden');\n    super({\n      element: html[0],\n      target: target[0]\n    });\n    this.id = dim.locator;\n    this._options = dim.values;\n    this.name = dim.name;\n    html.find('span.dim_title').text(this.name);\n    this.value = dim.values[0][0];\n    html.find('span.dim_value').attr(\"value\", this.value);\n    const self = this;\n    html.find('li').on('click', function () {\n      html.find('span.dim_value').attr(\"value\", this.getAttribute('value'));\n      self.value = this.getAttribute('value');\n    });\n    this.html = html;\n    this.usage = 0;\n    this.html.toggle(false);\n  }\n  setMap(map) {\n    super.setMap(map);\n    const ov = map.getOverlayContainerStopEvent();\n    if ($(ov).closest('html').length)\n      $('#dimensions').appendTo(ov);\n    else\n      $('#dimensions').appendTo($('div.botonera'));\n  }\n\n  get options() {\n    return this._options;\n  }\n  get value() {\n    return this._value;\n  }\n  get caption() {\n    return this._caption;\n  }\n  set value(new_value) {\n    this._value = new_value;\n    const li = $(this.element).find(`li[value='${new_value}']`)\n    this._caption = li.text();\n    $(this.element).find('span.dim_value').text(this._caption);\n    this.set('value', this.value);\n    const mapa = this.getMap();\n    let info, dimension_controls;\n    if (mapa) {\n      info = mapa.get('info');\n      dimension_controls = mapa.get('dimension_controls');\n    }\n    if (dimension_controls) {\n      mapa.unset('dimension_controls');\n      mapa.set('dimension_controls', dimension_controls);\n    }\n    if (info) {\n      mapa.unset('info', true);\n      mapa.set('info', info);\n    }\n  }\n  use() {\n    this.enabled = ++this.usage > 0;\n  }\n\n  unuse() {\n    this.enabled = --this.usage > 0;\n  }\n\n  get enabled() {\n    return this.html.is(\":visible\");\n  }\n  set enabled(enabled) {\n    this.html.toggle(enabled);\n  }\n}\n\n","/*eslint no-implicit-globals: \"error\"*/\nimport { $, dayjs, flatpickr, updateUnselectedHorizons, getParameterByName } from '../../../../moderna_meteogrid/statix/js/base.mjs';\nimport { Control } from 'ol/control';\nimport { DataSet, Timeline } from \"vis-timeline/standalone\";\nimport 'vis-timeline/styles/vis-timeline-graph2d.css';\n\nconst sideCarets =\n  '<i class=\"fa-solid fa-diamond\"></i>';\n\nexport function roundNextXMin(date, X) {\n  let intervals = Math.floor(date.minutes() / X);\n  if (date.minutes() % X != 0)\n    intervals++;\n  if (intervals == 60 / X) {\n    date = date.add(1, 'hours');\n    intervals = 0;\n  }\n  date = date.minutes(intervals * X).seconds(0);\n  return date;\n}\n\nexport class TimelineControl extends Control {\n  constructor(opt) {\n    const target = $('.time-selector')[0];\n    window.time_type = opt.time_type;\n    super({\n      target: target,\n    })\n    this.target = target;\n    const enumTime = opt.time_type.locator.startsWith('ENUM');\n    const self = this;\n    if (enumTime) {\n      self.configure = this.configureTimelineENUM(opt);\n      self.create = this.createTimelineENUM(self.configure);\n    }\n    else {\n      self.configure = this.configureTimelineDefault(opt)\n      self.create = this.createTimelineDefault(self.configure);\n      window.setTimeout(() => self.moveToDate(\n        dayjs(this.timeline.getCustomTime('current'))), 100);\n    }\n  }\n  moveToDate(date) {\n    setCurrentValue(date);\n    const { start, end } = this.timeline.getWindow();\n    if (date > end || date < start)\n      this.timeline.moveTo(date.toDate());\n    this.timeline.setCustomTime(date.toDate(), 'current');\n  }\n  createTimelineDefault(config) {\n    const {\n      start,\n      end,\n      marks,\n      scale,\n      step,\n      snap,\n      // moment_function\n    } = config;\n\n    // Create a DataSet with data\n    const data = new DataSet([]);\n\n    // Configuration for the Timeline as JSON object\n    const options = {\n      moment: dayjs,\n      showCurrentTime: true,\n      snap: snap,\n      format: {\n        minorLabels: {\n          millisecond: 'SSS',\n          second: 's',\n          minute: 'HH:mm',\n          hour: 'HH',\n          weekday: 'dddd D',\n          day: 'dddd D',\n          month: 'MMMM',\n          year: 'YYYY'\n        }\n      },\n      width: '100%',\n      editable: {\n        add: false, // add new items by double tapping\n        updateTime: true, // drag items horizontally\n        updateGroup: false, // drag items from one group to another\n        remove: false // delete an item by tapping the delete button top right\n      },\n      margin: {\n        item: {\n          horizontal: 0,\n          vertical: 0\n        },\n        axis: 0\n      },\n      itemsAlwaysDraggable: true,\n      start: dayjs(start).toDate(),\n      maxHeight: '30pt',\n      timeAxis: {\n        scale,\n        step\n      },\n    };\n    if (end) {\n      options.end = dayjs(end);\n      const delta = end.diff(start);\n      options.end = options.end.add(delta / 10, 'milliseconds').toDate();\n      options.start = dayjs(options.start).subtract(delta / 10, 'milliseconds').toDate();\n      options.height = 28;\n    }\n    const timeline = new Timeline(this.target, data, [], options);\n    this.target.style.position = 'absolute';\n    const current = dayjs(config.new_initdate ? config.new_initdate : start)\n    const enableTime = ['hour', 'minute'].includes(config.scale);\n    const ts_config = {\n      wrap: true,\n      defaultDate: current.format('YYYY-M-D HH:mm'),\n      enableTime: false,\n      dateFormat: 'Y-m-dTH:i',\n      altInput: true,\n      allowInput: true,\n      altFormat: enableTime ? 'd-m-Y H:i' : 'd-m-Y',\n      time_24hr: true,\n      minuteIncrement: 1,\n      onClose: function (selectedDates, dateStr) {\n        let current_time = dayjs(dateStr);\n        setCurrentValue(current_time);\n        window.timelinectl.timeline.moveTo(current_time.toDate());\n        window.timelinectl.timeline.setCustomTime(current_time.toDate(), 'current');\n      }\n    };\n    const calendar = $($('.calendar')[0]);\n    const time_selector_picker = flatpickr(calendar, ts_config);\n    timeline.addCustomTime(current.toDate(), 'current');\n    timeline.setCustomTimeTitle('', 'current');\n    timeline.on('timechange', function (properties) {\n      const time = dayjs(snap(properties.time));\n      time_selector_picker.setDate(time.format('YYYY-M-D HH:mm'));\n    });\n    function onTimeChanged(properties) {\n      const time = dayjs(snap(properties.time));\n      timeline.setCustomTime(time.toDate(), 'current');\n      setCurrentValue(time);\n      time_selector_picker.setDate(time.format('YYYY-M-D HH:mm'));\n    }\n    timeline.on('timechanged', onTimeChanged);\n    timeline.on('click', onTimeChanged);\n    this.timeline = timeline;\n    window.timelinectl = this;\n    const mapa = document.getElementsByClassName('map interactive');\n    if (mapa.length) {\n      ts_config.appendTo = $(mapa).find('.calendar input.form-control')[0];\n    }\n    calendar.on('keydown', event => {\n      if (event.key == 'Enter') {\n        time_selector_picker.setDate(new Date(time_selector_picker._input.value.replace(/(\\d{2})-(\\d{2})-(\\d{4})/, \"$2/$1/$3\")));\n        time_selector_picker.close();\n      }\n    });\n    setTimeout(function () {\n      $('div.vis-current-time')\n        .text('')\n        .append('<i class=\"fa fa-sort-down\"></i>');\n      $('div.vis-custom-time.current div').append(sideCarets);\n    }, 300);\n\n    for (const [mark, dt] of Object.entries(marks)) {\n      window.timelinectl.timeline.addCustomTime(dt.toDate(), mark);\n      window.timelinectl.timeline.setCustomTimeTitle(mark, mark);\n      window.timelinectl.timeline.customTimes[\n        window.timelinectl.timeline.customTimes.length - 1\n      ].hammer.off('panstart panmove panend');\n    }\n    this.animateMapIfArrowDown(time_selector_picker, scale, step);\n  }\n  createTimelineENUM(config) {\n    const {\n      start,\n      end,\n      marks,\n      scale,\n      step,\n      snap,\n      years,\n      new_initdate,\n    } = config;\n\n    let diff;\n\n    // Create a DataSet with data\n    const data = new DataSet([]);\n\n    // Configuration for the Timeline as JSON object\n    const options = {\n      moment: dayjs,\n      showCurrentTime: false,\n      snap: snap,\n      format: {\n        minorLabels: () => ''\n      },\n      width: '100%',\n      editable: {\n        add: false, // add new items by double tapping\n        updateTime: true, // drag items horizontally\n        updateGroup: false, // drag items from one group to another\n        remove: false // delete an item by tapping the delete button top right\n      },\n      margin: {\n        item: {\n          horizontal: 0,\n          vertical: 0\n        },\n        axis: 0\n      },\n      itemsAlwaysDraggable: true,\n      start,\n      maxHeight: '30pt',\n      timeAxis: {\n        scale: scale,\n        step: step\n      },\n    };\n    let current = new_initdate || start;\n    if (end) {\n      options.moveable = false;\n      options.hiddenDates = [];\n      years.forEach((y, idx) => {\n        if (idx < years.length - 1)\n          options.hiddenDates.push({ start: String(y.year() + 1), end: String(years[idx + 1].year()) })\n        if (current <= years[idx + 1] && current >= y)\n          current = y;\n      })\n      options.start = dayjs(options.start).subtract(step, scale).toDate();\n      options.end = dayjs(end).add(2 * step, scale).toDate();\n    }\n    const timeline = new Timeline(this.target, data, [], options);\n    this.target.style.position = 'absolute';\n    timeline.addCustomTime(current.toDate(), 'current');\n    timeline.setCustomTimeTitle('', 'current');\n    const calendar = $('.calendar');\n    const ts_config = {\n      wrap: true,\n      defaultDate: current.format('YYYY-M-D HH:mm'),\n      enableTime: false,\n      dateFormat: 'Y-m-dTH:i',\n      altInput: true,\n      allowInput: true,\n      altFormat: 'd-m-Y H:i',\n      time_24hr: true,\n      minuteIncrement: 1,\n      onClose: function (selectedDates, dateStr) {\n        const current_time = dayjs(dateStr);\n        setCurrentValue(current_time);\n        window.timelinectl.timeline.moveTo(current_time.toDate());\n        window.timelinectl.timeline.setCustomTime(current_time.toDate(), 'current');\n      }\n    };\n    const time_selector_picker = flatpickr(calendar, ts_config);\n    timeline.on('timechange', function (properties) {\n      const time = dayjs(snap(properties.time));\n      time_selector_picker.setDate(time.format('YYYY-M-D HH:mm'));\n    });\n    function onTimeChanged(properties) {\n      const time = dayjs(snap(properties.time));\n      timeline.setCustomTime(time.toDate(), 'current');\n      setCurrentValue(time);\n      time_selector_picker.setDate(time.format('YYYY-M-D HH:mm'));\n    }\n    timeline.on('timechanged', onTimeChanged);\n    timeline.on('click', onTimeChanged);\n    this.timeline = timeline;\n    window.timelinectl = this;\n    const mapa = document.getElementsByClassName('map interactive');\n    if (mapa.length) {\n      ts_config.appendTo = $(mapa).find('.calendar input.form-control')[0];\n    }\n    calendar.on('keydown', event => {\n      if (event.key == 'Enter') {\n        time_selector_picker.setDate(new Date(time_selector_picker._input.value.replace(/(\\d{2})-(\\d{2})-(\\d{4})/, \"$2/$1/$3\")));\n        time_selector_picker.close();\n      }\n    });\n    setTimeout(function () {\n      $('div.vis-current-time')\n        .text('')\n        .append('<i class=\"fa fa-sort-down\"></i>');\n      $('div.vis-custom-time.current div').append(sideCarets);\n    }, 2000);\n\n    for (const [mark, dt] of Object.entries(marks)) {\n      window.timelinectl.timeline.addCustomTime(dt.toDate(), mark);\n      window.timelinectl.timeline.setCustomTimeTitle(mark, mark);\n      window.timelinectl.timeline.setCustomTimeMarker(mark, mark, false);\n      window.timelinectl.timeline.customTimes[\n        window.timelinectl.timeline.customTimes.length - 1\n      ].hammer.off('panstart panmove panend');\n    }\n    diff = [];\n    years.forEach((year, i) => {\n      if (i > 0) {\n        diff.push(year.diff(years[i - 1], 'y'));\n      }\n    })\n    this.animateMapIfArrowDown(time_selector_picker, scale, step, diff, years);\n  }\n  configureTimelineDefault(config) {\n    let marks = {};\n    let resolution, start, scale, step;\n    let end = null;\n    let year_list;\n    const time_type = config.time_type.locator;\n    const moment_function = time_type.slice(-1) == 'D' ? function (date) {\n      return dayjs(date).utc();\n    } : dayjs;\n    if (config.dyn) {\n      if (config.dyn.initdate) {\n        start = dayjs(config.dyn.initdate);\n        marks.Inicio = start;\n      }\n    } else {\n      start = dayjs(config.start);\n      if (config.initial_time) {\n        start = start.local();\n        start = start.hour(config.initial_time).minute(0).second(0).millisecond(0);\n        start = start.utc();\n      }\n    }\n\n    if (time_type == '1H') {\n      resolution = 1;\n      scale = 'hour';\n      step = 1;\n      end = start.add(window.innerWidth / 1300 * 24, 'hour');\n    } else if (time_type == '1D' || time_type == '1D_1H') {\n      resolution = 24;\n      scale = 'day';\n      step = 1;\n      end = start.add(window.innerWidth / 1300 * 10, 'day');\n    } else if (time_type == '10M') {\n      resolution = 1 / 6;\n      scale = 'minute';\n      step = 10;\n      end = start.add(window.innerWidth / 1300 * 3, 'hour');\n    } else if (time_type == '1MO') {\n      resolution = 720;\n      scale = 'month';\n      step = 1;\n      end = start.add(window.innerWidth / 1300 * 10, 'month');\n    } else if (time_type == '6H') {\n      resolution = 6;\n      scale = 'hour';\n      step = 6;\n      end = start.add(window.innerWidth / 1300 * 144, 'hour');\n    }\n    const snap = function (mdate) {\n      mdate = dayjs(mdate);\n      if (resolution < 1) mdate = roundNextXMin(mdate, 60 * resolution);\n      else if (resolution == 1) mdate = mdate.startOf('hour');\n      else if (resolution == 24) mdate = mdate.startOf('day').add(14, 'hours');\n      else if (resolution > 24) mdate = mdate.startOf('month').add(15, 'days');\n      else if (resolution == 6) mdate = findMoment6H(mdate);\n      return mdate.toDate();\n    };\n    start = snap(start);\n    if (config.dyn?.initdate && config.dyn?.hours)\n      marks.Fin = dayjs(config.dyn.initdate).add(config.dyn.hours, 'hours');\n    function findMoment6H(mdate) {\n      const nHour = [0, 6, 12, 18];\n      mdate = mdate.startOf('hour');\n      const idxHour = Math.floor(mdate.hours() / resolution);\n      return mdate.startOf('day').add(nHour[idxHour], 'hour');\n    }\n\n    return {\n      snap: snap,\n      start: start,\n      end: end,\n      dyn: config.dyn,\n      marks: marks,\n      years: (year_list) ? year_list : null,\n      scale: scale,\n      step: step,\n      moveable: true,\n      moment_function: moment_function,\n      new_initdate: config.new_initdate,\n    };\n  }\n  configureTimelineENUM(config) {\n    let marks = {};\n    let resolution, start, scale, step;\n    let end = null;\n    let year_list;\n    if (config.dyn) {\n      if (config.dyn.initdate) {\n        start = dayjs(config.dyn.initdate);\n        marks.Inicio = start;\n      }\n    } else {\n      start = dayjs();\n    }\n    if (config.dyn && config.dyn.hours) {\n      if (config.dyn.initdate) {\n        end = dayjs(config.dyn.initdate).add(config.dyn.hours, 'hours');\n        marks.Fin = end;\n      }\n    }\n    scale = 'year';\n    step = 1;\n    const years = config.time_type.locator\n      .split(':')[1]\n      .split('/')\n      .map(x => dayjs(x + '-01-01T00:00:00Z'));\n    const labelsj = config.time_type.data.find(x => x.locator == 'LABELS');\n    const labels = labelsj ? JSON.parse(labelsj.value) : null;\n    for (const yr of years) {\n      const k = labels ? labels[yr.year()] : yr.year();\n      marks[k] = yr;\n    }\n    year_list = years;\n    start = years[0];\n    end = years[years.length - 1];\n    end = dayjs(end);\n    const last = years[years.length - 1];\n    const snap = function (date) {\n      let mdate = dayjs(date);\n      for (let i = 1; i < years.length; i++) {\n        if (mdate <= years[i])\n          return years[i - 1];\n      }\n      return last.toDate();\n    };\n\n    if (!resolution) resolution = 1;\n    const now = new Date();\n    if (typeof start === 'undefined') start = now.getTime();\n\n    return {\n      snap,\n      start,\n      end,\n      dyn: config.dyn,\n      marks,\n      years: (year_list) ? year_list : null,\n      scale,\n      step,\n      moveable: false,\n      new_initdate: config.new_initdate,\n    };\n  }\n  animateMapIfArrowDown(time_selector_picker, scale, step, diff, y) {\n    // FIXME: Cuando los eventos no son periódicos\n    document.addEventListener(\n      'keydown',\n      event => {\n        const keyName = event.key;\n        if (!['ArrowRight', 'ArrowLeft'].includes(keyName))\n          return;\n        if ((event.target.tagName == 'INPUT') || (event.target.tagName == 'TEXTAREA'))\n          return;\n        event.preventDefault();\n        event.stopPropagation();\n        const current_time = window.timelinectl.timeline.getCustomTime('current');\n        let current_pos;\n        if (diff) {\n          y.forEach((year, i) => {\n            if (year.isSame(current_time))\n              current_pos = i;\n          })\n          if (keyName === 'ArrowRight') {\n            // forward map\n            if (current_pos < diff.length) {\n              let next_date = dayjs(current_time).add(diff[current_pos], 'years');\n              this.moveToDate(next_date);\n              time_selector_picker.setDate(next_date.format('YYYY-M-D HH:mm'));\n              return;\n            }\n          }\n\n          if (keyName === 'ArrowLeft') {\n            // rewind map\n            if (current_pos > 0) {\n              let prev_date = dayjs(current_time).subtract(diff[current_pos - 1], 'years');\n              this.moveToDate(prev_date);\n              time_selector_picker.setDate(prev_date.format('YYYY-M-D HH:mm'));\n              return;\n            }\n          }\n        }\n        else {\n          if (keyName === 'ArrowRight') {\n            // forward map\n            let next_date = dayjs(current_time).add(step, scale + 's');\n            this.moveToDate(next_date);\n            time_selector_picker.setDate(next_date.format('YYYY-M-D HH:mm'));\n            return;\n          }\n\n          if (keyName === 'ArrowLeft') {\n            // rewind map\n            let prev_date = dayjs(current_time).subtract(step, scale + 's');\n            this.moveToDate(prev_date);\n            time_selector_picker.setDate(prev_date.format('YYYY-M-D HH:mm'));\n            return;\n          }\n        }\n\n      },\n      false\n    );\n  }\n}\nfunction highlight(newElem, oldElem) {\n  const oldText = oldElem.text();\n\n  let text = '';\n  newElem\n    .text()\n    .split('')\n    .forEach(function (value, index) {\n      if (value != oldText.charAt(index))\n        text += \"<span class='highlight'>\" + value + '</span>';\n      else text += value;\n    });\n  newElem.html(text);\n}\nexport function getFormatString(time_type) {\n  if (time_type.includes('D'))\n    return 'DD-MM-YYYY';\n  else if (time_type.includes('1MO'))\n    return 'MMMM YYYY';\n  else if (time_type.startsWith('ENUM'))\n    return 'YYYY';\n  else\n    return 'DD - MM - YYYY HH: mm[(UTC]Z[)]';\n}\nexport function setCurrentValue(start) {\n  if (!start)\n    start = dayjs(window.timelinectl.timeline.getCustomTime('current'));\n  const isMosaic = $('div.mosaics').length > 0;\n  let time_type_map, labels;\n  if (isMosaic) {\n    $('div.mosaics td div.mosaic_map').parent().show();\n    time_type_map = window.time_type?.locator;\n    const labelsj = window.time_type.data.find(x => x.locator == 'LABELS');\n    labels = labelsj ? JSON.parse(labelsj.value) : null;\n  }\n  const utc_start = start.utc();\n  for (const ns of window.namespaces)\n    for (const [i, mapa] of ns.mapas.entries()) {\n      if (isMosaic && time_type_map.startsWith('ENUM') && $(mapa.getTargetElement()).find('_info').text() != '...') {\n        if (i == 0) continue;\n        const times = window.timelinectl.timeline.customTimes;\n        let iter_selected = null;\n        let i_time = 0;\n        let idx_hor_notsel = getParameterByName('idx_hor_notsel').split(',');\n        for (const time of times) {\n          if (time.options.id == 'current')\n            continue;\n          if (time.getCustomTime().toISOString() == utc_start.toISOString()) {\n            iter_selected = i_time;\n            break;\n          } else {\n            idx_hor_notsel.push(i_time.toString());\n          }\n          i_time++;\n        }\n        updateUnselectedHorizons(idx_hor_notsel);\n        const tgt = mapa.getTargetElement();\n        if (tgt) {\n          const map_iter = Number(tgt.id.split('_')[1]);\n          $(tgt).siblings('.time_info').text(Object.values(labels)[map_iter]);\n          $(tgt).parent().toggle(map_iter >= iter_selected)\n          $(tgt).parent().addClass('hidden');\n          mapa.getLayers().forEach(function (l) {\n            if (l.get('time_management')) {\n              const src = 'getSource' in l ?\n                l.getSource() :\n                l.getLayers().getArray()[0].getSource();\n              if (isMosaic)\n                src.on('imageloadend', evt => {\n                  const img = evt.image.getImage();\n                  if (img.width > 1 || img.height > 1)\n                    $(tgt).parent().removeClass('hidden');\n                });\n              src.set('time', utc_start);\n            }\n          });\n\n        }\n      }\n      else {\n        mapa.getLayers().forEach(function (l) {\n          if (l.get('time_management')) {\n            const time_type = window.time_type?.locator ? window.time_type.locator.slice(-1) : '';\n            const src = 'getSource' in l ?\n              l.getSource() :\n              l.getLayers().getArray()[0].getSource();\n            const tgt = mapa.getTargetElement();\n            if (tgt) {\n              if (isMosaic) {\n                $(tgt).parent().addClass('hidden');\n                src.on('imageloadend', evt => {\n                  const img = evt.image.getImage();\n                  if (img.width > 1 || img.height > 1)\n                    $(tgt).parent().removeClass('hidden');\n                });\n              }\n            }\n            src.set('time', utc_start);\n            let effective_time = src.get('effective_time');\n            effective_time = effective_time.utcOffset(start.utcOffset());\n            if (isMosaic && $('div.interval-field span#title').val() == '1MO') {\n              let aux_time = utc_start.utcOffset(start.utcOffset());\n              const init_day = aux_time.date() - 1;\n              aux_time = aux_time.startOf('month')\n                .add(15, 'days')\n                .add(src.get('time_delta') || 0, 'hours');\n              if (init_day < aux_time.daysInMonth())\n                aux_time = aux_time.startOf('month').add(init_day, 'days');\n              else\n                aux_time = aux_time.endOf('month').startOf('day');\n              effective_time = aux_time;\n              src.set('effective_time', aux_time);\n            }\n            const string_format_date = getFormatString(time_type_map ? time_type_map : time_type)\n            let time_info_txt = dayjs(effective_time.toDate()).format(string_format_date)\n            if (labels && time_info_txt in labels)\n              time_info_txt = labels[time_info_txt];\n            const targetElem = mapa.getTargetElement();\n            if (targetElem) {\n              const infoDiv = $(targetElem).siblings('.time_info');\n              infoDiv.text(time_info_txt);\n              if (src.get('time_delta') && window.time_type?.locator != '1MO' && (i != 0)) {\n                const prevInfo = $(ns.mapas[i - 1].getTargetElement()).siblings('.time_info');\n                highlight(infoDiv, prevInfo);\n              }\n            }\n          }\n        });\n      }\n      const info = mapa.get('info');\n      if (info) {\n        mapa.unset('info', true); \n        mapa.set('info', info);\n      }\n      const dimension_controls = mapa.get('dimension_controls');\n      if (dimension_controls) {\n        mapa.unset('dimension_controls');\n        mapa.set('dimension_controls', dimension_controls);\n      }\n    }\n  groupCellsByTimeInfo();\n}\n\nfunction groupCellsByTimeInfo() {\n  $('.fila_mapas').each(function () {\n    const $fila = $(this);\n    const $celdas = $fila.find('td').not(':first');\n\n    // Agrupar por el texto de .time_info\n    const grupos = {};\n    $celdas.each(function () {\n      const $celda = $(this);\n      const key = $celda.find('.time_info').text();\n      if (!grupos[key]) grupos[key] = [];\n      grupos[key].push($celda);\n    });\n    const ordenGrupos = Object.keys(grupos);\n    $celdas.remove();\n    for (const key of ordenGrupos) {\n      for (const celda of grupos[key]) {\n        $fila.append(celda);\n      }\n    }\n  });\n}","import { $, getParameterByName, flatpickr, dayjs, multiselectOptions, LAYERTYPES } from '../../../../moderna_meteogrid/statix/js/base.mjs';\nimport \"jquery-ui/ui/widgets/menu\";\nimport 'jquery.quicksearch';\nimport { Control } from 'ol/control';\nimport { Vector as VectorLayer } from 'ol/layer';\nimport { Vector as VectorSource } from 'ol/source';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport WKT from 'ol/format/WKT';\nimport { cargarMapa } from './mapa.mjs';\n\nimport { Layer } from './simmerlayer.mjs';\n\nconst dateInputFormat = 'YYYY-MM-DD HH:mm';\n\nlet datatable;\n\nfunction createSimulation(from_datatable) {\n    if (from_datatable)\n        datatable = $(from_datatable).DataTable();\n    $('#simulation-element-type-dialog table tbody').empty()\n    $('#simulation-element-type-dialog').dialog({\n        title: window.gettext('Seleccione tipo...'),\n        width: 180,\n        height: 'auto',\n        maxHeight: window.innerHeight,\n    });\n    $.ajax({\n        url: window.Urls.simulation_types(),\n        success: function (json) {\n            for (const elem_type of json) {\n                const row = $(`<tr element_type=\"${elem_type.id}\"><td>${elem_type.name}</td></tr>`);\n                $('#simulation-element-type-dialog table tbody').append(row);\n            }\n            $('#simulation-element-type-dialog').on('click', 'tr', 'create', function (evt) {\n                const element_type_id = $(evt.currentTarget).closest('tr').attr('element_type');\n                evt.element_type_id = element_type_id;\n                actOnElement.bind(this)(evt);\n                $('#simulation-element-type-dialog').dialog(\"close\");\n            });\n            if (json.length == 1)\n                $('#simulation-element-type-dialog tr').click();\n        }\n    });\n}\n\nfunction actOnElement(evt) {\n    let buttons, tableId;\n    const datatableId = this.getAttribute('table_id');\n    const activeControl = this.id;\n    if (datatableId)\n        datatable = $('#' + datatableId).DataTable();\n    evt.preventDefault()\n    const new_pos = {\n        my: 'center',\n        at: 'center',\n        collision: \"fit\"\n    };\n    let op = evt.data;\n    if (evt.data.action) {\n        op = evt.data.action;\n    }\n    const mapa = evt.data.mapa;\n    const element_id = this.id ? this.id.split('_')[1] : null;\n    const alertOverlay = evt.data.alertOverlay;\n    if (op === 'info') {\n        tableId = '#simulation-element-info';\n        const element = $(tableId);\n        buttons = [\n        ];\n        element.show().dialog({\n            title: window.gettext('Información'),\n            width: 'auto',\n            buttons: buttons,\n            position: new_pos,\n            autoOpen: false,\n        });\n        fillElementInfo(element, element_id, true);\n    }\n    else if (op === 'delete') {\n        tableId = '#simulation-element-info';\n        const element = $(tableId);\n        buttons = [\n            {\n                text: window.gettext('Cancelar'),\n                click: function () {\n                    $(this).dialog(\"close\");\n                },\n            },\n            {\n                text: window.gettext('Eliminar'),\n                click: function () {\n                    const dialog = this;\n                    $.ajax({\n                        url: window.Urls.simulation_delete(element_id),\n                        type: 'POST',\n                        success: function () {\n                            $(dialog).dialog(\"close\");\n                            if (datatable)\n                                datatable.ajax.reload();\n                        }\n                    });\n                },\n            },\n        ];\n        element.show().dialog({\n            title: window.gettext('Confirmar eliminación'),\n            width: 'auto',\n            buttons: buttons,\n            position: new_pos,\n            autoOpen: false,\n        });\n        fillElementInfo(element, element_id, true);\n    }\n    else if (op === 'share') {\n        tableId = '#simulation-share-dialog';\n        const share_window = $(tableId).clone().prop(\"id\", \"simulation-share-dialog_\" + element_id)\n        buttons = [\n            {\n                text: window.gettext('Guardar'),\n                click: function () {\n                    const dialog = this;\n                    const form = share_window.find('form');\n                    const formData = new FormData(form[0]);\n                    const edit_users = formData.getAll('edit_users');\n                    const ro_users = formData.getAll('readonly_users');\n                    if (edit_users.filter(element => ro_users.includes(element)).length) {\n                        const tableId = '#simulation-users-alert-dialog';\n                        const alert_window = $(tableId).clone().prop(\"id\", \"simulation-users-alert-dialog_\" + element_id)\n                        buttons = [\n                            {\n                                text: window.gettext('Aceptar'),\n                                click: () => alert_window.dialog(\"close\"),\n                            },\n                        ];\n                        alert_window.show().dialog({\n                            title: window.gettext('Error de permisos'),\n                            width: 'auto',\n                            height: 'auto',\n                            buttons: buttons,\n                            position: new_pos,\n                            autoOpen: true,\n                        });\n                    }\n                    else\n                        $.ajax({\n                            url: window.Urls.simulation_share(element_id),\n                            data: formData,\n                            cache: false,\n                            contentType: false,\n                            processData: false,\n                            method: 'POST',\n                            success: function (json) {\n                                if (json.result == 'OK') {\n                                    $(dialog).dialog(\"close\");\n                                    if (activeControl)\n                                        $('#' + activeControl).parent().fadeToggle(400).fadeToggle(400);\n                                }\n                                else {\n                                    alert(json.message);\n                                }\n                            }\n                        });\n                },\n            },\n        ];\n        $.ajax({\n            url: window.Urls.simulation_users(element_id),\n            success: function (json) {\n                const sel_edit = share_window.find('select#edit');\n                const sel_ro = share_window.find('select#readonly');\n                const rellena_sel = function (sel, json) {\n                    const rel = sel.attr('relation');\n                    for (const u of json) {\n                        sel.append($(`<option ${u.relation == rel ? 'selected' : ''} value=\"${u.id}\">${u.name}</option>`));\n                    }\n                    sel.multiSelect(multiselectOptions(\n                        '<div class=\"multiselect-header\">Sin permiso</div>',\n                        '<div class=\"multiselect-header\">Con permiso</div>'\n                    ));\n                    sel.on('change', function () {\n                        const form = sel.closest('form');\n                        form.find('.ms-selection li').attr('title', window.gettext('Deseleccionar'))\n                        form.find('.ms-selectable li').attr('title', window.gettext('Seleccionar'))\n                    });\n                    sel.trigger('change');\n                }\n                if (json.filter(c => c.self)[0].relation != 'EDIT')\n                    buttons = [];\n                rellena_sel(sel_edit, json);\n                rellena_sel(sel_ro, json);\n                share_window.show();\n                share_window.dialog({\n                    title: window.gettext('Seleccione personas con acceso'),\n                    width: 'auto',\n                    height: 'auto',\n                    buttons: buttons,\n                    position: new_pos,\n                    autoOpen: true,\n                });\n            },\n        })\n    }\n    else if (op === 'lock') {\n        tableId = '#simulation-lock-dialog';\n        const lock_window = $(tableId).clone().prop(\"id\", \"simulation-lock-dialog_\" + element_id)\n        buttons = [\n            {\n                text: window.gettext('Aceptar'),\n                click: function () {\n                    const dialog = this;\n                    $.ajax({\n                        url: window.Urls.simulation_lock(element_id),\n                        method: 'POST',\n                        success: function () {\n                            if (mapa.get('simulation_id') == element_id)\n                                window.reload();\n                            else {\n                                $(dialog).dialog(\"close\");\n                                if (activeControl)\n                                    $('#' + activeControl).parent().fadeToggle(400).fadeToggle(400);\n                            }\n                        }\n                    });\n\n                },\n            },\n        ];\n        lock_window.show().dialog({\n            title: window.gettext('Bloqueo de simulación'),\n            width: 'auto',\n            height: 'auto',\n            buttons: buttons,\n            position: new_pos,\n            autoOpen: true,\n        });\n    }\n    else if (op === 'de/sel-elem') {\n        if (mapa.get('geom_feature')) {\n\n            let element_layer;\n            mapa.getLayers().getArray().forEach(el => {\n                if (el.get('title') == 'elementsLayerGroup') {\n                    el.getLayersArray().forEach(element => {\n                        if (element.get('name') == 'elements') {\n                            element_layer = element;\n                        }\n                    })\n                }\n            })\n            tableId = '#simulation-elements-dialog';\n            buttons = [\n                {\n                    text: window.gettext('Guardar'),\n                    click: function () {\n                        const dialog = this;\n                        const form = $(tableId + ' form');\n                        const formData = new FormData(form[0]);\n\n                        $.ajax({\n                            url: window.Urls.element_update(element_id),\n                            data: formData,\n                            cache: false,\n                            contentType: false,\n                            processData: false,\n                            method: 'POST',\n                            success: function () {\n                                $(dialog).dialog(\"close\");\n                                mapa.set('update_elements', true);\n                            }\n                        });\n                    },\n                },\n                {\n                    text: window.gettext('Cancelar'),\n                    click: function () {\n                        const dialog = this;\n                        $(dialog).dialog(\"close\");\n                    }\n                }\n            ];\n            const view = mapa.getView();\n            const viewResolution = view.getResolution();\n            const viewProjection = view.getProjection();\n            const src = element_layer.getSource();\n            if (src.getParams().TYPES == ',')\n                src.getParams().TYPES = null;\n\n            const url = src.getFeatureInfoUrl(\n                view.getCenter(),\n                viewResolution,\n                viewProjection,\n                {\n                    INFO_FORMAT: 'application/vnd.meteogrid.emmet+json',\n                    geom_from_simulation: true,\n                    simulation_num: element_id\n                }\n            );\n            $.ajax({\n                url: url.replace(/&I=/, '&II='),\n                success: function (json) {\n                    const sel = $(tableId + ' select');\n                    sel.empty();\n                    for (const u of json.features) {\n                        const props = u.properties;\n                        sel.append($(`<option ${props.selected ? 'selected' : ''} value=\"${props.id}\">\n                            ${props.name ? props.name : props.element_type__name}\n                            </option>`));\n                    }\n                    sel.multiSelect(multiselectOptions());\n                    sel.on('change', function () {\n                        const form = sel.closest('form');\n                        form.find('.ms-selection li').attr('title', window.gettext('Deseleccionar'))\n                        form.find('.ms-selectable li').attr('title', window.gettext('Seleccionar'))\n\n                    });\n                    sel.trigger('change');\n                    $(tableId).show();\n                    $(tableId).dialog({\n                        title: window.gettext('Seleccione elementos asociados:'),\n                        width: 'auto',\n                        height: 'auto',\n                        buttons: buttons,\n                        position: new_pos,\n                        autoOpen: true,\n                    });\n                },\n            })\n        }\n        else {\n            alertOverlay.show(`<div><p>\n                ${window.gettext('Por favor, seleccione el área de simulación afectada antes de continuar...')}\n                </p></div>`);\n            setTimeout(() => {\n                alertOverlay.hide();\n            }, 10000)\n        }\n    }\n    else if (op === 'report') {\n        window.open(window.Urls.simulation_report(element_id))\n    }\n    else if (op === 'clone') {\n        tableId = '#simulation-element-info';\n        const element = $(tableId);\n        buttons = [\n            {\n                text: window.gettext('Cancelar'),\n                click: function () {\n                    $(this).dialog(\"close\");\n                },\n            },\n            {\n                text: window.gettext('Clonar'),\n                click: function () {\n                    const popup = window.open();\n                    const self = this;\n                    popup.document.write(window.gettext('Cargando copia de propagación...'));\n                    $.ajax({\n                        url: window.Urls.simulation_clone(element_id),\n                        type: 'POST',\n                    })\n                        .done(function (json) {\n                            popup.location = window.Urls.simulation_page(json.id);\n                            $(self).dialog(\"close\");\n                            if (datatable)\n                                datatable.ajax.reload();\n                        });\n                },\n            },\n        ];\n        element.show().dialog({\n            title: window.gettext('Confirmar clonado'),\n            width: 'auto',\n            buttons: buttons,\n            position: new_pos,\n            autoOpen: false,\n        });\n        fillElementInfo(element, element_id, true);\n    }\n    else if (op === 'FIRE_VIEW_ERA5LAND_FORECAST_BEHAVE') {\n        window.open(window.Urls.fire_view_era5land_forecast_behave(element_id));\n    }\n    else if (op === 'GEN_ERA5LAND_FORECAST_BEHAVE') {\n        window.open(window.Urls.gen_era5land_forecast_behave(element_id));\n    }\n    else if (op === 'edit' || op === 'create') {\n        tableId = '#simulation-edit-dialog';\n        buttons = [\n            {\n                text: window.gettext('Cancelar'),\n                click: function () {\n                    $(this).dialog(\"close\");\n                },\n            },\n        ];\n        buttons.unshift({\n            text: op === 'edit' ? window.gettext('Modificar') : window.gettext('Crear'),\n            click: function () {\n                const dialog = this;\n                const form = $(tableId + ' form');\n                const formData = new FormData(form[0]);\n                let datetime = formData.get('element_initdate');\n                datetime = dayjs(datetime);\n                formData.set('element_initdate', datetime.toISOString());\n                const popup = op === 'edit' ? null : window.open();\n                if (popup)\n                    popup.document.write(window.gettext('Cargando nueva propagación...'));\n                $.ajax({\n                    url: (op === 'edit' ? window.Urls.simulation_edit(element_id) : window.Urls.simulation_edit_new()),\n                    data: formData,\n                    cache: false,\n                    contentType: false,\n                    processData: false,\n                    method: 'POST',\n                    success: function (json) {\n                        $(dialog).dialog(\"close\");\n                        if (datatable)\n                            datatable.ajax.reload(\n                                () => activeControl && $('#' + activeControl).parent().fadeToggle(400).fadeToggle(400),\n                                false\n                            );\n                        if (popup)\n                            popup.location = window.Urls.simulation_page(json.id);\n                    },\n                    error: function () {\n                        if (popup)\n                            popup.close();\n                    }\n                });\n\n            },\n        });\n        const propDialog = createProp_dialog(tableId, buttons, op, new_pos);\n        fillElementInfo(propDialog, element_id, false, evt.element_type_id);\n    }\n    else {\n        console.debug('Modificar - ' + op + ' ' + element_id);\n    }\n    return false;\n}\nfunction createProp_dialog(tableId, buttons, op, new_pos) {\n    const createProp_element = $(tableId);\n    createProp_element.find('td.group_share').parent().remove()\n    if (op === 'create')\n        $.ajax({\n            url: window.Urls.simulation_user_groups(),\n            success: function (json) {\n                json.map(group => {\n                    createProp_element.find('form tbody').append(`\n                        <tr>\n                            <td class=\"group_share\"><label>\n                                <input name=\"group_${group.id}\" class=\"group_share\" type=\"checkbox\" checked>\n                                <a>${window.gettext('Compartir con el grupo')} \"${group.name}\"</a>\n                            </label></td>\n                        </tr>`)\n                })\n            }\n        })\n    createProp_element.dialog({\n        width: 'auto',\n        position: new_pos,\n        title: op === 'edit' ? window.gettext('Modificar') : window.gettext('Crear'),\n        zIndex: 10000,\n        autoOpen: false,\n        buttons: buttons,\n        open: function () {\n            $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar'))\n            if ($(this).parent().height() > $(window).height()) {\n                $(this).height($(window).height() * 0.7);\n                $(this).dialog({ position: \"center\" });\n            }\n        },\n    });\n    return createProp_element;\n}\nfunction fillElementInfo(propDialog, element_id, read_only, simulationtype_id) {\n    let elems, v;\n    const urlFunction = element_id ? window.Urls.simulation_info(element_id) : window.Urls.simulation_info_new(simulationtype_id);\n    $.getJSON(\n        urlFunction,\n        function (json) {\n            propDialog.find('ul.add-data').remove();\n            propDialog.find('.vardata').remove();\n            const old_data = json.data;\n            delete json.data;\n            json.initdate = dayjs(json.initdate).format(dateInputFormat);\n            const events = json.events;\n            delete json.events;\n            for (const k in json) {\n                const vdat = json[k];\n                v = elementValue(vdat);\n                elems = propDialog.find('.data_old.element_' + k);\n\n                elems.text(v);\n                const casilla = crearCasilla(vdat);\n                const elem = propDialog.find('.data_new.element_' + k);\n                if (elem.length && casilla) {\n                    casilla.attr('name', elem.attr('name'));\n                    for (let cls of elem.attr('class').split(' '))\n                        casilla.addClass(cls);\n                    elem.replaceWith(casilla);\n                }\n                else if (elem.length && elem[0].name === 'element_initdate') {\n                    elem[0].type = 'text';\n                    const appendTo = document.getElementsByClassName('map');\n                    flatpickr(elem,\n                        {\n                            defaultDate: json.initdate,\n                            enableTime: true,\n                            dateFormat: \"Y-m-dTH:i\",\n                            altInput: true,\n                            altFormat: \"d-m-Y H:i\",\n                            time_24hr: true,\n                            minuteIncrement: 1,\n                            appendTo: appendTo.length && appendTo[0],\n                        }\n                    );\n\n                }\n                else {\n                    elem.val(v);\n                }\n            }\n            const new_data = read_only ? [] : old_data;\n            if (old_data.length)\n                crearFilaData(propDialog, old_data.concat(read_only ? events : []), new_data, read_only);\n            if (propDialog.find('.data_new').length > 1) {\n                // Montamos lista de opciones para crear datos nuevos\n                const available_data = json.simulationtype.data;\n                const data_menu = $('<ul class=\"add-data\"></ul>');\n                let show_button = false;\n                for (let i = 0; i < available_data.length; i++) {\n                    const dat = available_data[i];\n                    if (dat.type.name.startsWith('_'))\n                        continue\n                    if (dat.type.calculation_id)\n                        continue\n                    delete dat.id;\n                    const it = $('<li idx_available_data=\"' + i + '\">Añadir ' + dat.type.name + '</li>');\n                    data_menu.append(it);\n                    show_button = true;\n                }\n                const buttons = propDialog.dialog('option', 'buttons');\n                if (!json.__edit)\n                    buttons.shift();\n                const button = {\n                    text: window.gettext('Añadir dato'),\n                    classes: 'add-data',\n                    click: function () {\n                        $(this).append(data_menu);\n                        data_menu.menu({\n                            select: function (event, ui) {\n                                const idx = ui.item[0].attributes.idx_available_data.value;\n                                const dat = available_data[idx];\n                                crearFilaData(propDialog, [], [dat], read_only);\n                            },\n                        });\n                    },\n                };\n                if (show_button)\n                    buttons.push(button);\n                propDialog.dialog('option', 'buttons', buttons);\n            }\n            propDialog.dialog('open');\n            /*\n            propDialog.find('table.events').DataTable( {\n                retrieve: true,\n                paging: false,\n                searching: false,\n                info: false,\n                dom: 't',\n                ordering: false,\n            } );\n            propDialog.find('table.files').DataTable( {\n                retrieve: true,\n                paging: false,\n                searching: false,\n                ordering:  false,\n                info: false,\n                dom: 't',\n            } );\n            */\n        }\n    );\n}\nfunction elementValue(value) {\n    if (value == null)\n        return '';\n    if (typeof value == 'object' && value.type && ['date', 'event'].includes(value.type.klass)) {\n        if (value.value == null)\n            return null\n        return dayjs(value.value).format(dateInputFormat);\n    }\n    if (typeof value == 'object' && value.type && value.type.klass === 'str')\n        return value.value;\n    if (typeof value == 'object' && value.type && value.type.klass === 'parameter')\n        return value.value && value.value.name;\n    if (typeof value == 'object' && value.name !== undefined)\n        return value.name;\n    if (typeof value == 'object' && value.url)\n        return value.url;\n    if (typeof value == 'object')\n        return value.toString();\n    return value;\n}\nfunction crearFilaData(propDialog, old_data, new_data) {\n    const old_vars = Object.groupBy(old_data, function (x) { return x.type.name; });\n    const new_vars = Object.groupBy(new_data, function (x) { return x.type.name; });\n    const all_vars = [...new Set(Object.keys(old_vars).concat(Object.keys(new_vars)))];\n    let order = propDialog.find('.data_new').length + 1;\n    for (let itype = 0; itype < all_vars.length; itype++) {\n        const type = all_vars[itype];\n        let rowspan = 1;\n        if (old_vars[type])\n            rowspan = old_vars[type].length;\n        if (new_vars.type && new_vars[type].length > rowspan)\n            rowspan = new_vars[type].length;\n        for (let i = 0; i < rowspan; i++) {\n            const vdat_old = type in old_vars && old_vars[type][i];\n            const vdat_new = type in new_vars && new_vars[type][i];\n            const vdat = vdat_new ? vdat_new : vdat_old;\n            const which_table = '.data';\n            const modelTR = propDialog.find(which_table).find('tr.model-row');\n            const tr = modelTR.clone();\n            tr.addClass('vardata');\n            tr.removeClass('model-row');\n            tr.find('.caption').text(type);\n            const existentes = propDialog.find('.data_new_' + vdat.type.id);\n            if (i == 0 && existentes.length && !vdat.multiple) {\n                existentes.fadeToggle(40).fadeToggle(40);\n                continue;\n            }\n            const suffix = (vdat.id ? vdat.id : '') + '_' + vdat.type.id + '_' + order;\n            order++;\n            const casilla = crearCasilla(vdat);\n            if (casilla) {\n                casilla.addClass('data_new')\n                tr.find('.data_new').replaceWith(casilla);\n            } else {\n                tr.find('.data_new').val(elementValue(vdat));\n            }\n            if (vdat.id)\n                tr.find('input.delete').attr('name', 'delete_' + suffix);\n            else\n                tr.find('input.delete').parent().remove();\n            tr.find('.data_new').addClass('data_new_' + vdat.type.id);\n            tr.find('.data_new').attr('name', 'data_' + suffix);\n\n            if (vdat_old) {\n                if (vdat_old.type.klass == 'file') {\n                    tr.find('span.data_old').replaceWith($(`<a target=\"_blank\" href=\"${vdat_old.value.url}\"><i class=\"enlace-icono fa fa-book\" ></i>${vdat_old.value.url.split(/[\\\\/]/).pop()}\n                    </a>`));\n                }\n                else\n                    tr.find('span.data_old').text(elementValue(vdat_old));\n            }\n            modelTR.before(tr);\n        }\n    }\n}\nfunction crearCasilla(vdat) {\n    if (vdat == null)\n        return null;\n    let url;\n    if (typeof vdat !== 'object')\n        return null;\n    if (Array.isArray(vdat))\n        return null;\n    const klass = vdat.type.klass;\n    if (klass === 'parameter' || klass == 'table') {\n        if (klass === 'parameter')\n            url = window.Urls.parameter_options(vdat.type.parameter_type.locator);\n        if (vdat.type.locator == \"SIMULATION_TYPE\")\n            url = window.Urls.simulation_types();\n        else if (klass == 'table')\n            url = window.Urls.table_options(vdat.type.name);\n        let casilla = $('<select></select>');\n        $.getJSON(\n            url,\n            function (json) {\n                // if (!vdat.fixed)\n                //     $('<option ' + (selected ? 'selected=\"selected\"' : '') + '/>').val(null).html('-').appendTo(casilla);\n                for (const k in json) {\n                    const opt = json[k];\n                    const selected = vdat.value ? vdat.value.name == opt.name : false;\n                    $('<option ' + (selected ? 'selected=\"selected\"' : '') + '/>').val(opt.id).html(opt.name).appendTo(casilla);\n                }\n            }\n        );\n        return casilla;\n    }\n    if (klass === 'date')\n        return $(`<input type=\"datetime-local\" value=\"${dayjs(vdat.value).format(dateInputFormat)}\">`);\n    if (klass === 'file')\n        if (vdat.id)\n            return $('<span/>');\n        else\n            return $('<input type=\"file\" />');\n    if (klass === 'integer')\n        return $(`<input type=\"number\" value=\"${vdat.value}\">`);\n    if (klass === 'float')\n        return $(`<input type=\"number\" value=\"${vdat.value}\">`);\n    if (klass === 'str')\n        return null;\n}\n\nclass NewLaunchControl extends Control {\n    constructor(opt_options) {\n        const options = opt_options || {};\n\n        const button = document.createElement('button');\n        button.innerHTML = `<i class=\"fa fa-${options.fa}\"></i>`;\n        button.title = options.title || options.action;\n        button.id = options.action + '_' + options.id;\n        const element = document.createElement('div');\n        element.className = 'ol-unselectable ol-control';\n        element.appendChild(button);\n        super({\n            element: element,\n            target: options.target\n        });\n        const self = this;\n        $(button).click(function () {\n            const element_id = this.id ? this.id.split('_')[1] : null;\n            $.ajax({\n                url: window.Urls.simulation_launch(element_id),\n                method: 'POST',\n                dataType: 'json',\n                contentType: 'application/json'\n            })\n                .done(function (resp) {\n                    console.log(resp);\n                    window.setTimeout(function () { refresco(element_id, self.getMap()); }, 3000);\n                })\n                .fail(function () {\n                    alert('error');\n                });\n        });\n    }\n}\n\nclass ActControl extends Control {\n    constructor(opt_options) {\n        const options = opt_options || {};\n\n        const button = document.createElement('button');\n        if (options.html) {\n            button.innerHTML = options.html\n        }\n        else button.innerHTML = `<i class=\"${options.fa}\"></i>`;\n        button.title = options.title || options.action;\n        button.id = options.action + '_' + options.id;\n\n        $(button).click(options, actOnElement);\n        const element = document.createElement('div');\n        element.className = 'ol-unselectable ol-control';\n        element.appendChild(button);\n        super({\n            element: element,\n            target: options.target\n        });\n    }\n}\nclass SimulationElementsLayer extends Layer {\n    get ol_factory() {\n        return VectorLayer;\n    }\n    get source() {\n        const src = new VectorSource({\n            format: new GeoJSON(),\n            url: this._url\n        });\n        src.on('change:time', function () {\n            const time = this.get('time');\n            const effective_time = time\n                .add(this.get('time_delta') || 0, 'hours');\n            this.set('effective_time', effective_time);\n        });\n        return src;\n    }\n}\nLAYERTYPES.SIMUL = SimulationElementsLayer;\n\nfunction refresco(id, mapa) {\n    $.ajax(window.Urls.simul_json(id))\n        .then(function (ret) {\n            if (ret.sigym_config.state == 'ready'){\n                location.reload();\n            }\n            if (ret.sigym_config.state == 'error'){\n                mapa.set('notification', `${window.gettext('error')}`);\n                console.log(`${window.gettext('error:')} ${ret.sigym_config.cause}`);\n                location.reload();\n            }\n            else if (ret.sigym_config.state == 'busy') {\n                window.setTimeout(function () { refresco(id, mapa); }, 3000);\n                mapa.set('notification', `${window.gettext(ret.sigym_config.progress_status)}`);\n            } else {\n                if (ret.sigym_config.state == 'ready'){\n                    mapa.set('notification', `${window.gettext('cargando resultado...')}`);\n                } else {\n                    mapa.set('notification', ret.sigym_config.state);\n                }\n            }\n            if (ret.sigym_config.extra_info)\n                console.log(`${window.gettext('info extra:')}`);\n                ret.sigym_config.extra_info.forEach(item => console.log(`- ${item}`));\n        });\n}\n\nasync function navigateToElement(mapa, element_id) {\n    const response = await fetch(window.Urls.element_info(element_id));\n    const json = await response.json();\n    const geom = json.geometry;\n    const wktFormat = new WKT();\n    const map_geom = wktFormat.readGeometry(geom, {\n        dataProjection: 'EPSG:4326',\n        featureProjection: window.epsg\n    });\n    const view = mapa.getView();\n    view.fit(map_geom, {\n        maxZoom: view.getMaxZoom() - 9,\n    });\n    for (const d of json.data)\n        if (d.type.locator == 'START_DATETIME') {\n            window.timelinectl.timeline.moveTo(d.value);\n            window.timelinectl.timeline.setCustomTime(d.value, 'current');\n            window.timelinectl.timeline.emit('click', { time: window.timelinectl.timeline.getCustomTime('current') });\n        }\n\n}\n\nexport function cargaInicialSimulacion(ns) {\n    if (ns.simulation_id)\n        $($.getJSON(window.Urls.simul_json(ns.simulation_id, ns.page_id),\n            async function (cfg) {\n                cfg.simul.relations = cfg.relations;\n                const mapa = await cargarMapa(ns, ns.page.find('.mapa'), cfg.page, cfg.simul);\n                if (cfg.sigym_config.state == 'busy') {\n                    window.setTimeout(function () { refresco(cfg.simul.id, mapa) }, 3000);\n                } else if (cfg.sigym_config.state == 'ready') {\n                    console.debug('cargando resultado...');\n                } else {\n                    $('.titulo_cabecera_izq').text(cfg.sigym_config.state)\n                }\n                if (cfg.sigym_config.state == 'error')\n                    console.log(`${window.gettext('error:')} ${cfg.sigym_config.cause}`);\n                if (cfg.sigym_config.extra_info) {\n                    console.log(`${window.gettext('info extra:')}`);\n                    cfg.sigym_config.extra_info.forEach(item => console.log(`- ${item}`));\n                }\n                const element_id = getParameterByName('element_id');\n                if (element_id)\n                    navigateToElement(mapa, element_id);\n            }\n        ))\n    if (ns.element_id)\n        $.getJSON(window.Urls.page_json(ns.page_id), async function (cfg) {\n            const mapa = await cargarMapa(ns, ns.page.find('.mapa'), cfg);\n            navigateToElement(mapa, ns.element_id);\n        })\n}\n\n\nexport {\n    actOnElement, createSimulation,\n    NewLaunchControl, ActControl, SimulationElementsLayer, fillElementInfo, createProp_dialog\n};\n","/*eslint no-implicit-globals: \"error\"*/\nimport { $, dayjs, flatpickr, getDTMessages, getFormCoords } from '../../../../moderna_meteogrid/statix/js/base.mjs';\n\nimport { actOnElement, createSimulation } from './simulaciones.mjs';\nimport { actOnElement as saverActOnElement, initializeMapa as saverInitializeMapa } from '../../../../saver/statix/js/mapa_elementos.mjs';\nimport BaseObject from 'ol/Object';\nimport { SaverElementsLayer } from '../../../../saver/statix/js/saver_layers.mjs';\nimport { showProblemDialog } from './mapa.mjs';\n\nconst emul_mapa = new BaseObject();\nsaverInitializeMapa(emul_mapa); //  FIXME: objeto global un poco feo\n\nfunction exportar(dt, layer_id, formato) {\n  const params = { ...dt.ajax.params() };\n  delete params.start;\n  delete params.length;\n  delete params.draw;\n  window.open(`${window.Urls.listingFile(layer_id)}?format=${formato}&${$.param(params)}`);\n}\n\nexport async function cargarTablas(ns, cfg) {\n  const coordForm = ns.page.find('.coord-input div.form');\n  window.site_cfg.site_epsgs.forEach(ep => {\n    const li = $(`<li value =\"${ep.code}\"></li>`)\n    li.text(ep.name + ' - ' + ep.code);\n    if (ep.code == window.epsg) {\n      li.addClass('select');\n      coordForm.find('div#projection input').val(li.text());\n      coordForm.find('div#projection input').attr('value', li.attr('value'));\n    }\n    coordForm.find('#latlon .chProj ul').append(li);\n  })\n  coordForm.find('div.combo-coord').on('click', function () {\n    $(this).find('div.dropdown').toggleClass('listshown');\n  })\n  coordForm.find('li').on('click', function () {\n    const input = $(this).parents('div.combo-coord').find('input');\n    input.val($(this).text());\n    input.attr('value', $(this).attr('value'))\n    $(this).parent().find('.select').removeClass('select')\n    $(this).addClass(\"select\");\n  })\n\n  ns.page.find('table.listado:visible').each(function (idx, table) {\n    const dt = cargarTablaMain(ns, table, cfg.pagelayer_set[idx]);\n    ns.page.find('table thead th[list]').each(async function () {\n      const elem = $(this);\n      const colId = this.getAttribute('col-id');\n      const colIdx = this.getAttribute('col-idx');\n      const selector = $(`<select class=\"form-control\" name=\"${colId}\"><option value=\"\" selected />${elem.text()}</selector>`);\n      elem.text('');\n      elem.append(selector);\n      const paramType = this.getAttribute('data-param-type');\n      const pagelayer_id = this.getAttribute('data-pagelayer-id');\n      if (colId == 'municipality__name') {\n        cargarMunicipios(selector);\n      } else if (paramType || pagelayer_id) {\n        const url = paramType ?\n          window.Urls.parameter_options(paramType) :\n          window.Urls.table_options_for_sourcetype(pagelayer_id, colId);\n        const response = await fetch(url);\n        const values = await response.json();\n        for (const m of values)\n          selector.append($(`<option>${m.name}</option>`))\n      }\n      selector.on('change', function (ev) {\n        dt\n          .column(colIdx)\n          .search($(this).val());\n        ev.preventDefault();\n      });\n    });\n    emul_mapa.on('change:update_elements', function () {\n      emul_mapa.set('update_elements', false, true);\n      dt.draw();\n    });\n\n  })\n}\n\nasync function cargarMunicipios(selector) {\n  const response = await fetch(window.Urls.municipalities());\n  const municipios = await response.json();\n  for (const m of municipios)\n    selector.append($(`<option>${m.name}</option>`))\n}\n\nexport function cargarTablaMain(ns, table, pageLayer) {\n  const buttons = [];\n  const layer_id = table.id.split('_')[2];\n  for (const action of window.parameters) {\n    if (action.type != 'LISTING_ACTION')\n      continue\n    if (action.parameter == 'CREATE_ELEMENT' && !(window.change_municipal_element || window.change_site_element))\n      continue\n    buttons.push({\n      text: `<i class=\"${action.CLASS}\"></i>`,\n      titleAttr: action.name,\n      action: function (evt, dt) {\n        if (action.parameter == 'XLSX_EXPORT')\n          exportar(dt, layer_id, 'xlsx')\n        else if (action.parameter == 'PDF_EXPORT')\n          exportar(dt, layer_id, 'pdf')\n        else if (action.parameter == 'CREATE_SIMULATION')\n          createSimulation('#' + table.id);\n        else if (action.parameter == 'CREATE_ELEMENT') {\n          const lyr = new SaverElementsLayer(pageLayer);\n          const filter = pageLayer.layer.source_type.model_query.filter;\n          if (filter.element_type__element_class__id)\n            lyr.element_class = [filter.element_type__element_class__id];\n          else\n            lyr.element_class = ',';\n          if (filter.element_type__id)\n            lyr.types = [filter.element_type__id];\n          if (filter.element_type__id__in)\n            lyr.types = filter.element_type__id__in;\n          lyr.createMapElement('#' + table.id);\n        }\n      }\n    });\n  }\n  const hideSearch = pageLayer.layer.extra?.hideSearch || pageLayer.extra?.hideSearch;\n  const hidePaging = pageLayer.layer.extra?.hidePaging || pageLayer.extra?.hidePaging;\n  const ret = $(table).DataTable({\n    language: getDTMessages(),\n    dom: `<'row'<'col-sm-6'r${hideSearch ? '' : 'f'}><'col-sm-6'B>>\n      <'row'<'col-sm-12't>>\n      <'row'<'col-sm-7'${hidePaging ? '' : 'i'}><'col-sm-5'${hidePaging ? '' : 'pl'}>>`,\n    fixedHeader: true,\n    lengthMenu: [20, 40, 80],\n    buttons: {\n      dom: {\n        button: {\n          tag: 'button'\n        }\n      },\n      buttons: buttons,\n      select: true,\n    },\n    pagingType: \"simple\",\n    retrieve: false,\n    serverSide: true,\n    processing: true,\n    searchDelay: 1000,\n    ajax: {\n      url: window.Urls.listing_json(layer_id),\n      dataSrc: 'data',\n    },\n    columnDefs: [{\n      // The `data` parameter refers to the data for the cell (defined by the\n      // `data` option, which defaults to the column being worked with, in\n      // this case `data: 0`.\n      orderable: false,\n      data: 0,\n      render: function (data) {\n        let ret = '';\n        for (const action of window.parameters) {\n          if (action.type != 'LISTING_ROW_ACTION')\n            continue\n          if ((action.parameter == 'EDIT_ELEMENT' || action.parameter == 'DELETE_ELEMENT') && !(window.change_municipal_element || window.change_site_element))\n            continue\n          // const action_id = action.parameter.replaceAll('_', ''); FIXME: 2022\n          const action_id = action.parameter.replace(/_/g, '');\n          ret += `<button title=\"${action.name}\" table_id=\"${table.id}\"\n                                 action=\"${action_id}\" id=\"${action_id}_${data}\"\n                                 class=\"${action.CLASS}\"></button>`;\n        }\n        if (ret === '')\n          ret += data;\n        return ret;\n      },\n      targets: 0\n    },],\n    drawCallback: function () {\n      const api = this.DataTable();\n      $(this).find('button').on('click', function (evt) {\n        evt.stopPropagation();\n        const data = api.row(this.closest('tr')).data();\n        const id = data[0];\n        const name = this.getAttribute('action');\n        evt.appendTo = '#listado_body';\n        evt.new_pos = {\n          my: 'center',\n          at: 'center',\n          of: evt.appendTo,\n          collision: 'fit',\n        };\n        if (name == 'OPENSIMULATION') {\n          window.open(window.Urls.simulation_page(id), '_blank');\n        } else if (name == 'EDITSIMULATION') {\n          evt.data = 'edit';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'SHARESIMULATION') {\n          evt.data = 'share';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'CLONESIMULATION') {\n          evt.data = 'clone';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'DELETESIMULATION') {\n          evt.data = 'delete';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'LOCKSIMULATION') {\n          evt.data = 'lock';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'INFOELEMENT') {\n          evt.data = 'info';\n          saverActOnElement.bind(this)(evt);\n        } else if (name == 'EDITELEMENT') {\n          evt.data = 'edit';\n          saverActOnElement.bind(this)(evt);\n        } else if (name == 'DELETEELEMENT') {\n          evt.data = 'delete';\n          saverActOnElement.bind(this)(evt);\n        } else if (name == 'GENERA5LANDFORECASTBEHAVE') {\n          evt.data = 'GEN_ERA5LAND_FORECAST_BEHAVE';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'FIREVIEWERA5LANDFORECASTBEHAVE') {\n          evt.data = 'FIRE_VIEW_ERA5LAND_FORECAST_BEHAVE';\n          actOnElement.bind(this)(evt);\n        } else if (name == 'DOWNLOADREPORT')\n          downloadReport(ns, data);\n      });\n    }\n  });\n  debounceSearch('#' + table.id);\n  $('#' + table.id).on('click', 'tr', function () {\n    $(this).toggleClass('selected');\n  });\n\n  return ret;\n}\n\nfunction verifyParameters(reportParameters) {\n  let ok = true;\n  const ask_for = this ? $(this).dialog('option', 'ask_for') : {};\n  const munis = reportParameters.find('select[name=\"municipality\"]');\n  const poi = reportParameters.find('select[name=\"pois\"]');\n  const layer = reportParameters.find('select[name=\"layer\"]');\n  const email_address = reportParameters.find('input[name=\"email_address\"]:valid');\n  if (ask_for.layer && !layer.val()) {\n    ok = false;\n    layer.fadeOut(500).fadeIn(500);\n  }\n  if (ask_for.email_address && (email_address.length && !email_address.val())) {\n    ok = false;\n    email_address.fadeOut(500).fadeIn(500);\n  }\n  const validCoords = getFormCoords(reportParameters);\n  if ((ask_for.municipalities || ask_for.pois || ask_for.coords) &&\n    ((poi.val().length + munis.val().length) == 0) && !validCoords.srcproj) {\n    ok = false;\n    if ($('#tabla_coords').is(':visible')) $('#tabla_coords').fadeOut(200).fadeIn(200);\n    if (munis.parent().is(':visible')) munis.parent().fadeOut(200).fadeIn(200);\n    if (poi.parent().is(':visible')) poi.parent().fadeOut(200).fadeIn(200);\n  }\n  const form = reportParameters.find('form');\n  if (ok) {\n    let url = form[0].action + '?' + form.serialize();\n    if (validCoords.srcproj) {\n      url += `&crs=${validCoords.srcproj}&x=${validCoords.xlong}&y=${validCoords.ylat}`;\n    }\n    if (ask_for.email_address) {\n      $.ajax({\n        url: url,\n        cache: false,\n        success: response => $(response.message).dialog()\n      })\n    }\n    else {\n      const onload_func = function () {\n        if (this?.document && 'error' == this.document.body.id) {\n          showProblemDialog(this, url);\n        }\n      }\n      const foo = window.open(url);\n      foo.addEventListener('DOMContentLoaded', onload_func)\n    }\n    if (this)\n      $(this).dialog('close');\n  }\n}\nfunction debounceSearch(tableId) {\n  const $searchBox = $(tableId + \"_filter input[type='search']\");\n  $searchBox.off();\n  const searchDebouncedFn = debounce(function () {\n    $(tableId).DataTable().search($searchBox.val()).draw();\n  }, 600);\n  $searchBox.on(\"keyup\", searchDebouncedFn);\n}\n\n/* from https://davidwalsh.name/javascript-debounce-function */\nfunction debounce(func, wait, immediate) {\n  let timeout;\n  return function () {\n    const context = this,\n      args = arguments;\n    const later = function () {\n      timeout = null;\n      if (!immediate) func.apply(context, args);\n    };\n    const callNow = immediate && !timeout;\n    clearTimeout(timeout);\n    timeout = setTimeout(later, wait);\n    if (callNow) func.apply(context, args);\n  };\n}\nfunction downloadReport(ns, data) {\n  const id = data[0];\n  $('input[name=\"report\"]').val(id);\n  const extra = data[data.length - 1];\n  const batch = extra.batch;\n  const ask_for = extra.ask_for || {};\n  if (batch) {\n    ask_for.email_address = true;\n  }\n  const reportParameters = ns.page.find('.report-parameters');\n  $('#email_address').toggle(ask_for.email_address !== undefined);\n  $('#tabla_municipios').toggle(ask_for.municipalities !== undefined);\n  $('#tabla_coords').toggle(ask_for.coords !== undefined);\n  $('#tabla_pois').toggle(ask_for.pois !== undefined);\n  $('#tabla_capas').toggle(ask_for.layers !== undefined);\n  if ($.isEmptyObject(ask_for))\n    return verifyParameters(reportParameters);\n  const calendar = reportParameters.find('div.calendar');\n  const fp = configureCalendar(calendar, false, extra);\n  if (ask_for.date) {\n    calendar.removeClass('hidden');\n  }\n  const yearCalendar = reportParameters.find('div.calendar_year');\n  if (ask_for.year && yearCalendar.is(':hidden')) {\n    yearCalendar.removeClass('hidden');\n    yearCalendar.find('input').val(new Date().getFullYear());\n  }\n  if (ask_for.layers)\n    cargarTabla('#tabla_capas', window.Urls.layers_by_report(id), undefined, true);\n  else\n    $('#tabla_capas select').val([]);\n  const model = $('.model.tabla_dimensiones');\n  model.siblings('.tabla_dimensiones').remove();\n  if (ask_for.dimensions) {\n    for (const [dim, title] of Object.entries(extra.ask_for.dimensions)) {\n      const new_tabla = model.clone();\n      const new_id = `tabla_dimensiones_${dim}`;\n      new_tabla.find('h4').text(title);\n      new_tabla.find('select').attr('name', dim);\n      new_tabla.attr('id', new_id).removeClass('model').insertBefore(model).show();\n      cargarTabla('#' + new_id, window.Urls.dimension_values(dim), undefined, true);\n    }\n  }\n  if (ask_for.coords !== undefined)\n    $('#tabla_coords input').val('');\n  if (ask_for.municipalities)\n    cargarTabla('#tabla_municipios', window.Urls.municipalities());\n  else\n    $('#tabla_municipios select').val([]);\n  const ask_for_pois = extra.ask_for?.pois;\n  if (ask_for_pois) {\n    if (ask_for_pois.title)\n      $('#tabla_pois h4').text(ask_for_pois.title)\n    const st = ask_for_pois.source_type;\n    const et = ask_for_pois?.element_type;\n    if (st)\n      cargarTabla('#tabla_pois', window.Urls.pois_json_by_st(st));\n    else if (et)\n      cargarTabla('#tabla_pois', window.Urls.pois_json_by_et(et));\n  }\n  else\n    $('#tabla_pois select').val([]);\n  reportParameters.removeClass('hidden');\n  reportParameters.show().animate({ width: 'auto', height: 'auto' });\n  reportParameters.dialog({\n    title: data[1],\n    height: 'auto',\n    width: 'auto',\n    buttons: [{\n      text: window.gettext('Aceptar'),\n      click: function () { verifyParameters.call(this, reportParameters) },\n    }],\n    modal: true,\n    ask_for,\n    open: () => $('button.ui-dialog-titlebar-close').attr('title', window.gettext('Cerrar')),\n    close: () => {\n      reportParameters.find('div.calendar').addClass('hidden');\n      reportParameters.find('div.calendar_year').addClass('hidden');\n      reportParameters.find('div#email_address').addClass('hidden');\n      reportParameters.find('div.multi.flex').toggle(false);\n      reportParameters.find('#tabla_coords').toggle(false);\n      fp.destroy();\n      reportParameters.dialog('destroy');\n    },\n  });\n}\n\nexport function configureCalendar(\n  calendar_element,\n  enableTime = true,\n  extra = {}\n) {\n  const pastDays = Number.isInteger(extra.past) ? extra.past : null;\n  const futureDays = Number.isInteger(extra.future) ? extra.future : null;\n  const now = dayjs();\n  const defaultDate = now.toDate();\n  const options = {};\n\n  if (pastDays !== null)\n    options.minDate = now.subtract(pastDays, 'day').toDate();\n\n  if (futureDays !== null)\n    options.maxDate = now.add(futureDays, 'day').toDate();\n\n  return flatpickr(calendar_element, {\n    defaultDate,\n    wrap: true,\n    altInput: true,\n    altFormat: enableTime ? 'd-m-Y H:i' : 'd-m-Y',\n    dateFormat: 'Y-m-d',\n    allowInput: true,\n    clickOpens: false,\n    enableTime,\n    time_24hr: true,\n    minuteIncrement: 1,\n    appendTo: calendar_element.find('input.form-control')[0],\n    ...options\n  });\n}\n\nexport function cargarTabla(tableId, url, selected_centroids) {\n  const sel = $(tableId + ' select');\n  if (sel.length === 0)\n    return;\n  if (sel.hasClass(\"select2-hidden-accessible\"))\n    // Ya inicializado, no hay api \n    // https://select2.org/programmatic-control/methods#checking-if-the-plugin-is-initialized\n    return;\n  if (selected_centroids) {\n    for (const r of selected_centroids) {\n      if (r.id === null)\n        continue\n      const opt = new Option(r.name, r.id, true, true);\n      opt.dataset.name = r.name;\n      opt.dataset.centroid = r?.centroid?.coordinates ? r.centroid.coordinates : r.centroid;\n      sel.append(opt);\n    }\n    selected_centroids.length = 0;\n  }\n\n  const ret = sel.select2({\n    placeholder: \"buscar...\",\n    dropdownParent: $('body'),\n    width: '100%',\n    closeOnSelect: false,\n    ajax: {\n      url,\n      dataType: 'json',\n      processResults: function (data) {\n        const ret = {\n          results: data.map(function (r) {\n            return {\n              id: r.id,\n              text: r.name,\n              data: {\n                name: r.name,\n                centroid: r?.centroid?.coordinates ? r.centroid.coordinates : r.centroid,\n              },\n            };\n          })\n        };\n        return ret;\n      },\n    },\n  });\n  return ret\n}\n\n","import { $, global_init } from '../../../../moderna_meteogrid/statix/js/base.mjs';\n\nimport { cargarTablas } from './informes.mjs';\n\n$(function () {\n  global_init();\n  $('#saver_dialogs').load(window.Urls.saver_dialogs());\n  $('#simulation_dialogs').load(window.Urls.simulation_dialogs());\n\n  for (const ns of window.namespaces)\n    if (ns.content_model == 'listingpage') {\n      $.getJSON(window.Urls.page_json(ns.page_id), async function (cfg) {\n        cargarTablas(ns, cfg);\n      });\n    }\n});\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 755;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t755: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkemmet\"] = self[\"webpackChunkemmet\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [96], () => (__webpack_require__(1679)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","leafPrototypes","getProto","window","$","customParseFormat","utc","duration","pluralGetSet","_","gettext","initialized","form","values","serializeArray","field","Object","find","name","length","value","toJSON","URL","location","searchParams","get","locale","langMap","en","es","fr","ca","lang","navigator","languages","l","split","localize","headerLeft","headerRight","selectableHeader","selectionHeader","afterInit","that","this","$selectableSearch","$selectableUl","prev","$selectionSearch","$selectionUl","selectableSearchString","$container","attr","selectionSearchString","select_all","select_none","click","$selectableContainer","elemsSelector","$selectionContainer","qs1","quicksearch","on","e","cache","which","focus","qs2","afterSelect","afterDeselect","isObject","item","Array","isArray","mergeDeep","target","sources","source","shift","key","assign","transform_point","xy","sourceProj","destProj","epsg","fluidDialog","each","$this","dialog","data","width","parseInt","options","maxWidth","css","height","maxHeight","option","position","closest","draggable","get_horizon","dims","v","startsWith","includes","ConvertDMSToDD","degrees","minutes","seconds","direction","dd","a","f","b","originalEvent","touches","preventDefault","c","changedTouches","d","document","createEvent","initMouseEvent","screenX","screenY","clientX","clientY","dispatchEvent","support","touch","ui","mouse","prototype","_mouseInit","_mouseDestroy","_touchStart","_mouseCapture","_touchMoved","_touchMove","_touchEnd","element","bind","touchstart","proxy","touchmove","touchend","call","unbind","tz","Intl","DateTimeFormat","resolvedOptions","timeZone","dimension_controls","getBigTileGrid","projectionObj","undefined","btn","id","my","at","of","collision","uniqId","i","id_counter","Layer","constructor","ns","pageLayer","time_delta","interactive_map","_pageLayer","_layer","layer","_layerTypeLocator","layertype","locator","_baseLayer","_refLayer","_varLayer","extra","extra_dim","_extra","title","_title","name_and_unit","service","url","replace","_url","source_type","_serviceLayer","servicelayer","_legend","legend","_information","information","_time_delta","_interactive_map","_dynDate","_dynInfo","getTooltip","ol_factory","Tile","zIndex","weight","order","getLayerInfo","checkbox","tooltipBtn","tooltip","hide","self","append","page","ishidden","is","info","empty","toggle","shown","checked","setSliderLayer","ol_layer","_ol_layer","sliderCnt","inpt","etq","onmouseover","w","innerHTML","parseFloat","style","left","String","hidden","onmouseout","oninput","setOpacity","setCalculatedDate","props","STATIC_LAYER","dt","base_time","time","year","Error","format","error","message","console","registerInTree","ol_map","_ol_map","closedTree","visible_layers","some","setVisible","raiz","arbol","existing_selector","selector","clone","leyenda","removeClass","show","folder","orig_path","path","component","push","join","carpeta_existente","carpetaDestino","text","thisPath","folderTitle","pop","toggleClass","prop","disabled","addClass","layerTitle","layers_opacity","layer_opacity","set","legendDialog","mapa","pl","lyr_name","getTargetElement","legendUrl","classList","contains","setTimeout","legend_element","new_pos","getPosDefault","pixel","getPixelFromCoordinate","coordinate","once","pos","mytarget","existing_legend_element","appendTo","classes","autoOpen","resizable","minHeight","open","one","showLegend","control","controls","use","unuse","unset","val","trigger","reload","dim","dimensions","value_type","dim_value","control_empty","reloaded_dims","updateParams","getVisible","_dimension_controls","crearCapaOL","extent_local","src","get_async_source","extraOpts","getExtraOpts","ret","opacity","visible","baseLayer","displayInLayerSwitcher","time_management","simmer_id","unit","effective_unit","unbound","setExtent","addLayer","layerCaption","_caption","WMSLayer","updateDynInfo","Urls","dyn_info","ajax","dataType","contentType","TIME","getParams","done","resp","debug","fail","_src","params","LAYERS","STYLES","repeat","__tz","tileGrid","projection","proxy_meteo2","VERSION","AUTH_TYPE","src_factory","ratio","singleTile","TileWMS","ImageWMS","finalTime","timeFormat","firstTime","secondTime","effective_time","add","ISOstart","ISOend","time_type","Math","random","Image","pageLayerId","TRANSPARENT","getLegendUrl","l_id","isVisible","fondo","getLayers","getArray","capas","map","toArray","references","filter","x","oldUrl","href","newUrl","history","replaceState","className","typing","super","polygon","viewbox","bounded","alertmsg","getTitle","search","type","address","requestData_idee","s","name_equals","maxresults","polygon_geojson","requestData_cc","addressdetails","q","limit","select","getMap","success","cord","processData","results","err","alert","encodeURI","portal","portalNumber","JSON","parse","slice","opt","result","lat","Number","lng","isNaN","cords","olproj","getView","getProjection","animate","center","zoom","max","getZoom","marker","geometry","color_marker","getComputedStyle","body","getPropertyValue","trim","iconStyle","image","color","crossOrigin","anchorOrigin","anchor","anchorXUnits","anchorYUnits","scale","setStyle","vectorSource","features","markerVectorLayer","Vector","setZIndex","Infinity","getMarkerVectorLayer","json","obj","Promise","resolve","reject","test","toQueryString","encodeUrlXhr","callback","head","script","createElement","callbackName","round","Date","now","setAttribute","indexOf","removeChild","appendChild","jsonp","fetch","method","mode","then","r","catch","keys","reduce","k","encodeURIComponent","autocomplete","cback","cont","protocol","res","handleResponse","drawList_","auto","ul","querySelector","_list","li","min","equalFeatures","addEventListener","_handleSelect","currentTarget","getAttribute","Element","initializeMapa","mapa_","configureCalendar","calendar_element","enableTime","timelinectl","minDate","timeline","getCustomTime","toISOString","maxDate","wrap","dateFormat","altInput","altFormat","allowInput","clickOpens","time_24hr","minuteIncrement","elementValue","toString","crearSubCasilla","vdat","klass","readOnly","casilla","getJSON","parameter_options","parameter_type","fixed","html","selected","dvalue","mvalue","local","hasTime","input_date","columns","evt","crearCasilla","recuadro","klasses","idx","entries","cell","file_input","uploadFileReader","fileInput","input","maxSize","handleSelected","handleEvent","event","floor","loaded","total","buttons","showAlertDialog","removeListeners","reader","addListeners","removeEventListener","FileReader","parent","remove","selectedFile","files","size","readAsDataURL","msg","div_error","error_element","modal","close","crearFilaData","tableId","old_data","new_data","element_id","poi_coords","old_vars","groupBy","calc_vars","dimension_values","new_vars","all_vars","Set","concat","map_dimensions","button","class","model_table","total_table","table_one","table_two","table_n","tabs","horizon_opt","table","data_dim","forEach","horizon_name","splice","div_table","dim_opt","ordered_values","td","innerText","parentElement","NumberFormat","maximumFractionDigits","div_tab","this_tab","other_dim","tab","dim_opt2","dimensionalTables2Pdf","scrollTop","hmax","poi","elements","target_graphs","gc","addControl","element_ids","activeDimensions","groupByValue","boxplot","hasClass","layers","layers_loc","set_layers","mdt","centroid","radius","coordinates_epsg","group_by_unit","print_pluma","openNewWindow","plumas_pdf","redraw","create_graph_control","same_srid","showCalcVars","edTable","rowspan","possibleVars","cells","vdat_old","existentes","multiple","fadeToggle","calculation_id","HORIZON","currentYear","getFullYear","hasMapDimensions","dat","simpleData","modelTR","tr","insertBefore","firstTD","first","replaceWith","miscCell","edRow","col","suffix","comments","next","change","bocadillo","before","fillElementTypes","currentTypeId","element_class","selectElem","types","element_types","pk","is_new","elems","urlFunction","element_change_info","element_info","pending_changes","center_proj","toFixed","vv","model_row","related","new_row","element_type__name","element_type_id","geomx","parameter_change","element_type","geom","old_geom_data","wkt","old_geom","readGeometry","dataProjection","area_data","area","formatArea","feat","readFeature","featureProjection","available_data","data_menu","elem","createAddDataButton","unshift","showUserInfo","username","user_info","actOnElement","mapTarget","op","attributes","lastElementPixel","width_edit","innerWidth","minWidth_edit","clipboard","writeText","innerHeight","print_element_info","element_delete","operation","element_commit_delete","writeFeature","element_commit_edit","fixDates","FormData","ipt","element_edit","ww","outerWidth","doble_height","resize","diff","element_commit_create","element_edit_new","is_pending_create","element_cancel_create","element_cancel_edit","pickr","datetime","isValid","menu","idx_available_data","updateStyles","tree","srcElements","type_filters","substring","TYPES","zoomToPoint","view","map_geom","GeoJSON","fit","setZoom","SaverElementsLayer","site","readonly","showElementsAffected","hideFilter","hidefilter","hideChanges","hidechanges","type_locator","model_query","element_type__locator","type_locator_in","element_type__locator__in","registerGeomButtons","y","srcEpsg","x2","y2","p","intersectsExtent","calculateExtent","new_geom","epsgSelect","site_cfg","site_epsgs","ep","code","pointByCoords","polygonBySize","h","getCenter","pol_extent","getExtent","pol_extent_w","pol_extent_h","transform","getPolygonFromDistance","copia","carpeta_nueva","children","calendar_element_from","calendar_element_to","lyrElements","load","saver_dialogs","lyrElementChanges","async","getSource","municipio","response","municipality","extent","corners","transform_extent","from","to","defaultValue","cbx","createMapElement","elementsAffected","doElementsAffected","olmap","wms","SIMULATION_ID","simulation_id","CLASE","SRS","MASK_SITE","SITE","srcElementChanges","clearTimeout","requestList","refresh","requestInfo","fileref","iconos_css","getElementsByTagName","cargarCSS","cargarArbol","cargarMunicipios","municipalities","municipios","m","element_tree","ok","selection","nodes","n","refreshIndeterminateState","et_ids","indeterminate","mapDiv","old_img","offset","pageX","top","pageY","et_id","dataset","uid","img","getLayersArray","elementRow","tt","properties","stringify","element_type__element_class","change_municipal_element","element_type__municipal","validate_element_changes","change_site_element","elementchange__parameter_change__locator","after","references__id","parameter_change__locator","elementTable","newDiv","viewResolution","getResolution","viewProjection","urls","getFeatureInfoUrl","INFO_FORMAT","TOLERANCE","simple","when","jsons","containerId","elem_type","row","it","locatable","fadeTo","getGeometry","writeGeometry","element_create","textContent","simul_affected_elements","elements_by_minutes","abs_time_for_time","elements_by_type","all_features","abs_time_iso","abs_time","uniq_features","layer_features","col_abs","total_col","ids","ids_by_type","uniq_ids_by_type","count_model","off","stopPropagation","getColor","colors","Control","isDialog","info_tabla","oProj","deg","units","coordXY","projDesc","epsg_name","toUpperCase","new_type","targets","base_data","new_data_groups","allgroupedDimValues","groupedDim","infoDims","groupColumns","dimsName","entry","hasOwnProperty","uniqueValues","acc","columnsWithMultipleValues","index","valueToMove","orig_serie","fromEntries","dimsLabel","columnControl","uniqueColumn","multiColumn","groupLabel","layer_name","boxmean","line","serie","j","new_values","groupedString","newValue","dimsnewValue","delenda","old_layout","layout","xaxis","yaxis","hoverlabel","namelength","hovermode","font","margin","showlegend","boxmode","offsetgroup","hoverinfo","threshold","purge","observer","unobserve","analyers","pixelSize","frameState","pixelToCoordinateTransform","point","con_pluma","newActiveDimensions","dc","dim_values","dval","o","caption","getTarget","setSize","setResolution","setCenter","data_plumas_mapping","dimDataByLayer","getQueryLayers","lyr","urls_plumas","group_dims","isEmptyObject","layers_by_graphs","this_url","dim_mapping","getCombinatedDims","numUrls","calls","graphs","allSettled","loadGraphs","ResizeObserver","paddingLeft","paddingRight","paddingTop","paddingBottom","clientWidth","origHeight","newLayout","clientHeight","infolayer","observe","dimensionValues","graph_layers","info_punto_json","layerObj","queryable","layerDimensions","layerDimensionValues","combinations","graph_layer","getTimeParams","combination","title_dims","dims_names","saved_params","dim_name","showDimSelector","dimsDialogExistente","dimControls","captions","divSel","$divSel","sel","fadeOut","fadeIn","keepType","ctl","div","multiSelect","usage","dimsDialog","selectHTML","prepend","tzFunction","pt","id_mdt","all_data","subplots","yaxises","unit_mapping","order_mapping","var_mapping","can_be_grouped","y_idx","status","carga_serie","jqTitle","subplot","datum","jqTarget","titles","fixed_times","legend_title","short_name","sort","d1","d2","hovertext","automargin","range","target_tab","dim_id","layer_loc","obj_name","obj_count","dim_title_opt","dim_title","legendgroup","hovertemplate","dynDate","t","pad","xlegend","family","xanchor","yanchor","orientation","bgcolor","create_graph","Event","mrange0","mrange1","range0","range1","emit","listOfDates","listOfValues","listOfTable","listOfFixed_times","listOfDimMapping","layerdataFromJson","name_vars","arrayOfDates","arrayOfValues","arrayOfTable","arrayOfFixed_times","arrayOfDimMapping","horizon_dim","info_dim_data","title_opt","n_opt","info_dim_series","info_dim_serie","id2","ordered","dates","fixed_dates","createItems","elementdataFromJson","count_obj","name_obj","i_serie","data_pluma","with","name_opt","label_columns","table_info","nexttotitle","columnsObject","tr_title","table_info_element","colspan","alias","templateIn","_template","content","vvv","customdata","NaN","element_name","zeroline","showgrid","showline","ticks","showticklabels","layout_extra","minx","maxx","xmargin","subtract","data_sorted","Map","flatMap","xValue","new_x","new_y","ft","fixedTime","bordercolor","gridcolor","tickformat","fixedrange","ticktext","tickmode","tickvals","every","match","displayModeBar","g","trace","flechas","angle","flecha","currentTime","other_target","numSeries","xx","ix","xxx","isAfter","dx","xpx","hover","eventdata","ed","toExcel","zip","headers_dimensions","data_rows","header","layerActualDims","i_value","full_name","json_dimensions","dimData","locator_unit","utcOffset","toDate","replaceAll","$x","headers","numFmt","wb","ws","addWorksheet","fileName","addRows","buffer","xlsx","writeBuffer","fileExtension","blob","Blob","file","saveAs","variable","data_history","arrayFeatures","time_prop","has_time","i_v","single_table","fixedYears","ef_time","dim_mapping_length","id_dim2","grouped_combinations","n_op","dim_op","RegExp","days_back","days_forward","round_to_days","t1_iso","t1p","t1","startOf","t2","t3","toLocaleString","CESIUM_BASE_URL","Cesium","Ion","defaultAccessToken","defs","SAVER","OSM","WMS","WMSFLOW","getColorStops","SERVICE","REQUEST","FORMAT","PAGELAYERID","WIDTH","HEIGHT","URLSearchParams","colorStops","jsonColors","maxSpeed","Flow","dataTileSize","CRS","dataTileGrid","dataTileProjection","wind","DataTile","transition","wrapX","loader","z","tileCoord","BBOX","getTileCoordExtent","warn","Float32Array","u","setSource","WMTS","matrixSet","WMTSCapabilities","read","setUrl","Bing","BingMaps","imagerySet","XYZ","maxZoom","KML","dateInputFormat","datatable","datatableId","activeControl","DataTable","action","alertOverlay","simulation_delete","share_window","formData","edit_users","getAll","ro_users","alert_window","simulation_share","simulation_users","sel_edit","sel_ro","rellena_sel","rel","relation","lock_window","simulation_lock","element_layer","el","element_update","geom_from_simulation","simulation_num","simulation_report","popup","write","simulation_clone","simulation_page","fire_view_era5land_forecast_behave","gen_era5land_forecast_behave","simulation_edit","simulation_edit_new","propDialog","createProp_element","simulation_user_groups","group","read_only","simulationtype_id","simulation_info","simulation_info_new","initdate","events","cls","getElementsByClassName","defaultDate","simulationtype","show_button","__edit","itype","which_table","simulation_types","table_options","SIMUL","emul_mapa","exportar","layer_id","formato","start","draw","listingFile","param","cargarTablas","cfg","coordForm","parents","parameters","parameter","CLASS","titleAttr","from_datatable","element_type__element_class__id","element_type__id","element_type__id__in","hideSearch","hidePaging","language","dom","fixedHeader","lengthMenu","tag","pagingType","retrieve","serverSide","processing","searchDelay","listing_json","dataSrc","columnDefs","orderable","render","action_id","drawCallback","api","batch","ask_for","email_address","reportParameters","coords","pois","verifyParameters","calendar","fp","pastDays","isInteger","past","futureDays","future","date","yearCalendar","cargarTabla","layers_by_report","model","siblings","new_tabla","new_id","ask_for_pois","st","et","pois_json_by_st","pois_json_by_et","destroy","downloadReport","$searchBox","searchDebouncedFn","func","timeout","context","args","arguments","apply","debounce","debounceSearch","cargarTablaMain","pagelayer_set","colId","colIdx","paramType","pagelayer_id","table_options_for_sourcetype","ev","column","munis","validCoords","srcproj","xlong","ylat","lat_degrees","lat_mins","lat_segs","lat_dir","long_degrees","long_mins","long_segs","long_dir","serialize","onload_func","showProblemDialog","selected_centroids","Option","coordinates","select2","placeholder","dropdownParent","closeOnSelect","processResults","csrftoken","beforeSend","xhr","settings","crossDomain","setRequestHeader","ajaxStart","ajaxComplete","handles","delay","slideUp","not","$dropdowns","documentElement","parentNode","closeDropdown","namespaces","page_id","mapas","csrfmiddlewaretoken","getElementById","fileuploader","class_","uploadFile","layerTree","setup_layer_tree_filter","global_init","simulation_dialogs","content_model","page_json","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","O","chunkIds","fn","priority","notFulfilled","fulfilled","getPrototypeOf","__esModule","create","def","current","getOwnPropertyNames","definition","defineProperty","enumerable","globalThis","Function","Symbol","toStringTag","nmd","paths","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","chunkLoadingGlobal","__webpack_exports__"],"sourceRoot":""}