MediaWiki:Common.js: Perbedaan antara revisi

Admin (bicara | kontrib)
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Admin (bicara | kontrib)
Tidak ada ringkasan suntingan
 
(2 revisi perantara oleh pengguna yang sama tidak ditampilkan)
Baris 1: Baris 1:
/**
/**
  * ====================================================================
  * ====================================================================
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V9.0 SECURE ULTIMATE)
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.7 SECURE ULTIMATE)
  * Fitur Baru: Top Social Media Container, Smart Image/Media Preview,  
  * Fitur: ALL ORIGINAL V8 FEATURES KEPT + Global Social Media Box,  
  * Wiki Page Autocomplete (OpenSearch), Auto-Wikilink Detection.
  * Smart Autocomplete/Preview Wikilink, Ultra-Strict Security, Mobile Ready.
  * ====================================================================
  * ====================================================================
  */
  */
Baris 76: Baris 76:
         var svgVerified = '<svg width="15" height="15" viewBox="0 0 24 24" fill="#3b82f6" stroke="#ffffff" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>';
         var svgVerified = '<svg width="15" height="15" viewBox="0 0 24 24" fill="#3b82f6" stroke="#ffffff" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>';
         var svgHelp = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>';
         var svgHelp = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>';
        var svgMedia = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>';


         // 4. HELPER UTILITY & ADVANCED SECURITY (Tingkat Tinggi OWASP)
         // 4. HELPER UTILITY & ADVANCED SECURITY
         function sanitizeHTML(str) {
         function sanitizeHTML(str) {
             if (typeof str !== 'string') return str;
             if (typeof str !== 'string') return str;
Baris 128: Baris 127:
         }
         }


         // 5. STYLESHEET (V9.0 dengan Komponen Baru)
         // 5. STYLESHEET (TERMASUK LAYOUT MEDIA SOSIAL GLOBAL & AUTOCOMPLETE)
         var css = `
         var css = `
             #mippedia-data-app {
             #mippedia-data-app {
Baris 153: Baris 152:
             .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; }
             .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; }


             /* NEW: Container Media Sosial Terpisah di Atas */
             /* Kotak Global Sosial Media Terpisah di Atas */
             .md-top-social-container { background: #f8fafc; border: 1px solid #e2e8f0; padding: 14px 16px; border-radius: 12px; margin-bottom: 16px; box-shadow: inset 0 2px 4px rgba(0,0,0,0.02); }
             .md-global-social-box { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.02); }
             .md-top-social-label { font-size: 0.72rem; font-weight: 800; color: #64748b; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.6px; display: flex; align-items: center; gap: 5px; }
             .md-social-box-title { font-size: 0.85rem; font-weight: 800; color: #475569; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 12px; border-bottom: 1px dashed #cbd5e1; padding-bottom: 8px; }
             .md-social-group { display: flex; flex-wrap: wrap; gap: 8px; }
             .md-social-group { display: flex; flex-wrap: wrap; gap: 8px; }
             .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; color: white !important; text-decoration: none; transition: transform 0.2s, opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
             .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; color: white !important; text-decoration: none !important; 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; text-decoration: none; }
             .md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; }


             .md-row-display { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s; border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff; }
             .md-row-display { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s; border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff; }
