soiz1 commited on
Commit
0bd2147
·
verified ·
1 Parent(s): f586bef

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +831 -0
index.html CHANGED
@@ -0,0 +1,831 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ja">
3
+
4
+ <head>
5
+ <link rel="preconnect" href="https://fonts.googleapis.com">
6
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
7
+ <link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;700&display=swap" rel="stylesheet">
8
+ <meta charset="UTF-8">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1">
10
+ <title>MAP EDITOR v1.3.7</title>
11
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css">
12
+ <script src="https://cdn.tailwindcss.com"></script>
13
+ <style>
14
+ :root {
15
+ --primary: #4fc3f7;
16
+ --secondary: #b3e5fc;
17
+ --bg: #fafafa;
18
+ --text: #424242;
19
+ --accent: #4fc3f7;
20
+ --border: #e0e0e0;
21
+ --danger: #e53935;
22
+ }
23
+
24
+ body {
25
+ font-family: 'Source Code Pro', monospace;
26
+ background-color: var(--bg);
27
+ color: var(--text);
28
+ background-image: radial-gradient(circle at 10% 20%, rgba(79, 195, 247, 0.05) 0%, rgba(179, 229, 252, 0.1) 90%);
29
+ min-height: 100vh;
30
+ overflow-x: hidden;
31
+ }
32
+
33
+ .header {
34
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0.9) 0%, rgba(179, 229, 252, 0.7) 100%);
35
+ border-bottom: 1px solid var(--border);
36
+ box-shadow: 0 0 15px rgba(79, 195, 247, 0.1);
37
+ padding: 1rem;
38
+ margin-bottom: 1rem;
39
+ position: relative;
40
+ overflow: hidden;
41
+ }
42
+
43
+ .header::before {
44
+ content: "";
45
+ position: absolute;
46
+ top: 0;
47
+ left: 0;
48
+ width: 100%;
49
+ height: 100%;
50
+ background: linear-gradient(90deg,
51
+ transparent 0%,
52
+ rgba(79, 195, 247, 0.1) 50%,
53
+ transparent 100%);
54
+ animation: scanline 5s linear infinite;
55
+ }
56
+
57
+ @keyframes scanline {
58
+ 0% { transform: translateX(-100%); }
59
+ 100% { transform: translateX(100%); }
60
+ }
61
+
62
+ #map {
63
+ height: 600px;
64
+ width: 100%;
65
+ border: 2px solid var(--border);
66
+ box-shadow: 0 0 20px rgba(79, 195, 247, 0.2);
67
+ transition: all 0.3s ease;
68
+ background-color: white;
69
+ }
70
+
71
+ #map:hover {
72
+ box-shadow: 0 0 30px rgba(79, 195, 247, 0.3);
73
+ }
74
+
75
+ #marker-editor {
76
+ display: none;
77
+ position: absolute;
78
+ top: 10px;
79
+ left: 10px;
80
+ background: rgba(255, 255, 255, 0.95);
81
+ padding: 1.5rem;
82
+ border-radius: 4px;
83
+ border: 1px solid var(--border);
84
+ box-shadow: 0 0 20px rgba(79, 195, 247, 0.2);
85
+ z-index: 1000;
86
+ cursor: move;
87
+ font-family: 'Source Code Pro', monospace;
88
+ color: var(--text);
89
+ }
90
+
91
+ #marker-editor h3 {
92
+ color: var(--primary);
93
+ border-bottom: 1px solid var(--border);
94
+ padding-bottom: 0.5rem;
95
+ margin-bottom: 1rem;
96
+ font-weight: 700;
97
+ }
98
+
99
+ #marker-editor label {
100
+ color: var(--text);
101
+ display: block;
102
+ margin-bottom: 0.5rem;
103
+ font-size: 0.9rem;
104
+ }
105
+
106
+ #marker-editor input,
107
+ #marker-editor textarea {
108
+ background: rgba(255, 255, 255, 0.9);
109
+ border: 1px solid var(--border);
110
+ color: var(--text);
111
+ padding: 0.5rem;
112
+ margin-bottom: 1rem;
113
+ width: 100%;
114
+ font-family: 'Source Code Pro', monospace;
115
+ transition: all 0.3s ease;
116
+ }
117
+
118
+ #marker-editor input:focus,
119
+ #marker-editor textarea:focus {
120
+ outline: none;
121
+ border-color: var(--primary);
122
+ box-shadow: 0 0 10px rgba(79, 195, 247, 0.2);
123
+ }
124
+
125
+ #marker-editor button {
126
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(179, 229, 252, 0.7) 100%);
127
+ color: var(--text);
128
+ border: 1px solid var(--border);
129
+ padding: 0.75rem 1.5rem;
130
+ margin: 0.5rem 0;
131
+ cursor: pointer;
132
+ font-family: 'Source Code Pro', monospace;
133
+ font-weight: 700;
134
+ text-transform: uppercase;
135
+ letter-spacing: 1px;
136
+ transition: all 0.3s ease;
137
+ width: 100%;
138
+ }
139
+
140
+ #marker-editor button:hover {
141
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(79, 195, 247, 0.4) 100%);
142
+ transform: translateY(-2px);
143
+ }
144
+
145
+ #marker-editor button#delete-marker {
146
+ background: linear-gradient(180deg, rgba(255, 235, 238, 0.9) 0%, rgba(229, 57, 53, 0.4) 100%);
147
+ color: var(--danger);
148
+ }
149
+
150
+ #marker-editor button#delete-marker:hover {
151
+ background: linear-gradient(180deg, rgba(255, 235, 238, 0.9) 0%, rgba(229, 57, 53, 0.6) 100%);
152
+ }
153
+
154
+ #icon-preview {
155
+ display: none;
156
+ margin: 1rem 0;
157
+ border: 1px solid var(--border);
158
+ max-width: 100%;
159
+ }
160
+
161
+ #icon-settings {
162
+ display: none;
163
+ margin-top: 1rem;
164
+ border-top: 1px dashed var(--border);
165
+ padding-top: 1rem;
166
+ }
167
+
168
+ #icon-settings label {
169
+ color: var(--text);
170
+ margin-bottom: 0.5rem;
171
+ }
172
+
173
+ input[type=range] {
174
+ -webkit-appearance: none;
175
+ width: 100%;
176
+ height: 5px;
177
+ background: rgba(179, 229, 252, 0.5);
178
+ border-radius: 5px;
179
+ margin: 1rem 0;
180
+ }
181
+
182
+ input[type=range]::-webkit-slider-thumb {
183
+ -webkit-appearance: none;
184
+ width: 15px;
185
+ height: 15px;
186
+ background: var(--primary);
187
+ border-radius: 50%;
188
+ cursor: pointer;
189
+ }
190
+
191
+ input[type=number] {
192
+ width: 60px;
193
+ margin-left: 1rem;
194
+ }
195
+
196
+ .btn {
197
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(179, 229, 252, 0.7) 100%);
198
+ color: var(--text);
199
+ border: 1px solid var(--border);
200
+ padding: 0.75rem 1.5rem;
201
+ margin: 0.5rem;
202
+ cursor: pointer;
203
+ font-family: 'Source Code Pro', monospace;
204
+ font-weight: 700;
205
+ text-transform: uppercase;
206
+ letter-spacing: 1px;
207
+ transition: all 0.3s ease;
208
+ }
209
+
210
+ .btn:hover {
211
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(79, 195, 247, 0.4) 100%);
212
+ transform: translateY(-2px);
213
+ }
214
+
215
+ .btn.danger {
216
+ background: linear-gradient(180deg, rgba(255, 235, 238, 0.9) 0%, rgba(229, 57, 53, 0.4) 100%);
217
+ color: var(--danger);
218
+ }
219
+
220
+ .btn.danger:hover {
221
+ background: linear-gradient(180deg, rgba(255, 235, 238, 0.9) 0%, rgba(229, 57, 53, 0.6) 100%);
222
+ }
223
+
224
+ .btn.secondary {
225
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(207, 216, 220, 0.7) 100%);
226
+ }
227
+
228
+ .btn.secondary:hover {
229
+ background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(179, 229, 252, 0.4) 100%);
230
+ }
231
+
232
+ .container {
233
+ background: rgba(255, 255, 255, 0.8);
234
+ border: 1px solid var(--border);
235
+ padding: 1.5rem;
236
+ margin: 1rem 0;
237
+ box-shadow: 0 0 15px rgba(79, 195, 247, 0.1);
238
+ border-radius: 4px;
239
+ }
240
+
241
+ .title {
242
+ color: var(--primary);
243
+ font-weight: 700;
244
+ margin-bottom: 1rem;
245
+ border-bottom: 1px solid var(--border);
246
+ padding-bottom: 0.5rem;
247
+ }
248
+
249
+ #output-code {
250
+ background: rgba(255, 255, 255, 0.9);
251
+ border: 1px solid var(--border);
252
+ padding: 1rem;
253
+ font-family: 'Source Code Pro', monospace;
254
+ color: var(--text);
255
+ white-space: pre-wrap;
256
+ word-break: break-all;
257
+ max-height: 300px;
258
+ overflow-y: auto;
259
+ margin: 1rem 0;
260
+ box-shadow: inset 0 0 10px rgba(179, 229, 252, 0.3);
261
+ border-radius: 4px;
262
+ }
263
+
264
+ #loading {
265
+ position: fixed;
266
+ top: 0;
267
+ left: 0;
268
+ width: 100%;
269
+ height: 100%;
270
+ background-color: rgba(255, 255, 255, 0.9);
271
+ display: flex;
272
+ flex-direction: column;
273
+ align-items: center;
274
+ justify-content: center;
275
+ font-size: 1.5rem;
276
+ z-index: 9999;
277
+ color: var(--primary);
278
+ }
279
+
280
+ .loader {
281
+ width: 100px;
282
+ aspect-ratio: 1;
283
+ padding: 10px;
284
+ box-sizing: border-box;
285
+ display: grid;
286
+ filter: blur(5px) contrast(10) hue-rotate(180deg);
287
+ mix-blend-mode: multiply;
288
+ }
289
+
290
+ .loader:before,
291
+ .loader:after {
292
+ content: "";
293
+ grid-area: 1/1;
294
+ width: 40px;
295
+ height: 40px;
296
+ background: var(--primary);
297
+ animation: l7 2s infinite;
298
+ }
299
+
300
+ .loader:after {
301
+ animation-delay: -1s;
302
+ }
303
+
304
+ @keyframes l7 {
305
+ 0% { transform: translate(0, 0); }
306
+ 25% { transform: translate(100%, 0); }
307
+ 50% { transform: translate(100%, 100%); }
308
+ 75% { transform: translate(0, 100%); }
309
+ 100% { transform: translate(0, 0); }
310
+ }
311
+
312
+ .terminal-line {
313
+ position: relative;
314
+ padding-left: 1.5rem;
315
+ margin-bottom: 0.5rem;
316
+ }
317
+
318
+ .terminal-line::before {
319
+ content: ">";
320
+ position: absolute;
321
+ left: 0;
322
+ color: var(--primary);
323
+ }
324
+
325
+ .blink {
326
+ animation: blink 1s step-end infinite;
327
+ }
328
+
329
+ @keyframes blink {
330
+ from, to { opacity: 1; }
331
+ 50% { opacity: 0; }
332
+ }
333
+
334
+ .divider {
335
+ height: 1px;
336
+ background: linear-gradient(90deg, transparent 0%, var(--border) 50%, transparent 100%);
337
+ margin: 1rem 0;
338
+ }
339
+
340
+ body::-webkit-scrollbar {
341
+ width: 8px;
342
+ background-color: rgba(179, 229, 252, 0.3);
343
+ }
344
+
345
+ body::-webkit-scrollbar-thumb {
346
+ background: var(--primary);
347
+ border-radius: 4px;
348
+ }
349
+ </style>
350
+ </head>
351
+
352
+ <body>
353
+ <div id="loading">
354
+ <div class="loader"></div>
355
+ <div class="terminal-line">INITIALIZING MAP SYSTEM<span class="blink">_</span></div>
356
+ <div class="terminal-line">LOADING ASSETS...</div>
357
+ <div class="terminal-line">CONNECTING TO DATABASE...</div>
358
+ </div>
359
+
360
+ <div class="header">
361
+ <h1 class="text-3xl font-bold text-center" style="color: var(--primary);">MAP EDITOR <span class="text-sm">v1.3.7</span></h1>
362
+ <p class="text-center text-sm mt-2" style="color: var(--text);">GEO-LOCATION MARKER SYSTEM</p>
363
+ </div>
364
+
365
+ <div class="container mx-auto px-4">
366
+ <div class="flex flex-wrap mb-4">
367
+ <button id="edit-next-marker" class="btn secondary">
368
+ EDIT NEXT MARKER
369
+ </button>
370
+ <button id="generate-html" class="btn">
371
+ GENERATE HTML
372
+ </button>
373
+ <button id="copyButton" class="btn secondary">
374
+ COPY CODE
375
+ </button>
376
+ <button onclick="if(confirm('DELETE ALL DATA? THIS CANNOT BE UNDONE.')){if(confirm('CONFIRM FULL SYSTEM RESET?')){localStorage.removeItem('leafletMap');location.reload()}}" class="btn danger">
377
+ FULL RESET
378
+ </button>
379
+ </div>
380
+
381
+ <div class="container">
382
+ <div class="terminal-line">MAP RENDERING AREA:</div>
383
+ <div id="map"></div>
384
+ </div>
385
+
386
+ <div id="marker-editor">
387
+ <h3>MARKER EDITOR</h3>
388
+ <div class="terminal-line">LATITUDE:</div>
389
+ <input type="text" id="marker-lat" placeholder="35.681236">
390
+ <div class="divider"></div>
391
+ <div class="terminal-line">LONGITUDE:</div>
392
+ <input type="text" id="marker-lng" placeholder="139.767125">
393
+ <div class="divider"></div>
394
+ <div class="terminal-line">ICON SOURCE:</div>
395
+ <div id="icon-upload-input" style="display: block; margin-bottom: 20px;">
396
+ <label for="marker-icon-upload">UPLOAD ICON:</label>
397
+ <input type="file" id="marker-icon-upload" accept="image/*">
398
+ </div>
399
+ <div class="divider"></div>
400
+ <div id="icon-url-input" style="display: block; margin-bottom: 20px;">
401
+ <label for="marker-icon-url">ICON URL:</label>
402
+ <input type="text" id="marker-icon-url" value="https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png">
403
+ <button id="load-icon-url" class="btn secondary mt-2">LOAD IMAGE</button>
404
+ </div>
405
+ <img id="icon-preview" src="" alt="ICON PREVIEW">
406
+ <div id="icon-settings">
407
+ <div class="terminal-line">ICON WIDTH:</div>
408
+ <input type="range" id="icon-width" min="10" max="100" value="25">
409
+ <input type="number" id="icon-width-input" min="10" max="100" value="25">
410
+ <span id="icon-width-value" style="color: var(--primary);">25</span>px
411
+
412
+ <div class="terminal-line">ICON HEIGHT:</div>
413
+ <input type="range" id="icon-height" min="10" max="100" value="41">
414
+ <input type="number" id="icon-height-input" min="10" max="100" value="41">
415
+ <span id="icon-height-value" style="color: var(--primary);">41</span>px
416
+ </div>
417
+ <div class="divider"></div>
418
+ <div class="terminal-line">POPUP HTML:</div>
419
+ <textarea id="marker-popup" placeholder="<b>LOCATION NAME</b><br>Additional info here"></textarea>
420
+ <div class="terminal-line">TOOLTIP HTML:</div>
421
+ <textarea id="marker-tooltip" placeholder="Hover text here"></textarea>
422
+ <div class="divider"></div>
423
+ <button id="save-marker" class="btn">
424
+ SAVE MARKER
425
+ </button>
426
+ <button id="delete-marker" class="btn danger">
427
+ DELETE MARKER
428
+ </button>
429
+ </div>
430
+
431
+ <div class="container">
432
+ <div class="terminal-line">GENERATED CODE:</div>
433
+ <div id="output-code">CODE WILL APPEAR HERE AFTER GENERATION</div>
434
+ </div>
435
+ </div>
436
+
437
+ <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
438
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/github.min.css">
439
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js"></script>
440
+ <script>
441
+ window.onload = function() {
442
+ const loading = document.getElementById('loading');
443
+ loading.style.opacity = '0';
444
+ setTimeout(() => {
445
+ loading.style.display = 'none';
446
+ loadMapFromStorage();
447
+ }, 1000);
448
+ };
449
+ function saveMapToStorage() {
450
+ const markers = [];
451
+ map.eachLayer((layer) => {
452
+ if (layer instanceof L.Marker) {
453
+ const marker = layer;
454
+ const icon = marker.options.icon;
455
+ const { lat, lng } = marker.getLatLng();
456
+ markers.push({
457
+ lat: lat,
458
+ lng: lng,
459
+ iconUrl: icon.options.iconUrl,
460
+ iconSize: icon.options.iconSize,
461
+ popupContent: marker.getPopup() ? marker.getPopup().getContent() : '',
462
+ tooltipContent: marker.getTooltip() ? marker.getTooltip().getContent() : '',
463
+ });
464
+ }
465
+ });
466
+ localStorage.setItem('leafletMap', JSON.stringify(markers));
467
+ }
468
+
469
+ function loadMapFromStorage() {
470
+ const storedMarkers = JSON.parse(localStorage.getItem('leafletMap'));
471
+ if (!storedMarkers) {
472
+ console.warn('No markers found in local storage.');
473
+ return;
474
+ }
475
+
476
+ if (!map) {
477
+ console.error('Map is not initialized.');
478
+ return;
479
+ }
480
+
481
+ storedMarkers.forEach((data) => {
482
+ if (!data.iconUrl || !data.iconSize) {
483
+ console.error('Icon data is incomplete.');
484
+ return;
485
+ }
486
+
487
+ const icon = L.icon({
488
+ iconUrl: data.iconUrl,
489
+ iconSize: data.iconSize,
490
+ iconAnchor: [data.iconSize[0] / 2, data.iconSize[1]],
491
+ popupAnchor: [0, -data.iconSize[1]],
492
+ tooltipAnchor: [data.iconSize[0] / 2, -data.iconSize[1] / 2],
493
+ });
494
+ const marker = L.marker([data.lat, data.lng], { icon: icon }).addTo(map);
495
+ if (data.popupContent) marker.bindPopup(data.popupContent);
496
+ if (data.tooltipContent) marker.bindTooltip(data.tooltipContent);
497
+
498
+ marker.on("mouseover", function() {
499
+ hoveredMarker = marker;
500
+ });
501
+ marker.on("mouseout", function() {
502
+ if (hoveredMarker === marker) {
503
+ hoveredMarker = null;
504
+ }
505
+ });
506
+ });
507
+ }
508
+
509
+ function updatePreviewSize() {
510
+ var e = document.getElementById("icon-width").value;
511
+ var t = document.getElementById("icon-height").value;
512
+ var n = document.getElementById("icon-preview");
513
+ n.style.width = e + "px";
514
+ n.style.height = t + "px";
515
+ document.getElementById("icon-width-value").textContent = e;
516
+ document.getElementById("icon-height-value").textContent = t;
517
+ if (editingMarker) {
518
+ var o = n.src;
519
+ var i = L.icon({
520
+ iconUrl: o,
521
+ iconSize: [e, t],
522
+ iconAnchor: [e / 2, t],
523
+ popupAnchor: [0, -t],
524
+ tooltipAnchor: [e / 2, -t / 2]
525
+ });
526
+ editingMarker.setIcon(i);
527
+ saveMapToStorage();
528
+ }
529
+ }
530
+
531
+ function openEditor(e) {
532
+ const t = e.getLatLng();
533
+ document.getElementById("marker-lat").value = t.lat;
534
+ document.getElementById("marker-lng").value = t.lng;
535
+ document.getElementById("marker-popup").value = e.getPopup() ? e.getPopup().getContent() : "";
536
+ document.getElementById("marker-tooltip").value = e.getTooltip() ? e.getTooltip().getContent() : "";
537
+ document.getElementById("marker-editor").style.display = "block";
538
+ editingMarker = e;
539
+
540
+ const icon = e.options.icon;
541
+ if (icon && icon.options) {
542
+ if (icon.options.iconUrl) {
543
+ document.getElementById("marker-icon-url").value = icon.options.iconUrl;
544
+ document.getElementById("icon-preview").src = icon.options.iconUrl;
545
+ document.getElementById("icon-preview").style.display = 'block';
546
+ document.getElementById("icon-settings").style.display = "block";
547
+ } else {
548
+ document.getElementById("marker-icon-url").value = icon.options.iconUrl;
549
+ document.getElementById("icon-preview").src = icon.options.iconUrl;
550
+ document.getElementById("icon-preview").style.display = 'block';
551
+ document.getElementById("icon-settings").style.display = "block";
552
+ }
553
+ document.getElementById("icon-width").value = icon.options.iconSize[0];
554
+ document.getElementById("icon-height").value = icon.options.iconSize[1];
555
+ document.getElementById("icon-width-value").textContent = icon.options.iconSize[0];
556
+ document.getElementById("icon-height-value").textContent = icon.options.iconSize[1];
557
+ }
558
+
559
+ updatePreviewSize();
560
+ }
561
+
562
+ function generateMapHTML() {
563
+ const e = [];
564
+ map.eachLayer((function(t) {
565
+ if (t instanceof L.Marker) {
566
+ const n = t;
567
+ const o = n.options.icon;
568
+ const i = o.options.iconUrl;
569
+ const r = o.options.iconSize;
570
+ const c = n.getLatLng();
571
+ const l = n.getPopup() ? n.getPopup().getContent() : "";
572
+ const a = n.getTooltip() ? n.getTooltip().getContent() : "";
573
+ e.push({
574
+ lat: c.lat,
575
+ lng: c.lng,
576
+ iconUrl: i,
577
+ iconWidth: r[0],
578
+ iconHeight: r[1],
579
+ popupContent: l,
580
+ tooltipContent: a
581
+ });
582
+ }
583
+ }));
584
+ const t = map.getCenter();
585
+ const n = map.getZoom();
586
+ let o = `
587
+ <div id="map" style="height: 600px; width: 100%;">
588
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />
589
+ <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"><\/script>
590
+ <script>
591
+ var map = L.map('map').setView([${t.lat}, ${t.lng}], ${n});
592
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
593
+ attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors'
594
+ }).addTo(map);
595
+
596
+ ${e.map(e => `
597
+ var icon = L.icon({
598
+ iconUrl: '${e.iconUrl}',
599
+ iconSize: [${e.iconWidth}, ${e.iconHeight}],
600
+ iconAnchor: [${e.iconWidth} / 2, ${e.iconHeight}],
601
+ popupAnchor: [0, -${e.iconHeight}],
602
+ tooltipAnchor: [${e.iconWidth} / 2, -${e.iconHeight} / 2]
603
+ });
604
+
605
+ var marker = L.marker([${e.lat}, ${e.lng}], {
606
+ icon: icon,
607
+ zIndexOffset: 1000
608
+ }).addTo(map);
609
+
610
+ ${e.popupContent ? `marker.bindPopup('${e.popupContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""}
611
+ ${e.tooltipContent ? `marker.bindTooltip('${e.tooltipContent.replace(/'/g, "\\'").replace(/<\/script>/g, "<\\/script>")}');` : ""}
612
+ `).join("\n")}
613
+ <\/script>
614
+ `;
615
+ o = o.replace(/iconUrl: 'marker-icon\.png'/g, `iconUrl: '${location.origin}/marker-icon.png'`);
616
+ document.getElementById("output-html").value = o;
617
+ const input = document.getElementById('output-html').value;
618
+ const output = document.getElementById('output-code');
619
+ output.innerHTML = hljs.highlight('html', input).value;
620
+ output.classList.add('hljs');
621
+ }
622
+
623
+ function resizeImage(e, t, n, o) {
624
+ const i = new FileReader();
625
+ i.onload = function(e) {
626
+ const i = new Image();
627
+ i.onload = function() {
628
+ const e = document.createElement("canvas");
629
+ e.width = t;
630
+ e.height = n;
631
+ e.getContext("2d").drawImage(i, 0, 0, t, n);
632
+ o(e.toDataURL());
633
+ };
634
+ i.src = e.target.result;
635
+ };
636
+ i.readAsDataURL(e);
637
+ }
638
+
639
+ document.getElementById("marker-icon-upload").addEventListener("change", function() {
640
+ const e = this.files[0];
641
+ const t = document.getElementById("icon-preview");
642
+ if (e) {
643
+ resizeImage(e, parseInt(document.getElementById("icon-width").value), parseInt(document.getElementById("icon-height").value), function(imageDataUrl) {
644
+ t.src = imageDataUrl;
645
+ t.style.display = "block";
646
+ document.getElementById("icon-settings").style.display = "block";
647
+ updatePreviewSize();
648
+ });
649
+ } else {
650
+ t.style.display = "none";
651
+ document.getElementById("icon-settings").style.display = "none";
652
+ }
653
+ });
654
+
655
+ document.getElementById("load-icon-url").addEventListener("click", function() {
656
+ const e = document.getElementById("marker-icon-url").value;
657
+ const t = document.getElementById("icon-preview");
658
+ if (e) {
659
+ t.src = e;
660
+ t.onload = function() {
661
+ t.style.display = "block";
662
+ document.getElementById("icon-settings").style.display = "block";
663
+ updatePreviewSize();
664
+ };
665
+ t.onerror = function() {
666
+ alert("IMAGE LOAD FAILED. CHECK URL.");
667
+ t.style.display = "none";
668
+ document.getElementById("icon-settings").style.display = "none";
669
+ };
670
+ } else {
671
+ t.style.display = "none";
672
+ document.getElementById("icon-settings").style.display = "none";
673
+ }
674
+ });
675
+
676
+ document.getElementById("icon-width").addEventListener("input", syncWidth);
677
+ document.getElementById("icon-width-input").addEventListener("input", syncWidth);
678
+ document.getElementById("icon-height").addEventListener("input", syncHeight);
679
+ document.getElementById("icon-height-input").addEventListener("input", syncHeight);
680
+
681
+ function syncWidth(event) {
682
+ let value = event.target.value;
683
+ document.getElementById("icon-width").value = value;
684
+ document.getElementById("icon-width-input").value = value;
685
+ updatePreviewSize();
686
+ }
687
+
688
+ function syncHeight(event) {
689
+ let value = event.target.value;
690
+ document.getElementById("icon-height").value = value;
691
+ document.getElementById("icon-height-input").value = value;
692
+ updatePreviewSize();
693
+ }
694
+
695
+ const map = L.map("map").setView([33.321797711641395, 130.52061378343208], 16);
696
+ L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors' }).addTo(map);
697
+
698
+ let editingMarker = null;
699
+ let hoveredMarker = null;
700
+
701
+ map.on("click", function(e) {
702
+ if (nextMarkerEdit) {
703
+ return;
704
+ }
705
+
706
+ if (editingMarker) {
707
+ const t = e.latlng;
708
+ editingMarker.setLatLng([t.lat, t.lng]);
709
+ document.getElementById("marker-lat").value = t.lat;
710
+ document.getElementById("marker-lng").value = t.lng;
711
+ updatePreviewSize();
712
+ saveMapToStorage();
713
+ } else {
714
+ const t = e.latlng;
715
+ const n = L.marker(t).addTo(map);
716
+ n.bindPopup("NEW MARKER");
717
+ n.bindTooltip("NEW MARKER TOOLTIP");
718
+ n.on("mouseover", function() {
719
+ hoveredMarker = n;
720
+ });
721
+ n.on("mouseout", function() {
722
+ hoveredMarker === n && (hoveredMarker = null);
723
+ });
724
+ document.getElementById("marker-icon-url").value = "https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon-2x.png";
725
+ openEditor(n);
726
+ saveMapToStorage();
727
+ }
728
+ });
729
+
730
+ document.getElementById("save-marker").addEventListener("click", function() {
731
+ if (editingMarker) {
732
+ const lat = parseFloat(document.getElementById("marker-lat").value);
733
+ const lng = parseFloat(document.getElementById("marker-lng").value);
734
+ const popupContent = document.getElementById("marker-popup").value;
735
+ const tooltipContent = document.getElementById("marker-tooltip").value;
736
+
737
+ iconUrl = document.getElementById("icon-preview").src;
738
+
739
+ applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl);
740
+ }
741
+ });
742
+
743
+ function applyIconAndSaveMarker(lat, lng, popupContent, tooltipContent, iconUrl) {
744
+ const iconWidth = parseInt(document.getElementById("icon-width").value);
745
+ const iconHeight = parseInt(document.getElementById("icon-height").value);
746
+
747
+ editingMarker.setLatLng([lat, lng]);
748
+ if (iconUrl) {
749
+ const icon = L.icon({
750
+ iconUrl: iconUrl,
751
+ iconSize: [iconWidth, iconHeight],
752
+ iconAnchor: [iconWidth / 2, iconHeight],
753
+ popupAnchor: [0, -iconHeight],
754
+ tooltipAnchor: [iconWidth / 2, -iconHeight / 2]
755
+ });
756
+ editingMarker.setIcon(icon);
757
+ }
758
+
759
+ editingMarker.bindPopup(popupContent);
760
+ editingMarker.bindTooltip(tooltipContent);
761
+
762
+ document.getElementById("marker-editor").style.display = "none";
763
+ editingMarker = null;
764
+ saveMapToStorage();
765
+ }
766
+
767
+ document.addEventListener("keydown", function(e) {
768
+ if (e.key === "e" && hoveredMarker) {
769
+ openEditor(hoveredMarker);
770
+ }
771
+ });
772
+
773
+ (function() {
774
+ const e = document.getElementById("marker-editor");
775
+ let t, n, o = false;
776
+ e.addEventListener("mousedown", function(i) {
777
+ if (!i.target.closest("input, textarea, button")) {
778
+ t = i.clientX - e.getBoundingClientRect().left;
779
+ n = i.clientY - e.getBoundingClientRect().top;
780
+ o = true;
781
+ }
782
+ });
783
+ document.addEventListener("mousemove", function(i) {
784
+ if (o) {
785
+ e.style.left = i.clientX - t + "px";
786
+ e.style.top = i.clientY - n + "px";
787
+ }
788
+ });
789
+ document.addEventListener("mouseup", function() {
790
+ o = false;
791
+ });
792
+ })();
793
+
794
+ document.getElementById("copyButton").onclick = function() {
795
+ const textToCopy = document.getElementById("output-code").innerText;
796
+ navigator.clipboard.writeText(textToCopy).then(() => {
797
+ alert("CODE COPIED TO CLIPBOARD!");
798
+ }).catch(err => {
799
+ console.error('COPY FAILED:', err);
800
+ });
801
+ };
802
+
803
+ document.getElementById("generate-html").addEventListener("click", generateMapHTML);
804
+
805
+ let nextMarkerEdit = false;
806
+
807
+ document.getElementById("edit-next-marker").addEventListener("click", function () {
808
+ nextMarkerEdit = true;
809
+ alert("CLICK ON NEXT MARKER TO EDIT");
810
+ });
811
+
812
+ map.on('popupopen', function (e) {
813
+ const marker = e.popup._source;
814
+ if (nextMarkerEdit) {
815
+ openEditor(marker);
816
+ nextMarkerEdit = false;
817
+ alert("EDITING MARKER");
818
+ }
819
+ });
820
+
821
+ document.getElementById("delete-marker").addEventListener("click", function() {
822
+ if (confirm("CONFIRM MARKER DELETION?")) {
823
+ map.removeLayer(editingMarker);
824
+ editingMarker=false;
825
+ document.getElementById("marker-editor").style.display = "none";
826
+ saveMapToStorage();
827
+ }
828
+ });
829
+ </script>
830
+ </body>
831
+ </html>