MediaWiki:Common.js: Perbedaan antara revisi

Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Baris 528: Baris 528:
         }
         }
     });
     });
});
/* ==========================================================
  📍 MIPPEDIA DATA - ULTIMATE TEXT-TO-MAP LOCATOR
  Fitur: Deteksi lokasi dari teks dengan database label lengkap
  ========================================================== */
(function() {
    $(document).ready(function() {
        var locationText = "";
       
        // --- DAFTAR LABEL SUPER LENGKAP & MASUK AKAL ---
        var locationLabels = [
            // Umum & Geografis
            'lokasi', 'tempat', 'wilayah', 'daerah', 'koordinat', 'alamat',
            // Orang (Biografi)
            'tempat lahir', 'asal', 'kediaman', 'domisili', 'negara asal',
            // Organisasi & Perusahaan
            'kantor pusat', 'markas', 'cabang utama', 'titik operasi',
            // Makanan & Budaya
            'asal wilayah', 'daerah asal', 'negara sumber', 'kawasan',
            // Sejarah & Bangunan
            'letak', 'posisi', 'titik temu', 'orbit'
        ];
        // Jalankan pencarian di tabel data (infobox atau wikitable)
        $('.wikitable tr, .infobox tr, .mip-data-table tr').each(function() {
            var label = $(this).find('th').text().toLowerCase().trim();
            // Hilangkan karakter spesial kayak titik dua biar matching-nya akurat
            label = label.replace(/[:]/g, '');
            var isMatch = locationLabels.some(function(target) {
                return label === target || label.includes(target);
            });
            if (isMatch) {
                var rawValue = $(this).find('td').text().trim();
                // Ambil bagian utama sebelum tanda koma, kurung, atau titik koma
                // Misal: "Bandung, Jawa Barat" -> ambil "Bandung"
                locationText = rawValue.split(/[,(\[;]/)[0].trim();
               
                if (locationText.length > 2) return false; // Stop jika sudah ketemu yang valid
            }
        });
        // Eksekusi Render Peta
        if (locationText && locationText.length > 2) {
            var $mapWrapper = $('<div>').css({
                'margin': '15px 0',
                'padding': '12px',
                'border': '1px solid #ddd',
                'background': '#ffffff',
                'border-radius': '10px',
                'box-shadow': '0 4px 12px rgba(0,0,0,0.08)'
            });
            $mapWrapper.append('<div style="font-weight:bold; font-size:0.9em; margin-bottom:10px; color:#444; display:flex; align-items:center;">' +
                              '<span style="margin-right:8px;">🗺️</span>Pratinjau Lokasi : ' + locationText + '</div>');
            // Embed URL dengan pencarian teks (Nominatim)
            var embedUrl = "https://www.openstreetmap.org/export/embed.html?layer=mapnik&q=" + encodeURIComponent(locationText);
            var $iframe = $('<iframe>').attr({
                'src': embedUrl,
                'width': '100%',
                'height': '280',
                'frameborder': '0',
                'style': 'border-radius: 8px; border: 1px solid #eee;'
            });
            $mapWrapper.append($iframe);
           
            // Link eksternal yang lebih rapi
            var gMapsUrl = "https://www.google.com/maps/search/" + encodeURIComponent(locationText);
            $mapWrapper.append('<div style="text-align:right; margin-top:8px;">' +
                              '<a href="' + gMapsUrl + '" target="_blank" style="font-size:0.75em; color:#6a5acd; font-weight:bold; text-decoration:none; text-transform:uppercase; letter-spacing:0.5px;">Buka di Google Maps →</a></div>');
            // Masukkan ke bawah section deskripsi otomatis
            if ($('#mip-desc-section').length) {
                $('#mip-desc-section').after($mapWrapper);
            }
        }
    });
})();
/* ==========================================================
  ⏳ MIPPEDIA DATA - SMART KRONOLOGI 2.0 (INTELLIGENT MODE)
  Fitur: Floating Button, Deep Analysis Timeline, No-Leak Panel
  ========================================================== */
(function() {
    $(document).ready(function() {
        var events = [];
        var currentYear = 2026;
       
        // 1. Scan data secara cerdas & tentukan Titik Nol (Lahir/Berdiri)
        $('.infobox tr, .wikitable tr, .mip-data-table tr').each(function() {
            var label = $(this).find('th').text().trim().replace(':', '');
            var value = $(this).find('td').text().trim();
            var yearMatch = value.match(/\b(19|20)\d{2}\b/);
           
            if (yearMatch && label && label.length < 25) {
                events.push({ year: parseInt(yearMatch[0]), label: label, info: value });
            }
        });
        if (events.length === 0) return;
        events.sort((a, b) => a.year - b.year);
        var baseYear = events[0].year; // Tahun pertama sebagai referensi
        // 2. Buat Floating Button (Pastikan bersih)
        $('#mip-timeline-btn, #mip-timeline-panel').remove(); // Bersihkan yang lama
        var $floatBtn = $('<div id="mip-timeline-btn">⏳</div>').css({
            'position': 'fixed', 'bottom': '25px', 'right': '25px',
            'width': '50px', 'height': '50px', 'background': '#6a5acd',
            'color': 'white', 'border-radius': '50%', 'display': 'flex',
            'align-items': 'center', 'justify-content': 'center',
            'font-size': '20px', 'cursor': 'pointer', 'z-index': '9999',
            'box-shadow': '0 4px 15px rgba(106, 92, 205, 0.4)', 'transition': '0.3s'
        });
        // 3. Buat Sidebar Panel (Gunakan % agar tidak bocor di samping)
        var $sidePanel = $('<div id="mip-timeline-panel">').css({
            'position': 'fixed', 'top': '0', 'right': '-110%', // Sembunyi total
            'width': '85%', 'max-width': '350px', 'height': '100%', 'background': '#fff',
            'box-shadow': '-10px 0 30px rgba(0,0,0,0.2)', 'z-index': '10000',
            'transition': '0.5s cubic-bezier(0.19, 1, 0.22, 1)', 'padding': '25px',
            'overflow-y': 'auto'
        });
        // Header
        var panelHtml = '<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:25px; border-bottom:2px solid #6a5acd; padding-bottom:10px;">' +
                        '<span style="font-weight:bold; color:#333; font-size:1.2em;">Kronologi Entitas</span>' +
                        '<span id="close-mip-timeline" style="cursor:pointer; font-size:28px; color:#999; line-height:1;">×</span></div>';
       
        var listHtml = '<div style="border-left:2px solid #6a5acd; margin-left:12px; padding-left:25px;">';
       
        events.forEach(function(ev, index) {
            var gap = ev.year - baseYear;
            var timeKonteks = "";
           
            if (index === 0) {
                timeKonteks = "— Titik Awal";
            } else {
                timeKonteks = "— " + gap + " tahun kemudian";
            }
            listHtml += '<div style="position:relative; margin-bottom:30px;">' +
                        '<div style="position:absolute; left:-32px; top:5px; width:12px; height:12px; background:#6a5acd; border-radius:50%; border:3px solid #fff; box-shadow:0 0 0 2px #6a5acd;"></div>' +
                        '<div style="font-weight:bold; color:#6a5acd; font-size:1.1em;">' + ev.year + ' <span style="font-size:0.75em; color:#888; font-weight:normal;">' + timeKonteks + '</span></div>' +
                        '<div style="font-size:0.9em; color:#333; margin-top:5px; font-weight:600;">' + ev.label + '</div>' +
                        '<div style="font-size:0.85em; color:#666; font-style:italic; line-height:1.4;">' + ev.info + '</div></div>';
        });
       
        listHtml += '</div>';
        $sidePanel.html(panelHtml + listHtml);
        $('body').append($floatBtn).append($sidePanel);
        // 4. Handler Interaksi
        $floatBtn.on('click', function() { $sidePanel.css('right', '0'); });
        $('#close-mip-timeline').on('click', function() { $sidePanel.css('right', '-110%'); });
        $(document).on('mouseup', function(e) {
            if (!$sidePanel.is(e.target) && $sidePanel.has(e.target).length === 0 && !$floatBtn.is(e.target)) {
                $sidePanel.css('right', '-110%');
            }
        });
    });
})();
/* ==========================================================
  🧠 MIPPEDIA DATA - SMART REDIRECT SUGGESTION
  Mendeteksi typo dan menyarankan halaman yang benar
  ========================================================== */
(function() {
    $(document).ready(function() {
        // Cek apakah ini halaman "Halaman tidak ditemukan"
        if (!$('.noarticletext').length && !$('#noarticletext').length) return;
        var brokenTitle = mw.config.get('wgPageName').replace(/_/g, ' ');
        var api = new mw.Api();
        api.get({
            action: 'query',
            list: 'search',
            srsearch: brokenTitle,
            srlimit: 3,
            format: 'json'
        }).done(function(data) {
            var suggestions = data.query.search;
           
            if (suggestions.length > 0) {
                var $suggestBox = $('<div id="mip-suggest-box">').css({
                    'margin': '20px 0', 'padding': '20px', 'background': '#f4f1ff',
                    'border': '1px solid #6a5acd', 'border-radius': '12px', 'text-align': 'center'
                });
                $suggestBox.append('<div style="font-size:1.5em; margin-bottom:10px;">🤔</div>');
                $suggestBox.append('<div style="font-weight:bold; color:#333;">Halaman tidak ditemukan, tapi mungkin maksud Anda:</div>');
               
                var $list = $('<div style="margin-top:15px; display:flex; flex-wrap:wrap; justify-content:center; gap:10px;"></div>');
               
                suggestions.forEach(function(s) {
                    var sLink = '<a href="/wiki/' + encodeURIComponent(s.title.replace(/ /g, '_')) + '" ' +
                                'style="padding:8px 15px; background:#6a5acd; color:white; border-radius:20px; text-decoration:none; font-weight:bold; font-size:0.9em;">' +
                                s.title + '</a>';
                    $list.append(sLink);
                });
                $suggestBox.append($list);
                $('.noarticletext').first().after($suggestBox);
            }
        });
    });
})();
/* MIPPEDIA DATA CENTRAL METADATA MANAGER (FINAL CLEAN VERSION) */
$(document).ready(function() {
    var ns = mw.config.get('wgNamespaceNumber');
    var isMain = mw.config.get('wgIsMainPage');
    if (ns === 0 && !isMain) {
        var editIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#54595d" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="cursor:pointer;"><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 skeleton = `
            <div id="mippedia-metadata-manager" style="border: 1px solid #c8ccd1; background: #fff; padding: 15px; margin: 10px 0; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
                <div style="display:flex; justify-content:space-between; align-items:center; border-bottom: 1px solid #eee; padding-bottom: 8px; margin-bottom: 10px;">
                    <span style="font-weight:bold; font-size: 13px; color: #54595d;">DESKRIPSI EKOSISTEM MIPPEDIA</span>
                    <div id="mippedia-btn-trigger">${editIcon}</div>
                </div>
                <div id="meta-content-area" style="font-size: 14px; color: #202122;">
                    <div id="row-id"><b>ID:</b> <span class="v-id">Memuat...</span></div>
                    <div id="row-en"><b>EN:</b> <span class="v-en">Memuat...</span></div>
                    <div id="row-cn"><b>Concise:</b> <span class="v-cn">Memuat...</span></div>
                </div>
            </div>
        `;
        $('.mw-parser-output').prepend(skeleton);
        var api = new mw.Api();
        // 1. Fungsi Ambil Data dari Server
        api.get({
            action: 'query',
            prop: 'revisions',
            titles: mw.config.get('wgPageName'),
            rvprop: 'content',
            format: 'json'
        }).done(function(data) {
            var page = Object.values(data.query.pages)[0];
            if (!page || !page.revisions) {
                $('.v-id, .v-en, .v-cn').html("<i>Belum ada deskripsi</i>");
                return;
            }
            var content = page.revisions[0]['*'];
            var dID = content.match(/ID_DESC=(.*)/) ? content.match(/ID_DESC=(.*)/)[1].split('-->')[0].trim() : "";
            var dEN = content.match(/EN_DESC=(.*)/) ? content.match(/EN_DESC=(.*)/)[1].split('-->')[0].trim() : "";
            var dCN = content.match(/CN_DESC=(.*)/) ? content.match(/CN_DESC=(.*)/)[1].split('-->')[0].trim() : "";
            $('.v-id').html(dID || "<i>Belum ada deskripsi</i>");
            $('.v-en').html(dEN || "<i>Belum ada deskripsi</i>");
            $('.v-cn').html(dCN || "<i>Belum ada deskripsi</i>");
        });
        // 2. Klik Edit
        $('#mippedia-btn-trigger').on('click', function() {
            var currID = $('.v-id').text().replace('Belum ada deskripsi', '').trim();
            var currEN = $('.v-en').text().replace('Belum ada deskripsi', '').trim();
            var currCN = $('.v-cn').text().replace('Belum ada deskripsi', '').trim();
            $('#meta-content-area').html(`
                <div style="display: flex; flex-direction: column; gap: 8px;">
                    <input type="text" id="target-id" style="width:100%; padding:8px;" placeholder="Deskripsi ID" value="${currID}">
                    <input type="text" id="target-en" style="width:100%; padding:8px;" placeholder="Deskripsi EN" value="${currEN}">
                    <input type="text" id="target-cn" style="width:100%; padding:8px;" placeholder="Deskripsi Concise" value="${currCN}">
                    <div style="display:flex; gap:8px;">
                        <button id="save-final" style="flex:1; background:#36c; color:#fff; border:none; padding:10px; border-radius:4px; font-weight:bold; cursor:pointer;">Simpan Permanen</button>
                        <button id="cancel-final" style="flex:1; background:#eee; border:1px solid #ccc; padding:10px; border-radius:4px; cursor:pointer;">Batal</button>
                    </div>
                </div>
            `);
            $(this).hide();
        });
        // 3. Simpan Permanen (Hidden) & Cleanup
        $(document).on('click', '#save-final', function() {
            var title = mw.config.get('wgPageName');
            var valID = $('#target-id').val().trim();
            var valEN = $('#target-en').val().trim();
            var valCN = $('#target-cn').val().trim();
            var hiddenData = "\n";
            api.get({
                action: 'query',
                prop: 'revisions',
                titles: title,
                rvprop: 'content'
            }).done(function(res) {
                var p = Object.values(res.query.pages)[0];
                var oldContent = (p && p.revisions) ? p.revisions[0]['*'] : "";
               
                api.postWithToken('csrf', {
                    action: 'edit',
                    title: title,
                    text: finalBody,
                    summary: 'Sinkronisasi Metadata Mippedia (Hidden Mode)'
                }).done(function() {
                    location.reload();
                });
            });
        });
        // 4. Batal
        $(document).on('click', '#cancel-final', function() {
            location.reload();
        });
    }
});
});