From 51f0b5c238b1f850e5359c4b8ade24cb5d901e90 Mon Sep 17 00:00:00 2001 From: tyrasd Date: Sun, 3 Nov 2024 18:08:05 +0000 Subject: [PATCH] deploy: b3702214d7639ff901a298736d2f26038ab2588c --- assets/{index-CQ5sbdEf.js => index-CfgRz6jI.js} | 4 ++-- assets/{index-CQ5sbdEf.js.map => index-CfgRz6jI.js.map} | 2 +- index.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename assets/{index-CQ5sbdEf.js => index-CfgRz6jI.js} (99%) rename assets/{index-CQ5sbdEf.js.map => index-CfgRz6jI.js.map} (99%) diff --git a/assets/index-CQ5sbdEf.js b/assets/index-CfgRz6jI.js similarity index 99% rename from assets/index-CQ5sbdEf.js rename to assets/index-CfgRz6jI.js index 23758350..32091794 100644 --- a/assets/index-CQ5sbdEf.js +++ b/assets/index-CfgRz6jI.js @@ -751,7 +751,7 @@ ${H}${D}`)}for(let D=0;D{var R=(Y,G)=>{Y?P(new Error(Y)):H(G)};_generatePkceChallenge(Y=>x(Y,R))}))};function x(H,P){var R=generateState(),Y=g.url+"/oauth2/authorize?"+utilQsString({client_id:g.client_id,redirect_uri:g.redirect_uri,response_type:"code",scope:g.scope,state:R,code_challenge:H.code_challenge,code_challenge_method:H.code_challenge_method});if(g.singlepage){if(!store.enabled){var G=new Error("local storage unavailable, but require in singlepage mode");G.status="pkce-localstorage-unavailable",P(G);return}var X=utilStringQs(window.location.search.slice(1));X.code?B.bootstrapToken(X.code,P):(S("oauth2_state",R),S("oauth2_pkce_code_verifier",H.code_verifier),window.location=Y)}else{var ee=600,Ae=550,le=[["width",ee],["height",Ae],["left",window.screen.width/2-ee/2],["top",window.screen.height/2-Ae/2]].map(function(fe){return fe.join("=")}).join(","),ae=window.open("about:blank","oauth_window",le);B.popupWindow=ae,ae.location=Y,ae||(G=new Error("Popup was blocked"),G.status="popup-blocked",P(G))}window.authComplete=function(fe){var ye=utilStringQs(fe.split("?")[1]);if(ye.state!==R){G=new Error("Invalid state"),G.status="invalid-state",P(G);return}Q(ye.code,H.code_verifier,ge),delete window.authComplete};function ge(fe,ye){if(g.done(),fe){P(fe);return}var me=JSON.parse(ye.response);S("oauth2_access_token",me.access_token),P(null,B)}}function Q(H,P,R){var Y=g.url+"/oauth2/token?"+utilQsString({client_id:g.client_id,redirect_uri:g.redirect_uri,grant_type:"authorization_code",code:H,code_verifier:P});B.rawxhr("POST",Y,null,null,null,R),g.loading()}B.bringPopupWindowToFront=function(){var H=!1;try{B.popupWindow&&!B.popupWindow.closed&&(B.popupWindow.focus(),H=!0)}catch{}return H},B.bootstrapToken=function(H,P){var R=S("oauth2_state");S("oauth2_state","");var Y=utilStringQs(window.location.search.slice(1));if(Y.state!==R){var G=new Error("Invalid state");G.status="invalid-state",P(G);return}var X=S("oauth2_pkce_code_verifier");S("oauth2_pkce_code_verifier",""),Q(H,X,ee);function ee(Ae,le){if(g.done(),Ae){P(Ae);return}var ae=JSON.parse(le.response);S("oauth2_access_token",ae.access_token),P(null,B)}},B.fetch=function(H,P){if(B.authenticated())return R();return g.auto?B.authenticateAsync().then(R):Promise.reject(new Error("not authenticated"));function R(){return P=P||{},P.headers||(P.headers={"Content-Type":"application/x-www-form-urlencoded"}),P.headers.Authorization="Bearer "+S("oauth2_access_token"),fetch(H,P)}},B.xhr=function(H,P){if(B.authenticated())return R();if(g.auto){B.authenticate(R);return}else{P("not authenticated",null);return}function R(){var G=H.prefix!==!1?g.url+H.path:H.path;return B.rawxhr(H.method,G,S("oauth2_access_token"),H.content,H.headers,Y)}function Y(G,X){G?P(G):X.responseXML?P(G,X.responseXML):P(G,X.response)}},B.rawxhr=function(H,P,R,Y,G,X){G=G||{"Content-Type":"application/x-www-form-urlencoded"},R&&(G.Authorization="Bearer "+R);var ee=new XMLHttpRequest;ee.onreadystatechange=function(){ee.readyState===4&&ee.status!==0&&(/^20\d$/.test(ee.status)?X(null,ee):X(ee,null))},ee.onerror=function(le){X(le,null)},ee.open(H,P,!0);for(var Ae in G)ee.setRequestHeader(Ae,G[Ae]);return ee.send(Y),ee},B.preauth=function(H){return H&&H.access_token&&S("oauth2_access_token",H.access_token),B},B.options=function(H){return arguments.length?(g=H,g.url=g.url||"https://www.openstreetmap.org",g.auto=g.auto||!1,g.singlepage=g.singlepage||!1,g.loading=g.loading||function(){},g.done=g.done||function(){},B.preauth(g)):g};var S;if(store.enabled)S=function(H,P){if(arguments.length===1)return store.get(g.url+H);if(arguments.length===2)return store.set(g.url+H,P)};else{var D={};S=function(H,P){if(arguments.length===1)return D[g.url+H];if(arguments.length===2)return D[g.url+H]=P}}return B.options(g),B}function utilQsString(g){return Object.keys(g).filter(function(B){return g[B]!==void 0}).sort().map(function(B){return encodeURIComponent(B)+"="+encodeURIComponent(g[B])}).join("&")}function utilStringQs(g){for(var B=0;B{if(B)return g(B);loadQueries(g)})},save(g,B){auth.authenticated()?saveQuery(g,B):auth.authenticate(x=>{if(x)return B(x);saveQuery(g,B)})},delete(g,B){if(!auth.authenticated())return B(new Error("must be logged in to delete a synced query"));g={name:g,deleteMe:!0},saveQuery(g,B)},logout(){auth.authenticated()&&auth.logout()},authenticated(){return enabled&&auth.authenticated()}};function loadQueries(g){auth.xhr({method:"GET",path:"/api/0.6/user/preferences"},(B,x)=>{if(B)return g(B);let Q=0,S;(S=x.querySelector(`preference[k="${configs.settingNamespace}_query-count"]`))&&(Q=+S.getAttribute("v"));const D=[];for(let H=0;H{if(x)return B(x);const D=S.querySelector("preferences"),H=D.querySelectorAll(`preference[k^="${configs.settingNamespace}_query"]`);for(const Y of H)Y.remove();let P=!0;Q.forEach((Y,G)=>{Y.name==g.name&&(Y.query=g.query,P=G)}),P===!0?Q.push(g):g.deleteMe&&Q.splice(P,1);const R=S.createElement("preference");R.setAttribute("k",`${configs.settingNamespace}_query-count`),R.setAttribute("v",Q.length),D.appendChild(R);for(let Y=0;Y200)return B(new Error("query name too long to be saved on osm.org"));const X=Math.ceil((G.query.length+G.name.length+8)/255);if(X>9)return B(new Error("query too long to be saved on osm.org"));let ee=`p=${X}`;ee+=`&n=${G.name}`,ee+=`&q=${G.query}`,ee=ee.match(/.{1,255}/g);for(let Ae=0;Ae{if(Y)return B(Y);B(null,Q)})})}const cache={};class nominatim{static request(B,x){$.ajax(`https://nominatim.openstreetmap.org/search?X-Requested-With=${configs.appname}`,{data:{format:"json",q:B},success(Q){if(typeof Q=="string")try{Q=JSON.parse(Q)}catch{}cache[B]=Q,x(void 0,Q)},error(){const Q="An error occurred while contacting the osm search server nominatim.openstreetmap.org :(";console.log(Q),x(Q,null)}})}static get(B,x){return cache[B]===void 0?this.request(B,x):x(void 0,cache[B]),this}static getBest(B,x,Q){return Q||(Q=x,x=null),this.get(B,(S,D)=>{if(S){Q(S,null);return}x&&(D=D.filter(x)),D.length===0?Q("No result found",null):Q(S,D[0])}),this}}function map2bbox(g){let B;ide.map.bboxfilter&&ide.map.bboxfilter.isEnabled()?B=ide.map.bboxfilter.getBounds():B=ide.map.getBounds();const x=Math.min(Math.max(B.getSouthWest().lat,-90),90),Q=Math.min(Math.max(B.getNorthEast().lat,-90),90),S=Math.min(Math.max(B.getSouthWest().lng,-180),180),D=Math.min(Math.max(B.getNorthEast().lng,-180),180);if(g=="OverpassQL")return`${x},${S},${Q},${D}`;if(g=="xml")return`s="${x}" w="${S}" n="${Q}" e="${D}"`}function map2coord(g){const B=ide.map.getCenter();if(g=="OverpassQL")return`${B.lat},${B.lng}`;if(g=="xml")return`lat="${B.lat}" lon="${B.lng}"`}function relativeTime(g,B){const x=Date.now();if(g==""&&(g="0 seconds"),g=g.toLowerCase().match(/(-?[0-9]+) ?(seconds?|minutes?|hours?|days?|weeks?|months?|years?)?/),g===null){B("");return}const Q=parseInt(g[1]);let S;switch(g[2]){case"second":case"seconds":S=1;break;case"minute":case"minutes":S=60;break;case"hour":case"hours":S=3600;break;case"day":case"days":default:S=86400;break;case"week":case"weeks":S=604800;break;case"month":case"months":S=2628e3;break;case"year":case"years":S=31536e3;break}const D=x-Q*S*1e3;B(new Date(D).toISOString())}function geocodeId(g,B){const x=ide.getQueryLang();function Q(S){return S.osm_type&&S.osm_id}nominatim.getBest(g,Q,(S,D)=>{if(S)return ide.onNominatimError(g,"Id");x=="OverpassQL"?D=`${D.osm_type}(${D.osm_id})`:x=="xml"&&(D=`type="${D.osm_type}" ref="${D.osm_id}"`),B(D)})}function geocodeArea(g,B){const x=ide.getQueryLang();function Q(S){return S.osm_type&&S.osm_id&&S.osm_type!=="node"}nominatim.getBest(g,Q,(S,D)=>{if(S)return ide.onNominatimError(g,"Area");let H=1*D.osm_id;if(D.osm_type=="way"&&(H+=24e8),D.osm_type=="relation"&&(H+=36e8),x=="OverpassQL")return D.osm_type==="way"&&(H+=`,${D.osm_id}`),B(`area(id:${H})`);if(x=="xml")return D.osm_type==="way"&&(H+=`" ref_1="${D.osm_id}`),B(`type="area" ref="${H}"`)})}function geocodeBbox(g,B){const x=ide.getQueryLang();nominatim.getBest(g,(Q,S)=>{if(Q)return ide.onNominatimError(g,"Bbox");const D=Math.min(Math.max(S.boundingbox[0],-90),90),H=Math.min(Math.max(S.boundingbox[1],-90),90),P=Math.min(Math.max(S.boundingbox[2],-180),180),R=Math.min(Math.max(S.boundingbox[3],-180),180);x=="OverpassQL"?S=`${D},${P},${H},${R}`:x=="xml"&&(S=`s="${D}" w="${P}" n="${H}" e="${R}"`),B(S)})}function geocodeCoords(g,B){const x=ide.getQueryLang();nominatim.getBest(g,(Q,S)=>{if(Q)return ide.onNominatimError(g,"Coords");x=="OverpassQL"?S=`${S.lat},${S.lon}`:x=="xml"&&(S=`lat="${S.lat}" lon="${S.lon}"`),B(S)})}function shortcuts(){const g=ide.getQueryLang();return{bbox:map2bbox(g),center:map2coord(g),__bbox__global_bbox_xml__ezs4K8__:map2bbox("OverpassQL"),date:relativeTime,geocodeId,geocodeArea,geocodeBbox,geocodeCoords,nominatimId:g=="xml"?geocodeId:(B,x)=>geocodeId(B,Q=>x(`${Q};`)),nominatimArea:g=="xml"?geocodeArea:(B,x)=>geocodeArea(B,Q=>x(`${Q};`)),nominatimBbox:geocodeBbox,nominatimCoords:geocodeCoords}}let copyData;$(document).on("copy",g=>{copyData&&g.originalEvent&&g.originalEvent.clipboardData?(Object.keys(copyData).forEach(B=>{g.originalEvent.clipboardData.setData(B,copyData[B])}),g.originalEvent.preventDefault(),copyData=void 0):copyData&©Data["text/plain"]&&(prompt(i18n.t("export.copy_to_clipboard"),copyData["text/plain"]),copyData=null)});function make_combobox(g,B,x,Q){if(g[0].is_combobox){g.autocomplete("option",{source:B});return}const S=g.wrap("").parent().addClass("ui-combobox");g.autocomplete({source:B,minLength:0}).addClass("ui-widget ui-widget-content ui-corner-left ui-state-default").autocomplete("instance")._renderItem=(D,H)=>$("
  • ").append(x&&x.indexOf(H.value)!==-1?`
    ${H.label}
    `:`
    ${H.label}
    `).on("click",function(P){if(P.shiftKey&&x.indexOf(H.value)!==-1){Q(H.value),$(this).remove();const R=g.autocomplete("option","source");return R.splice(R.indexOf(H),1),g.autocomplete("option","source",R),!1}}).appendTo(D),$("").attr("tabIndex",-1).attr("title","show all items").appendTo(S).button({icons:{primary:"ui-icon-triangle-1-s"},text:!1}).removeClass("ui-corner-all").addClass("ui-corner-right ui-combobox-toggle").click(()=>{if(g.autocomplete("widget").is(":visible")){g.autocomplete("close");return}g.autocomplete("search",""),g.focus()}),g[0].is_combobox=!0}function showDialog(g,B,x){const Q=` `,S=$(Q);$(".delete",S).click(()=>$(S).remove());for(const D in x){const H=x[D];$(``).click(()=>{var P;(P=H.callback)==null||P.call(H),$(S).remove()}).appendTo($("footer .level-item",S))}S.appendTo("body")}class IDE{constructor(){this.attribControl=null,this.scaleControl=null,this.queryParser=new parser,this.run_query_on_startup=!1,this.codeEditor=null,this.dataViewer=null,this.map=null,this.waiter=new class{constructor(){this.opened=!0,this.frames=["◴","◷","◶","◵"],this.frameDelay=250,this.onAbort=void 0,this.interval=0,this._initialTitle=document.title}open(x){x?($(".modal .wait-info h4").text(x),$(".wait-info").show()):$(".wait-info").hide(),$("#loading-dialog").addClass("is-active"),document.title=`${this.frames[0]} ${this._initialTitle}`;let Q=0;this.interval=setInterval(()=>{const S=this.isAlert?this.alertFrame:this.frames[++Q%this.frames.length];document.title=`${S} ${this._initialTitle}`},this.frameDelay),this.opened=!0}close(x=""){this.opened&&(clearInterval(this.interval),document.title=`${x}${this._initialTitle}`,$("#loading-dialog").removeClass("is-active"),$(".wait-info ul li").remove(),delete this.onAbort,this.opened=!1)}addInfo(x,Q){$("#aborter").remove(),$(".wait-info ul li:nth-child(n+1)").css("opacity",.5),$(".wait-info ul li span.fas").removeClass("fa-spinner").removeClass("fa-spin").addClass("fa-check"),$(".wait-info ul li:nth-child(n+4)").hide();const S=$(`
  • ${x}
  • `);if(typeof Q=="function"){this.onAbort=Q;const D=$(' (abort)
    ').on("click",()=>(this.abort(),!1));S.append(D)}$(".wait-info ul").prepend(S)}abort(){typeof this.onAbort=="function"&&(this.addInfo("aborting"),this.onAbort(this.close))}}}init(){this.waiter.addInfo("ide starting up"),$("#overpass-turbo-version").html("overpass-turbo 2024-11-03/6138b6e"),$("#overpass-turbo-dependencies").html('@fortawesome/fontawesome-free 5.15.4 ((CC-BY-4.0 AND OFL-1.1 AND MIT)), @openstreetmap/id-tagging-schema 3.5.1 (ISC), bulma 0.9.4 (MIT), canvg 4.0.1 (MIT), codemirror 2.38.00 (undefined), html2canvas 1.4.1 (MIT), jquery 3.7.1 (MIT), jquery-ui 1.13.2 (MIT), jquery-ui-dist 1.13.2 (MIT), leaflet 1.9.4 (BSD-2-Clause), leaflet-polylineoffset 1.1.1 (MIT), leaflet-locationfilter 0.1.3 (MIT), lodash 4.17.21 (MIT), osm-auth 2.2.0 (ISC), osmtogeojson 3.0.0-beta.5 (MIT), rgbcolor 1.0.1 (MIT OR SEE LICENSE IN FEEL-FREE.md), stackblur 1.0.0 (BSD-2-Clause), tag2link 2024.05.21 (ISC), togpx 0.5.4 (MIT), tokml 0.4.0 (BSD-2-Clause)'),($.support.cors!=!0||typeof function(){let B;try{localStorage.setItem("startup_localstorage_quota_test",123),localStorage.removeItem("startup_localstorage_quota_test"),B=localStorage}catch{}return B}()!="object")&&(this.not_supported=!0,$("#warning-unsupported-browser").addClass("is-active")),this.waiter.addInfo("load settings"),settings.load(),this.waiter.addInfo("translate ui"),i18n.translate().then(()=>this.initAfterI18n()),sync.enabled&&($("#load-dialog .osm").show(),sync.authenticated()&&($("#logout").show(),$("#logout").appendTo($("#logout").parent())))}initAfterI18n(){const B=this;B.waiter.addInfo("parse url parameters");const x=urlParameters();x.has_coords&&(settings.coords_lat=x.coords.lat,settings.coords_lon=x.coords.lng),x.has_zoom&&(settings.coords_zoom=x.zoom),x.run_query&&(B.run_query_on_startup=!0),settings.save(),B.waiter.addInfo("initialize page");const Q=$(window).width()/$(window).height()<.8;if(settings.editor_width!=""&&!Q&&($("#editor").css("width",settings.editor_width),$("#dataviewer").css("left",settings.editor_width)),Q&&$("#editor, #dataviewer").addClass("portrait"),$("#editor").resizable({handles:Q?"s":"e",minWidth:Q?void 0:"200",resize(){if(!Q)$(this).next().css("left",`${$(this).outerWidth()}px`);else{const G=$(this).offset().top+$(this).outerHeight();$(this).next().css("top",`${G}px`)}B.map.invalidateSize(!1)},stop(){Q||(settings.editor_width=$("#editor").css("width"),settings.save())}}),$("#editor").prepend(""),$("#editor textarea")[0].value=settings.code.overpass,settings.use_rich_editor){let G=0;CodeMirror.defineMIME("text/x-overpassQL",{name:"clike",keywords:function(X){const ee={},Ae=X.split(" ");for(const le of Ae)ee[le]=!0;return ee}("out json xml custom popup timeout maxsize bbox date diff adiff foreach relation rel way node is_in area around user uid newer changed poly pivot nwr nw nr wr derived out meta body skel tags ids count qt asc center bb geom")}),CodeMirror.defineMIME("text/x-overpassXML","xml"),CodeMirror.defineMode("xml+mustache",X=>CodeMirror.multiplexingMode(CodeMirror.multiplexingMode(CodeMirror.getMode(X,"xml"),{open:"{{",close:"}}",mode:CodeMirror.getMode(X,"text/plain"),delimStyle:"mustache"}),{open:"{{style:",close:"}}",mode:CodeMirror.getMode(X,"text/css"),delimStyle:"mustache"})),CodeMirror.defineMode("ql+mustache",X=>CodeMirror.multiplexingMode(CodeMirror.multiplexingMode(CodeMirror.getMode(X,"text/x-overpassQL"),{open:"{{",close:"}}",mode:CodeMirror.getMode(X,"text/plain"),delimStyle:"mustache"}),{open:"{{style:",close:"}}",mode:CodeMirror.getMode(X,"text/css"),delimStyle:"mustache"})),B.codeEditor=CodeMirror.fromTextArea($("#editor textarea")[0],{lineNumbers:!0,lineWrapping:!0,mode:"text/plain",onChange(X){clearTimeout(G),G=setTimeout(()=>{B.getQueryLang()=="xml"?X.getOption("mode")!="xml+mustache"&&(X.closeTagEnabled=!0,X.setOption("matchBrackets",!1),X.setOption("mode","xml+mustache")):X.getOption("mode")!="ql+mustache"&&(X.closeTagEnabled=!1,X.setOption("matchBrackets",!0),X.setOption("mode","ql+mustache"));const ee=$(".leaflet-control-buttons-bboxfilter");B.getRawQuery().match(/\{\{bbox\}\}/)?ee.hasClass("disabled")&&(ee.removeClass("disabled"),ee.attr("data-t","[title]map_controlls.select_bbox"),i18n.translate_ui(ee[0])):ee.hasClass("disabled")||(ee.addClass("disabled"),ee.attr("data-t","[title]map_controlls.select_bbox_disabled"),i18n.translate_ui(ee[0]))},500),settings.code.overpass=X.getValue(),settings.save()},closeTagEnabled:!0,closeTagIndent:["osm-script","query","union","foreach","difference"],extraKeys:{"'>'"(X){X.closeTag(X,">")},"'/'"(X){X.closeTag(X,"/")}}}),B.codeEditor.getOption("onChange")(B.codeEditor)}else B.codeEditor=$("#editor textarea")[0],B.codeEditor.getValue=function(){return this.value},B.codeEditor.setValue=function(G){this.value=G},B.codeEditor.lineCount=function(){return this.value.split(/\r\n|\r|\n/).length},B.codeEditor.setLineClass=function(){},$("#editor textarea").bind("input change",G=>{settings.code.overpass=G.target.getValue(),settings.save()});x.has_query&&B.codeEditor.setValue(x.query),B.dataViewer=CodeMirror($("#data")[0],{value:"no data loaded yet",lineNumbers:!0,readOnly:!0,mode:"javascript"}),B.map=new L.Map("map",{attributionControl:!0,minZoom:0,maxZoom:configs.maxMapZoom,worldCopyJump:!1});const S=settings.tile_server,D=configs.tileServerAttribution,H=new L.TileLayer(S,{attribution:D,noWrap:!0,maxNativeZoom:19,maxZoom:B.map.options.maxZoom});B.attribControl=new L.Control.Attribution({prefix:!1}),B.attribControl.addAttribution(D);const P=new L.LatLng(settings.coords_lat,settings.coords_lon);B.map.setView(P,settings.coords_zoom).addLayer(H),B.map.tile_layer=H,B.map.inv_opacity_layer=L.tileLayer("data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==").setOpacity(1-settings.background_opacity),settings.background_opacity!=1&&B.map.inv_opacity_layer.addTo(B.map),B.scaleControl=new L.Control.Scale({metric:!0,imperial:!1}),B.scaleControl.addTo(B.map),B.map.on("moveend",()=>{settings.coords_lat=B.map.getCenter().lat,settings.coords_lon=B.map.getCenter().lng,settings.coords_zoom=B.map.getZoom(),settings.save()}),$("#dataviewer > div#data")[0].style.zIndex=-1001,$(".tabs li").bind("click",G=>{$(G.target).hasClass("is-active")||($("#dataviewer > div#data")[0].style.zIndex=-1*$("#dataviewer > div#data")[0].style.zIndex,$(".tabs li").toggleClass("is-active"))}),$(document).keydown(G=>B.onKeyPress(G));const R=L.Control.extend({options:{position:"topleft"},onAdd(){const G=L.DomUtil.create("div","leaflet-control-buttons leaflet-bar");let X=L.DomUtil.create("a","leaflet-control-buttons-fitdata leaflet-bar-part leaflet-bar-part-top",G);return $('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.zoom_to_data"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",()=>{try{B.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(),{maxZoom:18})}catch{}return!1},B.map),X=L.DomUtil.create("a","leaflet-control-buttons-myloc leaflet-bar-part",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.localize_user"),window.isSecureContext||(X.className+=" disabled",X.setAttribute("data-t","[title]map_controlls.localize_user_disabled")),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",()=>{try{navigator.geolocation.getCurrentPosition(ee=>{const Ae=new L.LatLng(ee.coords.latitude,ee.coords.longitude);B.map.setView(Ae,settings.coords_zoom)})}catch{}return!1},B.map),X=L.DomUtil.create("a","leaflet-control-buttons-bboxfilter leaflet-bar-part",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.select_bbox"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",ee=>($(ee.target).parent().hasClass("disabled")||(B.map.bboxfilter.isEnabled()?B.map.bboxfilter.disable():(B.map.bboxfilter.setBounds(B.map.getBounds().pad(-.2)),B.map.bboxfilter.enable()),$(ee.target).toggleClass("fa-times-circle").toggleClass("fa-image")),!1),B.map),X=L.DomUtil.create("a","leaflet-control-buttons-fullscreen leaflet-bar-part",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.toggle_wide_map"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",ee=>($("#dataviewer").toggleClass("fullscreen"),B.map.invalidateSize(),$(ee.target).toggleClass("fa-step-forward").toggleClass("fa-step-backward"),$("#editor").toggleClass("hidden"),$("#editor").resizable("option","disabled")?$("#editor").resizable("enable"):$("#editor").resizable("disable"),!1),B.map),X=L.DomUtil.create("a","leaflet-control-buttons-clearoverlay leaflet-bar-part leaflet-bar-part-bottom",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.toggle_data"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",ee=>(ee.preventDefault(),B.map.hasLayer(overpass.osmLayer)?B.map.removeLayer(overpass.osmLayer):B.map.addLayer(overpass.osmLayer),!1),B.map),G}});B.map.addControl(new R),$(".leaflet-control-buttons > a").bind("dblclick",G=>G.stopPropagation()),$(".leaflet-control-buttons > a").tooltip({items:"a[title]",hide:{effect:"fadeOut",duration:100},position:{my:"left+5 center",at:"right center"}});const Y=L.Control.extend({options:{position:"topright"},onAdd(){const G=L.DomUtil.create("div","leaflet-control-search control has-icons-left");G.style.position="absolute",G.style.right="0";const X=L.DomUtil.create("input","input is-rounded",G);return $('').click(function(){$(this).prev().autocomplete("search")}).insertAfter(X),X.id="search",X.type="search",X.onclick=function(){this.focus()},G.ondblclick=function(ee){ee.stopPropagation()},$(X).autocomplete({source(ee,Ae){$.ajax(`https://search.osmnames.org/q/${encodeURIComponent(ee.term)}.js?key=${configs.osmnamesApiKey}`,{success(le){if(typeof le=="string")try{le=$.parseJSON(le)}catch{}Ae($.map(le.results.slice(0,10),ae=>({label:ae.display_name,value:ae.display_name,lat:ae.lat,lon:ae.lon,boundingbox:ae.boundingbox})))},error(){console.error("An error occured while contacting the search server osmnames.org :(")}})},minLength:2,autoFocus:!0,select(ee,Ae){return Ae.item.boundingbox&&Ae.item.boundingbox instanceof Array?B.map.fitBounds(L.latLngBounds([[Ae.item.boundingbox[1],Ae.item.boundingbox[0]],[Ae.item.boundingbox[3],Ae.item.boundingbox[2]]]),{maxZoom:18}):B.map.panTo(new L.LatLng(Ae.item.lat,Ae.item.lon)),this.value="",!1},open(){$(this).removeClass("ui-corner-all").addClass("ui-corner-top")},close(){$(this).addClass("ui-corner-all").removeClass("ui-corner-top")}}),$(X).autocomplete("option","delay",20),G}});B.map.addControl(new Y),$('').addClass("crosshairs").hide().appendTo("#map"),settings.enable_crosshairs&&$(".crosshairs").show(),B.map.bboxfilter=new L.LocationFilter({enable:!1,adjustButton:!1,enableButton:!1}).addTo(B.map),B.map.on("popupopen popupclose",G=>{if(typeof G.popup.layer<"u"){const X=G.popup.layer.placeholder||G.popup.layer,ee=overpass.osmLayer._baseLayer.options.style(X.feature,G.type=="popupopen");typeof X.eachLayer!="function"?typeof X.setStyle=="function"&&X.setStyle(ee):X.eachLayer(Ae=>{typeof Ae.setStyle=="function"&&Ae.setStyle(ee)})}}),overpass.init(),overpass.handlers.onProgress=function(G,X){B.waiter.addInfo(G,X)},overpass.handlers.onDone=function(){const G=B.getRawQuery().match(/@name ([^\n]+)/),X=G?`${G[1]} | `:"";B.waiter.close(X);const ee=B.map.getBounds(),Ae=overpass.osmLayer.getBaseLayer().getBounds();if(Ae.isValid()&&!ee.intersects(Ae)){const le=$(".leaflet-control-buttons-fitdata").tooltip("option","content");$(".leaflet-control-buttons-fitdata").tooltip("option","content",`← ${i18n.t("map_controlls.suggest_zoom_to_data")}`),$(".leaflet-control-buttons-fitdata").tooltip("open"),$(".leaflet-control-buttons-fitdata").tooltip("option","hide",{effect:"fadeOut",duration:1e3}),setTimeout(()=>{$(".leaflet-control-buttons-fitdata").tooltip("option","content",le),$(".leaflet-control-buttons-fitdata").tooltip("close"),$(".leaflet-control-buttons-fitdata").tooltip("option","hide",{effect:"fadeOut",duration:100})},2600)}},overpass.handlers.onEmptyMap=function(G,X){const ee=B.getRawQuery(),Ae=/out[^;]+?count/.test(ee);if(G=="no visible data")if(!Ae&&!settings.no_autorepair){const le=`

    ${i18n.t("warning.incomplete.expl.1")}

    ${i18n.t("warning.incomplete.expl.2")}

     ${i18n.t("warning.incomplete.not_again")}

    `,ae=[{name:i18n.t("dialog.repair_query"),callback(){B.repairQuery("no visible data")}},{name:i18n.t("dialog.show_data"),callback(){var ge,fe;(fe=(ge=$("input[name=hide_incomplete_data_warning]"))==null?void 0:ge[0])!=null&&fe.checked&&(settings.no_autorepair=!0,settings.save()),B.switchTab("Data")}}];showDialog(i18n.t("warning.incomplete.title"),le,ae)}else Ae&&B.switchTab("Data");G=="only areas returned"&&B.switchTab("Data"),G=="no coordinates returned"&&B.switchTab("Data"),X=="unknown"&&B.switchTab("Data"),$(`
    ${i18n.t("map.intentionally_blank")} (${G})
    `).appendTo("#map")},overpass.handlers.onDataReceived=function(G,X,ee,Ae){if(G>1e6){B.waiter.close();const le=document.title;document.title=`❗ ${le}`;const ae=[{name:i18n.t("dialog.abort"),callback(){document.title=le,ee()}},{name:i18n.t("dialog.continue_anyway"),callback(){document.title=le,Ae()}}],ge=`

    ${i18n.t("warning.huge_data.expl.1").replace("{{amount_txt}}",X)}

    ${i18n.t("warning.huge_data.expl.2")}

    `;showDialog(i18n.t("warning.huge_data.title"),ge,ae)}else Ae()},overpass.handlers.onAbort=function(){B.waiter.close()},overpass.handlers.onAjaxError=function(G){B.waiter.close();const X=document.title;document.title=`❗ ${X}`;const ee=[{name:i18n.t("dialog.dismiss"),callback(){document.title=X}}],Ae=`

    ${i18n.t("error.ajax.expl")}

    ${G}`;showDialog(i18n.t("error.ajax.title"),Ae,ee),overpass.resultText&&B.dataViewer.setValue(overpass.resultText)},overpass.handlers.onQueryError=function(G){B.waiter.close();const X=document.title;document.title=`❗ ${X}`;const ee=[{name:i18n.t("dialog.dismiss"),callback(){document.title=X}}],Ae=`
    ${i18n.t("error.query.expl")}
    ${G}
    `;showDialog(i18n.t("error.query.title"),Ae,ee)},overpass.handlers.onStyleError=function(G){const X=[{name:i18n.t("dialog.dismiss")}],ee=`

    ${i18n.t("error.mapcss.expl")}

    ${G}`;showDialog(i18n.t("error.mapcss.title"),ee,X)},overpass.handlers.onQueryErrorLine=function(G){B.highlightError(G)},overpass.handlers.onRawDataPresent=function(){B.dataViewer.setOption("mode",overpass.resultType),B.dataViewer.setValue(overpass.resultText)},overpass.handlers.onGeoJsonReady=function(){if(B.map.addLayer(overpass.osmLayer),typeof B.run_query_on_startup=="function"&&B.run_query_on_startup(),settings.show_data_stats){const G=overpass.stats,X=`${i18n.t("data_stats.loaded")} – ${i18n.t("data_stats.nodes")}: ${G.data.nodes}, ${i18n.t("data_stats.ways")}: ${G.data.ways}, ${i18n.t("data_stats.relations")}: ${G.data.relations}${G.data.areas>0?`, ${i18n.t("data_stats.areas")}: ${G.data.areas}`:""}
    ${i18n.t("data_stats.displayed")} – ${i18n.t("data_stats.pois")}: ${G.geojson.pois}, ${i18n.t("data_stats.lines")}: ${G.geojson.lines}, ${i18n.t("data_stats.polygons")}: ${G.geojson.polys}`;$(`
    ${X}
    `).insertAfter("#map .leaflet-control-attribution");const ee=overpass.timestamp&&Date.now()-Date.parse(overpass.timestamp),Ae=overpass.timestampAreas&&Date.now()-Date.parse(overpass.timestampAreas);$("#data_stats").tooltip({items:"div",tooltipClass:"stats",content(){let le="
    ";if(overpass.ajax_request_duration){let ae=overpass.ajax_request_duration;ae.toLocaleString&&(ae=ae.toLocaleString()),le+=`${i18n.t("data_stats.request_duration")}: ${ae}ms
    `}return overpass.timestamp&&(le+=`${i18n.t("data_stats.lag")}: ${Math.floor(ee/1e3)}s ${i18n.t("data_stats.lag.expl")}`),overpass.timestampAreas&&(le+=`
    ${i18n.t("data_stats.lag_areas")}: ${Math.floor(Ae/1e3)}s ${i18n.t("data_stats.lag.expl")}`),le+="
    ",le},hide:{effect:"fadeOut",duration:100},position:{my:"right bottom-5",at:"right top"}}),(ee>24*60*60*1e3||Ae>96*60*60*1e3)&&$("#data_stats").css("background-color","yellow")}},overpass.handlers.onPopupReady=function(G){G.openOn(B.map)},B.waiter.close(),B.run_query_on_startup===!0&&(B.update_map(),!x.has_coords&&x.has_query&&x.query.match(/\{\{(bbox|center)\}\}/)===null&&(B.run_query_on_startup=function(){B.run_query_on_startup=null;try{B.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(),{maxZoom:18})}catch{}}))}onNominatimError(B,x){this.waiter.close();let Q=this.getRawQuery();Q=Q.split(` +`+H+"}":"{"+P.join(",")+"}",gap=H,S}}typeof JSON.stringify!="function"&&(meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(g,B,x){var Q;if(gap="",indent="",typeof x=="number")for(Q=0;Q{var R=(Y,G)=>{Y?P(new Error(Y)):H(G)};_generatePkceChallenge(Y=>x(Y,R))}))};function x(H,P){var R=generateState(),Y=g.url+"/oauth2/authorize?"+utilQsString({client_id:g.client_id,redirect_uri:g.redirect_uri,response_type:"code",scope:g.scope,state:R,code_challenge:H.code_challenge,code_challenge_method:H.code_challenge_method});if(g.singlepage){if(!store.enabled){var G=new Error("local storage unavailable, but require in singlepage mode");G.status="pkce-localstorage-unavailable",P(G);return}var X=utilStringQs(window.location.search.slice(1));X.code?B.bootstrapToken(X.code,P):(S("oauth2_state",R),S("oauth2_pkce_code_verifier",H.code_verifier),window.location=Y)}else{var ee=600,Ae=550,le=[["width",ee],["height",Ae],["left",window.screen.width/2-ee/2],["top",window.screen.height/2-Ae/2]].map(function(fe){return fe.join("=")}).join(","),ae=window.open("about:blank","oauth_window",le);B.popupWindow=ae,ae.location=Y,ae||(G=new Error("Popup was blocked"),G.status="popup-blocked",P(G))}window.authComplete=function(fe){var ye=utilStringQs(fe.split("?")[1]);if(ye.state!==R){G=new Error("Invalid state"),G.status="invalid-state",P(G);return}Q(ye.code,H.code_verifier,ge),delete window.authComplete};function ge(fe,ye){if(g.done(),fe){P(fe);return}var me=JSON.parse(ye.response);S("oauth2_access_token",me.access_token),P(null,B)}}function Q(H,P,R){var Y=g.url+"/oauth2/token?"+utilQsString({client_id:g.client_id,redirect_uri:g.redirect_uri,grant_type:"authorization_code",code:H,code_verifier:P});B.rawxhr("POST",Y,null,null,null,R),g.loading()}B.bringPopupWindowToFront=function(){var H=!1;try{B.popupWindow&&!B.popupWindow.closed&&(B.popupWindow.focus(),H=!0)}catch{}return H},B.bootstrapToken=function(H,P){var R=S("oauth2_state");S("oauth2_state","");var Y=utilStringQs(window.location.search.slice(1));if(Y.state!==R){var G=new Error("Invalid state");G.status="invalid-state",P(G);return}var X=S("oauth2_pkce_code_verifier");S("oauth2_pkce_code_verifier",""),Q(H,X,ee);function ee(Ae,le){if(g.done(),Ae){P(Ae);return}var ae=JSON.parse(le.response);S("oauth2_access_token",ae.access_token),P(null,B)}},B.fetch=function(H,P){if(B.authenticated())return R();return g.auto?B.authenticateAsync().then(R):Promise.reject(new Error("not authenticated"));function R(){return P=P||{},P.headers||(P.headers={"Content-Type":"application/x-www-form-urlencoded"}),P.headers.Authorization="Bearer "+S("oauth2_access_token"),fetch(H,P)}},B.xhr=function(H,P){if(B.authenticated())return R();if(g.auto){B.authenticate(R);return}else{P("not authenticated",null);return}function R(){var G=H.prefix!==!1?g.url+H.path:H.path;return B.rawxhr(H.method,G,S("oauth2_access_token"),H.content,H.headers,Y)}function Y(G,X){G?P(G):X.responseXML?P(G,X.responseXML):P(G,X.response)}},B.rawxhr=function(H,P,R,Y,G,X){G=G||{"Content-Type":"application/x-www-form-urlencoded"},R&&(G.Authorization="Bearer "+R);var ee=new XMLHttpRequest;ee.onreadystatechange=function(){ee.readyState===4&&ee.status!==0&&(/^20\d$/.test(ee.status)?X(null,ee):X(ee,null))},ee.onerror=function(le){X(le,null)},ee.open(H,P,!0);for(var Ae in G)ee.setRequestHeader(Ae,G[Ae]);return ee.send(Y),ee},B.preauth=function(H){return H&&H.access_token&&S("oauth2_access_token",H.access_token),B},B.options=function(H){return arguments.length?(g=H,g.url=g.url||"https://www.openstreetmap.org",g.auto=g.auto||!1,g.singlepage=g.singlepage||!1,g.loading=g.loading||function(){},g.done=g.done||function(){},B.preauth(g)):g};var S;if(store.enabled)S=function(H,P){if(arguments.length===1)return store.get(g.url+H);if(arguments.length===2)return store.set(g.url+H,P)};else{var D={};S=function(H,P){if(arguments.length===1)return D[g.url+H];if(arguments.length===2)return D[g.url+H]=P}}return B.options(g),B}function utilQsString(g){return Object.keys(g).filter(function(B){return g[B]!==void 0}).sort().map(function(B){return encodeURIComponent(B)+"="+encodeURIComponent(g[B])}).join("&")}function utilStringQs(g){for(var B=0;B{if(B)return g(B);loadQueries(g)})},save(g,B){auth.authenticated()?saveQuery(g,B):auth.authenticate(x=>{if(x)return B(x);saveQuery(g,B)})},delete(g,B){if(!auth.authenticated())return B(new Error("must be logged in to delete a synced query"));g={name:g,deleteMe:!0},saveQuery(g,B)},logout(){auth.authenticated()&&auth.logout()},authenticated(){return enabled&&auth.authenticated()}};function loadQueries(g){auth.xhr({method:"GET",path:"/api/0.6/user/preferences"},(B,x)=>{if(B)return g(B);let Q=0,S;(S=x.querySelector(`preference[k="${configs.settingNamespace}_query-count"]`))&&(Q=+S.getAttribute("v"));const D=[];for(let H=0;H{if(x)return B(x);const D=S.querySelector("preferences"),H=D.querySelectorAll(`preference[k^="${configs.settingNamespace}_query"]`);for(const Y of H)Y.remove();let P=!0;Q.forEach((Y,G)=>{Y.name==g.name&&(Y.query=g.query,P=G)}),P===!0?Q.push(g):g.deleteMe&&Q.splice(P,1);const R=S.createElement("preference");R.setAttribute("k",`${configs.settingNamespace}_query-count`),R.setAttribute("v",Q.length),D.appendChild(R);for(let Y=0;Y200)return B(new Error("query name too long to be saved on osm.org"));const X=Math.ceil((G.query.length+G.name.length+8)/255);if(X>9)return B(new Error("query too long to be saved on osm.org"));let ee=`p=${X}`;ee+=`&n=${G.name}`,ee+=`&q=${G.query}`,ee=ee.match(/.{1,255}/g);for(let Ae=0;Ae{if(Y)return B(Y);B(null,Q)})})}const cache={};class nominatim{static request(B,x){$.ajax(`https://nominatim.openstreetmap.org/search?X-Requested-With=${configs.appname}`,{data:{format:"json",q:B},success(Q){if(typeof Q=="string")try{Q=JSON.parse(Q)}catch{}cache[B]=Q,x(void 0,Q)},error(){const Q="An error occurred while contacting the osm search server nominatim.openstreetmap.org :(";console.log(Q),x(Q,null)}})}static get(B,x){return cache[B]===void 0?this.request(B,x):x(void 0,cache[B]),this}static getBest(B,x,Q){return Q||(Q=x,x=null),this.get(B,(S,D)=>{if(S){Q(S,null);return}x&&(D=D.filter(x)),D.length===0?Q("No result found",null):Q(S,D[0])}),this}}function map2bbox(g){let B;ide.map.bboxfilter&&ide.map.bboxfilter.isEnabled()?B=ide.map.bboxfilter.getBounds():B=ide.map.getBounds();const x=Math.min(Math.max(B.getSouthWest().lat,-90),90),Q=Math.min(Math.max(B.getNorthEast().lat,-90),90),S=Math.min(Math.max(B.getSouthWest().lng,-180),180),D=Math.min(Math.max(B.getNorthEast().lng,-180),180);if(g=="OverpassQL")return`${x},${S},${Q},${D}`;if(g=="xml")return`s="${x}" w="${S}" n="${Q}" e="${D}"`}function map2coord(g){const B=ide.map.getCenter();if(g=="OverpassQL")return`${B.lat},${B.lng}`;if(g=="xml")return`lat="${B.lat}" lon="${B.lng}"`}function relativeTime(g,B){const x=Date.now();if(g==""&&(g="0 seconds"),g=g.toLowerCase().match(/(-?[0-9]+) ?(seconds?|minutes?|hours?|days?|weeks?|months?|years?)?/),g===null){B("");return}const Q=parseInt(g[1]);let S;switch(g[2]){case"second":case"seconds":S=1;break;case"minute":case"minutes":S=60;break;case"hour":case"hours":S=3600;break;case"day":case"days":default:S=86400;break;case"week":case"weeks":S=604800;break;case"month":case"months":S=2628e3;break;case"year":case"years":S=31536e3;break}const D=x-Q*S*1e3;B(new Date(D).toISOString())}function geocodeId(g,B){const x=ide.getQueryLang();function Q(S){return S.osm_type&&S.osm_id}nominatim.getBest(g,Q,(S,D)=>{if(S)return ide.onNominatimError(g,"Id");x=="OverpassQL"?D=`${D.osm_type}(${D.osm_id})`:x=="xml"&&(D=`type="${D.osm_type}" ref="${D.osm_id}"`),B(D)})}function geocodeArea(g,B){const x=ide.getQueryLang();function Q(S){return S.osm_type&&S.osm_id&&S.osm_type!=="node"}nominatim.getBest(g,Q,(S,D)=>{if(S)return ide.onNominatimError(g,"Area");let H=1*D.osm_id;if(D.osm_type=="way"&&(H+=24e8),D.osm_type=="relation"&&(H+=36e8),x=="OverpassQL")return D.osm_type==="way"&&(H+=`,${D.osm_id}`),B(`area(id:${H})`);if(x=="xml")return D.osm_type==="way"&&(H+=`" ref_1="${D.osm_id}`),B(`type="area" ref="${H}"`)})}function geocodeBbox(g,B){const x=ide.getQueryLang();nominatim.getBest(g,(Q,S)=>{if(Q)return ide.onNominatimError(g,"Bbox");const D=Math.min(Math.max(S.boundingbox[0],-90),90),H=Math.min(Math.max(S.boundingbox[1],-90),90),P=Math.min(Math.max(S.boundingbox[2],-180),180),R=Math.min(Math.max(S.boundingbox[3],-180),180);x=="OverpassQL"?S=`${D},${P},${H},${R}`:x=="xml"&&(S=`s="${D}" w="${P}" n="${H}" e="${R}"`),B(S)})}function geocodeCoords(g,B){const x=ide.getQueryLang();nominatim.getBest(g,(Q,S)=>{if(Q)return ide.onNominatimError(g,"Coords");x=="OverpassQL"?S=`${S.lat},${S.lon}`:x=="xml"&&(S=`lat="${S.lat}" lon="${S.lon}"`),B(S)})}function shortcuts(){const g=ide.getQueryLang();return{bbox:map2bbox(g),center:map2coord(g),__bbox__global_bbox_xml__ezs4K8__:map2bbox("OverpassQL"),date:relativeTime,geocodeId,geocodeArea,geocodeBbox,geocodeCoords,nominatimId:g=="xml"?geocodeId:(B,x)=>geocodeId(B,Q=>x(`${Q};`)),nominatimArea:g=="xml"?geocodeArea:(B,x)=>geocodeArea(B,Q=>x(`${Q};`)),nominatimBbox:geocodeBbox,nominatimCoords:geocodeCoords}}let copyData;$(document).on("copy",g=>{copyData&&g.originalEvent&&g.originalEvent.clipboardData?(Object.keys(copyData).forEach(B=>{g.originalEvent.clipboardData.setData(B,copyData[B])}),g.originalEvent.preventDefault(),copyData=void 0):copyData&©Data["text/plain"]&&(prompt(i18n.t("export.copy_to_clipboard"),copyData["text/plain"]),copyData=null)});function make_combobox(g,B,x,Q){if(g[0].is_combobox){g.autocomplete("option",{source:B});return}const S=g.wrap("").parent().addClass("ui-combobox");g.autocomplete({source:B,minLength:0}).addClass("ui-widget ui-widget-content ui-corner-left ui-state-default").autocomplete("instance")._renderItem=(D,H)=>$("
  • ").append(x&&x.indexOf(H.value)!==-1?`
    ${H.label}
    `:`
    ${H.label}
    `).on("click",function(P){if(P.shiftKey&&x.indexOf(H.value)!==-1){Q(H.value),$(this).remove();const R=g.autocomplete("option","source");return R.splice(R.indexOf(H),1),g.autocomplete("option","source",R),!1}}).appendTo(D),$("").attr("tabIndex",-1).attr("title","show all items").appendTo(S).button({icons:{primary:"ui-icon-triangle-1-s"},text:!1}).removeClass("ui-corner-all").addClass("ui-corner-right ui-combobox-toggle").click(()=>{if(g.autocomplete("widget").is(":visible")){g.autocomplete("close");return}g.autocomplete("search",""),g.focus()}),g[0].is_combobox=!0}function showDialog(g,B,x){const Q=` `,S=$(Q);$(".delete",S).click(()=>$(S).remove());for(const D in x){const H=x[D];$(``).click(()=>{var P;(P=H.callback)==null||P.call(H),$(S).remove()}).appendTo($("footer .level-item",S))}S.appendTo("body")}class IDE{constructor(){this.attribControl=null,this.scaleControl=null,this.queryParser=new parser,this.run_query_on_startup=!1,this.codeEditor=null,this.dataViewer=null,this.map=null,this.waiter=new class{constructor(){this.opened=!0,this.frames=["◴","◷","◶","◵"],this.frameDelay=250,this.onAbort=void 0,this.interval=0,this._initialTitle=document.title}open(x){x?($(".modal .wait-info h4").text(x),$(".wait-info").show()):$(".wait-info").hide(),$("#loading-dialog").addClass("is-active"),document.title=`${this.frames[0]} ${this._initialTitle}`;let Q=0;this.interval=setInterval(()=>{const S=this.isAlert?this.alertFrame:this.frames[++Q%this.frames.length];document.title=`${S} ${this._initialTitle}`},this.frameDelay),this.opened=!0}close(x=""){this.opened&&(clearInterval(this.interval),document.title=`${x}${this._initialTitle}`,$("#loading-dialog").removeClass("is-active"),$(".wait-info ul li").remove(),delete this.onAbort,this.opened=!1)}addInfo(x,Q){$("#aborter").remove(),$(".wait-info ul li:nth-child(n+1)").css("opacity",.5),$(".wait-info ul li span.fas").removeClass("fa-spinner").removeClass("fa-spin").addClass("fa-check"),$(".wait-info ul li:nth-child(n+4)").hide();const S=$(`
  • ${x}
  • `);if(typeof Q=="function"){this.onAbort=Q;const D=$(' (abort)
    ').on("click",()=>(this.abort(),!1));S.append(D)}$(".wait-info ul").prepend(S)}abort(){typeof this.onAbort=="function"&&(this.addInfo("aborting"),this.onAbort(this.close))}}}init(){this.waiter.addInfo("ide starting up"),$("#overpass-turbo-version").html("overpass-turbo 2024-11-03/b370221"),$("#overpass-turbo-dependencies").html('@fortawesome/fontawesome-free 5.15.4 ((CC-BY-4.0 AND OFL-1.1 AND MIT)), @openstreetmap/id-tagging-schema 3.5.1 (ISC), bulma 0.9.4 (MIT), canvg 4.0.1 (MIT), codemirror 2.38.00 (undefined), html2canvas 1.4.1 (MIT), jquery 3.7.1 (MIT), jquery-ui 1.13.2 (MIT), jquery-ui-dist 1.13.2 (MIT), leaflet 1.9.4 (BSD-2-Clause), leaflet-polylineoffset 1.1.1 (MIT), leaflet-locationfilter 0.1.3 (MIT), lodash 4.17.21 (MIT), osm-auth 2.2.0 (ISC), osmtogeojson 3.0.0-beta.5 (MIT), rgbcolor 1.0.1 (MIT OR SEE LICENSE IN FEEL-FREE.md), stackblur 1.0.0 (BSD-2-Clause), tag2link 2024.05.21 (ISC), togpx 0.5.4 (MIT), tokml 0.4.0 (BSD-2-Clause)'),($.support.cors!=!0||typeof function(){let B;try{localStorage.setItem("startup_localstorage_quota_test",123),localStorage.removeItem("startup_localstorage_quota_test"),B=localStorage}catch{}return B}()!="object")&&(this.not_supported=!0,$("#warning-unsupported-browser").addClass("is-active")),this.waiter.addInfo("load settings"),settings.load(),this.waiter.addInfo("translate ui"),i18n.translate().then(()=>this.initAfterI18n()),sync.enabled&&($("#load-dialog .osm").show(),sync.authenticated()&&($("#logout").show(),$("#logout").appendTo($("#logout").parent())))}initAfterI18n(){const B=this;B.waiter.addInfo("parse url parameters");const x=urlParameters();x.has_coords&&(settings.coords_lat=x.coords.lat,settings.coords_lon=x.coords.lng),x.has_zoom&&(settings.coords_zoom=x.zoom),x.run_query&&(B.run_query_on_startup=!0),settings.save(),B.waiter.addInfo("initialize page");const Q=$(window).width()/$(window).height()<.8;if(settings.editor_width!=""&&!Q&&($("#editor").css("width",settings.editor_width),$("#dataviewer").css("left",settings.editor_width)),Q&&$("#editor, #dataviewer").addClass("portrait"),$("#editor").resizable({handles:Q?"s":"e",minWidth:Q?void 0:"200",resize(){if(!Q)$(this).next().css("left",`${$(this).outerWidth()}px`);else{const G=$(this).offset().top+$(this).outerHeight();$(this).next().css("top",`${G}px`)}B.map.invalidateSize(!1)},stop(){Q||(settings.editor_width=$("#editor").css("width"),settings.save())}}),$("#editor").prepend(""),$("#editor textarea")[0].value=settings.code.overpass,settings.use_rich_editor){let G=0;CodeMirror.defineMIME("text/x-overpassQL",{name:"clike",keywords:function(X){const ee={},Ae=X.split(" ");for(const le of Ae)ee[le]=!0;return ee}("out json xml custom popup timeout maxsize bbox date diff adiff foreach relation rel way node is_in area around user uid newer changed poly pivot nwr nw nr wr derived out meta body skel tags ids count qt asc center bb geom")}),CodeMirror.defineMIME("text/x-overpassXML","xml"),CodeMirror.defineMode("xml+mustache",X=>CodeMirror.multiplexingMode(CodeMirror.multiplexingMode(CodeMirror.getMode(X,"xml"),{open:"{{",close:"}}",mode:CodeMirror.getMode(X,"text/plain"),delimStyle:"mustache"}),{open:"{{style:",close:"}}",mode:CodeMirror.getMode(X,"text/css"),delimStyle:"mustache"})),CodeMirror.defineMode("ql+mustache",X=>CodeMirror.multiplexingMode(CodeMirror.multiplexingMode(CodeMirror.getMode(X,"text/x-overpassQL"),{open:"{{",close:"}}",mode:CodeMirror.getMode(X,"text/plain"),delimStyle:"mustache"}),{open:"{{style:",close:"}}",mode:CodeMirror.getMode(X,"text/css"),delimStyle:"mustache"})),B.codeEditor=CodeMirror.fromTextArea($("#editor textarea")[0],{lineNumbers:!0,lineWrapping:!0,mode:"text/plain",onChange(X){clearTimeout(G),G=setTimeout(()=>{B.getQueryLang()=="xml"?X.getOption("mode")!="xml+mustache"&&(X.closeTagEnabled=!0,X.setOption("matchBrackets",!1),X.setOption("mode","xml+mustache")):X.getOption("mode")!="ql+mustache"&&(X.closeTagEnabled=!1,X.setOption("matchBrackets",!0),X.setOption("mode","ql+mustache"));const ee=$(".leaflet-control-buttons-bboxfilter");B.getRawQuery().match(/\{\{bbox\}\}/)?ee.hasClass("disabled")&&(ee.removeClass("disabled"),ee.attr("data-t","[title]map_controlls.select_bbox"),i18n.translate_ui(ee[0])):ee.hasClass("disabled")||(ee.addClass("disabled"),ee.attr("data-t","[title]map_controlls.select_bbox_disabled"),i18n.translate_ui(ee[0]))},500),settings.code.overpass=X.getValue(),settings.save()},closeTagEnabled:!0,closeTagIndent:["osm-script","query","union","foreach","difference"],extraKeys:{"'>'"(X){X.closeTag(X,">")},"'/'"(X){X.closeTag(X,"/")}}}),B.codeEditor.getOption("onChange")(B.codeEditor)}else B.codeEditor=$("#editor textarea")[0],B.codeEditor.getValue=function(){return this.value},B.codeEditor.setValue=function(G){this.value=G},B.codeEditor.lineCount=function(){return this.value.split(/\r\n|\r|\n/).length},B.codeEditor.setLineClass=function(){},$("#editor textarea").bind("input change",G=>{settings.code.overpass=G.target.getValue(),settings.save()});x.has_query&&B.codeEditor.setValue(x.query),B.dataViewer=CodeMirror($("#data")[0],{value:"no data loaded yet",lineNumbers:!0,readOnly:!0,mode:"javascript"}),B.map=new L.Map("map",{attributionControl:!0,minZoom:0,maxZoom:configs.maxMapZoom,worldCopyJump:!1});const S=settings.tile_server,D=configs.tileServerAttribution,H=new L.TileLayer(S,{attribution:D,noWrap:!0,maxNativeZoom:19,maxZoom:B.map.options.maxZoom});B.attribControl=new L.Control.Attribution({prefix:!1}),B.attribControl.addAttribution(D);const P=new L.LatLng(settings.coords_lat,settings.coords_lon);B.map.setView(P,settings.coords_zoom).addLayer(H),B.map.tile_layer=H,B.map.inv_opacity_layer=L.tileLayer("data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==").setOpacity(1-settings.background_opacity),settings.background_opacity!=1&&B.map.inv_opacity_layer.addTo(B.map),B.scaleControl=new L.Control.Scale({metric:!0,imperial:!1}),B.scaleControl.addTo(B.map),B.map.on("moveend",()=>{settings.coords_lat=B.map.getCenter().lat,settings.coords_lon=B.map.getCenter().lng,settings.coords_zoom=B.map.getZoom(),settings.save()}),$("#dataviewer > div#data")[0].style.zIndex=-1001,$(".tabs li").bind("click",G=>{$(G.target).hasClass("is-active")||($("#dataviewer > div#data")[0].style.zIndex=-1*$("#dataviewer > div#data")[0].style.zIndex,$(".tabs li").toggleClass("is-active"))}),$(document).keydown(G=>B.onKeyPress(G));const R=L.Control.extend({options:{position:"topleft"},onAdd(){const G=L.DomUtil.create("div","leaflet-control-buttons leaflet-bar");let X=L.DomUtil.create("a","leaflet-control-buttons-fitdata leaflet-bar-part leaflet-bar-part-top",G);return $('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.zoom_to_data"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",()=>{try{B.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(),{maxZoom:18})}catch{}return!1},B.map),X=L.DomUtil.create("a","leaflet-control-buttons-myloc leaflet-bar-part",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.localize_user"),window.isSecureContext||(X.className+=" disabled",X.setAttribute("data-t","[title]map_controlls.localize_user_disabled")),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",()=>{try{navigator.geolocation.getCurrentPosition(ee=>{const Ae=new L.LatLng(ee.coords.latitude,ee.coords.longitude);B.map.setView(Ae,settings.coords_zoom)})}catch{}return!1},B.map),X=L.DomUtil.create("a","leaflet-control-buttons-bboxfilter leaflet-bar-part",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.select_bbox"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",ee=>($(ee.target).parent().hasClass("disabled")||(B.map.bboxfilter.isEnabled()?B.map.bboxfilter.disable():(B.map.bboxfilter.setBounds(B.map.getBounds().pad(-.2)),B.map.bboxfilter.enable()),$(ee.target).toggleClass("fa-times-circle").toggleClass("fa-image")),!1),B.map),X=L.DomUtil.create("a","leaflet-control-buttons-fullscreen leaflet-bar-part",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.toggle_wide_map"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",ee=>($("#dataviewer").toggleClass("fullscreen"),B.map.invalidateSize(),$(ee.target).toggleClass("fa-step-forward").toggleClass("fa-step-backward"),$("#editor").toggleClass("hidden"),$("#editor").resizable("option","disabled")?$("#editor").resizable("enable"):$("#editor").resizable("disable"),!1),B.map),X=L.DomUtil.create("a","leaflet-control-buttons-clearoverlay leaflet-bar-part leaflet-bar-part-bottom",G),$('').appendTo($(X)),X.href="#",X.className+=" t",X.setAttribute("data-t","[title]map_controlls.toggle_data"),i18n.translate_ui(X),L.DomEvent.addListener(X,"click",ee=>(ee.preventDefault(),B.map.hasLayer(overpass.osmLayer)?B.map.removeLayer(overpass.osmLayer):B.map.addLayer(overpass.osmLayer),!1),B.map),G}});B.map.addControl(new R),$(".leaflet-control-buttons > a").bind("dblclick",G=>G.stopPropagation()),$(".leaflet-control-buttons > a").tooltip({items:"a[title]",hide:{effect:"fadeOut",duration:100},position:{my:"left+5 center",at:"right center"}});const Y=L.Control.extend({options:{position:"topright"},onAdd(){const G=L.DomUtil.create("div","leaflet-control-search control has-icons-left");G.style.position="absolute",G.style.right="0";const X=L.DomUtil.create("input","input is-rounded",G);return $('').click(function(){$(this).prev().autocomplete("search")}).insertAfter(X),X.id="search",X.type="search",X.onclick=function(){this.focus()},G.ondblclick=function(ee){ee.stopPropagation()},$(X).autocomplete({source(ee,Ae){$.ajax(`https://search.osmnames.org/q/${encodeURIComponent(ee.term)}.js?key=${configs.osmnamesApiKey}`,{success(le){if(typeof le=="string")try{le=$.parseJSON(le)}catch{}Ae($.map(le.results.slice(0,10),ae=>({label:ae.display_name,value:ae.display_name,lat:ae.lat,lon:ae.lon,boundingbox:ae.boundingbox})))},error(){console.error("An error occured while contacting the search server osmnames.org :(")}})},minLength:2,autoFocus:!0,select(ee,Ae){return Ae.item.boundingbox&&Ae.item.boundingbox instanceof Array?B.map.fitBounds(L.latLngBounds([[Ae.item.boundingbox[1],Ae.item.boundingbox[0]],[Ae.item.boundingbox[3],Ae.item.boundingbox[2]]]),{maxZoom:18}):B.map.panTo(new L.LatLng(Ae.item.lat,Ae.item.lon)),this.value="",!1},open(){$(this).removeClass("ui-corner-all").addClass("ui-corner-top")},close(){$(this).addClass("ui-corner-all").removeClass("ui-corner-top")}}),$(X).autocomplete("option","delay",20),G}});B.map.addControl(new Y),$('').addClass("crosshairs").hide().appendTo("#map"),settings.enable_crosshairs&&$(".crosshairs").show(),B.map.bboxfilter=new L.LocationFilter({enable:!1,adjustButton:!1,enableButton:!1}).addTo(B.map),B.map.on("popupopen popupclose",G=>{if(typeof G.popup.layer<"u"){const X=G.popup.layer.placeholder||G.popup.layer,ee=overpass.osmLayer._baseLayer.options.style(X.feature,G.type=="popupopen");typeof X.eachLayer!="function"?typeof X.setStyle=="function"&&X.setStyle(ee):X.eachLayer(Ae=>{typeof Ae.setStyle=="function"&&Ae.setStyle(ee)})}}),overpass.init(),overpass.handlers.onProgress=function(G,X){B.waiter.addInfo(G,X)},overpass.handlers.onDone=function(){const G=B.getRawQuery().match(/@name ([^\n]+)/),X=G?`${G[1]} | `:"";B.waiter.close(X);const ee=B.map.getBounds(),Ae=overpass.osmLayer.getBaseLayer().getBounds();if(Ae.isValid()&&!ee.intersects(Ae)){const le=$(".leaflet-control-buttons-fitdata").tooltip("option","content");$(".leaflet-control-buttons-fitdata").tooltip("option","content",`← ${i18n.t("map_controlls.suggest_zoom_to_data")}`),$(".leaflet-control-buttons-fitdata").tooltip("open"),$(".leaflet-control-buttons-fitdata").tooltip("option","hide",{effect:"fadeOut",duration:1e3}),setTimeout(()=>{$(".leaflet-control-buttons-fitdata").tooltip("option","content",le),$(".leaflet-control-buttons-fitdata").tooltip("close"),$(".leaflet-control-buttons-fitdata").tooltip("option","hide",{effect:"fadeOut",duration:100})},2600)}},overpass.handlers.onEmptyMap=function(G,X){const ee=B.getRawQuery(),Ae=/out[^;]+?count/.test(ee);if(G=="no visible data")if(!Ae&&!settings.no_autorepair){const le=`

    ${i18n.t("warning.incomplete.expl.1")}

    ${i18n.t("warning.incomplete.expl.2")}

     ${i18n.t("warning.incomplete.not_again")}

    `,ae=[{name:i18n.t("dialog.repair_query"),callback(){B.repairQuery("no visible data")}},{name:i18n.t("dialog.show_data"),callback(){var ge,fe;(fe=(ge=$("input[name=hide_incomplete_data_warning]"))==null?void 0:ge[0])!=null&&fe.checked&&(settings.no_autorepair=!0,settings.save()),B.switchTab("Data")}}];showDialog(i18n.t("warning.incomplete.title"),le,ae)}else Ae&&B.switchTab("Data");G=="only areas returned"&&B.switchTab("Data"),G=="no coordinates returned"&&B.switchTab("Data"),X=="unknown"&&B.switchTab("Data"),$(`
    ${i18n.t("map.intentionally_blank")} (${G})
    `).appendTo("#map")},overpass.handlers.onDataReceived=function(G,X,ee,Ae){if(G>1e6){B.waiter.close();const le=document.title;document.title=`❗ ${le}`;const ae=[{name:i18n.t("dialog.abort"),callback(){document.title=le,ee()}},{name:i18n.t("dialog.continue_anyway"),callback(){document.title=le,Ae()}}],ge=`

    ${i18n.t("warning.huge_data.expl.1").replace("{{amount_txt}}",X)}

    ${i18n.t("warning.huge_data.expl.2")}

    `;showDialog(i18n.t("warning.huge_data.title"),ge,ae)}else Ae()},overpass.handlers.onAbort=function(){B.waiter.close()},overpass.handlers.onAjaxError=function(G){B.waiter.close();const X=document.title;document.title=`❗ ${X}`;const ee=[{name:i18n.t("dialog.dismiss"),callback(){document.title=X}}],Ae=`

    ${i18n.t("error.ajax.expl")}

    ${G}`;showDialog(i18n.t("error.ajax.title"),Ae,ee),overpass.resultText&&B.dataViewer.setValue(overpass.resultText)},overpass.handlers.onQueryError=function(G){B.waiter.close();const X=document.title;document.title=`❗ ${X}`;const ee=[{name:i18n.t("dialog.dismiss"),callback(){document.title=X}}],Ae=`
    ${i18n.t("error.query.expl")}
    ${G}
    `;showDialog(i18n.t("error.query.title"),Ae,ee)},overpass.handlers.onStyleError=function(G){const X=[{name:i18n.t("dialog.dismiss")}],ee=`

    ${i18n.t("error.mapcss.expl")}

    ${G}`;showDialog(i18n.t("error.mapcss.title"),ee,X)},overpass.handlers.onQueryErrorLine=function(G){B.highlightError(G)},overpass.handlers.onRawDataPresent=function(){B.dataViewer.setOption("mode",overpass.resultType),B.dataViewer.setValue(overpass.resultText)},overpass.handlers.onGeoJsonReady=function(){if(B.map.addLayer(overpass.osmLayer),typeof B.run_query_on_startup=="function"&&B.run_query_on_startup(),settings.show_data_stats){const G=overpass.stats,X=`${i18n.t("data_stats.loaded")} – ${i18n.t("data_stats.nodes")}: ${G.data.nodes}, ${i18n.t("data_stats.ways")}: ${G.data.ways}, ${i18n.t("data_stats.relations")}: ${G.data.relations}${G.data.areas>0?`, ${i18n.t("data_stats.areas")}: ${G.data.areas}`:""}
    ${i18n.t("data_stats.displayed")} – ${i18n.t("data_stats.pois")}: ${G.geojson.pois}, ${i18n.t("data_stats.lines")}: ${G.geojson.lines}, ${i18n.t("data_stats.polygons")}: ${G.geojson.polys}`;$(`
    ${X}
    `).insertAfter("#map .leaflet-control-attribution");const ee=overpass.timestamp&&Date.now()-Date.parse(overpass.timestamp),Ae=overpass.timestampAreas&&Date.now()-Date.parse(overpass.timestampAreas);$("#data_stats").tooltip({items:"div",tooltipClass:"stats",content(){let le="
    ";if(overpass.ajax_request_duration){let ae=overpass.ajax_request_duration;ae.toLocaleString&&(ae=ae.toLocaleString()),le+=`${i18n.t("data_stats.request_duration")}: ${ae}ms
    `}return overpass.timestamp&&(le+=`${i18n.t("data_stats.lag")}: ${Math.floor(ee/1e3)}s ${i18n.t("data_stats.lag.expl")}`),overpass.timestampAreas&&(le+=`
    ${i18n.t("data_stats.lag_areas")}: ${Math.floor(Ae/1e3)}s ${i18n.t("data_stats.lag.expl")}`),le+="
    ",le},hide:{effect:"fadeOut",duration:100},position:{my:"right bottom-5",at:"right top"}}),(ee>24*60*60*1e3||Ae>96*60*60*1e3)&&$("#data_stats").css("background-color","yellow")}},overpass.handlers.onPopupReady=function(G){G.openOn(B.map)},B.waiter.close(),B.run_query_on_startup===!0&&(B.update_map(),!x.has_coords&&x.has_query&&x.query.match(/\{\{(bbox|center)\}\}/)===null&&(B.run_query_on_startup=function(){B.run_query_on_startup=null;try{B.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(),{maxZoom:18})}catch{}}))}onNominatimError(B,x){this.waiter.close();let Q=this.getRawQuery();Q=Q.split(` `),Q.forEach((H,P)=>{H.indexOf(`{{geocode${x}:${B}}}`)!==-1&&this.highlightError(P+1)});const S=[{name:i18n.t("dialog.dismiss")}],D=`

    ${i18n.t("error.nominatim.expl")}

    ${htmlentities(B)}

    `;showDialog(i18n.t("error.nominatim.title"),D,S)}getRawQuery(){return this.codeEditor.getValue()}async getQuery(){let B=this.getRawQuery();B=B.replace(/(]+bbox[^=]*=[^"'']*["'])({{bbox}})(["'])/,"$1{{__bbox__global_bbox_xml__ezs4K8__}}$3"),B=await this.queryParser.parse(B,shortcuts());let x="";this.queryParser.hasStatement("style")&&(x=this.queryParser.getStatement("style")),this.mapcss=x;let Q=null;if(this.queryParser.hasStatement("data")){Q=this.queryParser.getStatement("data"),Q=Q.split(",");const S=Q[0].toLowerCase();Q=Q.slice(1);const D={};for(const H of Q){const P=H.split("=");D[P[0]]=P[1]}Q={mode:S,options:D}}return this.data_source=Q,B}setQuery(B){this.codeEditor.setValue(B)}getQueryLang(){return $.trim(this.getRawQuery().replace(/{{.*?}}/g,"")).match(/^{delete settings.saves[B],settings.save(),this.onLoadClick()}},{name:i18n.t("dialog.cancel")}],Q=`

    ${i18n.t("dialog.delete_query.expl")}: "${B}"?

    `;showDialog(i18n.t("dialog.delete_query.title"),Q,x)}removeExampleSync(B,x){const Q=[{name:i18n.t("dialog.delete"),callback(){sync.delete(B.name,D=>{if(D)return console.error(D);$(x).parent().remove()})}},{name:i18n.t("dialog.cancel")}],S=`

    ${i18n.t("dialog.delete_query.expl-osm")}: "${B.name}"?

    `;showDialog(i18n.t("dialog.delete_query.title"),S,Q)}onLoadClick(){const B=this;$("#load-dialog .panel.saved_query .panel-block").remove(),$("#load-dialog .panel.example .panel-block").remove();let x=!1;for(const Q in settings.saves){const S=settings.saves[Q].type;S!="template"&&($('').attr("href","#").text(Q).on("click",()=>(B.loadExample(Q),$("#load-dialog").removeClass("is-active"),!1)).append($('`).on("click",()=>{B.loadOsmQueries()})).appendTo(Q)):Q.hide()}}loadOsmQueries(){const B=this,x=$("#load-dialog .panel.osm-queries");x.show(),x.find(".panel-block").remove(),$('
    ').text(i18n.t("load.saved_queries-osm-loading")).appendTo(x),sync.load((Q,S)=>{if(Q)return x.find(".panel-block").remove(),$('
    ').text(i18n.t("load.saved_queries-osm-error")).appendTo(x),console.error(Q);x.find(".panel-block").remove(),$("#logout").show(),$("#logout").appendTo($("#logout").parent()),S.forEach(D=>{$('').attr("href","#").text(D.name).on("click",()=>(B.setQuery(lzw_decode(Base64.decode(D.query))),$("#load-dialog").removeClass("is-active"),!1)).append($('\\\n \\\n
    \\\n ${content}\\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n `;\n\n // Create modal in body\n const element = $(dialogContent);\n // Handle close event\n $(\".delete\", element).click(() => $(element).remove());\n\n // Add all the buttons\n for (const index in buttons) {\n const button = buttons[index];\n $(``)\n .click(() => {\n button.callback?.();\n // destroy modal dialog after callback, see #528\n $(element).remove();\n })\n .appendTo($(\"footer .level-item\", element));\n }\n\n // Add the element to the body\n element.appendTo(\"body\");\n}\n\nclass IDE {\n // == private members ==\n private attribControl = null;\n private scaleControl = null;\n private queryParser = new Query();\n private run_query_on_startup = false;\n // == public members ==\n codeEditor = null;\n dataViewer = null;\n map: L.Map = null;\n\n // == public sub objects ==\n\n waiter = new (class Waiter {\n opened = true;\n frames = [\"◴\", \"◷\", \"◶\", \"◵\"];\n frameDelay = 250;\n onAbort = undefined;\n interval = 0;\n _initialTitle = document.title;\n\n open(show_info) {\n if (show_info) {\n $(\".modal .wait-info h4\").text(show_info);\n $(\".wait-info\").show();\n } else {\n $(\".wait-info\").hide();\n }\n $(\"#loading-dialog\").addClass(\"is-active\");\n document.title = `${this.frames[0]} ${this._initialTitle}`;\n let f = 0;\n this.interval = setInterval(() => {\n const title = this.isAlert\n ? this.alertFrame\n : this.frames[++f % this.frames.length];\n document.title = `${title} ${this._initialTitle}`;\n }, this.frameDelay);\n this.opened = true;\n }\n close(title_prefix = \"\") {\n if (!this.opened) return;\n clearInterval(this.interval);\n document.title = `${title_prefix}${this._initialTitle}`;\n $(\"#loading-dialog\").removeClass(\"is-active\");\n $(\".wait-info ul li\").remove();\n delete this.onAbort;\n this.opened = false;\n }\n addInfo(txt, abortCallback) {\n $(\"#aborter\").remove(); // remove previously added abort button, which cannot be used anymore.\n $(\".wait-info ul li:nth-child(n+1)\").css(\"opacity\", 0.5);\n $(\".wait-info ul li span.fas\")\n .removeClass(\"fa-spinner\")\n .removeClass(\"fa-spin\")\n .addClass(\"fa-check\");\n $(\".wait-info ul li:nth-child(n+4)\").hide();\n const li = $(\n `
  • ${txt}
  • `\n );\n if (typeof abortCallback == \"function\") {\n this.onAbort = abortCallback;\n const aborter = $(\n ' (
    abort)
    '\n ).on(\"click\", () => {\n this.abort();\n return false;\n });\n li.append(aborter);\n }\n $(\".wait-info ul\").prepend(li);\n }\n abort() {\n if (typeof this.onAbort == \"function\") {\n this.addInfo(\"aborting\");\n this.onAbort(this.close);\n }\n }\n })();\n\n // == public methods ==\n\n init() {\n this.waiter.addInfo(\"ide starting up\");\n $(\"#overpass-turbo-version\").html(\n `overpass-turbo ${GIT_VERSION}` // eslint-disable-line no-undef\n );\n $(\"#overpass-turbo-dependencies\").html(\n APP_DEPENDENCIES // eslint-disable-line no-undef\n );\n // (very raw) compatibility check <- TODO: put this into its own function\n if (\n jQuery.support.cors != true ||\n //typeof localStorage != \"object\" ||\n typeof (function () {\n let ls = undefined;\n try {\n localStorage.setItem(\"startup_localstorage_quota_test\", 123);\n localStorage.removeItem(\"startup_localstorage_quota_test\");\n ls = localStorage;\n } catch (e) {}\n return ls;\n })() != \"object\" ||\n false\n ) {\n // the currently used browser is not capable of running the IDE. :(\n this.not_supported = true;\n $(\"#warning-unsupported-browser\").addClass(\"is-active\");\n }\n // load settings\n this.waiter.addInfo(\"load settings\");\n settings.load();\n // translate ui\n this.waiter.addInfo(\"translate ui\");\n i18n.translate().then(() => this.initAfterI18n());\n\n if (sync.enabled) {\n $(\"#load-dialog .osm\").show();\n if (sync.authenticated()) {\n $(\"#logout\").show();\n $(\"#logout\").appendTo($(\"#logout\").parent());\n }\n }\n }\n\n initAfterI18n() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ide = this;\n // parse url string parameters\n ide.waiter.addInfo(\"parse url parameters\");\n const args = urlParameters();\n // set appropriate settings\n if (args.has_coords) {\n // map center coords set via url\n settings.coords_lat = args.coords.lat;\n settings.coords_lon = args.coords.lng;\n }\n if (args.has_zoom) {\n // map zoom set via url\n settings.coords_zoom = args.zoom;\n }\n if (args.run_query) {\n // query autorun activated via url\n ide.run_query_on_startup = true;\n }\n settings.save();\n\n ide.waiter.addInfo(\"initialize page\");\n // init page layout\n const isInitialAspectPortrait =\n $(window).width() / $(window).height() < 0.8;\n if (settings.editor_width != \"\" && !isInitialAspectPortrait) {\n $(\"#editor\").css(\"width\", settings.editor_width);\n $(\"#dataviewer\").css(\"left\", settings.editor_width);\n }\n if (isInitialAspectPortrait) {\n $(\"#editor, #dataviewer\").addClass(\"portrait\");\n }\n // make panels resizable\n $(\"#editor\").resizable({\n handles: isInitialAspectPortrait ? \"s\" : \"e\",\n minWidth: isInitialAspectPortrait ? undefined : \"200\",\n resize() {\n if (!isInitialAspectPortrait) {\n $(this)\n .next()\n .css(\"left\", `${$(this).outerWidth()}px`);\n } else {\n const top = $(this).offset().top + $(this).outerHeight();\n $(this).next().css(\"top\", `${top}px`);\n }\n ide.map.invalidateSize(false);\n },\n stop() {\n if (isInitialAspectPortrait) return;\n settings.editor_width = $(\"#editor\").css(\"width\");\n settings.save();\n }\n });\n $(\"#editor\").prepend(\n \"\"\n );\n\n // init codemirror\n $(\"#editor textarea\")[0].value = settings.code[\"overpass\"];\n if (settings.use_rich_editor) {\n let pending = 0;\n CodeMirror.defineMIME(\"text/x-overpassQL\", {\n name: \"clike\",\n keywords: (function (str) {\n const r = {};\n const a = str.split(\" \");\n for (const ai of a) r[ai] = true;\n return r;\n })(\n \"out json xml custom popup timeout maxsize bbox\" + // initial declarations\n \" date diff adiff\" + //attic declarations\n \" foreach\" + // block statements\n \" relation rel way node is_in area around user uid newer changed poly pivot nwr nw nr wr derived\" + // queries\n \" out meta body skel tags ids count qt asc\" + // actions\n \" center bb geom\" // geometry types\n //+\"r w n br bw\" // recursors\n )\n });\n CodeMirror.defineMIME(\"text/x-overpassXML\", \"xml\");\n CodeMirror.defineMode(\"xml+mustache\", (config) =>\n CodeMirror.multiplexingMode(\n CodeMirror.multiplexingMode(CodeMirror.getMode(config, \"xml\"), {\n open: \"{{\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/plain\"),\n delimStyle: \"mustache\"\n }),\n {\n open: \"{{style:\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/css\"),\n delimStyle: \"mustache\"\n }\n )\n );\n CodeMirror.defineMode(\"ql+mustache\", (config) =>\n CodeMirror.multiplexingMode(\n CodeMirror.multiplexingMode(\n CodeMirror.getMode(config, \"text/x-overpassQL\"),\n {\n open: \"{{\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/plain\"),\n delimStyle: \"mustache\"\n }\n ),\n {\n open: \"{{style:\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/css\"),\n delimStyle: \"mustache\"\n }\n )\n );\n ide.codeEditor = CodeMirror.fromTextArea($(\"#editor textarea\")[0], {\n //value: settings.code[\"overpass\"],\n lineNumbers: true,\n lineWrapping: true,\n mode: \"text/plain\",\n onChange(e) {\n clearTimeout(pending);\n pending = setTimeout(() => {\n // update syntax highlighting mode\n if (ide.getQueryLang() == \"xml\") {\n if (e.getOption(\"mode\") != \"xml+mustache\") {\n e.closeTagEnabled = true;\n e.setOption(\"matchBrackets\", false);\n e.setOption(\"mode\", \"xml+mustache\");\n }\n } else {\n if (e.getOption(\"mode\") != \"ql+mustache\") {\n e.closeTagEnabled = false;\n e.setOption(\"matchBrackets\", true);\n e.setOption(\"mode\", \"ql+mustache\");\n }\n }\n // check for inactive ui elements\n const bbox_filter = $(\".leaflet-control-buttons-bboxfilter\");\n if (ide.getRawQuery().match(/\\{\\{bbox\\}\\}/)) {\n if (bbox_filter.hasClass(\"disabled\")) {\n bbox_filter.removeClass(\"disabled\");\n bbox_filter.attr(\"data-t\", \"[title]map_controlls.select_bbox\");\n i18n.translate_ui(bbox_filter[0]);\n }\n } else {\n if (!bbox_filter.hasClass(\"disabled\")) {\n bbox_filter.addClass(\"disabled\");\n bbox_filter.attr(\n \"data-t\",\n \"[title]map_controlls.select_bbox_disabled\"\n );\n i18n.translate_ui(bbox_filter[0]);\n }\n }\n }, 500);\n settings.code[\"overpass\"] = e.getValue();\n settings.save();\n },\n closeTagEnabled: true,\n closeTagIndent: [\n \"osm-script\",\n \"query\",\n \"union\",\n \"foreach\",\n \"difference\"\n ],\n extraKeys: {\n \"'>'\"(cm) {\n cm.closeTag(cm, \">\");\n },\n \"'/'\"(cm) {\n cm.closeTag(cm, \"/\");\n }\n }\n });\n // fire onChange after initialization\n ide.codeEditor.getOption(\"onChange\")(ide.codeEditor);\n } else {\n // use non-rich editor\n ide.codeEditor = $(\"#editor textarea\")[0];\n ide.codeEditor.getValue = function () {\n return this.value;\n };\n ide.codeEditor.setValue = function (v) {\n this.value = v;\n };\n ide.codeEditor.lineCount = function () {\n return this.value.split(/\\r\\n|\\r|\\n/).length;\n };\n ide.codeEditor.setLineClass = function () {};\n $(\"#editor textarea\").bind(\"input change\", (e) => {\n settings.code[\"overpass\"] = e.target.getValue();\n settings.save();\n });\n }\n // set query if provided as url parameter or template:\n if (args.has_query) {\n // query set via url\n ide.codeEditor.setValue(args.query);\n }\n // init dataviewer\n ide.dataViewer = CodeMirror($(\"#data\")[0], {\n value: \"no data loaded yet\",\n lineNumbers: true,\n readOnly: true,\n mode: \"javascript\"\n });\n\n // init leaflet\n ide.map = new L.Map(\"map\", {\n attributionControl: true,\n minZoom: 0,\n maxZoom: configs.maxMapZoom,\n worldCopyJump: false\n });\n const tilesUrl = settings.tile_server;\n const tilesAttrib = configs.tileServerAttribution;\n const tiles = new L.TileLayer(tilesUrl, {\n attribution: tilesAttrib,\n noWrap: true,\n maxNativeZoom: 19,\n maxZoom: ide.map.options.maxZoom\n });\n ide.attribControl = new L.Control.Attribution({prefix: false});\n ide.attribControl.addAttribution(tilesAttrib);\n const pos = new L.LatLng(settings.coords_lat, settings.coords_lon);\n ide.map.setView(pos, settings.coords_zoom).addLayer(tiles);\n ide.map.tile_layer = tiles;\n // inverse opacity layer\n ide.map.inv_opacity_layer = L.tileLayer(\n \"data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==\"\n ).setOpacity(1 - settings.background_opacity);\n if (settings.background_opacity != 1)\n ide.map.inv_opacity_layer.addTo(ide.map);\n ide.scaleControl = new L.Control.Scale({metric: true, imperial: false});\n ide.scaleControl.addTo(ide.map);\n ide.map.on(\"moveend\", () => {\n settings.coords_lat = ide.map.getCenter().lat;\n settings.coords_lon = ide.map.getCenter().lng;\n settings.coords_zoom = ide.map.getZoom();\n settings.save(); // save settings\n });\n\n // tabs\n $(\"#dataviewer > div#data\")[0].style.zIndex = -1001;\n $(\".tabs li\").bind(\"click\", (e) => {\n if ($(e.target).hasClass(\"is-active\")) {\n return;\n } else {\n $(\"#dataviewer > div#data\")[0].style.zIndex =\n -1 * $(\"#dataviewer > div#data\")[0].style.zIndex;\n $(\".tabs li\").toggleClass(\"is-active\");\n }\n });\n\n // keyboard event listener\n $(document).keydown((event) => ide.onKeyPress(event));\n\n // leaflet extension: more map controls\n const MapButtons = L.Control.extend({\n options: {\n position: \"topleft\"\n },\n onAdd() {\n // create the control container with a particular class name\n const container = L.DomUtil.create(\n \"div\",\n \"leaflet-control-buttons leaflet-bar\"\n );\n let link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-fitdata leaflet-bar-part leaflet-bar-part-top\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.zoom_to_data\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n () => {\n // hardcoded maxZoom of 18, should be ok for most real-world use-cases\n try {\n ide.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(), {\n maxZoom: 18\n });\n } catch (e) {}\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-myloc leaflet-bar-part\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.localize_user\");\n if (!window.isSecureContext) {\n link.className += \" disabled\";\n link.setAttribute(\n \"data-t\",\n \"[title]map_controlls.localize_user_disabled\"\n );\n }\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n () => {\n // One-shot position request.\n try {\n navigator.geolocation.getCurrentPosition((position) => {\n const pos = new L.LatLng(\n position.coords.latitude,\n position.coords.longitude\n );\n ide.map.setView(pos, settings.coords_zoom);\n });\n } catch (e) {}\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-bboxfilter leaflet-bar-part\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.select_bbox\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n (e) => {\n if (\n $(e.target).parent().hasClass(\"disabled\") // check if this button is enabled\n )\n return false;\n if (!ide.map.bboxfilter.isEnabled()) {\n ide.map.bboxfilter.setBounds(ide.map.getBounds().pad(-0.2));\n ide.map.bboxfilter.enable();\n } else {\n ide.map.bboxfilter.disable();\n }\n $(e.target).toggleClass(\"fa-times-circle\").toggleClass(\"fa-image\");\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-fullscreen leaflet-bar-part\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.toggle_wide_map\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n (e) => {\n $(\"#dataviewer\").toggleClass(\"fullscreen\");\n ide.map.invalidateSize();\n $(e.target)\n .toggleClass(\"fa-step-forward\")\n .toggleClass(\"fa-step-backward\");\n $(\"#editor\").toggleClass(\"hidden\");\n if ($(\"#editor\").resizable(\"option\", \"disabled\"))\n $(\"#editor\").resizable(\"enable\");\n else $(\"#editor\").resizable(\"disable\");\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-clearoverlay leaflet-bar-part leaflet-bar-part-bottom\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.toggle_data\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n (e) => {\n e.preventDefault();\n if (ide.map.hasLayer(overpass.osmLayer))\n ide.map.removeLayer(overpass.osmLayer);\n else ide.map.addLayer(overpass.osmLayer);\n return false;\n },\n ide.map\n );\n return container;\n }\n });\n ide.map.addControl(new MapButtons());\n // prevent propagation of doubleclicks on map controls\n $(\".leaflet-control-buttons > a\").bind(\"dblclick\", (e) =>\n e.stopPropagation()\n );\n // add tooltips to map controls\n $(\".leaflet-control-buttons > a\").tooltip({\n items: \"a[title]\",\n hide: {\n effect: \"fadeOut\",\n duration: 100\n },\n position: {\n my: \"left+5 center\",\n at: \"right center\"\n }\n });\n // leaflet extension: search box\n const SearchBox = L.Control.extend({\n options: {\n position: \"topright\"\n },\n onAdd() {\n const container = L.DomUtil.create(\n \"div\",\n \"leaflet-control-search control has-icons-left\"\n );\n container.style.position = \"absolute\";\n container.style.right = \"0\";\n const inp = L.DomUtil.create(\"input\", \"input is-rounded\", container);\n $('')\n .click(function () {\n $(this).prev().autocomplete(\"search\");\n })\n .insertAfter(inp);\n inp.id = \"search\";\n inp.type = \"search\";\n // hack against focus stealing leaflet :/\n inp.onclick = function () {\n this.focus();\n };\n // prevent propagation of doubleclicks to map container\n container.ondblclick = function (e) {\n e.stopPropagation();\n };\n // autocomplete functionality\n $(inp).autocomplete({\n source(request, response) {\n // ajax (GET) request to nominatim\n $.ajax(\n `https://search.osmnames.org/q/${encodeURIComponent(\n request.term\n )}.js?key=${configs.osmnamesApiKey}`,\n {\n success(data) {\n // hacky firefox hack :( (it is not properly detecting json from the content-type header)\n if (typeof data == \"string\") {\n // if the data is a string, but looks more like a json object\n try {\n data = $.parseJSON(data);\n } catch (e) {}\n }\n response(\n $.map(data.results.slice(0, 10), (item) => ({\n label: item.display_name,\n value: item.display_name,\n lat: item.lat,\n lon: item.lon,\n boundingbox: item.boundingbox\n }))\n );\n },\n error() {\n // todo: better error handling\n console.error(\n \"An error occured while contacting the search server osmnames.org :(\"\n );\n }\n }\n );\n },\n minLength: 2,\n autoFocus: true,\n select(event, ui) {\n if (ui.item.boundingbox && ui.item.boundingbox instanceof Array)\n ide.map.fitBounds(\n L.latLngBounds([\n [ui.item.boundingbox[1], ui.item.boundingbox[0]],\n [ui.item.boundingbox[3], ui.item.boundingbox[2]]\n ]),\n {maxZoom: 18}\n );\n else ide.map.panTo(new L.LatLng(ui.item.lat, ui.item.lon));\n this.value = \"\";\n return false;\n },\n open() {\n $(this).removeClass(\"ui-corner-all\").addClass(\"ui-corner-top\");\n },\n close() {\n $(this).addClass(\"ui-corner-all\").removeClass(\"ui-corner-top\");\n }\n });\n $(inp).autocomplete(\"option\", \"delay\", 20);\n return container;\n }\n });\n ide.map.addControl(new SearchBox());\n // add cross hairs to map\n $('')\n .addClass(\"crosshairs\")\n .hide()\n .appendTo(\"#map\");\n if (settings.enable_crosshairs) $(\".crosshairs\").show();\n\n ide.map.bboxfilter = new L.LocationFilter({\n enable: !true,\n adjustButton: false,\n enableButton: false\n }).addTo(ide.map);\n\n ide.map.on(\"popupopen popupclose\", (e) => {\n if (typeof e.popup.layer != \"undefined\") {\n const layer = e.popup.layer.placeholder || e.popup.layer;\n // re-call style handler to eventually modify the style of the clicked feature\n const stl = overpass.osmLayer._baseLayer.options.style(\n layer.feature,\n e.type == \"popupopen\"\n );\n if (typeof layer.eachLayer != \"function\") {\n if (typeof layer.setStyle == \"function\") layer.setStyle(stl); // other objects (pois, ways)\n } else\n layer.eachLayer((layer) => {\n if (typeof layer.setStyle == \"function\") layer.setStyle(stl);\n }); // for multipolygons!\n }\n });\n\n // init overpass object\n overpass.init();\n\n // event handlers for overpass object\n overpass.handlers[\"onProgress\"] = function (msg, abortcallback) {\n ide.waiter.addInfo(msg, abortcallback);\n };\n overpass.handlers[\"onDone\"] = function () {\n const name_match = ide.getRawQuery().match(/@name ([^\\n]+)/);\n // parse document title from @name in query\n const title_prefix = name_match ? `${name_match[1]} | ` : \"\";\n ide.waiter.close(title_prefix);\n const map_bounds = ide.map.getBounds();\n const data_bounds = overpass.osmLayer.getBaseLayer().getBounds();\n if (data_bounds.isValid() && !map_bounds.intersects(data_bounds)) {\n // show tooltip for button \"zoom to data\"\n const prev_content = $(\".leaflet-control-buttons-fitdata\").tooltip(\n \"option\",\n \"content\"\n );\n $(\".leaflet-control-buttons-fitdata\").tooltip(\n \"option\",\n \"content\",\n `← ${i18n.t(\"map_controlls.suggest_zoom_to_data\")}`\n );\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"open\");\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"option\", \"hide\", {\n effect: \"fadeOut\",\n duration: 1000\n });\n setTimeout(() => {\n $(\".leaflet-control-buttons-fitdata\").tooltip(\n \"option\",\n \"content\",\n prev_content\n );\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"close\");\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"option\", \"hide\", {\n effect: \"fadeOut\",\n duration: 100\n });\n }, 2600);\n }\n };\n overpass.handlers[\"onEmptyMap\"] = function (empty_msg, data_mode) {\n // get the current query\n const query = ide.getRawQuery();\n\n // check if 'out' followed by any number of characters (non-greedy) and then 'count' is present in the query\n const isCountPresent = /out[^;]+?count/.test(query);\n\n // show warning/info if only invisible data is returned and 'out...count' is not present in the query\n if (empty_msg == \"no visible data\") {\n if (!isCountPresent && !settings.no_autorepair) {\n const content = `

    ${i18n.t(\n \"warning.incomplete.expl.1\"\n )}

    ${i18n.t(\n \"warning.incomplete.expl.2\"\n )}

     ${i18n.t(\n \"warning.incomplete.not_again\"\n )}

    `;\n\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.repair_query\"),\n callback() {\n ide.repairQuery(\"no visible data\");\n }\n },\n {\n name: i18n.t(\"dialog.show_data\"),\n callback() {\n if (\n $(\"input[name=hide_incomplete_data_warning]\")?.[0]?.checked\n ) {\n settings.no_autorepair = true;\n settings.save();\n }\n ide.switchTab(\"Data\");\n }\n }\n ];\n showDialog(\n i18n.t(\"warning.incomplete.title\"),\n content,\n dialog_buttons\n );\n } else if (isCountPresent) {\n ide.switchTab(\"Data\");\n }\n }\n // auto tab switching (if only areas are returned)\n if (empty_msg == \"only areas returned\") ide.switchTab(\"Data\");\n // auto tab switching (if nodes without coordinates are returned)\n if (empty_msg == \"no coordinates returned\") ide.switchTab(\"Data\");\n // auto tab switching (if unstructured data is returned)\n if (data_mode == \"unknown\") ide.switchTab(\"Data\");\n // display empty map badge\n $(\n `
    ${i18n.t(\n \"map.intentionally_blank\"\n )} (${empty_msg})
    `\n ).appendTo(\"#map\");\n };\n overpass.handlers[\"onDataReceived\"] = function (\n amount,\n amount_txt,\n abortCB,\n continueCB\n ) {\n if (amount > 1000000) {\n ide.waiter.close();\n const _originalDocumentTitle = document.title;\n document.title = `❗ ${_originalDocumentTitle}`;\n // more than ~1MB of data\n // show warning dialog\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.abort\"),\n callback() {\n document.title = _originalDocumentTitle;\n abortCB();\n }\n },\n {\n name: i18n.t(\"dialog.continue_anyway\"),\n callback() {\n document.title = _originalDocumentTitle;\n continueCB();\n }\n }\n ];\n\n const content = `

    ${i18n\n .t(\"warning.huge_data.expl.1\")\n .replace(\"{{amount_txt}}\", amount_txt)}

    ${i18n.t(\n \"warning.huge_data.expl.2\"\n )}

    `;\n showDialog(i18n.t(\"warning.huge_data.title\"), content, dialog_buttons);\n } else continueCB();\n };\n overpass.handlers[\"onAbort\"] = function () {\n ide.waiter.close();\n };\n overpass.handlers[\"onAjaxError\"] = function (errmsg) {\n ide.waiter.close();\n const _originalDocumentTitle = document.title;\n document.title = `❗ ${_originalDocumentTitle}`;\n // show error dialog\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.dismiss\"),\n callback() {\n document.title = _originalDocumentTitle;\n }\n }\n ];\n\n const content = `

    ${i18n.t(\n \"error.ajax.expl\"\n )}

    ${errmsg}`;\n showDialog(i18n.t(\"error.ajax.title\"), content, dialog_buttons);\n\n // print error text, if present\n if (overpass.resultText) ide.dataViewer.setValue(overpass.resultText);\n };\n overpass.handlers[\"onQueryError\"] = function (errmsg) {\n ide.waiter.close();\n const _originalDocumentTitle = document.title;\n document.title = `❗ ${_originalDocumentTitle}`;\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.dismiss\"),\n callback() {\n document.title = _originalDocumentTitle;\n }\n }\n ];\n const content = `
    ${i18n.t(\n \"error.query.expl\"\n )}
    ${errmsg}
    `;\n showDialog(i18n.t(\"error.query.title\"), content, dialog_buttons);\n };\n overpass.handlers[\"onStyleError\"] = function (errmsg) {\n const dialog_buttons = [{name: i18n.t(\"dialog.dismiss\")}];\n const content = `

    ${i18n.t(\n \"error.mapcss.expl\"\n )}

    ${errmsg}`;\n showDialog(i18n.t(\"error.mapcss.title\"), content, dialog_buttons);\n };\n overpass.handlers[\"onQueryErrorLine\"] = function (linenumber) {\n ide.highlightError(linenumber);\n };\n overpass.handlers[\"onRawDataPresent\"] = function () {\n ide.dataViewer.setOption(\"mode\", overpass.resultType);\n ide.dataViewer.setValue(overpass.resultText);\n };\n overpass.handlers[\"onGeoJsonReady\"] = function () {\n // show layer\n ide.map.addLayer(overpass.osmLayer);\n // autorun callback (e.g. zoom to data)\n if (typeof ide.run_query_on_startup === \"function\") {\n ide.run_query_on_startup();\n }\n // display stats\n if (settings.show_data_stats) {\n const stats = overpass.stats;\n const stats_txt =\n `${i18n.t(\"data_stats.loaded\")} – ` +\n `${i18n.t(\"data_stats.nodes\")}: ${stats.data.nodes}, ${i18n.t(\n \"data_stats.ways\"\n )}: ${stats.data.ways}, ${i18n.t(\n \"data_stats.relations\"\n )}: ${stats.data.relations}${\n stats.data.areas > 0\n ? `, ${i18n.t(\"data_stats.areas\")}: ${stats.data.areas}`\n : \"\"\n }
    ` +\n `${i18n.t(\n \"data_stats.displayed\"\n )} – ` +\n `${i18n.t(\"data_stats.pois\")}: ${stats.geojson.pois}, ${i18n.t(\n \"data_stats.lines\"\n )}: ${stats.geojson.lines}, ${i18n.t(\n \"data_stats.polygons\"\n )}: ${stats.geojson.polys}`;\n $(\n `
    ${stats_txt}
    `\n ).insertAfter(\"#map .leaflet-control-attribution\");\n // show more stats as a tooltip\n const backlogOverpass =\n overpass.timestamp && Date.now() - Date.parse(overpass.timestamp);\n const backlogOverpassAreas =\n overpass.timestampAreas &&\n Date.now() - Date.parse(overpass.timestampAreas);\n $(\"#data_stats\").tooltip({\n items: \"div\",\n tooltipClass: \"stats\",\n content() {\n let str = \"
    \";\n if (overpass.ajax_request_duration) {\n let duration = overpass.ajax_request_duration;\n if (duration.toLocaleString) {\n duration = duration.toLocaleString();\n }\n str += `${i18n.t(\n \"data_stats.request_duration\"\n )}: ${duration}ms
    `;\n }\n if (overpass.timestamp) {\n str +=\n `${i18n.t(\"data_stats.lag\")}: ${Math.floor(\n backlogOverpass / 1000\n )}s` + ` ${i18n.t(\"data_stats.lag.expl\")}`;\n }\n if (overpass.timestampAreas) {\n str +=\n `
    ${i18n.t(\"data_stats.lag_areas\")}: ${Math.floor(\n backlogOverpassAreas / 1000\n )}s` + ` ${i18n.t(\"data_stats.lag.expl\")}`;\n }\n str += \"
    \";\n return str;\n },\n hide: {\n effect: \"fadeOut\",\n duration: 100\n },\n position: {\n my: \"right bottom-5\",\n at: \"right top\"\n }\n });\n if (\n backlogOverpass > 24 * 60 * 60 * 1000 ||\n backlogOverpassAreas > 96 * 60 * 60 * 1000\n ) {\n $(\"#data_stats\").css(\"background-color\", \"yellow\");\n }\n }\n };\n overpass.handlers[\"onPopupReady\"] = function (p) {\n p.openOn(ide.map);\n };\n\n // close startup waiter\n ide.waiter.close();\n\n // run the query immediately, if the appropriate flag was set.\n if (ide.run_query_on_startup === true) {\n ide.update_map();\n // automatically zoom to data.\n if (\n !args.has_coords &&\n args.has_query &&\n args.query.match(/\\{\\{(bbox|center)\\}\\}/) === null\n ) {\n ide.run_query_on_startup = function () {\n ide.run_query_on_startup = null;\n // hardcoded maxZoom of 18, should be ok for most real-world use-cases\n try {\n ide.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(), {\n maxZoom: 18\n });\n } catch (e) {}\n // todo: zoom only to specific zoomlevel if args.has_zoom is given\n };\n }\n }\n } // init()\n\n onNominatimError(search, type) {\n // close waiter\n this.waiter.close();\n // highlight error lines\n let query = this.getRawQuery();\n query = query.split(\"\\n\");\n query.forEach((line, i) => {\n if (line.indexOf(`{{geocode${type}:${search}}}`) !== -1)\n this.highlightError(i + 1);\n });\n // show error message dialog\n const dialog_buttons = [{name: i18n.t(\"dialog.dismiss\")}];\n const content = `

    ${i18n.t(\n \"error.nominatim.expl\"\n )}

    ${htmlentities(search)}

    `;\n showDialog(i18n.t(\"error.nominatim.title\"), content, dialog_buttons);\n }\n\n /* this returns the current raw query in the editor.\n * shortcuts are not expanded. */\n getRawQuery() {\n return this.codeEditor.getValue();\n }\n\n /* this returns the current query in the editor.\n * shortcuts are expanded. */\n async getQuery(): Promise {\n let query = this.getRawQuery();\n // parse query and process shortcuts\n // special handling for global bbox in xml queries (which uses an OverpassQL-like notation instead of n/s/e/w parameters):\n query = query.replace(\n /(]+bbox[^=]*=[^\"'']*[\"'])({{bbox}})([\"'])/,\n \"$1{{__bbox__global_bbox_xml__ezs4K8__}}$3\"\n );\n query = await this.queryParser.parse(query, shortcuts());\n // parse mapcss declarations\n let mapcss = \"\";\n if (this.queryParser.hasStatement(\"style\"))\n mapcss = this.queryParser.getStatement(\"style\");\n this.mapcss = mapcss;\n // parse data-source statements\n let data_source = null;\n if (this.queryParser.hasStatement(\"data\")) {\n data_source = this.queryParser.getStatement(\"data\");\n data_source = data_source.split(\",\");\n const data_mode = data_source[0].toLowerCase();\n data_source = data_source.slice(1);\n const options = {};\n for (const src of data_source) {\n const tmp = src.split(\"=\");\n options[tmp[0]] = tmp[1];\n }\n data_source = {\n mode: data_mode,\n options: options\n };\n }\n this.data_source = data_source;\n return query;\n }\n\n setQuery(query) {\n this.codeEditor.setValue(query);\n }\n getQueryLang() {\n if ($.trim(this.getRawQuery().replace(/{{.*?}}/g, \"\")).match(/^ {\n delete settings.saves[ex];\n settings.save();\n this.onLoadClick();\n }\n },\n {name: i18n.t(\"dialog.cancel\")}\n ];\n\n const content =\n `

    ` +\n `${i18n.t(\n \"dialog.delete_query.expl\"\n )}: "${ex}"?

    `;\n showDialog(i18n.t(\"dialog.delete_query.title\"), content, dialog_buttons);\n }\n removeExampleSync(query, self) {\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.delete\"),\n callback() {\n sync.delete(query.name, (err) => {\n if (err) return console.error(err);\n\n $(self).parent().remove();\n });\n }\n },\n {\n name: i18n.t(\"dialog.cancel\")\n }\n ];\n\n const content = `

    ${i18n.t(\n \"dialog.delete_query.expl-osm\"\n )}: "${query.name}"?

    `;\n showDialog(i18n.t(\"dialog.delete_query.title\"), content, dialog_buttons);\n }\n\n // Event handlers\n onLoadClick() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ide = this;\n $(\"#load-dialog .panel.saved_query .panel-block\").remove();\n $(\"#load-dialog .panel.example .panel-block\").remove();\n // load example list\n let has_saved_query = false;\n for (const example in settings.saves) {\n const type = settings.saves[example].type;\n if (type == \"template\") continue;\n $('')\n .attr(\"href\", \"#\")\n .text(example)\n .on(\"click\", () => {\n ide.loadExample(example);\n $(\"#load-dialog\").removeClass(\"is-active\");\n return false;\n })\n .append(\n $('`\n ).on(\"click\", () => {\n ide.loadOsmQueries();\n })\n )\n .appendTo(ui);\n } else {\n ui.hide();\n }\n }\n }\n loadOsmQueries() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ide = this;\n const ui = $(\"#load-dialog .panel.osm-queries\");\n ui.show();\n ui.find(\".panel-block\").remove();\n $('
    ')\n .text(i18n.t(\"load.saved_queries-osm-loading\"))\n .appendTo(ui);\n\n sync.load((err, queries) => {\n if (err) {\n ui.find(\".panel-block\").remove();\n $('
    ')\n .text(i18n.t(\"load.saved_queries-osm-error\"))\n .appendTo(ui);\n return console.error(err);\n }\n ui.find(\".panel-block\").remove();\n $(\"#logout\").show();\n $(\"#logout\").appendTo($(\"#logout\").parent());\n queries.forEach((q) => {\n $('')\n .attr(\"href\", \"#\")\n .text(q.name)\n .on(\"click\", () => {\n ide.setQuery(lzw_decode(Base64.decode(q.query)));\n $(\"#load-dialog\").removeClass(\"is-active\");\n return false;\n })\n .append(\n $('\\\n \\\n
    \\\n ${content}\\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n
    \\\n `;\n\n // Create modal in body\n const element = $(dialogContent);\n // Handle close event\n $(\".delete\", element).click(() => $(element).remove());\n\n // Add all the buttons\n for (const index in buttons) {\n const button = buttons[index];\n $(``)\n .click(() => {\n button.callback?.();\n // destroy modal dialog after callback, see #528\n $(element).remove();\n })\n .appendTo($(\"footer .level-item\", element));\n }\n\n // Add the element to the body\n element.appendTo(\"body\");\n}\n\nclass IDE {\n // == private members ==\n private attribControl = null;\n private scaleControl = null;\n private queryParser = new Query();\n private run_query_on_startup = false;\n // == public members ==\n codeEditor = null;\n dataViewer = null;\n map: L.Map = null;\n\n // == public sub objects ==\n\n waiter = new (class Waiter {\n opened = true;\n frames = [\"◴\", \"◷\", \"◶\", \"◵\"];\n frameDelay = 250;\n onAbort = undefined;\n interval = 0;\n _initialTitle = document.title;\n\n open(show_info) {\n if (show_info) {\n $(\".modal .wait-info h4\").text(show_info);\n $(\".wait-info\").show();\n } else {\n $(\".wait-info\").hide();\n }\n $(\"#loading-dialog\").addClass(\"is-active\");\n document.title = `${this.frames[0]} ${this._initialTitle}`;\n let f = 0;\n this.interval = setInterval(() => {\n const title = this.isAlert\n ? this.alertFrame\n : this.frames[++f % this.frames.length];\n document.title = `${title} ${this._initialTitle}`;\n }, this.frameDelay);\n this.opened = true;\n }\n close(title_prefix = \"\") {\n if (!this.opened) return;\n clearInterval(this.interval);\n document.title = `${title_prefix}${this._initialTitle}`;\n $(\"#loading-dialog\").removeClass(\"is-active\");\n $(\".wait-info ul li\").remove();\n delete this.onAbort;\n this.opened = false;\n }\n addInfo(txt, abortCallback) {\n $(\"#aborter\").remove(); // remove previously added abort button, which cannot be used anymore.\n $(\".wait-info ul li:nth-child(n+1)\").css(\"opacity\", 0.5);\n $(\".wait-info ul li span.fas\")\n .removeClass(\"fa-spinner\")\n .removeClass(\"fa-spin\")\n .addClass(\"fa-check\");\n $(\".wait-info ul li:nth-child(n+4)\").hide();\n const li = $(\n `
  • ${txt}
  • `\n );\n if (typeof abortCallback == \"function\") {\n this.onAbort = abortCallback;\n const aborter = $(\n ' (
    abort)
    '\n ).on(\"click\", () => {\n this.abort();\n return false;\n });\n li.append(aborter);\n }\n $(\".wait-info ul\").prepend(li);\n }\n abort() {\n if (typeof this.onAbort == \"function\") {\n this.addInfo(\"aborting\");\n this.onAbort(this.close);\n }\n }\n })();\n\n // == public methods ==\n\n init() {\n this.waiter.addInfo(\"ide starting up\");\n $(\"#overpass-turbo-version\").html(\n `overpass-turbo ${GIT_VERSION}` // eslint-disable-line no-undef\n );\n $(\"#overpass-turbo-dependencies\").html(\n APP_DEPENDENCIES // eslint-disable-line no-undef\n );\n // (very raw) compatibility check <- TODO: put this into its own function\n if (\n jQuery.support.cors != true ||\n //typeof localStorage != \"object\" ||\n typeof (function () {\n let ls = undefined;\n try {\n localStorage.setItem(\"startup_localstorage_quota_test\", 123);\n localStorage.removeItem(\"startup_localstorage_quota_test\");\n ls = localStorage;\n } catch (e) {}\n return ls;\n })() != \"object\" ||\n false\n ) {\n // the currently used browser is not capable of running the IDE. :(\n this.not_supported = true;\n $(\"#warning-unsupported-browser\").addClass(\"is-active\");\n }\n // load settings\n this.waiter.addInfo(\"load settings\");\n settings.load();\n // translate ui\n this.waiter.addInfo(\"translate ui\");\n i18n.translate().then(() => this.initAfterI18n());\n\n if (sync.enabled) {\n $(\"#load-dialog .osm\").show();\n if (sync.authenticated()) {\n $(\"#logout\").show();\n $(\"#logout\").appendTo($(\"#logout\").parent());\n }\n }\n }\n\n initAfterI18n() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ide = this;\n // parse url string parameters\n ide.waiter.addInfo(\"parse url parameters\");\n const args = urlParameters();\n // set appropriate settings\n if (args.has_coords) {\n // map center coords set via url\n settings.coords_lat = args.coords.lat;\n settings.coords_lon = args.coords.lng;\n }\n if (args.has_zoom) {\n // map zoom set via url\n settings.coords_zoom = args.zoom;\n }\n if (args.run_query) {\n // query autorun activated via url\n ide.run_query_on_startup = true;\n }\n settings.save();\n\n ide.waiter.addInfo(\"initialize page\");\n // init page layout\n const isInitialAspectPortrait =\n $(window).width() / $(window).height() < 0.8;\n if (settings.editor_width != \"\" && !isInitialAspectPortrait) {\n $(\"#editor\").css(\"width\", settings.editor_width);\n $(\"#dataviewer\").css(\"left\", settings.editor_width);\n }\n if (isInitialAspectPortrait) {\n $(\"#editor, #dataviewer\").addClass(\"portrait\");\n }\n // make panels resizable\n $(\"#editor\").resizable({\n handles: isInitialAspectPortrait ? \"s\" : \"e\",\n minWidth: isInitialAspectPortrait ? undefined : \"200\",\n resize() {\n if (!isInitialAspectPortrait) {\n $(this)\n .next()\n .css(\"left\", `${$(this).outerWidth()}px`);\n } else {\n const top = $(this).offset().top + $(this).outerHeight();\n $(this).next().css(\"top\", `${top}px`);\n }\n ide.map.invalidateSize(false);\n },\n stop() {\n if (isInitialAspectPortrait) return;\n settings.editor_width = $(\"#editor\").css(\"width\");\n settings.save();\n }\n });\n $(\"#editor\").prepend(\n \"\"\n );\n\n // init codemirror\n $(\"#editor textarea\")[0].value = settings.code[\"overpass\"];\n if (settings.use_rich_editor) {\n let pending = 0;\n CodeMirror.defineMIME(\"text/x-overpassQL\", {\n name: \"clike\",\n keywords: (function (str) {\n const r = {};\n const a = str.split(\" \");\n for (const ai of a) r[ai] = true;\n return r;\n })(\n \"out json xml custom popup timeout maxsize bbox\" + // initial declarations\n \" date diff adiff\" + //attic declarations\n \" foreach\" + // block statements\n \" relation rel way node is_in area around user uid newer changed poly pivot nwr nw nr wr derived\" + // queries\n \" out meta body skel tags ids count qt asc\" + // actions\n \" center bb geom\" // geometry types\n //+\"r w n br bw\" // recursors\n )\n });\n CodeMirror.defineMIME(\"text/x-overpassXML\", \"xml\");\n CodeMirror.defineMode(\"xml+mustache\", (config) =>\n CodeMirror.multiplexingMode(\n CodeMirror.multiplexingMode(CodeMirror.getMode(config, \"xml\"), {\n open: \"{{\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/plain\"),\n delimStyle: \"mustache\"\n }),\n {\n open: \"{{style:\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/css\"),\n delimStyle: \"mustache\"\n }\n )\n );\n CodeMirror.defineMode(\"ql+mustache\", (config) =>\n CodeMirror.multiplexingMode(\n CodeMirror.multiplexingMode(\n CodeMirror.getMode(config, \"text/x-overpassQL\"),\n {\n open: \"{{\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/plain\"),\n delimStyle: \"mustache\"\n }\n ),\n {\n open: \"{{style:\",\n close: \"}}\",\n mode: CodeMirror.getMode(config, \"text/css\"),\n delimStyle: \"mustache\"\n }\n )\n );\n ide.codeEditor = CodeMirror.fromTextArea($(\"#editor textarea\")[0], {\n //value: settings.code[\"overpass\"],\n lineNumbers: true,\n lineWrapping: true,\n mode: \"text/plain\",\n onChange(e) {\n clearTimeout(pending);\n pending = setTimeout(() => {\n // update syntax highlighting mode\n if (ide.getQueryLang() == \"xml\") {\n if (e.getOption(\"mode\") != \"xml+mustache\") {\n e.closeTagEnabled = true;\n e.setOption(\"matchBrackets\", false);\n e.setOption(\"mode\", \"xml+mustache\");\n }\n } else {\n if (e.getOption(\"mode\") != \"ql+mustache\") {\n e.closeTagEnabled = false;\n e.setOption(\"matchBrackets\", true);\n e.setOption(\"mode\", \"ql+mustache\");\n }\n }\n // check for inactive ui elements\n const bbox_filter = $(\".leaflet-control-buttons-bboxfilter\");\n if (ide.getRawQuery().match(/\\{\\{bbox\\}\\}/)) {\n if (bbox_filter.hasClass(\"disabled\")) {\n bbox_filter.removeClass(\"disabled\");\n bbox_filter.attr(\"data-t\", \"[title]map_controlls.select_bbox\");\n i18n.translate_ui(bbox_filter[0]);\n }\n } else {\n if (!bbox_filter.hasClass(\"disabled\")) {\n bbox_filter.addClass(\"disabled\");\n bbox_filter.attr(\n \"data-t\",\n \"[title]map_controlls.select_bbox_disabled\"\n );\n i18n.translate_ui(bbox_filter[0]);\n }\n }\n }, 500);\n settings.code[\"overpass\"] = e.getValue();\n settings.save();\n },\n closeTagEnabled: true,\n closeTagIndent: [\n \"osm-script\",\n \"query\",\n \"union\",\n \"foreach\",\n \"difference\"\n ],\n extraKeys: {\n \"'>'\"(cm) {\n cm.closeTag(cm, \">\");\n },\n \"'/'\"(cm) {\n cm.closeTag(cm, \"/\");\n }\n }\n });\n // fire onChange after initialization\n ide.codeEditor.getOption(\"onChange\")(ide.codeEditor);\n } else {\n // use non-rich editor\n ide.codeEditor = $(\"#editor textarea\")[0];\n ide.codeEditor.getValue = function () {\n return this.value;\n };\n ide.codeEditor.setValue = function (v) {\n this.value = v;\n };\n ide.codeEditor.lineCount = function () {\n return this.value.split(/\\r\\n|\\r|\\n/).length;\n };\n ide.codeEditor.setLineClass = function () {};\n $(\"#editor textarea\").bind(\"input change\", (e) => {\n settings.code[\"overpass\"] = e.target.getValue();\n settings.save();\n });\n }\n // set query if provided as url parameter or template:\n if (args.has_query) {\n // query set via url\n ide.codeEditor.setValue(args.query);\n }\n // init dataviewer\n ide.dataViewer = CodeMirror($(\"#data\")[0], {\n value: \"no data loaded yet\",\n lineNumbers: true,\n readOnly: true,\n mode: \"javascript\"\n });\n\n // init leaflet\n ide.map = new L.Map(\"map\", {\n attributionControl: true,\n minZoom: 0,\n maxZoom: configs.maxMapZoom,\n worldCopyJump: false\n });\n const tilesUrl = settings.tile_server;\n const tilesAttrib = configs.tileServerAttribution;\n const tiles = new L.TileLayer(tilesUrl, {\n attribution: tilesAttrib,\n noWrap: true,\n maxNativeZoom: 19,\n maxZoom: ide.map.options.maxZoom\n });\n ide.attribControl = new L.Control.Attribution({prefix: false});\n ide.attribControl.addAttribution(tilesAttrib);\n const pos = new L.LatLng(settings.coords_lat, settings.coords_lon);\n ide.map.setView(pos, settings.coords_zoom).addLayer(tiles);\n ide.map.tile_layer = tiles;\n // inverse opacity layer\n ide.map.inv_opacity_layer = L.tileLayer(\n \"data:image/gif;base64,R0lGODlhAQABAIAAAP7//wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==\"\n ).setOpacity(1 - settings.background_opacity);\n if (settings.background_opacity != 1)\n ide.map.inv_opacity_layer.addTo(ide.map);\n ide.scaleControl = new L.Control.Scale({metric: true, imperial: false});\n ide.scaleControl.addTo(ide.map);\n ide.map.on(\"moveend\", () => {\n settings.coords_lat = ide.map.getCenter().lat;\n settings.coords_lon = ide.map.getCenter().lng;\n settings.coords_zoom = ide.map.getZoom();\n settings.save(); // save settings\n });\n\n // tabs\n $(\"#dataviewer > div#data\")[0].style.zIndex = -1001;\n $(\".tabs li\").bind(\"click\", (e) => {\n if ($(e.target).hasClass(\"is-active\")) {\n return;\n } else {\n $(\"#dataviewer > div#data\")[0].style.zIndex =\n -1 * $(\"#dataviewer > div#data\")[0].style.zIndex;\n $(\".tabs li\").toggleClass(\"is-active\");\n }\n });\n\n // keyboard event listener\n $(document).keydown((event) => ide.onKeyPress(event));\n\n // leaflet extension: more map controls\n const MapButtons = L.Control.extend({\n options: {\n position: \"topleft\"\n },\n onAdd() {\n // create the control container with a particular class name\n const container = L.DomUtil.create(\n \"div\",\n \"leaflet-control-buttons leaflet-bar\"\n );\n let link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-fitdata leaflet-bar-part leaflet-bar-part-top\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.zoom_to_data\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n () => {\n // hardcoded maxZoom of 18, should be ok for most real-world use-cases\n try {\n ide.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(), {\n maxZoom: 18\n });\n } catch (e) {}\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-myloc leaflet-bar-part\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.localize_user\");\n if (!window.isSecureContext) {\n link.className += \" disabled\";\n link.setAttribute(\n \"data-t\",\n \"[title]map_controlls.localize_user_disabled\"\n );\n }\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n () => {\n // One-shot position request.\n try {\n navigator.geolocation.getCurrentPosition((position) => {\n const pos = new L.LatLng(\n position.coords.latitude,\n position.coords.longitude\n );\n ide.map.setView(pos, settings.coords_zoom);\n });\n } catch (e) {}\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-bboxfilter leaflet-bar-part\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.select_bbox\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n (e) => {\n if (\n $(e.target).parent().hasClass(\"disabled\") // check if this button is enabled\n )\n return false;\n if (!ide.map.bboxfilter.isEnabled()) {\n ide.map.bboxfilter.setBounds(ide.map.getBounds().pad(-0.2));\n ide.map.bboxfilter.enable();\n } else {\n ide.map.bboxfilter.disable();\n }\n $(e.target).toggleClass(\"fa-times-circle\").toggleClass(\"fa-image\");\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-fullscreen leaflet-bar-part\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.toggle_wide_map\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n (e) => {\n $(\"#dataviewer\").toggleClass(\"fullscreen\");\n ide.map.invalidateSize();\n $(e.target)\n .toggleClass(\"fa-step-forward\")\n .toggleClass(\"fa-step-backward\");\n $(\"#editor\").toggleClass(\"hidden\");\n if ($(\"#editor\").resizable(\"option\", \"disabled\"))\n $(\"#editor\").resizable(\"enable\");\n else $(\"#editor\").resizable(\"disable\");\n return false;\n },\n ide.map\n );\n link = L.DomUtil.create(\n \"a\",\n \"leaflet-control-buttons-clearoverlay leaflet-bar-part leaflet-bar-part-bottom\",\n container\n );\n $('').appendTo($(link));\n link.href = \"#\";\n link.className += \" t\";\n link.setAttribute(\"data-t\", \"[title]map_controlls.toggle_data\");\n i18n.translate_ui(link);\n L.DomEvent.addListener(\n link,\n \"click\",\n (e) => {\n e.preventDefault();\n if (ide.map.hasLayer(overpass.osmLayer))\n ide.map.removeLayer(overpass.osmLayer);\n else ide.map.addLayer(overpass.osmLayer);\n return false;\n },\n ide.map\n );\n return container;\n }\n });\n ide.map.addControl(new MapButtons());\n // prevent propagation of doubleclicks on map controls\n $(\".leaflet-control-buttons > a\").bind(\"dblclick\", (e) =>\n e.stopPropagation()\n );\n // add tooltips to map controls\n $(\".leaflet-control-buttons > a\").tooltip({\n items: \"a[title]\",\n hide: {\n effect: \"fadeOut\",\n duration: 100\n },\n position: {\n my: \"left+5 center\",\n at: \"right center\"\n }\n });\n // leaflet extension: search box\n const SearchBox = L.Control.extend({\n options: {\n position: \"topright\"\n },\n onAdd() {\n const container = L.DomUtil.create(\n \"div\",\n \"leaflet-control-search control has-icons-left\"\n );\n container.style.position = \"absolute\";\n container.style.right = \"0\";\n const inp = L.DomUtil.create(\"input\", \"input is-rounded\", container);\n $('')\n .click(function () {\n $(this).prev().autocomplete(\"search\");\n })\n .insertAfter(inp);\n inp.id = \"search\";\n inp.type = \"search\";\n // hack against focus stealing leaflet :/\n inp.onclick = function () {\n this.focus();\n };\n // prevent propagation of doubleclicks to map container\n container.ondblclick = function (e) {\n e.stopPropagation();\n };\n // autocomplete functionality\n $(inp).autocomplete({\n source(request, response) {\n // ajax (GET) request to nominatim\n $.ajax(\n `https://search.osmnames.org/q/${encodeURIComponent(\n request.term\n )}.js?key=${configs.osmnamesApiKey}`,\n {\n success(data) {\n // hacky firefox hack :( (it is not properly detecting json from the content-type header)\n if (typeof data == \"string\") {\n // if the data is a string, but looks more like a json object\n try {\n data = $.parseJSON(data);\n } catch (e) {}\n }\n response(\n $.map(data.results.slice(0, 10), (item) => ({\n label: item.display_name,\n value: item.display_name,\n lat: item.lat,\n lon: item.lon,\n boundingbox: item.boundingbox\n }))\n );\n },\n error() {\n // todo: better error handling\n console.error(\n \"An error occured while contacting the search server osmnames.org :(\"\n );\n }\n }\n );\n },\n minLength: 2,\n autoFocus: true,\n select(event, ui) {\n if (ui.item.boundingbox && ui.item.boundingbox instanceof Array)\n ide.map.fitBounds(\n L.latLngBounds([\n [ui.item.boundingbox[1], ui.item.boundingbox[0]],\n [ui.item.boundingbox[3], ui.item.boundingbox[2]]\n ]),\n {maxZoom: 18}\n );\n else ide.map.panTo(new L.LatLng(ui.item.lat, ui.item.lon));\n this.value = \"\";\n return false;\n },\n open() {\n $(this).removeClass(\"ui-corner-all\").addClass(\"ui-corner-top\");\n },\n close() {\n $(this).addClass(\"ui-corner-all\").removeClass(\"ui-corner-top\");\n }\n });\n $(inp).autocomplete(\"option\", \"delay\", 20);\n return container;\n }\n });\n ide.map.addControl(new SearchBox());\n // add cross hairs to map\n $('')\n .addClass(\"crosshairs\")\n .hide()\n .appendTo(\"#map\");\n if (settings.enable_crosshairs) $(\".crosshairs\").show();\n\n ide.map.bboxfilter = new L.LocationFilter({\n enable: !true,\n adjustButton: false,\n enableButton: false\n }).addTo(ide.map);\n\n ide.map.on(\"popupopen popupclose\", (e) => {\n if (typeof e.popup.layer != \"undefined\") {\n const layer = e.popup.layer.placeholder || e.popup.layer;\n // re-call style handler to eventually modify the style of the clicked feature\n const stl = overpass.osmLayer._baseLayer.options.style(\n layer.feature,\n e.type == \"popupopen\"\n );\n if (typeof layer.eachLayer != \"function\") {\n if (typeof layer.setStyle == \"function\") layer.setStyle(stl); // other objects (pois, ways)\n } else\n layer.eachLayer((layer) => {\n if (typeof layer.setStyle == \"function\") layer.setStyle(stl);\n }); // for multipolygons!\n }\n });\n\n // init overpass object\n overpass.init();\n\n // event handlers for overpass object\n overpass.handlers[\"onProgress\"] = function (msg, abortcallback) {\n ide.waiter.addInfo(msg, abortcallback);\n };\n overpass.handlers[\"onDone\"] = function () {\n const name_match = ide.getRawQuery().match(/@name ([^\\n]+)/);\n // parse document title from @name in query\n const title_prefix = name_match ? `${name_match[1]} | ` : \"\";\n ide.waiter.close(title_prefix);\n const map_bounds = ide.map.getBounds();\n const data_bounds = overpass.osmLayer.getBaseLayer().getBounds();\n if (data_bounds.isValid() && !map_bounds.intersects(data_bounds)) {\n // show tooltip for button \"zoom to data\"\n const prev_content = $(\".leaflet-control-buttons-fitdata\").tooltip(\n \"option\",\n \"content\"\n );\n $(\".leaflet-control-buttons-fitdata\").tooltip(\n \"option\",\n \"content\",\n `← ${i18n.t(\"map_controlls.suggest_zoom_to_data\")}`\n );\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"open\");\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"option\", \"hide\", {\n effect: \"fadeOut\",\n duration: 1000\n });\n setTimeout(() => {\n $(\".leaflet-control-buttons-fitdata\").tooltip(\n \"option\",\n \"content\",\n prev_content\n );\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"close\");\n $(\".leaflet-control-buttons-fitdata\").tooltip(\"option\", \"hide\", {\n effect: \"fadeOut\",\n duration: 100\n });\n }, 2600);\n }\n };\n overpass.handlers[\"onEmptyMap\"] = function (empty_msg, data_mode) {\n // get the current query\n const query = ide.getRawQuery();\n\n // check if 'out' followed by any number of characters (non-greedy) and then 'count' is present in the query\n const isCountPresent = /out[^;]+?count/.test(query);\n\n // show warning/info if only invisible data is returned and 'out...count' is not present in the query\n if (empty_msg == \"no visible data\") {\n if (!isCountPresent && !settings.no_autorepair) {\n const content = `

    ${i18n.t(\n \"warning.incomplete.expl.1\"\n )}

    ${i18n.t(\n \"warning.incomplete.expl.2\"\n )}

     ${i18n.t(\n \"warning.incomplete.not_again\"\n )}

    `;\n\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.repair_query\"),\n callback() {\n ide.repairQuery(\"no visible data\");\n }\n },\n {\n name: i18n.t(\"dialog.show_data\"),\n callback() {\n if (\n $(\"input[name=hide_incomplete_data_warning]\")?.[0]?.checked\n ) {\n settings.no_autorepair = true;\n settings.save();\n }\n ide.switchTab(\"Data\");\n }\n }\n ];\n showDialog(\n i18n.t(\"warning.incomplete.title\"),\n content,\n dialog_buttons\n );\n } else if (isCountPresent) {\n ide.switchTab(\"Data\");\n }\n }\n // auto tab switching (if only areas are returned)\n if (empty_msg == \"only areas returned\") ide.switchTab(\"Data\");\n // auto tab switching (if nodes without coordinates are returned)\n if (empty_msg == \"no coordinates returned\") ide.switchTab(\"Data\");\n // auto tab switching (if unstructured data is returned)\n if (data_mode == \"unknown\") ide.switchTab(\"Data\");\n // display empty map badge\n $(\n `
    ${i18n.t(\n \"map.intentionally_blank\"\n )} (${empty_msg})
    `\n ).appendTo(\"#map\");\n };\n overpass.handlers[\"onDataReceived\"] = function (\n amount,\n amount_txt,\n abortCB,\n continueCB\n ) {\n if (amount > 1000000) {\n ide.waiter.close();\n const _originalDocumentTitle = document.title;\n document.title = `❗ ${_originalDocumentTitle}`;\n // more than ~1MB of data\n // show warning dialog\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.abort\"),\n callback() {\n document.title = _originalDocumentTitle;\n abortCB();\n }\n },\n {\n name: i18n.t(\"dialog.continue_anyway\"),\n callback() {\n document.title = _originalDocumentTitle;\n continueCB();\n }\n }\n ];\n\n const content = `

    ${i18n\n .t(\"warning.huge_data.expl.1\")\n .replace(\"{{amount_txt}}\", amount_txt)}

    ${i18n.t(\n \"warning.huge_data.expl.2\"\n )}

    `;\n showDialog(i18n.t(\"warning.huge_data.title\"), content, dialog_buttons);\n } else continueCB();\n };\n overpass.handlers[\"onAbort\"] = function () {\n ide.waiter.close();\n };\n overpass.handlers[\"onAjaxError\"] = function (errmsg) {\n ide.waiter.close();\n const _originalDocumentTitle = document.title;\n document.title = `❗ ${_originalDocumentTitle}`;\n // show error dialog\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.dismiss\"),\n callback() {\n document.title = _originalDocumentTitle;\n }\n }\n ];\n\n const content = `

    ${i18n.t(\n \"error.ajax.expl\"\n )}

    ${errmsg}`;\n showDialog(i18n.t(\"error.ajax.title\"), content, dialog_buttons);\n\n // print error text, if present\n if (overpass.resultText) ide.dataViewer.setValue(overpass.resultText);\n };\n overpass.handlers[\"onQueryError\"] = function (errmsg) {\n ide.waiter.close();\n const _originalDocumentTitle = document.title;\n document.title = `❗ ${_originalDocumentTitle}`;\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.dismiss\"),\n callback() {\n document.title = _originalDocumentTitle;\n }\n }\n ];\n const content = `
    ${i18n.t(\n \"error.query.expl\"\n )}
    ${errmsg}
    `;\n showDialog(i18n.t(\"error.query.title\"), content, dialog_buttons);\n };\n overpass.handlers[\"onStyleError\"] = function (errmsg) {\n const dialog_buttons = [{name: i18n.t(\"dialog.dismiss\")}];\n const content = `

    ${i18n.t(\n \"error.mapcss.expl\"\n )}

    ${errmsg}`;\n showDialog(i18n.t(\"error.mapcss.title\"), content, dialog_buttons);\n };\n overpass.handlers[\"onQueryErrorLine\"] = function (linenumber) {\n ide.highlightError(linenumber);\n };\n overpass.handlers[\"onRawDataPresent\"] = function () {\n ide.dataViewer.setOption(\"mode\", overpass.resultType);\n ide.dataViewer.setValue(overpass.resultText);\n };\n overpass.handlers[\"onGeoJsonReady\"] = function () {\n // show layer\n ide.map.addLayer(overpass.osmLayer);\n // autorun callback (e.g. zoom to data)\n if (typeof ide.run_query_on_startup === \"function\") {\n ide.run_query_on_startup();\n }\n // display stats\n if (settings.show_data_stats) {\n const stats = overpass.stats;\n const stats_txt =\n `${i18n.t(\"data_stats.loaded\")} – ` +\n `${i18n.t(\"data_stats.nodes\")}: ${stats.data.nodes}, ${i18n.t(\n \"data_stats.ways\"\n )}: ${stats.data.ways}, ${i18n.t(\n \"data_stats.relations\"\n )}: ${stats.data.relations}${\n stats.data.areas > 0\n ? `, ${i18n.t(\"data_stats.areas\")}: ${stats.data.areas}`\n : \"\"\n }
    ` +\n `${i18n.t(\n \"data_stats.displayed\"\n )} – ` +\n `${i18n.t(\"data_stats.pois\")}: ${stats.geojson.pois}, ${i18n.t(\n \"data_stats.lines\"\n )}: ${stats.geojson.lines}, ${i18n.t(\n \"data_stats.polygons\"\n )}: ${stats.geojson.polys}`;\n $(\n `
    ${stats_txt}
    `\n ).insertAfter(\"#map .leaflet-control-attribution\");\n // show more stats as a tooltip\n const backlogOverpass =\n overpass.timestamp && Date.now() - Date.parse(overpass.timestamp);\n const backlogOverpassAreas =\n overpass.timestampAreas &&\n Date.now() - Date.parse(overpass.timestampAreas);\n $(\"#data_stats\").tooltip({\n items: \"div\",\n tooltipClass: \"stats\",\n content() {\n let str = \"
    \";\n if (overpass.ajax_request_duration) {\n let duration = overpass.ajax_request_duration;\n if (duration.toLocaleString) {\n duration = duration.toLocaleString();\n }\n str += `${i18n.t(\n \"data_stats.request_duration\"\n )}: ${duration}ms
    `;\n }\n if (overpass.timestamp) {\n str +=\n `${i18n.t(\"data_stats.lag\")}: ${Math.floor(\n backlogOverpass / 1000\n )}s` + ` ${i18n.t(\"data_stats.lag.expl\")}`;\n }\n if (overpass.timestampAreas) {\n str +=\n `
    ${i18n.t(\"data_stats.lag_areas\")}: ${Math.floor(\n backlogOverpassAreas / 1000\n )}s` + ` ${i18n.t(\"data_stats.lag.expl\")}`;\n }\n str += \"
    \";\n return str;\n },\n hide: {\n effect: \"fadeOut\",\n duration: 100\n },\n position: {\n my: \"right bottom-5\",\n at: \"right top\"\n }\n });\n if (\n backlogOverpass > 24 * 60 * 60 * 1000 ||\n backlogOverpassAreas > 96 * 60 * 60 * 1000\n ) {\n $(\"#data_stats\").css(\"background-color\", \"yellow\");\n }\n }\n };\n overpass.handlers[\"onPopupReady\"] = function (p) {\n p.openOn(ide.map);\n };\n\n // close startup waiter\n ide.waiter.close();\n\n // run the query immediately, if the appropriate flag was set.\n if (ide.run_query_on_startup === true) {\n ide.update_map();\n // automatically zoom to data.\n if (\n !args.has_coords &&\n args.has_query &&\n args.query.match(/\\{\\{(bbox|center)\\}\\}/) === null\n ) {\n ide.run_query_on_startup = function () {\n ide.run_query_on_startup = null;\n // hardcoded maxZoom of 18, should be ok for most real-world use-cases\n try {\n ide.map.fitBounds(overpass.osmLayer.getBaseLayer().getBounds(), {\n maxZoom: 18\n });\n } catch (e) {}\n // todo: zoom only to specific zoomlevel if args.has_zoom is given\n };\n }\n }\n } // init()\n\n onNominatimError(search, type) {\n // close waiter\n this.waiter.close();\n // highlight error lines\n let query = this.getRawQuery();\n query = query.split(\"\\n\");\n query.forEach((line, i) => {\n if (line.indexOf(`{{geocode${type}:${search}}}`) !== -1)\n this.highlightError(i + 1);\n });\n // show error message dialog\n const dialog_buttons = [{name: i18n.t(\"dialog.dismiss\")}];\n const content = `

    ${i18n.t(\n \"error.nominatim.expl\"\n )}

    ${htmlentities(search)}

    `;\n showDialog(i18n.t(\"error.nominatim.title\"), content, dialog_buttons);\n }\n\n /* this returns the current raw query in the editor.\n * shortcuts are not expanded. */\n getRawQuery() {\n return this.codeEditor.getValue();\n }\n\n /* this returns the current query in the editor.\n * shortcuts are expanded. */\n async getQuery(): Promise {\n let query = this.getRawQuery();\n // parse query and process shortcuts\n // special handling for global bbox in xml queries (which uses an OverpassQL-like notation instead of n/s/e/w parameters):\n query = query.replace(\n /(]+bbox[^=]*=[^\"'']*[\"'])({{bbox}})([\"'])/,\n \"$1{{__bbox__global_bbox_xml__ezs4K8__}}$3\"\n );\n query = await this.queryParser.parse(query, shortcuts());\n // parse mapcss declarations\n let mapcss = \"\";\n if (this.queryParser.hasStatement(\"style\"))\n mapcss = this.queryParser.getStatement(\"style\");\n this.mapcss = mapcss;\n // parse data-source statements\n let data_source = null;\n if (this.queryParser.hasStatement(\"data\")) {\n data_source = this.queryParser.getStatement(\"data\");\n data_source = data_source.split(\",\");\n const data_mode = data_source[0].toLowerCase();\n data_source = data_source.slice(1);\n const options = {};\n for (const src of data_source) {\n const tmp = src.split(\"=\");\n options[tmp[0]] = tmp[1];\n }\n data_source = {\n mode: data_mode,\n options: options\n };\n }\n this.data_source = data_source;\n return query;\n }\n\n setQuery(query) {\n this.codeEditor.setValue(query);\n }\n getQueryLang() {\n if ($.trim(this.getRawQuery().replace(/{{.*?}}/g, \"\")).match(/^ {\n delete settings.saves[ex];\n settings.save();\n this.onLoadClick();\n }\n },\n {name: i18n.t(\"dialog.cancel\")}\n ];\n\n const content =\n `

    ` +\n `${i18n.t(\n \"dialog.delete_query.expl\"\n )}: "${ex}"?

    `;\n showDialog(i18n.t(\"dialog.delete_query.title\"), content, dialog_buttons);\n }\n removeExampleSync(query, self) {\n const dialog_buttons = [\n {\n name: i18n.t(\"dialog.delete\"),\n callback() {\n sync.delete(query.name, (err) => {\n if (err) return console.error(err);\n\n $(self).parent().remove();\n });\n }\n },\n {\n name: i18n.t(\"dialog.cancel\")\n }\n ];\n\n const content = `

    ${i18n.t(\n \"dialog.delete_query.expl-osm\"\n )}: "${query.name}"?

    `;\n showDialog(i18n.t(\"dialog.delete_query.title\"), content, dialog_buttons);\n }\n\n // Event handlers\n onLoadClick() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ide = this;\n $(\"#load-dialog .panel.saved_query .panel-block\").remove();\n $(\"#load-dialog .panel.example .panel-block\").remove();\n // load example list\n let has_saved_query = false;\n for (const example in settings.saves) {\n const type = settings.saves[example].type;\n if (type == \"template\") continue;\n $('')\n .attr(\"href\", \"#\")\n .text(example)\n .on(\"click\", () => {\n ide.loadExample(example);\n $(\"#load-dialog\").removeClass(\"is-active\");\n return false;\n })\n .append(\n $('`\n ).on(\"click\", () => {\n ide.loadOsmQueries();\n })\n )\n .appendTo(ui);\n } else {\n ui.hide();\n }\n }\n }\n loadOsmQueries() {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ide = this;\n const ui = $(\"#load-dialog .panel.osm-queries\");\n ui.show();\n ui.find(\".panel-block\").remove();\n $('
    ')\n .text(i18n.t(\"load.saved_queries-osm-loading\"))\n .appendTo(ui);\n\n sync.load((err, queries) => {\n if (err) {\n ui.find(\".panel-block\").remove();\n $('
    ')\n .text(i18n.t(\"load.saved_queries-osm-error\"))\n .appendTo(ui);\n return console.error(err);\n }\n ui.find(\".panel-block\").remove();\n $(\"#logout\").show();\n $(\"#logout\").appendTo($(\"#logout\").parent());\n queries.forEach((q) => {\n $('')\n .attr(\"href\", \"#\")\n .text(q.name)\n .on(\"click\", () => {\n ide.setQuery(lzw_decode(Base64.decode(q.query)));\n $(\"#load-dialog\").removeClass(\"is-active\");\n return false;\n })\n .append(\n $('