Baris 168: Baris 167:
             .md-data-value { font-size: 1.02rem; color: #0f172a; line-height: 1.4; font-weight: 600; word-break: break-word; }
             .md-data-value { font-size: 1.02rem; color: #0f172a; line-height: 1.4; font-weight: 600; word-break: break-word; }
              
              
            /* NEW: Image/Media Preview Styles */
            .md-media-preview-container { margin-top: 6px; width: 100%; display: block; }
            .md-media-preview-img { max-width: 100%; max-height: 250px; border-radius: 8px; border: 1px solid #cbd5e1; background: #f1f5f9; object-fit: contain; box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
           
            /* NEW: Autocomplete Styles */
            .md-autocomplete-wrapper { position: relative; width: 100%; }
            .md-autocomplete-list { position: absolute; top: calc(100% + 4px); left: 0; right: 0; background: #ffffff; border: 1px solid #cbd5e1; border-radius: 8px; z-index: 1000; max-height: 200px; overflow-y: auto; box-shadow: 0 10px 25px rgba(0,0,0,0.15); display: none; }
            .md-autocomplete-item { padding: 10px 14px; cursor: pointer; font-size: 0.9rem; border-bottom: 1px solid #f1f5f9; color: #0f172a; transition: 0.1s; display: flex; align-items: center; gap: 8px; }
            .md-autocomplete-item:last-child { border-bottom: none; }
            .md-autocomplete-item:hover { background: #e0e7ff; color: #4f46e5; font-weight: 600; padding-left: 18px; }
             .md-btn-copy { 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 { 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-btn-copy:hover { color: #4f46e5; background: #e0e7ff; }
Baris 202: Baris 190:
             .md-form-group { margin-bottom: 14px; }
             .md-form-group { margin-bottom: 14px; }
             .md-form-group label { display: flex; align-items:center; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; }
             .md-form-group label { display: flex; align-items:center; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; }
           
             .md-input, .md-select, .md-textarea { 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: 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: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-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); }
              
              
            /* Autocomplete Styles */
            .md-autocomplete-wrapper { position: relative; width: 100%; }
            .md-autocomplete-list { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid #cbd5e1; border-radius: 0 0 8px 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 1000; display: none; max-height: 200px; overflow-y: auto; margin-top: -2px; }
            .md-autocomplete-item { padding: 10px 12px; font-size: 0.88rem; color: #0f172a; cursor: pointer; border-bottom: 1px solid #f1f5f9; transition: 0.2s; display: flex; align-items: center; gap: 8px; }
            .md-autocomplete-item:last-child { border-bottom: none; }
            .md-autocomplete-item:hover { background: #f8fafc; color: #4f46e5; padding-left: 16px; }
             .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f8fafc; padding: 12px; border-radius: 8px; border: 1px dashed #cbd5e1; }
             .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-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; }
Baris 303: Baris 299:
         function buildWikitextVal(item) {
         function buildWikitextVal(item) {
             var val = item.val;
             var val = item.val;
           
            // Fix: Kalau item itu Pratinjau Gambar/Media, output URL standar tanpa kurung siku ganda.
            if (item.isMediaPreview && val.match(/^https?:\/\//i)) {
                return "[" + val + " Tautan Media]";
            }
             if (item.linkTarget && item.linkTarget.trim() !== '') {
             if (item.linkTarget && item.linkTarget.trim() !== '') {
                 return "[[" + item.linkTarget.trim() + "|" + val + "]]";
                 return "[[" + item.linkTarget.trim() + "|" + val + "]]";
Baris 344: Baris 335:
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
              
              
             var summaryTxt = customSummary ? ('Mippedia Data: ' + customSummary) : ('Mippedia Data V9.0: ' + actionType);
             var summaryTxt = customSummary ? ('Mippedia Data: ' + customSummary) : ('Mippedia Data V8.7: ' + actionType);
             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 406: Baris 397:
             $app.append($header);
             $app.append($header);


             // Tampilkan Search Box
             // Tampilkan kotak pencarian jika data banyak
             if (dataItems.length > 2) {
             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>');
                 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>');
Baris 419: Baris 410:
             }
             }


             // --- FITUR BARU: Pisahkan Sosial Media ke Kotak Atas ---
             // MENGUMPULKAN MEDIA SOSIAL GLOBAL (Memisahkan media sosial ke atas)
             var aggregatedSocials = {};
             var globalSocials = {};
            var hasSocials = false;
             dataItems.forEach(function(item) {
             dataItems.forEach(function(item) {
                 if (item.isPersonOrg && item.socials) {
                 if (item.isPersonOrg && item.socials) {
                     Object.assign(aggregatedSocials, item.socials);
                     Object.assign(globalSocials, item.socials);
                    hasSocials = true;
                 }
                 }
             });
             });


             if (hasSocials) {
             if (Object.keys(globalSocials).length > 0) {
                 var $topSocialContainer = $('<div class="md-top-social-container"></div>');
                 var $topSocials = $('<div class="md-global-social-box"></div>');
                 $topSocialContainer.append('<div class="md-top-social-label">' + svgVerified + ' PROFIL MEDIA SOSIAL & MUSIK</div>');
                 $topSocials.append('<div class="md-social-box-title">Media Sosial & Platform Resmi</div>');
                 var $socialGroup = $('<div class="md-social-group"></div>');
                 var $socialGroupGlobal = $('<div class="md-social-group"></div>');
               
                 Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                 Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                     if (aggregatedSocials[key]) {
                     var uname = globalSocials[key];
                    if (uname) {
                         var platform = SOCIAL_PLATFORMS[key];
                         var platform = SOCIAL_PLATFORMS[key];
                         var fullUrl = platform.base + aggregatedSocials[key].replace(/^@/, '');
                         var fullUrl = platform.base + uname.replace(/^@/, '');
                         var $badge = $('<a class="md-social-badge" href="' + sanitizeHTML(fullUrl) + '" target="_blank" rel="noopener noreferrer" style="background:' + platform.color + ';">' + platform.icon + ' ' + sanitizeHTML(platform.name) + '</a>');
                         var $badge = $('<a class="md-social-badge" href="' + sanitizeHTML(fullUrl) + '" target="_blank" rel="noopener noreferrer" style="background:' + platform.color + ';">' + platform.icon + ' ' + sanitizeHTML(platform.name) + '</a>');
                         $socialGroup.append($badge);
                         $socialGroupGlobal.append($badge);
                     }
                     }
                 });
                 });
                 $topSocialContainer.append($socialGroup);
                 $topSocials.append($socialGroupGlobal);
                 $app.append($topSocialContainer);
                 $app.append($topSocials);
             }
             }
            // -----------------------------------------------------


             var $list = $('<div class="md-list"></div>');
             var $list = $('<div class="md-list"></div>');
Baris 458: Baris 448:
                     var rawVal = item.val || '';
                     var rawVal = item.val || '';


                     // Jika ini Pratinjau Gambar/Media, maka deteksi URL nya dan masukkan ke tag img
                     if (rawVal.match(/^https?:\/\//i)) {
                    if (item.isMediaPreview && rawVal.match(/^https?:\/\//i)) {
                        displayValHtml = '<a href="' + sanitizeHTML(rawVal) + '" target="_blank" style="color:#2563eb; text-decoration:none; font-weight:700; word-break:break-all;">' + extractDomain(rawVal) + '</a>';
                        // Render Gambar Aman (OWASP xss escape via sanitizeHTML dan single quotes aman di atribut onerror)
                        displayValHtml += '<div class="md-media-preview-container"><a href="' + sanitizeHTML(rawVal) + '" target="_blank"><img src="' + sanitizeHTML(rawVal) + '" class="md-media-preview-img" alt="Pratinjau Media" onerror="this.outerHTML=\'<span style=\\\'color:#dc2626; font-size:0.75rem; font-weight:600; display:block; margin-top:4px;\\\'>[Gagal memuat pratinjau. Pastikan URL berupa gambar langsung]</span>\'"></a></div>';
                    }
                    else if (rawVal.match(/^https?:\/\//i)) {
                         displayValHtml = '<a href="' + sanitizeHTML(rawVal) + '" target="_blank" rel="noopener noreferrer" style="color:#2563eb; font-weight:700; text-decoration:none;">' + extractDomain(rawVal) + '</a>';
                         displayValHtml = '<a href="' + sanitizeHTML(rawVal) + '" target="_blank" rel="noopener noreferrer" style="color:#2563eb; font-weight:700; text-decoration:none;">' + extractDomain(rawVal) + '</a>';
                     } else if (item.linkTarget && item.linkTarget.trim() !== '') {
                     } else if (item.linkTarget && item.linkTarget.trim() !== '') {
Baris 525: Baris 509:
                         $refDetails.find('.md-verified-badge').on('click', function(e) {
                         $refDetails.find('.md-verified-badge').on('click', function(e) {
                             e.preventDefault(); e.stopPropagation();
                             e.preventDefault(); e.stopPropagation();
                             showModal('Situs Terverifikasi', 'Centang biru menandakan bahwa URL referensi ini valid dan berasal dari entitas, media publikasi besar, portal populer, atau pangkalan data resmi yang bereputasi kredibel.');
                             showModal('Situs Terverifikasi', 'Centang biru menandakan bahwa URL referensi ini valid dan berasal dari entitas, media publikasi besar, portal populer, atau pangkalan data resmi (seperti Kompas, YouTube, Apple Music, Spotify, dll) yang bereputasi kredibel.');
                         });
                         });


Baris 564: Baris 548:
              
              
             var draftData = localStorage.getItem(DRAFT_KEY);
             var draftData = localStorage.getItem(DRAFT_KEY);
             var currentData = isNew ? { prop: '', val: '', link: false, linkTarget: '', linkSplit: false, isMediaPreview: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index];
             var currentData = isNew ? { prop: '', val: '', link: false, linkTarget: '', linkSplit: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index];
              
              
             if (isNew && draftData) {
             if (isNew && draftData) {
Baris 591: Baris 575:
             $form.append($propGroup);
             $form.append($propGroup);
              
              
            // --- FITUR BARU: Pratinjau Autocomplete Wikilink ---
             var $valBox = $('<div class="md-form-group"></div>');
             var $valBox = $('<div class="md-form-group"></div>');
             $valBox.append('<label>Nilai Data <span class="md-help-icon" data-help="Isi dari data tersebut. Ketik kata kunci, kami akan memunculkan rekomendasi artikel yang sudah ada di Wiki ini!">' + svgHelp + '</span></label>');
             $valBox.append('<label>Nilai Data <span class="md-help-icon" data-help="Ketik nilai. Jika halaman sudah ada di Wiki, saran akan muncul (pratinjau) dan otomatis mencentang opsi Wikilink.">' + svgHelp + '</span></label>');
              
              
            // FITUR AUTOCOMPLETE PRATINJAU DIMULAI DI SINI
             var $autoWrap = $('<div class="md-autocomplete-wrapper"></div>');
             var $autoWrap = $('<div class="md-autocomplete-wrapper"></div>');
             var $valInput = $('<input type="text" id="md-inp-val" class="md-input" autocomplete="off" placeholder="Ketik nilai atau cari halaman di Wiki..." value="' + sanitizeHTML(currentData.val || '') + '">');
             var $valInput = $('<input type="text" id="md-inp-val" class="md-input" autocomplete="off" value="' + sanitizeHTML(currentData.val || '') + '">');
             var $autoList = $('<div class="md-autocomplete-list"></div>');
             var $autoList = $('<div class="md-autocomplete-list"></div>');
             $autoWrap.append($valInput).append($autoList);
             $autoWrap.append($valInput).append($autoList);
             $valBox.append($autoWrap);
             $valBox.append($autoWrap);
           
            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 chkSplit = currentData.linkSplit ? 'checked' : '';
           
            var $linkCheck = $('<input type="checkbox" id="md-inp-link" ' + chkLink + '>');
            var $lblLinkCheck = $('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"></label>');
            $lblLinkCheck.append($linkCheck).append(' Jadikan Wikilink Standar');


             var typingTimer;
             // Logika pratinjau ketika diketik
             var lastSelectedTitle = currentData.val || "";
             var isAutoChecked = false;  
           
             $valInput.on('input', function() {
             $valInput.on('input', function() {
                 var q = $(this).val().trim();
                 var q = $(this).val();
                  
                  
                 // Jika input diubah tidak sesuai dengan yang di-select sebelumnya, uncheck Wikilink Standar
                 // Jika input dikosongkan/berubah, kembalikan centang link ke false jika tadinya otomatis centang
                 if (q !== lastSelectedTitle) {
                 if (isAutoChecked) {
                     $('#md-inp-link').prop('checked', false);
                     $linkCheck.prop('checked', false);
                    isAutoChecked = false;
                 }
                 }
               
 
                clearTimeout(typingTimer);
                 if(q.length < 1) {
                 if (q.length < 1) { $autoList.hide(); return; }
                    $autoList.empty().hide();
               
                    return;
                 typingTimer = setTimeout(function() {
                }
                    // API Call ke Mediawiki untuk saran halaman
 
                    api.get({ action: 'opensearch', search: q, limit: 7, format: 'json' }).done(function(res) {
                 // Panggil API MediaWiki Prefix Search
                        var titles = res[1];
                api.get({
                        $autoList.empty();
                    action: 'query',
                        if (titles && titles.length > 0) {
                    list: 'prefixsearch',
                            titles.forEach(function(t) {
                    pssearch: q,
                                var $item = $('<div class="md-autocomplete-item">' + svgSearch + ' ' + sanitizeHTML(t) + '</div>');
                    pslimit: 6,
                                $item.on('click', function() {
                    format: 'json'
                                    $valInput.val(t);
                }).done(function(data) {
                                    lastSelectedTitle = t;
                    $autoList.empty();
                                    $('#md-inp-link').prop('checked', true); // AUTO-CENTANG
                    if(data.query && data.query.prefixsearch && data.query.prefixsearch.length > 0) {
                                    $autoList.hide();
                        data.query.prefixsearch.forEach(function(res) {
                                 });
                            var $item = $('<div class="md-autocomplete-item">' + svgSearch + ' ' + sanitizeHTML(res.title) + '</div>');
                                $autoList.append($item);
                            $item.on('click', function() {
                                $valInput.val(res.title);
                                $autoList.empty().hide();
                                $linkCheck.prop('checked', true); // OTOMATIS TERCENTANG
                                 isAutoChecked = true;
                             });
                             });
                             $autoList.show();
                             $autoList.append($item);
                        } else {
                        });
                            $autoList.hide();
                        $autoList.show();
                        }
                    } else {
                     });
                        $autoList.hide();
                 }, 400); // debounce
                     }
                 });
             });
             });


             // Klik di luar daftar hilangkan autocomplete
             // Sembunyikan pratinjau saat klik di luar
             $(document).on('click.auto', function(e) {
             $(document).on('click.mdauto', function(e) {
                 if (!$(e.target).closest('.md-autocomplete-wrapper').length) $autoList.hide();
                 if(!$(e.target).closest('.md-autocomplete-wrapper').length) {
                    $autoList.hide();
                }
             });
             });


            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>');
             $wikilinkOpts.append($lblLinkCheck);
            var chkLink = currentData.link ? 'checked' : '';
            var chkSplit = currentData.linkSplit ? 'checked' : '';
            var chkMedia = currentData.isMediaPreview ? 'checked' : '';
           
             $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</label>');
             $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</label>');
             $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</label>');
            $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer; color:#0369a1;"><input type="checkbox" id="md-inp-media" ' + chkMedia + '> ' + svgMedia + ' Jadikan Pratinjau Gambar/Media (Otomatis)</label>');
           
             var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569; margin-bottom:4px;">Target Halaman Khusus (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="' + sanitizeHTML(currentData.linkTarget || '') + '"></div>');
             var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569; margin-bottom:4px;">Target Halaman Khusus (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="' + sanitizeHTML(currentData.linkTarget || '') + '"></div>');
             $wikilinkOpts.append($pipedGroup);
             $wikilinkOpts.append($pipedGroup);
Baris 660: Baris 652:
             var $socialSec = $('<div class="md-form-group" style="margin-top:16px;"></div>');
             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:#e0e7ff; padding:10px; border-radius:8px; font-weight:700; color:#3730a3; font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Simpan Link Profil Media Sosial & Musik <span class="md-help-icon" data-help="Centang ini jika data ini mengandung identitas. Sistem akan memisahkan tombol sosial media ini secara otomatis ke dalam kotak khusus di panel atas (Header).">' + svgHelp + '</span></label>');
             $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 + '> Simpan Profil Media Sosial (Akan muncul di paling atas) <span class="md-help-icon" data-help="Centang ini untuk mengisi data sosial media. Datanya akan dihimpun dan dimunculkan di kotak teratas data struktur.">' + svgHelp + '</span></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 666: Baris 658:
                 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; margin-bottom:4px;">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="ID / Username / URL" value="' + sanitizeHTML(valUname) + '"></div>');
                 $socialGrid.append('<div><label style="font-size:0.78rem; color:#334155; font-weight:700; margin-bottom:4px;">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="ID / Username" value="' + sanitizeHTML(valUname) + '"></div>');
             });
             });
             $socialSec.append($socialGrid);
             $socialSec.append($socialGrid);
Baris 672: Baris 664:


             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; font-weight:800; color:#0f172a; margin-bottom:10px;">Sumber Referensi <span class="md-help-icon" data-help="Mohon berikan sumber referensi yang valid. Jika URL rujukan Anda mengarah ke situs web besar yang terverifikasi, lencana centang biru akan muncul otomatis.">' + svgHelp + '</span></label>');
             $refArea.append('<label style="font-size:0.95rem; font-weight:800; color:#0f172a; margin-bottom:10px;">Sumber Referensi <span class="md-help-icon" data-help="Mohon berikan sumber referensi yang valid, kredibel, dan dapat dipertanggungjawabkan (seperti portal berita resmi, jurnal akademik ilmiah, buku cetak ber-ISBN, atau pangkalan data terverifikasi). Referensi yang kuat sangat membantu memastikan keakuratan informasi. Jika URL rujukan Anda mengarah ke situs web besar yang terverifikasi, sistem keamanan akan secara otomatis menampilkan lencana centang biru premium sebagai tanda sumber tepercaya.">' + svgHelp + '</span></label>');
             var $refGrid = $('<div class="md-ref-grid"></div>');
             var $refGrid = $('<div class="md-ref-grid"></div>');
              
              
Baris 772: Baris 764:


             $('html, body').animate({ scrollTop: $form.offset().top - 60 }, 250);
             $('html, body').animate({ scrollTop: $form.offset().top - 60 }, 250);
           
             $btnCancel.on('click', function() { $container.empty(); });
             $btnCancel.on('click', function() {  
                $container.empty();  
                $(document).off('click.auto');
            });


             $btnDraft.on('click', function() {
             $btnDraft.on('click', function() {
Baris 792: Baris 780:
                     linkSplit: $('#md-inp-split').is(':checked'),
                     linkSplit: $('#md-inp-split').is(':checked'),
                     linkTarget: $('#md-inp-target').val().trim(),
                     linkTarget: $('#md-inp-target').val().trim(),
                    isMediaPreview: $('#md-inp-media').is(':checked'),
                     isPersonOrg: $('#md-chk-person').is(':checked'),
                     isPersonOrg: $('#md-chk-person').is(':checked'),
                     socials: socObj,
                     socials: socObj,
Baris 842: Baris 829:
                     linkSplit: $('#md-inp-split').is(':checked'),
                     linkSplit: $('#md-inp-split').is(':checked'),
                     linkTarget: $('#md-inp-target').val().trim(),
                     linkTarget: $('#md-inp-target').val().trim(),
                    isMediaPreview: $('#md-inp-media').is(':checked'),
                     isPersonOrg: isPerson,
                     isPersonOrg: isPerson,
                     socials: socObj,
                     socials: socObj,
Baris 1.371: Baris 1.357:
             '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
             '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
             '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
             '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
             'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah lisensi resmi ' +
             'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah ' +
             '<a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Creative Commons Attribution-ShareAlike 4.0 International</a>.' +
             '<a href="https://creativecommons.org/publicdomain/zero/1.0/"target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Lisensi Creative Commons CC0</a>.' +
             '</p>' +
             '</p>' +
             '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';
             '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';