PageSourceSearch

https://proparcel.com/static/js/core/map/map_runtime.js?v=20260706-parcel-style

js proparcel.com collected 2026-10-02 01:40:43 UTC 34,257 bytes, 895 lines download raw bytes

1(function (window, document) {
2  'use strict';
3
4  if (!window || !document || window.PPMapRuntime) return;
5
6  var STORAGE_MODE_KEY = 'pp_gpu_mode';
7  var STORAGE_REASON_KEY = 'pp_gpu_reason';
8  var VERSION = '20260519-gpu-capability-v1';
9  var DEFAULT_SATELLITE_TILE = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}';
10
11  function hasForcedLegacyFlag() {
12    try {
13      return /(?:\?|&)pp_force_legacy_map=1(?:&|$)/.test(window.location.search || '');
14    } catch (_) {
15      return false;
16    }
17  }
18
19  function getCompatState() {
20    var state = {
21      legacy: false,
22      minimal: false,
23      mode: 'full_gpu',
24      reason: '',
25      provider: 'mapbox',
26      supports3D: true,
27      supportsDrawing: true,
28      supportsMeasurement: true
29    };
30    try {
31      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.getMode === 'function') {
32        state.mode = window.PPWebGLCompat.getMode();
33        state.reason = (window.PPWebGLCompat.getState && window.PPWebGLCompat.getState().reason) || '';
34        state.legacy = state.mode === 'no_gpu';
35        state.minimal = state.mode === 'minimal_gpu';
36        state.provider = window.PPWebGLCompat.getProvider ? window.PPWebGLCompat.getProvider() : (state.legacy ? 'leaflet' : 'mapbox');
37        state.supports3D = window.PPWebGLCompat.supports ? window.PPWebGLCompat.supports('3d_mode') : !state.legacy;
38        return state;
39      }
40    } catch (_) {}
41    try {
42      if (hasForcedLegacyFlag()) {
43        state.legacy = true;
44        state.mode = 'no_gpu';
45        state.reason = 'forced_query';
46      }
47    } catch (_) {}
48    try {
49      var sessionMode = window.sessionStorage && window.sessionStorage.getItem(STORAGE_MODE_KEY);
50      var localMode = window.localStorage && window.localStorage.getItem(STORAGE_MODE_KEY);
51      var mode = sessionMode || localMode;
52      if (!state.legacy && mode) {
53        state.mode = mode;
54        state.legacy = mode === 'no_gpu';
55        state.minimal = mode === 'minimal_gpu';
56        state.reason = (window.sessionStorage && window.sessionStorage.getItem(STORAGE_REASON_KEY)) ||
57          (window.localStorage && window.localStorage.getItem(STORAGE_REASON_KEY)) || 'persisted';
58      }
59    } catch (_) {}
60    if (state.legacy) {
61      state.provider = 'leaflet';
62      state.supports3D = false;
63    } else if (state.minimal) {
64      state.provider = 'mapbox';
65      state.supports3D = false;
66    }
67    return state;
68  }
69
70  function markLegacy(reason) {
71    try {
72      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.getMode === 'function') {
73        if (window.PPWebGLCompat.getMode() !== 'no_gpu') {
74          if (typeof window.PPWebGLCompat.mark3DDisabled === 'function') {
75            window.PPWebGLCompat.mark3DDisabled(reason || 'leaflet_visual_fallback');
76          }
77          state.legacy = false;
78          state.provider = 'mapbox';
79          return;
80        }
81      }
82    } catch (_) {}
83    markNoGpu(reason);
84  }
85
86  function markNoGpu(reason) {
87    try {
88      if (window.PPWebGLCompat && typeof window.PPWebGLCompat.markNoGpu === 'function') {
89        window.PPWebGLCompat.markNoGpu(reason || 'map_runtime');
90        return;
91      }
92    } catch (_) {}
93    try {
94      if (window.sessionStorage) {
95        window.sessionStorage.setItem(STORAGE_MODE_KEY, 'no_gpu');
96        window.sessionStorage.setItem(STORAGE_REASON_KEY, reason || 'map_runtime');
97      }
98      if (window.localStorage) {
99        window.localStorage.setItem(STORAGE_MODE_KEY, 'no_gpu');
100        window.localStorage.setItem(STORAGE_REASON_KEY, reason || 'map_runtime');
101      }
102    } catch (_) {}
103  }
104
105  function toFeatureCollection(input) {
106    if (!input) return { type: 'FeatureCollection', features: [] };
107    if (input.type === 'FeatureCollection') return input;
108    if (input.type === 'Feature') return { type: 'FeatureCollection', features: [input] };
109    if (input.type && input.coordinates) {
110      return { type: 'FeatureCollection', features: [{ type: 'Feature', geometry: input, properties: {} }] };
111    }
112    if (Array.isArray(input)) return { type: 'FeatureCollection', features: 
112input.filter(Boolean) };
113    return { type: 'FeatureCollection', features: [] };
114  }
115
116  function firstPaintValue(paint, keys, fallback) {
117    paint = paint || {};
118    for (var i = 0; i < keys.length; i += 1) {
119      var value = paint[keys[i]];
120      if (value == null) continue;
121      if (Array.isArray(value)) continue;
122      return value;
123    }
124    return fallback;
125  }
126
127  function styleFromMapboxLayer(layer, fallback) {
128    layer = layer || {};
129    fallback = fallback || {};
130    var paint = layer.paint || {};
131    return {
132      color: firstPaintValue(paint, ['line-color', 'fill-outline-color', 'circle-color'], fallback.color || '#2563eb'),
133      weight: Number(firstPaintValue(paint, ['line-width'], fallback.weight || 3)) || fallback.weight || 3,
134      opacity: Number(firstPaintValue(paint, ['line-opacity', 'circle-opacity'], fallback.opacity == null ? 0.9 : fallback.opacity)),
135      fillColor: firstPaintValue(paint, ['fill-color', 'circle-color', 'line-color'], fallback.fillColor || fallback.color || '#2563eb'),
136      fillOpacity: Number(firstPaintValue(paint, ['fill-opacity'], fallback.fillOpacity == null ? 0.18 : fallback.fillOpacity)),
137      radius: Number(firstPaintValue(paint, ['circle-radius'], fallback.radius || 7)) || fallback.radius || 7
138    };
139  }
140
141  function evaluateMapboxExpression(value, feature, fallback) {
142    if (!Array.isArray(value)) return value == null ? fallback : value;
143    var props = (feature && feature.properties) || {};
144    if (value[0] === 'match') {
145      var keyExpr = value[1];
146      var key = Array.isArray(keyExpr) && keyExpr[0] === 'get' ? props[keyExpr[1]] : null;
147      for (var i = 2; i < value.length - 1; i += 2) {
148        if (value[i] === key) return value[i + 1];
149      }
150      return value[value.length - 1] || fallback;
151    }
152    if (value[0] === 'case') {
153      for (var j = 1; j < value.length - 1; j += 2) {
154        var cond = value[j];
155        if (Array.isArray(cond) && cond.length >= 3) {
156          var op = cond[0];
157          var left = cond[1];
158          var right = cond[2];
159          var leftValue = Array.isArray(left) && left[0] === 'get' ? Number(props[left[1]]) : Number(left);
160          var rightValue = Number(right);
161          if ((op === '<=' && leftValue <= rightValue) || (op === '==' && leftValue === rightValue)) return value[j + 1];
162        }
163      }
164      return value[value.length - 1] || fallback;
165    }
166    return fallback;
167  }
168
169  function createLeafletRuntime(map, options) {
170    options = options || {};
171    var layers = {};
172    var visibility = {};
173
174    function removeLayer(key) {
175      var layer = layers[key];
176      if (!layer) return;
177      try { map.removeLayer(layer); } catch (_) {}
178      delete layers[key];
179      delete visibility[key];
180    }
181
182    function drawGeoJson(key, data, opts) {
183      if (!map || !window.L || !key) return null;
184      opts = opts || {};
185      if (layers[key]) removeLayer(key);
186      var fc = toFeatureCollection(data);
187      var style = opts.style || {};
188      var layer = window.L.geoJSON(fc, {
189        pointToLayer: function (feature, latlng) {
190          var radius = opts.radius || style.radius || 7;
191          return window.L.circleMarker(latlng, {
192            radius: radius,
193            color: style.color || opts.color || '#2563eb',
194            weight: style.weight || opts.weight || 2,
195            opacity: style.opacity == null ? 0.95 : style.opacity,
196            fillColor: style.fillColor || opts.fillColor || style.color || '#2563eb',
197            fillOpacity: style.fillOpacity == null ? 0.75 : style.fillOpacity
198          });
199        },
200        style: function (feature) {
201          var featureColor = feature && feature.properties && feature.properties.color;
202          return {
203            color: featureColor || style.color || opts.color || '#2563eb',
204            weight: style.weight || opts.weight || 3,
205            opacity: style.opacity == null ? (opts.opacity == null ? 0.95 : opts.opacity) : style.opacity,
206            fillColor: style.fillColor || opts.fillColor || featureColor || style.color || opts.color || '#2563eb',
207            fillOpacity: style.fillOpacity == null ? (opts.fillOpacity == null ? 0.18 : opts.fillOpacity) : style.fillOpacity
208          };
209        },
210        onEachFeature: function (feature, leafletLayer) {
211          var label = feature && feature.properties && (feature.properties.adaParsel || feature.properties.AdaParsel || feature.properties.label || feature.properties.label_text || feature.properties.text);
212          if (label && leafletLayer && leafletLayer.getBounds) {
213            try {
214              window.L.marker(leafletLayer.getBounds().getCenter(), {
215                icon: window.L.divIcon({
216                  html: '<div style="background:rgba(255,255,255,.94);border:1px solid rgba(37,99,235,.55);border-radius:5px;padding:2px 6px;font-weight:700;color:#1e3a8a;white-space:nowrap;">' + String(label) + '</div>',
217                  className: 'pp-leaflet-label-icon'
218                })
219              }).addTo(map);
220            } catch (_) {}
221          }
222        }
223      }).addTo(map);
224      layers[key] = layer;
225      visibility[key] = true;
226      if (opts.fit !== false) {
227        try { map.fitBounds(layer.getBounds(), { padding: opts.padding || [40, 40] }); } catch (_) {}
228      }
229      return layer;
230    }
231
232    return {
233      provider: 'leaflet',
234      map: map,
235      isLegacy: true,
236      drawGeoJson: drawGeoJson,
237      drawPolygon: function (key, coords, opts) {
238        var geometry = { type: 'Polygon', coordinates: coords };
239        return drawGeoJson(key, { type: 'Feature', geometry: geometry, properties: (opts && opts.properties) || {} }, opts);
240      },
241      drawLine: function (key, coords, opts) {
242        var geometry = { type: 'LineString', coordinates: coords };
243        return drawGeoJson(key, { type: 'Feature', geometry: geometry, properties: (opts && opts.properties) || {} }, opts);
244      },
245      drawMarker: function (key, lngLat, opts) {
246        if (!window.L || !Array.isArray(lngLat)) return null;
247        removeLayer(key);
248        var marker = window.L.marker([lngLat[1], lngLat[0]], opts || {}).addTo(map);
249        layers[key] = marker;
250        return marker;
251      },
252      drawParcel: function (feature, opts) {
253        opts = opts || {};
254        opts.style = opts.style || {
255          color: '#D32F2F',
256          weight: 3,
257          fillColor: '#D32F2F',
258          fillOpacity: 0.14
259        };
260        if (opts.fit == null) opts.fit = true;
261        return drawGeoJson('parcel_polygon', feature, opts);
262      },
263      clearLayer: removeLayer,
264      setLayerVisibility: function (key, visible) {
265        var layer = layers[key];
266        if (!layer) return;
267        visibility[key] = !!visible;
268        try {
269          if (visible && !map.hasLayer(layer)) layer.addTo(map);
270          if (!visible && map.hasLayer(layer)) map.removeLayer(layer);
271        } catch (_) {}
272      },
273      fitGeoJson: function (data, opts) {
274        try {
275          var temp = window.L.geoJSON(toFeatureCollection(data));
276          map.fitBounds(temp.getBounds(), opts || { padding: [40, 40] });
277          return true;
278        } catch (_) {
279          return false;
280        }
281      },
282      onClick: function (handler) {
283        if (!handler) return;
284        var wrapped = function (event) {
285          handler(normalizeClick(event));
286        };
287        map.on('click', wrapped);
288        return wrapped;
289      },
290      offClick: function (wrapped) {
291        try { map.off('click', wrapped); } catch (_) {}
292      },
293      resize: function () {
294        try { map.invalidateSize(); } catch (_) {}
295      },
296      project: function (lngLat) {
297        var p = map.latLngToContainerPoint([lngLat[1], lngLat[0]]);
298        return { x: p.x, y: p.y };
299      },
300      unproject: function (point) {
301        var ll = map.containerPointToLatLng(point);
302        return { lng: ll.lng, lat: ll.lat };
303      },
304      _layers: layers,
305      _visibility: visibility
306    };
307  }
308
309  function createMapboxRuntime(map) {
310    function defaultPaintForLayer(key, type, opts) {
311      var paint = opts.paint || {};
312      if (key === 'parcel_polygon' || (typeof key === 'string' && /^parcel_polygon(_|$|-)/.test(key))) {
313        paint = Object.assign({
314          'fill-color': '#ff0000',
315          'fill-opacity': 0.25,
316          'fill-outline-color': '#ff0000',
317          'line-color': '#ff0000',
318          'line-width': 4,
319          'line-opacity': 0.95
320        }, paint);
321      }
322      return paint;
323    }
324
325    return {
326      provider: 'mapbox',
327      map: map,
328      isLegacy: false,
329      drawGeoJson: function (key, data, opts) {
330        opts = opts || {};
331        var fc = toFeatureCollection(data);
332        var style = opts.style || {};
333        var isParcelKey = key === 'parcel_polygon' || (typeof key === 'string' && /^parcel_polygon(_|$)/.test(key));
334        try {
335          if (map.getSource(key)) map.getSource(key).setData(fc);
336          else map.addSource(key, { type: 'geojson', data: fc });
337
338          if (isParcelKey) {
339            var fillId = key + '_fill';
340            var lineWidth = Number(style.weight) || 3;
341            var fillOpacity = style.fillOpacity == null ? 0.2 : Number(style.fillOpacity);
342            var visibility = opts.visible === false ? 'none' : 'visible';
343            if (!map.getLayer(fillId)) {
344              map.addLayer({
345                id: fillId,
346                type: 'fill',
347                source: key,
348                paint: { 'fill-color': '#ff0000', 'fill-opacity': fillOpacity },
349                layout: { visibility: visibility },
350              });
351            } else {
352              try { map.setPaintProperty(fillId, 'fill-opacity', fillOpacity); } catch (_) {}
353              try { map.setLayoutProperty(fillId, 'visibility', visibility); } catch (_) {}
354            }
355            if (!map.getLayer(key)) {
356              map.addLayer({
357                id: key,
358                type: 'line',
359                source: key,
360                paint: { 'line-color': '#ff0000', 'line-width': lineWidth, 'line-opacity': 0.95 },
361                layout: { visibility: visibility },
362              });
363            } else {
364              try { map.setPaintProperty(key, 'line-width', lineWidth); } catch (_) {}
365              try { map.setLayoutProperty(key, 'visibility', visibility); } catch (_) {}
366            }
367          } else if (!map.getLayer(key)) {
368            var geometryType = (fc.features[0] && fc.features[0].geometry && fc.features[0].geometry.type) || 'Polygon';
369            var type = geometryType.indexOf('Point') !== -1 ? 'circle' : (geometryType.indexOf('Line') !== -1 ? 'line' : 'fill');
370            map.addLayer({ id: key, type: type, source: key, paint: defaultPaintForLayer(key, type, opts), layout: { visibility: opts.visible === false ? 'none' : 'visible' } });
371          }
372          if (opts.fit !== false && window.PPMapRuntime) window.PPMapRuntime.fitMapboxToGeoJson(map, fc, opts);
373          return true;
374        } catch (_) {
375          return false;
376        }
377      },
378      clearLayer: function (key) {
379        try { if (map.getLayer(key)) map.removeLayer(key); } catch (_) {}
380        try { if (map.getSource(key)) map.removeSource(key); } catch (_) {}
381      },
382      setLayerVisibility: function (key, visible) {
383        try { if (map.getLayer(key)) map.setLayoutProperty(key, 'visibility', visible ? 'visible' : 'none'); } catch (_) {}
384      },
385      onClick: function (handler) {
386        if (!handler || !map || typeof map.on !== 'function') return null;
387        var wrapped = function (event) { handler(normalizeClick(event)); };
388        map.on('click', wrapped);
389        return wrapped;
390      },
391      offClick: function (wrapped) {
392        try { if (wrapped && map && typeof map.off === 'function') map.off('click', wrapped); } catch (_) {}
393      },
394      drawParcel: function (feature, opts) {
395        opts = opts || {};
396        opts.fit = opts.fit !== false;
397        opts.paint = Object.assign({
398          'fill-color': '#D32F2F',
399          'fill-opacity': 0.14,
400          'fill-outline-color': '#D32F2F'
401        }, opts.paint || {});
402        return this.drawGeoJson('parcel_polygon', feature, opts);
403      },
404      resize: function () { try { map.resize(); } catch (_) {} }
405    };
406  }
407
408  function normalizeClick(event) {
409    if (!event) return null;
410    if (event.lngLat) return event;
411    if (event.latlng) {
412      return {
413        lngLat: { lng: Number(event.latlng.lng), lat: Number(event.latlng.lat) },
414        originalEvent: event.originalEvent || event
415      };
416    }
417    if (event.lon != null && event.lat != null) {
418      return { lngLat: { lng: Number(event.lon), lat: Number(event.lat) }, originalEvent: event };
419    }
420    if (event.lng != null && event.lat != null) {
421      return { lngLat: { lng: Number(event.lng), lat: Number(event.lat) }, originalEvent: event };
422    }
423    return event;
424  }
425
426  function fitMapboxToGeoJson(map, data, opts) {
427    try {
428      var fc = toFeatureCollection(data);
429      var bounds = new mapboxgl.LngLatBounds();
430      fc.features.forEach(function (feature) {
431        walkCoords(feature && feature.geometry && feature.geometry.coordinates, function (coord) {
432          bounds.extend(coord);
433        });
434      });
435      if (!bounds.isEmpty()) map.fitBounds(bounds, { padding: (opts && opts.padding) || 40, maxZoom: (opts && opts.maxZoom) || 18 });
436      return true;
437    } catch (_) {
438      return false;
439    }
440  }
441
442  function walkCoords(coords, callback) {
443    if (!Array.isArray(coords)) return;
444    if (coords.length >= 2 && typeof coords[0] === 'number' && typeof coords[1] === 'number') {
445      callback([coords[0], coords[1]]);
446      return;
447    }
448    coords.forEach(function (item) { walkCoords(item, callback); });
449  }
450
451  function createLeafletMapboxFacade(leafletMap) {
452    var runtime = createLeafletRuntime(leafletMap);
453    var sources = {};
454    var layers = {};
455    var handlers = {};
456    function renderLayer(layer) {
457      if (!layer || !layer.id || !layer.source) return;
458      var source = sources[layer.source];
459      if (!source) return;
460      var style = styleFromMapboxLayer(layer);
461      var paint = layer.paint || {};
462      style.fillColor = evaluateMapboxExpression(paint['fill-color'], null, style.fillColor);
463      var visible = !(layer.layout && layer.layout.visibility === 'none');
464      runtime.drawGeoJson(layer.id, source.data, { style: style, fit: false });
465      runtime.setLayerVisibility(layer.id, visible);
466    }
467    var facade = {
468      __ppLeafletFacade: true,
469      __ppRuntime: runtime,
470      getContainer: function () { return leafletMap.getContainer(); },
471      getCanvasContainer: function () { return leafletMap.getContainer(); },
472      getCanvas: function () { return leafletMap.getContainer(); },
473      loaded: function () { return true; },
474      isStyleLoaded: function () { return true; },
475      getZoom: function () { return leafletMap.getZoom(); },
476      getCenter: function () {
477        var center = leafletMap.getCenter();
478        return { lng: center.lng, lat: center.lat };
479      },
480      setZoom: function (zoom) { try { leafletMap.setZoom(zoom); } catch (_) {} },
481      setCenter: function (lngLat) {
482        try {
483          var lng = Array.isArray(lngLat) ? lngLat[0] : lngLat.lng;
484          var lat = Array.isArray(lngLat) ? lngLat[1] : lngLat.lat;
485          leafletMap.panTo([lat, lng]);
486        } catch (_) {}
487      },
488      resize: function () { runtime.resize(); },
489      stop: function () {},
490      on: function (type, handler) {
491        if (type === 'load' || type === 'style.load') {
492          setTimeout(handler, 0);
493          return this;
494        }
495        handlers[type] = handlers[type] || new window.Map();
496        var wrapped = function (event) { handler(normalizeClick(event)); };
497        handlers[type].set(handler, wrapped);
498        leafletMap.on(type, wrapped);
499        return this;
500      },
501      once: function (type, handler) {
502        if (type === 'load' || type === 'style.load') {
503          setTimeout(handler, 0);
504          return this;
505        }
506        var wrapped = function (event) { handler(normalizeClick(event)); };
507        leafletMap.once(type, wrapped);
508        return this;
509      },
510      off: function (type, handler) {
511        try {
512          var wrapped = handlers[type] && handlers[type].get(handler);
513          leafletMap.off(type, wrapped || handler);
514          if (wrapped) handlers[type].delete(handler);
515        } catch (_) {}
516        return this;
517      },
518      remove: function () { try { leafletMap.remove(); } catch (_) {} },
519      project: function (lngLat) { return runtime.project(Array.isArray(lngLat) ? lngLat : [lngLat.lng, lngLat.lat]); },
520      unproject: function (point) { return runtime.unproject(point); },
521      flyTo: function (opts) { try { leafletMap.setView([opts.center[1], opts.center[0]], opts.zoom || leafletMap.getZoom()); } catch (_) {} },
522      fitBounds: function (bounds, opts) {
523        try {
524          var sw = bounds.getSouthWest ? bounds.getSouthWest() : bounds[0];
525          var ne = bounds.getNorthEast ? bounds.getNorthEast() : bounds[1];
526          leafletMap.fitBounds([[sw.lat || sw[1], sw.lng || sw[0]], [ne.lat || ne[1], ne.lng || ne[0]]], opts || {});
527        } catch (_) {}
528      },
529      addSource: function (id, source) {
530        sources[id] = { data: source && source.data };
531      },
532      getSource: function (id) {
533        if (!sources[id]) return null;
534        return {
535          _data: sources[id].data,
536          setData: function (data) {
537            sources[id].data = data;
538            Object.keys(layers).forEach(function (layerId) {
539              if (layers[layerId].source === id) renderLayer(layers[layerId]);
540            });
541          }
542        };
543      },
544      removeSource: function (id) { delete sources[id]; },
545      addLayer: function (layer) {
546        layers[layer.id] = layer;
547        renderLayer(layer);
548      },
549      getLayer: function (id) { return layers[id] || null; },
550      removeLayer: function (id) {
551        runtime.clearLayer(id);
552        delete layers[id];
553      },
554      setPaintProperty: function (id, prop, value) {
555        if (!layers[id]) return;
556        layers[id].paint = layers[id].paint || {};
557        layers[id].paint[prop] = value;
558        renderLayer(layers[id]);
559      },
560      getPaintProperty: function (id, prop) {
561        return layers[id] && layers[id].paint ? layers[id].paint[prop] : undefined;
562      },
563      setLayoutProperty: function (id, prop, value) {
564        if (prop === 'visibility') runtime.setLayerVisibility(id, value !== 'none');
565        if (layers[id]) {
566          layers[id].layout = layers[id].layout || {};
567          layers[id].layout[prop] = value;
568        }
569      },
570      getLayoutProperty: function (id, prop) {
571        return layers[id] && layers[id].layout ? layers[id].layout[prop] : undefined;
572      },
573      setFilter: function () {},
574      moveLayer: function () {},
575      addControl: function () {},
576      getStyle: function () {
577        return { layers: Object.keys(layers).map(function (id) { return layers[id]; }) };
578      },
579      queryRenderedFeatures: function () { return []; },
580      doubleClickZoom: { enable: function () {}, disable: function () {} },
581      dragPan: { enable: function () {}, disable: function () {} }
582    };
583    return facade;
584  }
585
586  function create(options) {
587    options = options || {};
588    var container = typeof options.container === 'string'
589      ? document.getElementById(options.container)
590      : options.container;
591    var state = getCompatState();
592    if (state.legacy || options.provider === 'leaflet') {
593      var leafletMap = createLeafletMap(container, options);
594      var facade = leafletMap ? createLeafletMapboxFacade(leafletMap) : null;
595      return {
596        provider: 'leaflet',
597        map: facade,
598        rawMap: leafletMap,
599        runtime: leafletMap ? createLeafletRuntime(leafletMap) : null
600      };
601    }
602    return {
603      provider: 'mapbox',
604      map: null,
605      rawMap: null,
606      runtime: null
607    };
608  }
609
610  function createLeafletMap(container, options) {
611    options = options || {};
612    if (!window.L || !container) return null;
613    var map = window.L.map(container, {
614      zoomControl: options.zoomControl !== false,
615      attributionControl: options.attributionControl !== false,
616      preferCanvas: true,
617      worldCopyJump: true
618    }).setView(options.centerLatLng || [39.0, 35.0], options.zoom || 6);
619    window.L.tileLayer(options.tileUrl || DEFAULT_SATELLITE_TILE, {
620      maxZoom: options.maxZoom || 19,
621      attribution: options.attribution || 'Tiles &copy; Esri, Maxar, Earthstar Geographics, and the GIS User Community'
622    }).addTo(map);
623    return map;
624  }
625
626  function distanceMeters(a, b) {
627    var R = 6371008.8;
628    var p1 = a[1] * Math.PI / 180;
629    var p2 = b[1] * Math.PI / 180;
630    var dp = (b[1] - a[1]) * Math.PI / 180;
631    var dl = (b[0] - a[0]) * Math.PI / 180;
632    var h = Math.sin(dp / 2) * Math.sin(dp / 2) + Math.cos(p1) * Math.cos(p2) * Math.sin(dl / 2) * Math.sin(dl / 2);
633    return 2 * R * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));
634  }
635
636  function polygonAreaM2(points) {
637    if (window.turf && points.length >= 3) {
638      try {
639        var ring = points.concat([points[0]]);
640        return window.turf.area({ type: 'Feature', geometry: { type: 'Polygon', coordinates: [ring] }, properties: {} });
641      } catch (_) {}
642    }
643    return 0;
644  }
645
646  function formatDistance(meters) {
647    return meters >= 1000 ? (meters / 1000).toFixed(2) + ' km' : Math.round(meters) + ' m';
648  }
649
650  function formatArea(area) {
651    return area >= 10000 ? (area / 10000).toFixed(2) + ' ha' : Math.round(area) + ' m²';
652  }
653
654  function createLeafletMeasurementManager(map) {
655    var manager = {
656      map: map,
657      mode: null,
658      isActive: false,
659      points: [],
660      layers: [],
661      drawColorRuler: '#3B82F6',
662      drawColorArea: '#F97316',
663      startRulerMode: function () { start('ruler'); },
664      startAreaMode: function () { start('area'); },
665      stopMeasurement: stop,
666      clearMeasurements: clear,
667      setDrawColor: function (color) {
668        if (manager.mode === 'area') manager.drawColorArea = color;
669        else manager.drawColorRuler = color;
670      },
671      clearMeasureSelection: function () {},
672      finishActiveMeasurementFromUi: stop,
673      applyColorToSelectedMeasure: function () {}
674    };
675
676    function start(mode) {
677      stop();
678      manager.mode = mode;
679      manager.isActive = true;
680      manager.points = [];
681      try { window.enableMapClick = false; } catch (_) {}
682      map.on('click', onClick);
683      map.getContainer().style.cursor = 'crosshair';
684    }
685
686    function stop() {
687      if (manager.isActive) {
688        try { map.off('click', onClick); } catch (_) {}
689      }
690      manager.mode = null;
691      manager.isActive = false;
692      manager.points = [];
693      try { map.getContainer().style.cursor = ''; } catch (_) {}
694      try { window.enableMapClick = true; } catch (_) {}
695    }
696
697    function clear() {
698      manager.layers.forEach(function (layer) {
699        try { map.removeLayer(layer); } catch (_) {}
700      });
701      manager.layers = [];
702      stop();
703    }
704
705    function onClick(event) {
706      if (!event || !event.latlng) return;
707      var point = [event.latlng.lng, event.latlng.lat];
708      manager.points.push(point);
709      redraw();
710      if (event.originalEvent) {
711        event.originalEvent.__annotationHandled = true;
712        try { event.originalEvent.preventDefault(); event.originalEvent.stopPropagation(); } catch (_) {}
713      }
714    }
715
716    function addLabel(text, latlng) {
717      var layer = window.L.marker(latlng, {
718        icon: window.L.divIcon({
719          html: '<div style="background:#0f172a;color:#fff;border-radius:6px;padding:3px 7px;font-weight:700;font-size:12px;white-space:nowrap;">
719' + text + '</div>',
720          className: 'pp-leaflet-label-icon'
721        })
722      }).addTo(map);
723      manager.layers.push(layer);
724    }
725
726    function redraw() {
727      manager.layers.forEach(function (layer) {
728        if (layer.__ppMeasurePreview) {
729          try { map.removeLayer(layer); } catch (_) {}
730        }
731      });
732      manager.layers = manager.layers.filter(function (layer) { return !layer.__ppMeasurePreview; });
733      if (!manager.points.length) return;
734      manager.points.forEach(function (p) {
735        var dot = window.L.circleMarker([p[1], p[0]], {
736          radius: 5,
737          color: manager.mode === 'area' ? manager.drawColorArea : manager.drawColorRuler,
738          fillColor: '#fff',
739          fillOpacity: 1,
740          weight: 2
741        }).addTo(map);
742        dot.__ppMeasurePreview = true;
743        manager.layers.push(dot);
744      });
745      if (manager.mode === 'ruler' && manager.points.length >= 2) {
746        var line = window.L.polyline(manager.points.map(function (p) { return [p[1], p[0]]; }), {
747          color: manager.drawColorRuler,
748          weight: 3
749        }).addTo(map);
750        line.__ppMeasurePreview = true;
751        manager.layers.push(line);
752        var total = 0;
753        for (var i = 1; i < manager.points.length; i += 1) total += distanceMeters(manager.points[i - 1], manager.points[i]);
754        var last = manager.points[manager.points.length - 1];
755        addLabel(formatDistance(total), [last[1], last[0]]);
756      }
757      if (manager.mode === 'area' && manager.points.length >= 3) {
758        var poly = window.L.polygon(manager.points.map(function (p) { return [p[1], p[0]]; }), {
759          color: manager.drawColorArea,
760          weight: 3,
761          fillColor: manager.drawColorArea,
762          fillOpacity: 0.22
763        }).addTo(map);
764        poly.__ppMeasurePreview = true;
765        manager.layers.push(poly);
766        var center = poly.getBounds().getCenter();
767        addLabel(formatArea(polygonAreaM2(manager.points)), center);
768      }
769    }
770
771    return manager;
772  }
773
774  function installLeafletAnnotationFallback(map) {
775    if (!map || !window.L || window.__ppLeafletAnnotationFallbackInstalled) return;
776    window.__ppLeafletAnnotationFallbackInstalled = true;
777    var layers = [];
778    var mode = null;
779    var points = [];
780    var color = '#ef4444';
781
782    function stop() {
783      mode = null;
784      points = [];
785      try { map.off('click', onClick); } catch (_) {}
786      try { map.getContainer().style.cursor = ''; } catch (_) {}
787      try { window.enableMapClick = true; } catch (_) {}
788    }
789
790    function clear() {
791      layers.forEach(function (layer) {
792        try { map.removeLayer(layer); } catch (_) {}
793      });
794      layers = [];
795      stop();
796    }
797
798    function onClick(event) {
799      if (!mode || !event || !event.latlng) return;
800      if (event.originalEvent) {
801        event.originalEvent.__annotationHandled = true;
802        try { event.originalEvent.preventDefault(); event.originalEvent.stopPropagation(); } catch (_) {}
803      }
804      if (mode === 'pin') {
805        layers.push(window.L.marker(event.latlng).addTo(map));
806        stop();
807      } else if (mode === 'text') {
808        var text = window.prompt('Haritaya eklenecek metin');
809        if (text) {
810          layers.push(window.L.marker(event.latlng, {
811            icon: window.L.divIcon({
812              html: '<div style="background:#fff;border:1px solid #2563eb;border-radius:6px;padding:4px 8px;font-weight:700;color:#1e3a8a;white-space:nowrap;">' + String(text) + '</div>',
813              className: 'pp-leaflet-label-icon'
814            })
815          }).addTo(map));
816        }
817        stop();
818      } else if (mode === 'freepolyline') {
819        points.push([event.latlng.lat, event.latlng.lng]);
820        if (points.length >= 2) {
821          if (layers.__preview) {
822            try { map.removeLayer(layers.__preview); } catch (_) {}
823          }
824          layers.__preview = window.L.polyline(points, { color: color, weight: 4 }).addTo(map);
825        }
826      }
827    }
828
829    document.addEventListener('click', function (event) {
830      var btn = event.target && event.target.closest && event.target.closest('[data-annotation-tool]');
831      if (!btn || !getCompatState().legacy) return;
832      var tool = btn.getAttribute('data-annotation-tool');
833      if (!tool) return;
834      event.preventDefault();
835      event.stopPropagation();
836      event.stopImmediatePropagation();
837      if (tool === 'clear') {
838        clear();
839        return;
840      }
841      if (tool === 'pencil') {
842        mode = 'freepolyline';
843      } else {
844        mode = tool;
845      }
846      points = [];
847      try { window.enableMapClick = false; } catch (_) {}
848      map.off('click', onClick);
849      map.on('click', onClick);
850      map.getContainer().style.cursor = 'crosshair';
851    }, true);
852
853    document.addEventListener('keydown', function (event) {
854      if (event.key === 'Escape') stop();
855      if (event.key === 'Enter' && mode === 'freepolyline') {
856        if (layers.__preview) {
857          layers.push(layers.__preview);
858          layers.__preview = null;
859        }
860        stop();
861      }
862    }, true);
863
864    window.ppLeafletAnnotationFallback = { clearAll: clear, stop: stop };
865  }
866
867  function attachToManager(manager, provider, map) {
868    if (!manager || !map) return null;
869    var runtime = provider === 'leaflet' ? createLeafletRuntime(map) : createMapboxRuntime(map);
870    manager.activeMapRuntime = runtime;
871    return runtime;
872  }
873
874  window.PPMapRuntime = {
875    version: VERSION,
876    getCompatState: getCompatState,
877    isLegacy: function () { return getCompatState().legacy; },
878    isMinimal: function () { return getCompatState().minimal; },
879    getMode: function () { return getCompatState().mode; },
880    markLegacy: markLegacy,
881    markNoGpu: markNoGpu,
882    createLeafletMap: createLeafletMap,
883    create: create,
884    createLeafletRuntime: createLeafletRuntime,
885    createMapboxRuntime: createMapboxRuntime,
886    createLeafletMapboxFacade: createLeafletMapboxFacade,
887    createLeafletMeasurementManager: createLeafletMeasurementManager,
888    installLeafletAnnotationFallback: installLeafletAnnotationFallback,
889    attachToManager: attachToManager,
890    normalizeClick: normalizeClick,
891    toFeatureCollection: toFeatureCollection,
892    styleFromMapboxLayer: styleFromMapboxLayer,
893    fitMapboxToGeoJson: fitMapboxToGeoJson
894  };
895})(window, document);

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