Update marker size and restore marker font size

This commit is contained in:
unknown
2026-05-26 19:33:51 +09:00
parent f5a1e49d20
commit 4b205be0c0

View File

@@ -188,7 +188,7 @@ body { font-family: 'Segoe UI', sans-serif; display: flex; height: 100vh; color:
.num-marker {
background: #2b6cb0; color: #fff; border-radius: 50%;
width: 28px; height: 28px; display: flex; align-items: center;
width: 34px; height: 34px; display: flex; align-items: center;
justify-content: center; font-size: 12px; font-weight: 700;
border: 3px solid #fff; box-shadow: 0 2px 6px rgba(0,0,0,0.3);
cursor: pointer;
@@ -288,8 +288,9 @@ body { font-family: 'Segoe UI', sans-serif; display: flex; height: 100vh; color:
<div class="modal-overlay" id="name-edit-modal">
<div class="modal-box">
<h3>Edit Name</h3>
<input type="text" id="name-edit-input" />
<h3>Edit Flag</h3>
<input type="text" id="name-edit-input" placeholder="Name" />
<input type="text" id="phrase-edit-input" placeholder="Flag phrase (optional)" />
<div class="modal-actions">
<button id="name-edit-cancel">Cancel</button>
<button id="name-edit-apply" class="btn-apply">Apply</button>
@@ -481,7 +482,7 @@ document.getElementById('api-key-btn').addEventListener('click', () => {
function makeNumIcon(num) {
return L.divIcon({
html: `<div class="num-marker">${num}</div>`,
className: '', iconSize: [28, 28], iconAnchor: [14, 14]
className: '', iconSize: [34, 34], iconAnchor: [17, 17]
});
}
@@ -494,6 +495,11 @@ function esc(s) {
({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'})[c]);
}
function getFlagTooltipText(flag) {
if (!flag.name) return flag.phrase || '';
return flag.phrase ? `${flag.name} · ${flag.phrase}` : flag.name;
}
// ═══════════════════════════════════════════════════════════
// ─── Photo ─────────────────────────────────────────────
// ═══════════════════════════════════════════════════════════
@@ -559,7 +565,7 @@ function renderList() {
<span class="status-dot ${flag.placed ? 'placed' : 'unplaced'}"></span>
<div class="info">
<div class="name">${esc(flag.name)}</div>
<div class="detail">${flag.number ? '#' + esc(flag.number) : ''}${detailText ? ' · ' + detailText : ''}</div>
<div class="detail">${flag.number ? '#' + esc(flag.number) : ''}${flag.phrase ? (flag.number ? ' · ' : '') + esc(flag.phrase) : ''}${detailText ? ((flag.number || flag.phrase) ? ' · ' : '') + detailText : ''}</div>
</div>
<span class="chevron ${flag.expanded ? 'open' : ''}">▾</span>
<div class="actions">
@@ -585,6 +591,10 @@ function renderList() {
bHTML += `<div class="detail-row"><span class="label">Address:</span>
<span>${flag.address ? esc(flag.address) : '<span class="address-loading">Loading…</span>'}</span></div>`;
}
if (flag.phrase) {
bHTML += `<div class="detail-row"><span class="label">Phrase:</span>
<span>${esc(flag.phrase)}</span></div>`;
}
bHTML += `<div class="photo-section"><div class="photo-label">📷 Photo</div>`;
if (flag.photoPath) bHTML += `<div class="photo-preview"><img src="${flag.photoPath}" alt="Photo" /></div>`;
bHTML += `<div class="photo-actions">
@@ -634,8 +644,8 @@ function removeFlag(id) {
renderList();
}
function addFlag(name, number) {
const flag = { id: nextId++, name, number,
function addFlag(name, number, phrase = '') {
const flag = { id: nextId++, name, number, phrase,
placed: false, lat: null, lng: null, address: null,
marker: null, expanded: false, photoPath: null };
flags.push(flag);
@@ -652,18 +662,24 @@ function openNameEdit(flagId) {
if (!flag) return;
editingFlagId = flagId;
document.getElementById('name-edit-input').value = flag.name;
document.getElementById('phrase-edit-input').value = flag.phrase || '';
document.getElementById('name-edit-modal').classList.add('open');
}
document.getElementById('name-edit-apply').addEventListener('click', () => {
const flag = flags.find(f => f.id === editingFlagId);
if (!flag) return;
const val = document.getElementById('name-edit-input').value.trim();
if (val) {
flag.name = val;
const nameVal = document.getElementById('name-edit-input').value.trim();
const phraseVal = document.getElementById('phrase-edit-input').value.trim();
if (nameVal) {
flag.name = nameVal;
flag.phrase = phraseVal;
if (flag.marker) {
flag.marker.unbindTooltip();
flag.marker.bindTooltip(esc(flag.name), { permanent: true, direction: 'right', offset: [10, 0], className: 'flag-marker-tooltip' });
const tooltipText = esc(getFlagTooltipText(flag));
if (tooltipText) {
flag.marker.bindTooltip(tooltipText, { permanent: true, direction: 'right', offset: [10, 0], className: 'flag-marker-tooltip' });
}
}
renderList();
}
@@ -712,7 +728,8 @@ map.on('click', (e) => {
const { lat, lng } = e.latlng;
const displayNum = flag.number || flags.indexOf(flag) + 1;
const marker = L.marker([lat, lng], { icon: makeNumIcon(displayNum), draggable: true }).addTo(map);
if (flag.name) marker.bindTooltip(esc(flag.name), { permanent: true, direction: 'right', offset: [10, 0], className: 'flag-marker-tooltip' });
const tooltipText = esc(getFlagTooltipText(flag));
if (tooltipText) marker.bindTooltip(tooltipText, { permanent: true, direction: 'right', offset: [10, 0], className: 'flag-marker-tooltip' });
marker.on('dragend', () => {
const p = marker.getLatLng(); flag.lat = p.lat; flag.lng = p.lng;
scheduleGeocode(flag); renderList();
@@ -756,8 +773,9 @@ document.getElementById('file-input').addEventListener('change', async (e) => {
for (const row of rows) {
const name = row.Name || row.name || row.이름 || row['Flag Name'] || Object.values(row)[0] || '';
const number = row.Number || row.number || row.숫자 || row['Flag Number'] || Object.values(row)[1] || '';
const phrase = row.Phrase || row.phrase || row.문구 || row['Flag Phrase'] || row['Flag Text'] || row.Text || '';
if (!String(name).trim()) continue;
const flag = addFlag(String(name).trim(), String(number).trim());
const flag = addFlag(String(name).trim(), String(number).trim(), String(phrase).trim());
const photo = row.Photo || row.photo || '';
if (photo) flag.photoPath = String(photo);
@@ -767,7 +785,8 @@ document.getElementById('file-input').addEventListener('change', async (e) => {
if (!isNaN(lat) && !isNaN(lng)) {
const displayNum = flag.number || flags.indexOf(flag) + 1;
const marker = L.marker([lat, lng], { icon: makeNumIcon(displayNum), draggable: true }).addTo(map);
if (flag.name) marker.bindTooltip(esc(flag.name), { permanent: true, direction: 'right', offset: [10, 0], className: 'flag-marker-tooltip' });
const tooltipText = esc(getFlagTooltipText(flag));
if (tooltipText) marker.bindTooltip(tooltipText, { permanent: true, direction: 'right', offset: [10, 0], className: 'flag-marker-tooltip' });
marker.on('dragend', () => {
const p = marker.getLatLng(); flag.lat = p.lat; flag.lng = p.lng;
scheduleGeocode(flag); renderList();
@@ -794,23 +813,23 @@ document.getElementById('file-input').addEventListener('change', async (e) => {
document.getElementById('template-btn').addEventListener('click', () => {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet([
{ Number: 'A001', Name: 'Flag 1' },
{ Number: 'A002', Name: 'Flag 2' },
{ Number: 'A003', Name: 'Flag 3' },
{ Number: 'A001', Name: 'Flag 1', Phrase: 'Welcome message' },
{ Number: 'A002', Name: 'Flag 2', Phrase: 'Sample phrase' },
{ Number: 'A003', Name: 'Flag 3', Phrase: 'Another note' },
]), 'Flags');
XLSX.writeFile(wb, 'flag_template.xlsx');
});
document.getElementById('export-btn').addEventListener('click', () => {
const rows = flags.map(f => ({
Number: f.number, Name: f.name,
Number: f.number, Name: f.name, Phrase: f.phrase,
Status: f.placed ? 'Placed' : 'Unplaced',
Latitude: f.lat ?? '', Longitude: f.lng ?? '', Address: f.address ?? '',
Photo: f.photoPath ?? '',
}));
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.json_to_sheet(rows);
ws['!cols'] = [{ wch: 12 }, { wch: 20 }, { wch: 10 }, { wch: 12 }, { wch: 12 }, { wch: 60 }, { wch: 30 }];
ws['!cols'] = [{ wch: 12 }, { wch: 20 }, { wch: 20 }, { wch: 10 }, { wch: 12 }, { wch: 12 }, { wch: 60 }, { wch: 30 }];
XLSX.utils.book_append_sheet(wb, ws, 'Flags');
XLSX.writeFile(wb, 'flag_export.xlsx');
});