MediaWiki:Common.js: Perbedaan antara revisi
Tidak ada ringkasan suntingan Tanda: Dikembalikan Suntingan perangkat seluler Suntingan peramban seluler |
Tidak ada ringkasan suntingan Tanda: Pengembalian manual Suntingan perangkat seluler Suntingan peramban seluler |
||
| Baris 1: | Baris 1: | ||
/** | /** | ||
* ==================================================================== | * ==================================================================== | ||
* MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM ( | * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V7.0 ULTIMATE) | ||
* Fitur: | * Fitur: Complete Music & Socials, Explicit Ref Labels, Preset Templates, | ||
* JSON Export/Import, Mobile Perfect, Auto-Domain & Instant Validation | |||
* ==================================================================== | * ==================================================================== | ||
*/ | */ | ||
| Baris 17: | Baris 18: | ||
var dataItems = []; | var dataItems = []; | ||
var isLocked = false; | var isLocked = false; | ||
var api = new mw.Api(); | var api = new mw.Api(); | ||
| Baris 35: | Baris 34: | ||
linkedin: { name: 'LinkedIn', base: 'https://linkedin.com/in/', color: '#0a66c2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>' }, | linkedin: { name: 'LinkedIn', base: 'https://linkedin.com/in/', color: '#0a66c2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>' }, | ||
github: { name: 'GitHub', base: 'https://github.com/', color: '#24292e', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>' }, | github: { name: 'GitHub', base: 'https://github.com/', color: '#24292e', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>' }, | ||
pinterest: { name: 'Pinterest', base: 'https://pinterest.com/', color: '#e60023', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.372 0 12c0 5.084 3.163 9.426 7.627 11.174-.105-.949-.2-2.405.042-3.441.218-.937 1.407-5.965 1.407-5.965s-.359-.719-.359-1.782c0-1.668.967-2.914 2.171-2.914 1.023 0 1.518.769 1.518 1.69 0 1.029-.655 2.568-.994 3.995-.283 1.194.599 2.169 1.777 2.169 2.133 0 3.772-2.249 3.772-5.495 0-2.873-2.064-4.882-5.012-4.882-3.414 0-5.418 2.561-5.418 5.207 0 1.031.397 2.138.893 2.738.098.119.112.224.083.345l-.333 1.36c-.053.22-.174.267-.402.161-1.499-.698-2.436-2.889-2.436-4.649 0-3.785 2.75-7.262 7.929-7.262 4.163 0 7.398 2.967 7.398 6.931 0 4.136-2.607 7.464-6.227 7.464-1.216 0-2.359-.631-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12 24c6.627 0 12-5.373 12-12 0-6.628-5.373-12-12-12z"/></svg>' } | pinterest: { name: 'Pinterest', base: 'https://pinterest.com/', color: '#e60023', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.372 0 12c0 5.084 3.163 9.426 7.627 11.174-.105-.949-.2-2.405.042-3.441.218-.937 1.407-5.965 1.407-5.965s-.359-.719-.359-1.782c0-1.668.967-2.914 2.171-2.914 1.023 0 1.518.769 1.518 1.69 0 1.029-.655 2.568-.994 3.995-.283 1.194.599 2.169 1.777 2.169 2.133 0 3.772-2.249 3.772-5.495 0-2.873-2.064-4.882-5.012-4.882-3.414 0-5.418 2.561-5.418 5.207 0 1.031.397 2.138.893 2.738.098.119.112.224.083.345l-.333 1.36c-.053.22-.174.267-.402.161-1.499-.698-2.436-2.889-2.436-4.649 0-3.785 2.75-7.262 7.929-7.262 4.163 0 7.398 2.967 7.398 6.931 0 4.136-2.607 7.464-6.227 7.464-1.216 0-2.359-.631-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12 24c6.627 0 12-5.373 12-12 0-6.628-5.373-12-12-12z"/></svg>' }, | ||
telegram: { name: 'Telegram', base: 'https://t.me/', color: '#0088cc', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12s5.37 12 12 12 12-5.37 12-12S18.63 0 12 0zm5.562 8.161c-.18 1.897-.962 6.502-1.359 8.627-.168.9-.5 1.201-.82 1.23-.697.064-1.226-.461-1.901-.903-1.056-.692-1.653-1.123-2.678-1.799-1.185-.781-.417-1.21.258-1.911.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.244-1.349-.374-1.297-.789.027-.216.324-.437.893-.663 3.498-1.524 5.831-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635.099-.002.321.023.465.141.119.098.152.228.166.321.015.093.033.308.018.473z"/></svg>' }, | |||
wikipedia: { name: 'Wikipedia / Wikidata', base: 'https://id.wikipedia.org/wiki/', color: '#636466', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12.09 13.118l-2.034-4.82 2.034-4.818h2.034l-3.05 7.227 3.05 7.228h-2.034zm-6.098 0l-2.033-4.82 2.033-4.818h2.034l-3.05 7.227 3.05 7.228H5.992zm12.196 0l-2.034-4.82 2.034-4.818h2.034l-3.05 7.227 3.05 7.228h-2.034z"/></svg>' } | |||
}; | }; | ||
// 2. PRESET TEMPLATES LABEL LENGKAP | |||
var PRESET_LABELS = [ | var PRESET_LABELS = [ | ||
"Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan", | "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan", | ||
| Baris 44: | Baris 46: | ||
]; | ]; | ||
// 3. MASTER TIPE RUJUKAN | |||
var REF_TYPES = { | var REF_TYPES = { | ||
"Berita": ["Berita Online / Portal", "Berita Cetak / Koran", "Wawancara Eksklusif", "Liputan Khusus", "Editorial / Opini"], | "Berita": ["Berita Online / Portal", "Berita Cetak / Koran", "Wawancara Eksklusif", "Liputan Khusus", "Editorial / Opini", "Investigasi Media", "Siaran Radio / TV"], | ||
"Website": ["Situs Resmi / Official", "Blog / Portal Informasi", "Basis Data / Database Web", "Portal Komunitas"], | "Website": ["Situs Resmi / Official", "Blog / Portal Informasi", "Basis Data / Database Web", "Portal Komunitas", "Forum Diskusi", "Portal Edukasi", "Direktori Web"], | ||
"Buku": ["Buku Cetak", "E-Book", "Bab / Bagian Buku", "Monograf"], | "Buku": ["Buku Cetak", "E-Book", "Bab / Bagian Buku", "Monograf", "Katalog / Biografi Cetak", "Buku Teks Akademik"], | ||
"Jurnal": ["Jurnal Ilmiah Peer-Reviewed", "Paper Konferensi", "Artikel Review"], | "Jurnal": ["Jurnal Ilmiah Peer-Reviewed", "Paper Konferensi", "Artikel Review", "Pre-print / Draft Penelitian", "Tesis / Disertasi"], | ||
"Studio / Database Musik": ["MusicBrainz", "Discogs", "Genius", "AllMusic", "Spotify For Artists", "Apple Music Catalogue"], | "Siaran Pers": ["Siaran Pers Resmi", "Pengumuman Instansi / BUMN", "Pernyataan Pers Hukrim", "Keterangan Pers Artis/Manajemen"], | ||
"Video": ["YouTube Video", "Film Dokumenter", "Wawancara Video"], | "Dokumen PDF": ["Laporan Tahunan / Annual Report", "Dokumen Kebijakan / Regulasi", "Brosur / Pamflet Resmi", "Naskah Akademik"], | ||
"Media Sosial": ["Postingan / Tweet", "Video Singkat (Reels/TikTok)", "Live Stream"] | "Studio / Database Musik": ["MusicBrainz", "Discogs", "Genius", "AllMusic", "Spotify For Artists", "Database BPI / RIAA", "Songfacts", "Apple Music Catalogue"], | ||
"Video": ["YouTube Video", "Film Dokumenter", "Wawancara Video", "Arsip Siaran TV", "Vlog Resmi"], | |||
"Podcast": ["Episode Podcast", "Siniar Audio Resmi", "Wawancara Audio"], | |||
"Media Sosial": ["Postingan / Tweet", "Video Singkat (Reels/TikTok/Shorts)", "Live Stream", "Thread Resmi"], | |||
"Ensiklopedi": ["Ensiklopedi Cetak", "Ensiklopedi Online", "Kamus / Glosarium"], | |||
"Arsip": ["Arsip Nasional / Sejarah", "Web Archive (Wayback Machine)", "Dokumen Manuskrip"] | |||
}; | }; | ||
// | // 4. IKON SISTEM | ||
var svgEdit = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>'; | |||
var svgEdit = '<svg class="md-icon" width=" | var svgLock = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>'; | ||
var svgLock = '<svg class="md-icon" width=" | var svgUnlock = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 9.9-1"></path></svg>'; | ||
var svgUnlock = '<svg class="md-icon" width=" | var svgRef = '<svg class="md-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>'; | ||
var svgRef = '<svg class="md-icon" width=" | |||
var svgCopy = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>'; | var svgCopy = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>'; | ||
var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>'; | var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>'; | ||
var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>'; | var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>'; | ||
// | // 5. HELPER UTILITY | ||
function formatIndonesianDate(dateStr) { | function formatIndonesianDate(dateStr) { | ||
if (!dateStr) return ''; | if (!dateStr) return ''; | ||
| Baris 90: | Baris 92: | ||
return urlStr.replace(/^https?:\/\/(www\.)?/, '').split('/')[0]; | return urlStr.replace(/^https?:\/\/(www\.)?/, '').split('/')[0]; | ||
} | } | ||
} | } | ||
| Baris 107: | Baris 97: | ||
if (!urlStr) return ''; | if (!urlStr) return ''; | ||
urlStr = urlStr.trim(); | urlStr = urlStr.trim(); | ||
if (urlStr && !urlStr.match(/^https?:\/\//i)) { | |||
if (urlStr && !urlStr.match(/^https?:\/\//i)) return 'https://' + urlStr; | return 'https://' + urlStr; | ||
} | |||
return urlStr; | |||
} | } | ||
function getTodayString() { | |||
function | var now = new Date(); | ||
var | var y = now.getFullYear(); | ||
var m = String(now.getMonth() + 1).padStart(2, '0'); | |||
var d = String(now.getDate()).padStart(2, '0'); | |||
return y + '-' + m + '-' + d; | |||
} | } | ||
// | // 6. STYLESHEET MODERN V7.0 | ||
var css = ` | var css = ` | ||
#mippedia-data-app { | #mippedia-data-app { | ||
background: #ffffff; border-radius: | background: #ffffff; border-radius: 16px; box-shadow: 0 4px 24px rgba(0,0,0,0.06); | ||
padding: | padding: 20px; margin: 20px 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | ||
border: 1px solid #e2e8f0; width: 100%; box-sizing: border-box; | border: 1px solid #e2e8f0; max-width: 100%; box-sizing: border-box; overflow: hidden; | ||
} | } | ||
.md-header { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: | .md-header { | ||
display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; | |||
.md-title-container { display: flex; align-items: center; gap: | gap: 12px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid #f1f5f9; | ||
.md-title { font-size: 1.25rem; font-weight: | } | ||
.md-title-container { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 180px; } | |||
.md-title { font-size: 1.25rem; font-weight: 800; color: #0f172a; margin: 0; white-space: nowrap; letter-spacing: -0.3px; } | |||
.md-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; } | .md-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; } | ||
.md-btn-icon { | .md-btn-icon { | ||
background: #f8fafc; border: 1px solid #cbd5e1; cursor: pointer; color: # | background: #f8fafc; border: 1px solid #cbd5e1; cursor: pointer; color: #4f46e5; | ||
padding: 8px 14px; border-radius: | padding: 8px 14px; border-radius: 8px; transition: all 0.2s ease; | ||
display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600; white-space: nowrap; | display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600; white-space: nowrap; | ||
} | } | ||
.md-btn-icon:hover:not(:disabled) { background: # | .md-btn-icon:hover:not(:disabled) { background: #f1f5f9; border-color: #94a3b8; transform: translateY(-1px); } | ||
.md-btn-lock { color: #dc2626; background: #fef2f2; border-color: #fca5a5; } | |||
.md-btn-lock { color: # | |||
.md-search-box { position: relative; margin-bottom: 16px; width: 100%; box-sizing: border-box; } | |||
.md- | .md-search-input { | ||
width: 100%; padding: 8px 12px 8px 34px; border: 1px solid #cbd5e1; border-radius: 8px; | |||
font-size: 0.85rem; box-sizing: border-box; background: #f8fafc; transition: 0.2s; | |||
} | |||
.md-search-input:focus { background: #fff; border-color: #4f46e5; outline: none; } | |||
.md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; } | |||
.md-search-input { width: 100%; padding: | |||
.md-search-input:focus { border-color: # | |||
.md-search-icon { position: absolute; left: | |||
/* | /* Row Display Fix */ | ||
.md-row-display { | .md-row-display { | ||
display: flex; justify-content: space-between; align-items: flex-start; | display: flex; justify-content: space-between; align-items: flex-start; | ||
padding: 16px; border: 1px solid # | padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s; | ||
border-radius: | border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff; | ||
} | } | ||
.md-row-display:hover { | .md-row-display:hover { background: #faf5ff; box-shadow: inset 4px 0 0 #6366f1; } | ||
.md-data-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; } | .md-data-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; } | ||
.md-data-label-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } | .md-data-label { font-size: 0.72rem; color: #64748b; font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px; } | ||
.md-data- | .md-data-value-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } | ||
.md-data-value { font-size: 1.02rem; color: #0f172a; line-height: 1.4; font-weight: 600; word-break: break-word; } | |||
.md-btn-copy { | |||
.md- | background: none; border: none; color: #94a3b8; cursor: pointer; padding: 2px 4px; | ||
border-radius: 4px; transition: 0.2s; display: inline-flex; align-items: center; | |||
} | |||
.md-btn-copy:hover { color: #4f46e5; background: #e0e7ff; } | |||
.md- | |||
.md- | /* Tampilan Referensi V7.0 (Eksplisit & Elegan) */ | ||
.md- | .md-ref-container { margin-top: 10px; width: 100%; box-sizing: border-box; } | ||
.md-ref-card { | |||
background: #f8fafc; padding: 12px 14px; border-radius: 10px; | |||
border-left: 4px solid #4f46e5; font-size: 0.85rem; display: flex; flex-direction: column; gap: 6px; | |||
box-sizing: border-box; border-top: 1px solid #f1f5f9; border-right: 1px solid #f1f5f9; border-bottom: 1px solid #f1f5f9; | |||
} | |||
.md-ref-tag-header { | |||
font-size: 0.73rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px; | |||
color: #4f46e5; display: flex; align-items: center; gap: 5px; margin-bottom: 2px; | |||
} | |||
.md-ref-header { font-weight: 700; color: #2563eb; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; word-break: break-word; } | |||
.md-ref-header:hover { text-decoration: underline; } | |||
.md- | .md-ref-details-grid { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; } | ||
.md-ref-detail-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; font-size: 0.82rem; color: #334155; } | |||
.md-ref-lbl { font-weight: 700; color: #64748b; white-space: nowrap; flex-shrink: 0; } | |||
.md-ref-val { color: #0f172a; font-weight: 500; word-break: break-word; } | |||
.md-ref-badge { | |||
.md-ref- | display: inline-block; background: #e2e8f0; color: #334155; padding: 2px 8px; | ||
.md-ref- | border-radius: 6px; font-weight: 700; font-size: 0.72rem; margin-top: 4px; width: fit-content; | ||
.md-ref- | } | ||
/* | /* Media Sosial Badges V7 */ | ||
.md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } | .md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } | ||
.md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: | .md-social-badge { | ||
.md-social-badge:hover { opacity: 0. | display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 18px; | ||
font-size: 0.78rem; font-weight: 600; color: white; text-decoration: none; transition: transform 0.2s, opacity 0.2s; | |||
box-shadow: 0 2px 4px rgba(0,0,0,0.05); | |||
} | |||
.md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; color: white; text-decoration: none; } | |||
.md-preset-wrapper { display: flex; flex-wrap: wrap; gap: 6px; margin-top: | /* Preset Pill Badges */ | ||
.md-preset-pill { background: #f1f5f9; border: 1px solid #cbd5e1; padding: 4px 10px; border-radius: | .md-preset-wrapper { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; } | ||
.md-preset-pill:hover { background: # | .md-preset-pill { | ||
background: #f1f5f9; border: 1px solid #cbd5e1; padding: 4px 10px; border-radius: 12px; | |||
font-size: 0.75rem; font-weight: 600; color: #475569; cursor: pointer; transition: 0.2s; | |||
} | |||
.md-preset-pill:hover { background: #e0e7ff; color: #3730a3; border-color: #a5b4fc; } | |||
/* Form | /* Form Elements Responsif */ | ||
.md-form-box { background: #ffffff; border-radius: | .md-form-box { background: #ffffff; border-radius: 12px; padding: 18px; margin-top: 16px; border: 1px solid #cbd5e1; box-shadow: 0 4px 16px rgba(0,0,0,0.05); } | ||
.md-form-title { font-size: 1.05rem; font-weight: 800; color: #0f172a; margin: 0 0 16px 0; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; } | |||
.md-form-title { font-size: 1. | .md-form-group { margin-bottom: 14px; } | ||
.md-form-group label { display: block; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; } | |||
.md-form-group { margin-bottom: | .md-input, .md-select, .md-textarea { | ||
.md-form-group label { display: block; font-size: 0. | width: 100%; padding: 9px 12px; border: 1px solid #cbd5e1; border-radius: 8px; | ||
box-sizing: border-box; font-family: inherit; font-size: 0.9rem; transition: 0.2s; background: #fff; | |||
.md-input, .md-select, .md-textarea { width: 100%; padding: | } | ||
.md-input:focus, .md-select:focus { border-color: # | .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: #4f46e5; outline: none; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); } | ||
.md- | .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f8fafc; padding: 12px; border-radius: 8px; border: 1px dashed #cbd5e1; } | ||
.md-social-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f1f5f9; padding: 12px; border-radius: 8px; border: 1px solid #cbd5e1; max-height: 280px; overflow-y: auto; } | |||
.md-grid-full { grid-column: span 2; } | .md-grid-full { grid-column: span 2; } | ||
.md-form-actions { display: flex; gap: 10px; align-items: center; margin-top: 20px; padding-top: | .md-form-actions { display: flex; gap: 10px; align-items: center; margin-top: 20px; padding-top: 14px; border-top: 1px solid #e2e8f0; flex-wrap: wrap; } | ||
.md-btn { padding: 10px 18px; border: none; border-radius: | .md-btn { | ||
.md-btn | padding: 10px 18px; border: none; border-radius: 8px; font-weight: 700; cursor: pointer; | ||
.md-btn-save | color: white; font-size: 0.85rem; transition: 0.2s; display: inline-flex; align-items: center; gap: 6px; justify-content: center; | ||
} | |||
.md-btn:hover:not(:disabled) { transform: translateY(-1px); } | |||
.md-btn-save { background: linear-gradient(135deg, #4f46e5, #4338ca); flex: 1; min-width: 140px; } | |||
.md-btn-cancel { background: #64748b; } | .md-btn-cancel { background: #64748b; } | ||
.md-btn-delete { background: #dc2626; margin-left: auto; } | |||
.md-btn-delete { background: # | |||
.md-spinner { display: none; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.4); border-radius: 50%; border-top-color: #fff; animation: md-spin 0. | .md-spinner { display: none; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.4); border-radius: 50%; border-top-color: #fff; animation: md-spin 0.8s linear infinite; } | ||
.is-loading .md-spinner { display: inline-block; } | .is-loading .md-spinner { display: inline-block; } | ||
@keyframes md-spin { to { transform: rotate(360deg); } } | @keyframes md-spin { to { transform: rotate(360deg); } } | ||
@media (max-width: 600px) { | |||
@media (max-width: | #mippedia-data-app { padding: 14px; margin: 14px 0; border-radius: 12px; } | ||
#mippedia-data-app { padding: | .md-header { flex-direction: column; align-items: flex-start; gap: 10px; } | ||
.md-header { flex-direction: column; align-items: flex-start; gap: | .md-actions { width: 100%; justify-content: flex-start; } | ||
.md-actions { width: 100%; | .md-btn-icon { padding: 7px 12px; font-size: 0.8rem; } | ||
.md-btn-icon { | .md-ref-grid, .md-social-grid { grid-template-columns: 1fr; } | ||
.md-ref-grid, .md-social-grid { grid-template-columns: 1fr | |||
.md-grid-full { grid-column: span 1; } | .md-grid-full { grid-column: span 1; } | ||
.md-form-actions { flex-direction: column; width: 100%; } | |||
.md-form-actions { flex-direction: column; width: 100% | |||
.md-btn { width: 100%; margin: 0 !important; } | .md-btn { width: 100%; margin: 0 !important; } | ||
.md-row-display { padding: 12px 8px; } | |||
} | } | ||
.md-native-render { display: none; } | |||
`; | `; | ||
$('<style>').text(css).appendTo('head'); | $('<style>').text(css).appendTo('head'); | ||
// | // 7. PARSER & PENYIMPANAN DATA | ||
function loadData() { | function loadData() { | ||
return api.get({ | return api.get({ | ||
| Baris 355: | Baris 266: | ||
function buildWikitextVal(item) { | function buildWikitextVal(item) { | ||
var val = item.val; | var val = item.val; | ||
if (item.linkTarget && item.linkTarget.trim() !== '') return "[[" + item.linkTarget.trim() + "|" + val + "]]"; | if (item.linkTarget && item.linkTarget.trim() !== '') { | ||
return "[[" + item.linkTarget.trim() + "|" + val + "]]"; | |||
} | |||
if (item.linkSplit) { | if (item.linkSplit) { | ||
return val.replace(/([a-zA-Z0-9_À-ÿ\- ]+)/g, function(match) { | return val.replace(/([a-zA-Z0-9_À-ÿ\- ]+)/g, function(match) { | ||
var trimmed = match.trim(); | var trimmed = match.trim(); | ||
if (trimmed.length > 2 && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') return "[[" + trimmed + "]]"; | if (trimmed.length > 2 && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') { | ||
return "[[" + trimmed + "]]"; | |||
} | |||
return match; | return match; | ||
}); | }); | ||
} | } | ||
if (item.link) return "[[" + val + "]]"; | if (item.link) { | ||
return "[[" + val + "]]"; | |||
} | |||
return val; | return val; | ||
} | } | ||
| Baris 369: | Baris 286: | ||
function buildWikitextRef(refObj) { | function buildWikitextRef(refObj) { | ||
if (!refObj) return ""; | if (!refObj) return ""; | ||
var title = refObj.title || " | var title = refObj.title || "Rujukan"; | ||
var text = refObj.url ? "[" + ensureHttps(refObj.url) + " " + title + "]" : "'''" + title + "'''"; | var text = refObj.url ? "[" + ensureHttps(refObj.url) + " " + title + "]" : "'''" + title + "'''"; | ||
var details = []; | var details = []; | ||
| Baris 375: | Baris 292: | ||
if (refObj.site) details.push("Situs: " + refObj.site); | if (refObj.site) details.push("Situs: " + refObj.site); | ||
if (refObj.publisher) details.push("Penerbit: " + refObj.publisher); | if (refObj.publisher) details.push("Penerbit: " + refObj.publisher); | ||
if (refObj.date) details.push("Akses: " + formatIndonesianDate(refObj.date)); | if (refObj.date) details.push("Tanggal Akses: " + formatIndonesianDate(refObj.date)); | ||
if (refObj.type) details.push("Jenis: " + refObj.type + (refObj.subType ? " (" + refObj.subType + ")" : "")); | if (refObj.type) details.push("Jenis: " + refObj.type + (refObj.subType ? " (" + refObj.subType + ")" : "")); | ||
if (details.length > 0) text += " — <small>" + details.join(" • ") + "</small>"; | if (details.length > 0) text += " — <small>" + details.join(" • ") + "</small>"; | ||
return text; | return text; | ||
| Baris 384: | Baris 302: | ||
if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true); | if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true); | ||
var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems }); | var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems }); | ||
var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n"; | var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n"; | ||
| Baris 407: | Baris 322: | ||
api.postWithToken('csrf', { | api.postWithToken('csrf', { | ||
action: 'edit', title: pageName, text: newContent, summary: 'Mippedia Data | action: 'edit', title: pageName, text: newContent, summary: 'Mippedia Data V7: ' + actionType, minor: false | ||
}).done(function() { | }).done(function() { | ||
var nocacheUrl = location.pathname + "?refresh=" + new Date().getTime(); | |||
window.location.href = nocacheUrl; | |||
}).fail(function(err) { | }).fail(function(err) { | ||
if ($btnEl) $btnEl.removeClass('is-loading').prop('disabled', false); | if ($btnEl) $btnEl.removeClass('is-loading').prop('disabled', false); | ||
| Baris 416: | Baris 332: | ||
} | } | ||
// | // 8. BUILDER UI UTAMA | ||
function buildUI(rawContent) { | function buildUI(rawContent) { | ||
var $app = $('<div id="mippedia-data-app"></div>'); | var $app = $('<div id="mippedia-data-app"></div>'); | ||
// HEADER | // HEADER | ||
var $header = $('<div class="md-header"></div>'); | var $header = $('<div class="md-header"></div>'); | ||
var $titleContainer = $('<div class="md-title-container"><h3 class="md-title">' + | var $titleContainer = $('<div class="md-title-container"><h3 class="md-title">' + svgEdit + ' Data Terstruktur</h3></div>'); | ||
var $actions = $('<div class="md-actions"></div>'); | var $actions = $('<div class="md-actions"></div>'); | ||
// Tombol Ekspor JSON | |||
var $jsonBtn = $('<button class="md-btn-icon" title="Ekspor/Impor JSON">' + svgCode + ' JSON</button>'); | |||
$jsonBtn.on('click', function() { showJsonModal(rawContent); }); | |||
$actions.append($jsonBtn); | |||
var $ | |||
$ | |||
$actions.append($ | |||
if (isSysop) { | if (isSysop) { | ||
var $lockBtn = $('<button class="md-btn-icon ' + (isLocked ? 'md-btn-unlock' : 'md-btn-lock') + '">' + (isLocked ? svgUnlock + ' | var $lockBtn = $('<button class="md-btn-icon ' + (isLocked ? 'md-btn-unlock' : 'md-btn-lock') + '">' + (isLocked ? svgUnlock + ' Buka Kunci' : svgLock + ' Kunci') + ' <span class="md-spinner"></span></button>'); | ||
$lockBtn.on('click', function() { | $lockBtn.on('click', function() { | ||
isLocked = !isLocked; | isLocked = !isLocked; | ||
saveData(isLocked ? ' | saveData(isLocked ? 'Mengunci data' : 'Membuka kunci data', $(this), rawContent); | ||
}); | }); | ||
$actions.append($lockBtn); | $actions.append($lockBtn); | ||
| Baris 456: | Baris 356: | ||
if (!isLocked || isSysop) { | if (!isLocked || isSysop) { | ||
var $addBtn = $('<button class="md-btn-icon" | var $addBtn = $('<button class="md-btn-icon" title="Tambah Data Baru">' + svgEdit + ' Tambah</button>'); | ||
$addBtn.on('click', function() { showForm(-1, rawContent); }); | $addBtn.on('click', function() { showForm(-1, rawContent); }); | ||
$actions.append($addBtn); | $actions.append($addBtn); | ||
| Baris 464: | Baris 364: | ||
$app.append($header); | $app.append($header); | ||
// SEARCH BAR | |||
if (dataItems.length > 2) { | |||
var $searchBox = $('<div class="md-search-box"><span class="md-search-icon">' + svgSearch + '</span><input type="text" class="md-search-input" placeholder="Cari data terstruktur..."></div>'); | |||
// SEARCH BAR | |||
if (dataItems.length > | |||
var $searchBox = $('<div class="md-search-box"><span class="md-search-icon">' + svgSearch + '</span><input type="text" class="md-search-input" placeholder=" | |||
$searchBox.find('input').on('keyup input', function() { | $searchBox.find('input').on('keyup input', function() { | ||
var q = $(this).val().toLowerCase(); | var q = $(this).val().toLowerCase(); | ||
$app.find('.md-row-display').each(function() { | $app.find('.md-row-display').each(function() { | ||
var text = $(this).text().toLowerCase(); | var text = $(this).text().toLowerCase(); | ||
$(this).toggle(text.indexOf(q) !== -1); | |||
}); | }); | ||
}); | }); | ||
| Baris 495: | Baris 377: | ||
} | } | ||
// DAFTAR BARIS DATA | // DAFTAR BARIS DATA | ||
var $list = $('<div class="md-list"></div>'); | var $list = $('<div class="md-list"></div>'); | ||
if (dataItems.length === 0) { | if (dataItems.length === 0) { | ||
$list.append('<div style="color:#64748b; text-align:center; padding: | $list.append('<div style="color:#64748b; text-align:center; padding: 25px 10px; background:#f8fafc; border-radius:10px; border:1px dashed #cbd5e1; font-size:0.88rem;">Belum ada data terstruktur. Klik <b>Tambah</b> untuk membuat baru.</div>'); | ||
} else { | } else { | ||
dataItems.forEach(function(item, index) { | dataItems.forEach(function(item, index) { | ||
var $row = $('<div class="md-row-display"></div>'); | var $row = $('<div class="md-row-display"></div>'); | ||
var $info = $('<div class="md-data-group"></div>'); | var $info = $('<div class="md-data-group"></div>'); | ||
$info.append('<span class="md-data-label">' + item.prop + '</span>'); | |||
// RENDER NILAI DATA | |||
var displayValHtml = ''; | var displayValHtml = ''; | ||
var rawVal = item.val || ''; | var rawVal = item.val || ''; | ||
if (rawVal.match(/^https?:\/\//i)) { | if (rawVal.match(/^https?:\/\//i)) { | ||
displayValHtml = '<a href="' + rawVal + '" target="_blank" style="color:#2563eb; font-weight: | var domain = extractDomain(rawVal); | ||
displayValHtml = '<a href="' + rawVal + '" target="_blank" style="color:#2563eb; font-weight:700; text-decoration:none;">' + domain + '</a>'; | |||
} else if (item.linkTarget && item.linkTarget.trim() !== '') { | } else if (item.linkTarget && item.linkTarget.trim() !== '') { | ||
displayValHtml = '<a href="' + mw.util.getUrl(item.linkTarget.trim()) + '" style="color:#2563eb; font-weight: | displayValHtml = '<a href="' + mw.util.getUrl(item.linkTarget.trim()) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + rawVal + '</a>'; | ||
} else if (item.linkSplit) { | } else if (item.linkSplit) { | ||
var parts = rawVal.split(/([,/\s]+dan\s+|[,/\s]+atau\s+|[,/]+)/gi); | var parts = rawVal.split(/([,/\s]+dan\s+|[,/\s]+atau\s+|[,/]+)/gi); | ||
| Baris 519: | Baris 401: | ||
var trimmed = p.trim(); | var trimmed = p.trim(); | ||
if (trimmed && !p.match(/^[,/\s]+$/) && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') { | if (trimmed && !p.match(/^[,/\s]+$/) && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') { | ||
return '<a href="' + mw.util.getUrl(trimmed) + '" style="color:#2563eb; font-weight: | return '<a href="' + mw.util.getUrl(trimmed) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + trimmed + '</a>'; | ||
} | } | ||
return p; | return p; | ||
}).join(''); | }).join(''); | ||
} else if (item.link) { | } else if (item.link) { | ||
displayValHtml = '<a href="' + mw.util.getUrl(rawVal) + '" style="color:#2563eb; font-weight: | displayValHtml = '<a href="' + mw.util.getUrl(rawVal) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + rawVal + '</a>'; | ||
} else { | } else { | ||
displayValHtml = rawVal; | displayValHtml = rawVal; | ||
| Baris 532: | Baris 414: | ||
$valWrap.append('<span class="md-data-value">' + displayValHtml + '</span>'); | $valWrap.append('<span class="md-data-value">' + displayValHtml + '</span>'); | ||
var $copyBtn = $('<button class="md-btn- | var $copyBtn = $('<button class="md-btn-copy" title="Salin teks">' + svgCopy + '</button>'); | ||
$copyBtn.on('click', function() { | $copyBtn.on('click', function() { | ||
navigator.clipboard.writeText(rawVal); | navigator.clipboard.writeText(rawVal); | ||
$(this).css('color', '#16a34a'); | $(this).css('color', '#16a34a'); | ||
setTimeout(function(){ $copyBtn.css('color', '#94a3b8'); }, | setTimeout(function(){ $copyBtn.css('color', '#94a3b8'); }, 1200); | ||
}); | }); | ||
$valWrap.append($copyBtn); | $valWrap.append($copyBtn); | ||
$info.append($valWrap); | $info.append($valWrap); | ||
// MEDIA SOSIAL | // RENDER MEDIA SOSIAL & MUSIK | ||
if (item.isPersonOrg && item.socials) { | if (item.isPersonOrg && item.socials) { | ||
var $socialGroup = $('<div class="md-social-group"></div>'); | var $socialGroup = $('<div class="md-social-group"></div>'); | ||
| Baris 560: | Baris 432: | ||
hasSocial = true; | hasSocial = true; | ||
var platform = SOCIAL_PLATFORMS[key]; | var platform = SOCIAL_PLATFORMS[key]; | ||
var fullUrl = platform.base + | var fullUrl = platform.base + uname.replace(/^@/, ''); | ||
var $badge = $('<a class="md-social-badge" href="' + fullUrl + '" target="_blank" style="background:' + platform.color + ';">' + platform.icon + ' ' + platform.name + '</a>'); | var $badge = $('<a class="md-social-badge" href="' + fullUrl + '" target="_blank" style="background:' + platform.color + ';">' + platform.icon + ' ' + platform.name + '</a>'); | ||
$socialGroup.append($badge); | $socialGroup.append($badge); | ||
| Baris 568: | Baris 440: | ||
} | } | ||
// REFERENSI | // RENDER REFERENSI EKSPLISIT (V7) | ||
if (item.ref && (item.ref.url || item.ref.title)) { | if (item.ref && (item.ref.url || item.ref.title)) { | ||
var ref = item.ref; | var ref = item.ref; | ||
var $refContainer = $('<div class="md-ref-container"></div>'); | var $refContainer = $('<div class="md-ref-container"></div>'); | ||
var $refCard = $('<div class="md-ref-card"></div>'); | var $refCard = $('<div class="md-ref-card"></div>'); | ||
$refCard.append('<div class="md-ref-tag-header">' + svgRef + ' | |||
// Header Penjelas Referensi | |||
$refCard.append('<div class="md-ref-tag-header">' + svgRef + ' Referensi / Sumber Rujukan:</div>'); | |||
var refTitle = ref.title || " | var refTitle = ref.title || "Sumber Rujukan"; | ||
if (ref.url) { | if (ref.url) { | ||
$refCard.append('<a href="' + | var safeUrl = ensureHttps(ref.url); | ||
$refCard.append('<a href="' + safeUrl + '" target="_blank" class="md-ref-header">' + refTitle + '</a>'); | |||
} else { | } else { | ||
$refCard.append('<span class="md-ref-header" style="color:#0f172a;">' + refTitle + '</span>'); | $refCard.append('<span class="md-ref-header" style="color:#0f172a;">' + refTitle + '</span>'); | ||
} | } | ||
var details | var $detailsGrid = $('<div class="md-ref-details-grid"></div>'); | ||
if (ref.author) | if (ref.author) { | ||
if (ref.site) | $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penulis:</span><span class="md-ref-val">' + ref.author + '</span></div>'); | ||
if (ref.publisher) | } | ||
if (ref.date) | if (ref.site) { | ||
if ( | $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Situs:</span><span class="md-ref-val">' + ref.site + '</span></div>'); | ||
$refCard.append('< | } | ||
if (ref.publisher) { | |||
$detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penerbit:</span><span class="md-ref-val">' + ref.publisher + '</span></div>'); | |||
} | |||
if (ref.date) { | |||
$detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Tanggal Akses:</span><span class="md-ref-val">' + formatIndonesianDate(ref.date) + '</span></div>'); | |||
} | |||
$refCard.append($detailsGrid); | |||
if (ref.type) { | |||
var typeLabel = ref.type + (ref.subType ? ' • ' + ref.subType : ''); | |||
$refCard.append('<span class="md-ref-badge">' + typeLabel + '</span>'); | |||
} | } | ||
| Baris 597: | Baris 484: | ||
$row.append($info); | $row.append($info); | ||
if (!isLocked || isSysop) { | if (!isLocked || isSysop) { | ||
var $editIcon = $('<button class="md-btn-icon edit-btn" style="padding:6px 10px;">' + svgEdit + ' Edit</button>'); | |||
var $ | |||
$editIcon.on('click', function() { showForm(index, rawContent); }); | $editIcon.on('click', function() { showForm(index, rawContent); }); | ||
$ | $row.append($editIcon); | ||
} | } | ||
$list.append($row); | $list.append($row); | ||
}); | }); | ||
| Baris 628: | Baris 501: | ||
} | } | ||
// | // 9. FORM EDIT DENGAN PRESET & PLATFORM LENGKAP | ||
function showForm(index, rawContent) { | function showForm(index, rawContent) { | ||
var $container = $('#md-form-container'); | var $container = $('#md-form-container'); | ||
| Baris 635: | Baris 508: | ||
var isNew = index === -1; | var isNew = index === -1; | ||
var currentData = isNew ? { prop: '', val: '', link: false, linkTarget: '', linkSplit: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index]; | var currentData = isNew ? { prop: '', val: '', link: false, linkTarget: '', linkSplit: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index]; | ||
var currentRef = currentData.ref || {}; | var currentRef = currentData.ref || {}; | ||
var currentSocials = currentData.socials || {}; | var currentSocials = currentData.socials || {}; | ||
var $form = $('<div class="md-form-box" | var $form = $('<div class="md-form-box"></div>'); | ||
$form.append('<h4 class="md-form-title">' + (isNew ? 'Tambah Data Baru' : 'Edit Data Terstruktur') + '</h4>'); | |||
// | // Label Data + Preset Fast Selector | ||
var $propGroup = $('<div class="md-form-group"><label>Label Data (Contoh: Pekerjaan, Sutradara, Tempat Lahir)</label><input type="text" id="md-inp-prop" class="md-input" value="' + (currentData.prop || '') + '"></div>'); | |||
var $propGroup = $('<div class="md-form-group"><label>Data | |||
var $presetWrap = $('<div class="md-preset-wrapper"></div>'); | var $presetWrap = $('<div class="md-preset-wrapper"></div>'); | ||
PRESET_LABELS.forEach(function(lbl) { | PRESET_LABELS.forEach(function(lbl) { | ||
var $pill = $('<span class="md-preset-pill">' + lbl + '</span>'); | var $pill = $('<span class="md-preset-pill">' + lbl + '</span>'); | ||
$pill.on('click', function() { $('#md-inp-prop').val(lbl | $pill.on('click', function() { $('#md-inp-prop').val(lbl); }); | ||
$presetWrap.append($pill); | $presetWrap.append($pill); | ||
}); | }); | ||
$propGroup.append($presetWrap); | $propGroup.append($presetWrap); | ||
$ | $form.append($propGroup); | ||
// | // Nilai Data & Wikilink Options | ||
var $valBox = $('<div class="md-form-group"></div>'); | var $valBox = $('<div class="md-form-group"></div>'); | ||
$valBox.append('<label>Data | $valBox.append('<label>Nilai Data</label><input type="text" id="md-inp-val" class="md-input" value="' + (currentData.val || '') + '">'); | ||
$ | |||
var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:#f8fafc; padding:10px; border-radius:8px; border:1px solid #e2e8f0;"></div>'); | |||
var chkLink = currentData.link ? 'checked' : ''; | var chkLink = currentData.link ? 'checked' : ''; | ||
var chkSplit = currentData.linkSplit ? 'checked' : ''; | var chkSplit = currentData.linkSplit ? 'checked' : ''; | ||
$wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0. | $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-link" ' + chkLink + '> Jadikan Wikilink Standar [[Judul]]</label>'); | ||
$wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0. | $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-split" ' + chkSplit + '> Smart Split Wikilink (Pisahkan kata berkoma/kata "dan")</label>'); | ||
$ | |||
var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569;">Target Halaman Khusus / Custom Piped Link (Opsional):</label><input type="text" id="md-inp-target" class="md-input" style="padding:6px 10px; font-size:0.85rem;" placeholder="Contoh: Diskografi Rumi Haitami" value="' + (currentData.linkTarget || '') + '"></div>'); | |||
$wikilinkOpts.append($pipedGroup); | |||
$valBox.append($wikilinkOpts); | $valBox.append($wikilinkOpts); | ||
$ | $form.append($valBox); | ||
// | // MEDIA SOSIAL & MUSIK LENGKAP | ||
var $socialSec = $('<div class="md-form-group" style="margin-top: | var $socialSec = $('<div class="md-form-group" style="margin-top:16px;"></div>'); | ||
var chkPerson = currentData.isPersonOrg ? 'checked' : ''; | var chkPerson = currentData.isPersonOrg ? 'checked' : ''; | ||
$socialSec.append('<label style="display:flex; align-items:center; gap:8px; cursor:pointer; background:# | $socialSec.append('<label style="display:flex; align-items:center; gap:8px; cursor:pointer; background:#e0e7ff; padding:10px; border-radius:8px; font-weight:700; color:#3730a3; font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Aktifkan Profil Orang / Organisasi (Media Sosial & Musik)</label>'); | ||
var $socialGrid = $('<div class="md-social-grid" id="md-social-box" style="display:' + (currentData.isPersonOrg ? 'grid' : 'none') + '; margin-top:8px;"></div>'); | var $socialGrid = $('<div class="md-social-grid" id="md-social-box" style="display:' + (currentData.isPersonOrg ? 'grid' : 'none') + '; margin-top:8px;"></div>'); | ||
| Baris 695: | Baris 552: | ||
var p = SOCIAL_PLATFORMS[key]; | var p = SOCIAL_PLATFORMS[key]; | ||
var valUname = currentSocials[key] || ''; | var valUname = currentSocials[key] || ''; | ||
$socialGrid.append('<div><label style="font-size:0.78rem; color:#334155; font-weight:700;">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="ID / Username" value="' + valUname + '"></div>'); | |||
}); | }); | ||
$socialSec.append($socialGrid); | $socialSec.append($socialGrid); | ||
$ | $form.append($socialSec); | ||
// | // GRID DETAIL RUJUKAN LENGKAP | ||
var $refArea = $('<div class="md-form-group" style="margin-top:20px;"></div>'); | var $refArea = $('<div class="md-form-group" style="margin-top:20px;"></div>'); | ||
$refArea.append('<label style="font-size:0.95rem; | $refArea.append('<label style="font-size:0.95rem; font-weight:800; color:#0f172a;">Sumber Referensi / Rujukan Spesifik</label>'); | ||
var $typeSel = $('<select id="md-ref-type" class="md-select"><option value="">-- | var $refGrid = $('<div class="md-ref-grid"></div>'); | ||
var $typeSel = $('<select id="md-ref-type" class="md-select"><option value="">-- Pilih Tipe Utama --</option></select>'); | |||
Object.keys(REF_TYPES).forEach(function(t) { | Object.keys(REF_TYPES).forEach(function(t) { | ||
var sel = currentRef.type === t ? 'selected' : ''; | var sel = currentRef.type === t ? 'selected' : ''; | ||
| Baris 714: | Baris 569: | ||
}); | }); | ||
var $subTypeSel = $('<select id="md-ref-subtype" class="md-select"><option value="">-- Sub | var $subTypeSel = $('<select id="md-ref-subtype" class="md-select"><option value="">-- Pilih Sub-Tipe Spesifik --</option></select>'); | ||
function updateSubTypes(mainType, selectedSub) { | function updateSubTypes(mainType, selectedSub) { | ||
$subTypeSel.empty().append('<option value="">-- Sub | $subTypeSel.empty().append('<option value="">-- Pilih Sub-Tipe Spesifik --</option>'); | ||
if (mainType && REF_TYPES[mainType]) { | if (mainType && REF_TYPES[mainType]) { | ||
REF_TYPES[mainType].forEach(function(st) { | REF_TYPES[mainType].forEach(function(st) { | ||
| Baris 724: | Baris 580: | ||
} | } | ||
} | } | ||
$typeSel.on('change', function() { updateSubTypes($(this).val(), ''); }); | $typeSel.on('change', function() { updateSubTypes($(this).val(), ''); }); | ||
updateSubTypes(currentRef.type, currentRef.subType); | updateSubTypes(currentRef.type, currentRef.subType); | ||
$refGrid.append('<div><label style="font-size:0. | $refGrid.append('<div><label style="font-size:0.78rem;">Tipe Utama</label></div>').find('div').last().append($typeSel); | ||
$refGrid.append('<div><label style="font-size:0. | $refGrid.append('<div><label style="font-size:0.78rem;">Sub-Tipe</label></div>').find('div').last().append($subTypeSel); | ||
var $urlInput = $('<input type="url" id="md-ref-url" class="md-input" placeholder="https://..." value="' + (currentRef.url || '') + '">'); | var $urlInput = $('<input type="url" id="md-ref-url" class="md-input" placeholder="URL Tautan (https://...)" value="' + (currentRef.url || '') + '">'); | ||
$urlInput.on('blur', function() { | $urlInput.on('blur', function() { | ||
var u = ensureHttps($(this).val()); | var u = ensureHttps($(this).val()); | ||
$(this).val(u); | $(this).val(u); | ||
var $siteInp = $('#md-ref-site'); | |||
if (u && !$ | if (u && !$siteInp.val().trim()) { | ||
$siteInp.val(extractDomain(u)); | |||
} | |||
}); | }); | ||
$refGrid.append('<div class="md-grid-full"><label style="font-size:0. | $refGrid.append('<div class="md-grid-full"><label style="font-size:0.78rem;">URL Rujukan</label></div>').find('div').last().append($urlInput); | ||
$refGrid.append('<div><label style="font-size:0. | $refGrid.append('<div><label style="font-size:0.78rem;">Judul Artikel/Halaman</label><input type="text" id="md-ref-title" class="md-input" placeholder="Judul Rujukan" value="' + (currentRef.title || '') + '"></div>'); | ||
$refGrid.append('<div><label style="font-size:0. | $refGrid.append('<div><label style="font-size:0.78rem;">Nama Situs/Media</label><input type="text" id="md-ref-site" class="md-input" placeholder="Situs" value="' + (currentRef.site || '') + '"></div>'); | ||
$refGrid.append('<div><label style="font-size:0. | $refGrid.append('<div><label style="font-size:0.78rem;">Penulis</label><input type="text" id="md-ref-author" class="md-input" placeholder="Penulis" value="' + (currentRef.author || '') + '"></div>'); | ||
$refGrid.append('<div><label style="font-size:0. | $refGrid.append('<div><label style="font-size:0.78rem;">Penerbit</label><input type="text" id="md-ref-publisher" class="md-input" placeholder="Penerbit" value="' + (currentRef.publisher || '') + '"></div>'); | ||
// Tanggal Akses + Hari Ini | |||
var $dateBox = $('<div><label style="font-size:0.78rem;">Tanggal Akses</label></div>'); | |||
var $dateInpWrap = $('<div style="display:flex; gap:6px;"></div>'); | |||
var $dateInp = $('<input type="date" id="md-ref-date" class="md-input" value="' + (currentRef.date || '') + '">'); | |||
var $todayBtn = $('<button type="button" class="md-btn-icon" style="padding:4px 8px; font-size:0.75rem;" title="Set Hari Ini">Hari Ini</button>'); | |||
$todayBtn.on('click', function() { $dateInp.val(getTodayString()); }); | |||
$dateInpWrap.append($dateInp).append($todayBtn); | |||
$dateBox.append($dateInpWrap); | |||
$refGrid.append($dateBox); | |||
$refArea.append($refGrid); | $refArea.append($refGrid); | ||
$ | $form.append($refArea); | ||
// TOMBOL AKSI FORM | |||
var $actions = $('<div class="md-form-actions"></div>'); | var $actions = $('<div class="md-form-actions"></div>'); | ||
var $btnSave = $('<button class="md-btn md-btn-save"> | var $btnSave = $('<button class="md-btn md-btn-save">Simpan Data <span class="md-spinner"></span></button>'); | ||
var $btnCancel = $('<button class="md-btn md-btn-cancel"> | var $btnCancel = $('<button class="md-btn md-btn-cancel">Batal</button>'); | ||
$actions.append($btnSave).append($btnCancel); | |||
$actions.append($btnSave | |||
if (!isNew) { | if (!isNew) { | ||
var $btnDelete = $('<button class="md-btn md-btn-delete"> | var $btnDelete = $('<button class="md-btn md-btn-delete">Hapus Data <span class="md-spinner"></span></button>'); | ||
$btnDelete.on('click', function() { | $btnDelete.on('click', function() { | ||
if(confirm(' | if(confirm('Yakin ingin menghapus item data ini?')) { | ||
dataItems.splice(index, 1); | dataItems.splice(index, 1); | ||
saveData(' | saveData('Menghapus data', $(this), rawContent); | ||
} | } | ||
}); | }); | ||
$actions.append($btnDelete); | $actions.append($btnDelete); | ||
} | } | ||
$form.append($ | $form.append($actions); | ||
$container.append($form); | $container.append($form); | ||
$('#md-chk-person').on('change', function() { | $('#md-chk-person').on('change', function() { | ||
$('#md-social-box').css('display', | if($(this).is(':checked')) $('#md-social-box').css('display', 'grid'); | ||
else $('#md-social-box').hide(); | |||
}); | }); | ||
$('html, body').animate({ scrollTop: $form.offset().top - | $('html, body').animate({ scrollTop: $form.offset().top - 60 }, 250); | ||
$btnCancel.on('click', function() { $container.empty(); }); | $btnCancel.on('click', function() { $container.empty(); }); | ||
| Baris 858: | Baris 650: | ||
if (!newProp || !newVal) { | if (!newProp || !newVal) { | ||
alert("Data | alert("Label Data dan Nilai wajib diisi!"); return; | ||
} | } | ||
| Baris 865: | Baris 657: | ||
if (isPerson) { | if (isPerson) { | ||
Object.keys(SOCIAL_PLATFORMS).forEach(function(k) { | Object.keys(SOCIAL_PLATFORMS).forEach(function(k) { | ||
var valU = | var valU = $('#md-soc-' + k).val().trim(); | ||
if (valU) socObj[k] = valU; | if (valU) socObj[k] = valU; | ||
}); | }); | ||
| Baris 877: | Baris 669: | ||
site: $('#md-ref-site').val().trim(), | site: $('#md-ref-site').val().trim(), | ||
author: $('#md-ref-author').val().trim(), | author: $('#md-ref-author').val().trim(), | ||
publisher: $('#md-ref-publisher').val().trim() | publisher: $('#md-ref-publisher').val().trim(), | ||
date: $('#md-ref-date').val() | |||
}; | }; | ||
| Baris 901: | Baris 694: | ||
} | } | ||
// | // 10. JSON EXPORT & IMPORT MODAL | ||
function showJsonModal(rawContent) { | function showJsonModal(rawContent) { | ||
var $container = $('#md-form-container'); | var $container = $('#md-form-container'); | ||
| Baris 908: | Baris 701: | ||
var jsonStr = JSON.stringify(dataItems, null, 2); | var jsonStr = JSON.stringify(dataItems, null, 2); | ||
var $box = $('<div class="md-form-box"></div>'); | var $box = $('<div class="md-form-box"></div>'); | ||
$box.append('< | $box.append('<h4 class="md-form-title">Ekspor / Impor JSON Data</h4>'); | ||
$box.append('<p style="font-size:0.82rem; color:#64748b; margin-bottom:10px;">Anda dapat menyalin struktur JSON di bawah untuk cadangan atau menempelkan JSON dari artikel lain.</p>'); | |||
var $txt = $('<textarea class="md-textarea" rows=" | var $txt = $('<textarea class="md-textarea" rows="10" style="font-family:monospace; font-size:0.8rem;"></textarea>').val(jsonStr); | ||
$box.append($txt); | $box.append($txt); | ||
var $actions = $('<div class="md-form-actions"></div>'); | var $actions = $('<div class="md-form-actions"></div>'); | ||
var $btnImport = $('<button class="md-btn md-btn-save"> | var $btnImport = $('<button class="md-btn md-btn-save">Impor JSON & Simpan <span class="md-spinner"></span></button>'); | ||
var $btnCancel = $('<button class="md-btn md-btn-cancel"> | var $btnCancel = $('<button class="md-btn md-btn-cancel">Tutup</button>'); | ||
$actions.append($btnImport).append($btnCancel); | $actions.append($btnImport).append($btnCancel); | ||
$box.append($actions); | $box.append($actions); | ||
$container.append($box); | $container.append($box); | ||
$btnCancel.on('click', function() { $container.empty(); }); | $btnCancel.on('click', function() { $container.empty(); }); | ||
| Baris 929: | Baris 721: | ||
if (Array.isArray(parsed)) { | if (Array.isArray(parsed)) { | ||
dataItems = parsed; | dataItems = parsed; | ||
saveData('Impor JSON', $(this), rawContent); | saveData('Impor data dari JSON', $(this), rawContent); | ||
} else { alert("JSON | } else { | ||
} catch(e) { alert(" | alert("Format JSON harus berupa Array items!"); | ||
} | |||
} catch(e) { | |||
alert("Format JSON tidak valid: " + e.message); | |||
} | |||
}); | }); | ||
} | } | ||
// | // 11. EXECUTE | ||
loadData().then(function(rawContent) { buildUI(rawContent); }); | loadData().then(function(rawContent) { buildUI(rawContent); }); | ||
}); | }); | ||