Not: Yayımladıktan sonra değişiklikleri görmeniz için tarayıcınızın önbelleğini temizlemeniz gerekebilir.
- Firefox / Safari: Shift tuşuna basılıyken Yeniden Yükle'ye tıklayın ya da Ctrl-F5 ya da Ctrl-R tıklayın (Mac için ⌘-R)
- Google Chrome: Ctrl-Shift-R'ye basın. (Mac için ⌘-Shift-R)
- Edge: Ctrl basılıyken Yenile'ye tıklayın ya da Ctrl-F5'e basın.
/* ============================================================
Minerva.js BİRLEŞİK BETİK (v3)
1) Timeless'ın "Gezinti" (site-navigation) içeriği sayfaya
GÖRÜNMEZ şekilde yerleştirilir (sayfa altı gizli alan).
- Çekmeceye/hamburger menüye HİÇBİR ŞEY eklenmez.
- Başlıklı alt portletler (h3 + link listeleri) KORUNUR,
böylece 📚 popup'ta linklerin başlıkları da görünür.
- İçerik sayfanın Timeless görünümünden bir kez çekilir,
sessionStorage'da tutulur.
2) FENPEDIA SAF POPUP MODAL SİSTEMİ (yüzen 📚/📋 butonlar):
Timeless.js ile aynı mantık — Minerva'da da çalışır.
📚 Ünite Menüsü (yalnızca Gezinti portletleri),
📋 İçindekiler.
============================================================ */
( function () {
'use strict';
/* ================= BÖLÜM 1: Yüzen 📚/📋 butonlar (jQuery) ================= */
// Ders menüsünü gizli "Gezinti" kaynağından çıkarır (TEK tanım, üst kapsam)
function extractLessonMenu() {
var $ = window.jQuery;
if ( !$ ) { return false; }
// Anasayfa'da ders/ünite menüsü gösterilmez (orijinal kural)
var mw = window.mw;
if ( mw && mw.config && mw.config.get( 'wgPageName' ) === 'Anasayfa' ) { return false; }
var $lessonMenuSource = null;
var useHidden = false;
// ÖNCELİK 1: Sayfa altına gizlice yerleştirilen Gezinti kutusu.
// İçinde EN AZ BİR bağlantı varsa gösterilir (ünite adından bağımsız —
// CategorySidebar/DynamicSidebar uygulanan HER sayfada çalışır).
var $hidden = $( '#fn-minerva-sidebar-source .sidebar-chunk' );
if ( $hidden.length && $hidden.find( 'a' ).length ) {
$lessonMenuSource = $hidden;
useHidden = true;
}
// Yedek: gizli kaynak yoksa genel tarama (Timeless benzeri).
// Çekmecenin (#mw-mf-page-left) kendisi veya içindeki öğeler ASLA
// kaynak seçilmez — aksi halde popup'a tüm hamburger menüsü dolar.
if ( !$lessonMenuSource ) {
$( '.sidebar-chunk, #mw-panel, .mw-sidebar-inner, nav, .custom-sidebar' ).each( function () {
var $this = $( this );
if ( $this.closest( '#mw-mf-page-left' ).length ) { return true; } // çekmece içini atla
var textContent = $this.text();
if ( textContent && ( /Konu Anlatim/i.test( textContent ) || ( /Güneş/i.test( textContent ) && /Dünya/i.test( textContent ) && /Ay/i.test( textContent ) ) ) ) {
$lessonMenuSource = $this;
return false; // İlk doğru paneli bulduğunda aramayı durdur
}
} );
}
if ( $lessonMenuSource && $lessonMenuSource.length > 0 ) {
var $compiledContent = $( '<div></div>' );
var seenHeaders = {}; // Eklenen başlıkların metinlerini tutacak nesne
$lessonMenuSource.find( 'h2, h3, ul' ).each( function () {
var $element = $( this ).clone();
$element.removeAttr( 'class' ).removeAttr( 'id' );
// Eğer element bir başlıksa (h2 veya h3)
if ( $element.is( 'h2, h3' ) ) {
var headerText = $.trim( $element.text() ).toUpperCase();
// "Gezinti" gibi gezinme etiketi başlıkları popup'ta gösterilmez
if ( useHidden && ( headerText === 'GEZINTI' || headerText === 'GEZİNTİ' ) ) {
return true; // continue anlamında
}
// Bu başlık metni daha önce eklendiyse pas geç (Çift başlığı engeller)
if ( seenHeaders[ headerText ] ) {
return true; // continue anlamında
}
seenHeaders[ headerText ] = true; // İlk kez görüldüyse listeye kaydet
}
$element.find( 'li, a' ).removeAttr( 'class' ).removeAttr( 'id' ); // İç stilleri temizle
$compiledContent.append( $element );
} );
if ( $compiledContent.children().length > 0 ) {
$( '.id-lesson-content .fn-modal-body' ).html( $compiledContent.html() );
$( '.btn-lesson' ).addClass( 'btn-visible' );
return true;
}
}
return false;
}
// Ağır tarama başarısız olursa sidebar'ı SADECE KISA SÜRE izle (TBT düzeltmesi)
function observeForLessonMenu() {
var mw = window.mw;
// Anasayfa ise süreci anında bitirir
if ( mw && mw.config && mw.config.get( 'wgPageName' ) === 'Anasayfa' ) { return; }
var observer = new MutationObserver( function ( mutations, obs ) {
if ( extractLessonMenu() ) {
obs.disconnect();
}
} );
observer.observe( document.body, { childList: true, subtree: true } );
// Menü bulunamazsa 3 saniye sonra gözlemciyi KESİN OLARAK kapat.
setTimeout( function () {
observer.disconnect();
}, 3000 );
}
// Ağır sidebar taramasını idle anına ertele (requestIdleCallback)
function scheduleLessonMenuExtraction() {
if ( window.requestIdleCallback ) {
window.requestIdleCallback( function () {
if ( !extractLessonMenu() ) {
observeForLessonMenu();
}
}, { timeout: 2000 } );
} else {
// Eski tarayıcılar için fallback: load + 500ms gecikme
window.addEventListener( 'load', function () {
setTimeout( function () {
if ( !extractLessonMenu() ) {
observeForLessonMenu();
}
}, 500 );
} );
}
}
// Yüzen buton grubu + modal pencereleri kur (tek sefer)
function initFloatingUI() {
var $ = window.jQuery;
if ( !$ ) { return; }
// Sağ alttaki buton grubunu ve gizli pencereleri sayfaya bas (tek sefer)
if ( $( '.fn-floating-btn-group' ).length === 0 ) {
$( 'body' ).append(
'<div class="fn-floating-btn-group">' +
' <button class="fn-floating-btn btn-lesson" type="button" title="Ünite Menüsü">📚</button>' +
' <button class="fn-floating-btn btn-toc" type="button" title="İçindekiler">📋</button>' +
'</div>' +
'<div class="fn-modal-overlay">' +
' <div class="fn-modal-content id-lesson-content"><div class="fn-modal-body"></div></div>' +
' <div class="fn-modal-content id-toc-content"><h2>İÇİNDEKİLER</h2><div class="fn-modal-body"></div></div>' +
'</div>'
);
}
// 📋 (mavi) buton kontrolü: TOC içeriğini çeker
var hasTOC = $( '#toc' ).length || $( '.toc' ).length || $( '.mw-toc' ).length;
if ( hasTOC ) {
var $cleanTOC = $( '#toc ul, .toc ul, .mw-toc ul' ).first().clone();
$( '.id-toc-content .fn-modal-body' ).html( $cleanTOC );
$( '.btn-toc' ).addClass( 'btn-visible' );
// Orijinal TOC elemanını boş kabuk bırakmamak için taşı (hedef yoksa no-op)
$( '#toc, .toc, .mw-toc' ).appendTo( '.fn-toc-wrapper' );
}
// 🟢 Yeşil Buton (📚) Tıklama
$( document ).on( 'click', '.btn-lesson', function ( e ) {
e.stopPropagation();
$( '.fn-modal-overlay' ).fadeIn( 200 );
$( '.fn-modal-content' ).removeClass( 'modal-active' );
$( '.id-lesson-content' ).addClass( 'modal-active' );
} );
// 🔵 Mavi Buton (📋) Tıklama
$( document ).on( 'click', '.btn-toc', function ( e ) {
e.stopPropagation();
$( '.fn-modal-overlay' ).fadeIn( 200 );
$( '.fn-modal-content' ).removeClass( 'modal-active' );
$( '.id-toc-content' ).addClass( 'modal-active' );
} );
function closeAllModals() {
$( '.fn-modal-overlay' ).fadeOut( 200 );
$( '.fn-modal-content' ).removeClass( 'modal-active' );
}
$( document ).on( 'click', '.fn-modal-overlay, .fn-modal-body a', function () {
closeAllModals();
} );
// MediaWiki'nin tıklama engelini baypas eder
$( window ).on( 'hashchange', function () {
closeAllModals();
} );
$( '.fn-modal-content' ).on( 'click', function ( e ) {
e.stopPropagation();
} );
// Ağır sidebar taramasını idle anına ertele
scheduleLessonMenuExtraction();
}
/* ========= BÖLÜM 2: Gizli "Gezinti" kaynağını sayfaya yerleştir ========= */
function esc( s ) {
return String( s ).replace( /&/g, '&' ).replace( /</g, '<' )
.replace( />/g, '>' ).replace( /"/g, '"' );
}
function timelessUrl() {
var u;
try {
u = new URL( window.location.href );
} catch ( e ) {
u = new URL( window.location.pathname, window.location.origin );
}
u.searchParams.set( 'useskin', 'timeless' );
u.searchParams.delete( 'action' );
return u.href;
}
function cacheKey() {
var p = window.location.pathname.replace( /\/+$/, '' );
return 'fn-minerva-sidebar:' + p;
}
// Timeless'ın "Gezinti" (site-navigation) bloğunu alır; başlıklı alt
// portlet yapısını (h3 + ul) korur. Dış "Gezinti" etiketi ve boş
// portletler atılır; id/class temizlenir.
function extractSidebar( doc ) {
var chunks = doc.querySelectorAll( '.sidebar-chunk' );
var pick = null;
chunks.forEach( function ( ch ) {
if ( !pick && ch.id === 'site-navigation' ) { pick = ch; }
} );
if ( !pick ) {
chunks.forEach( function ( ch ) {
if ( !pick ) {
var h = ch.querySelector( 'h2, h3' );
var t = h ? h.textContent.trim().toLowerCase() : '';
if ( t === 'gezinti' ) { pick = ch; }
}
} );
}
if ( !pick ) { return ''; }
var clone = pick.cloneNode( true );
// MediaWiki:Sidebar'da STATİK tanımlı portlet başlıkları (CategorySidebar
// üretimi DEĞİLDİR; gizli kaynaktan atılır).
var STATIC_PORTLETS = { 'SINIFINI SEÇ': true };
// Boş portletleri ve statik portletleri at (ör: boş p-navigation)
clone.querySelectorAll( '.mw-portlet' ).forEach( function ( pt ) {
var h = pt.querySelector( 'h3' );
var t = h ? ( h.textContent || '' ).trim().toUpperCase() : '';
var ul = pt.querySelector( 'ul' );
var empty = !ul || !ul.querySelector( 'a' );
if ( empty || STATIC_PORTLETS[ t ] ) {
if ( pt.parentNode ) { pt.parentNode.removeChild( pt ); }
}
} );
// Dış "Gezinti" (h2) etiketini kaldır — yalnız iç portletler kalsın
var outer = clone.querySelector( ':scope > h2' ) || clone.querySelector( 'h2' );
if ( outer && outer.parentNode ) { outer.parentNode.removeChild( outer ); }
// id/class temizliği (çakışma olmasın)
clone.querySelectorAll( '[id]' ).forEach( function ( el ) { el.removeAttribute( 'id' ); } );
clone.querySelectorAll( '[class]' ).forEach( function ( el ) { el.removeAttribute( 'class' ); } );
// Kalan içerikte bağlantı yoksa boş dön
if ( !clone.querySelector( 'a' ) ) { return ''; }
return clone.innerHTML;
}
function sourceWrap() {
return document.getElementById( 'fn-minerva-sidebar-source' );
}
function ensureSource() {
if ( !sourceWrap() && document.body ) {
var div = document.createElement( 'div' );
div.id = 'fn-minerva-sidebar-source';
div.hidden = true;
div.setAttribute( 'data-ready', '0' );
document.body.appendChild( div );
}
}
function applyHiddenSidebar( html ) {
ensureSource();
var wrap = sourceWrap();
if ( !wrap ) { return; }
wrap.innerHTML = '<div class="sidebar-chunk">' + html + '</div>';
wrap.setAttribute( 'data-ready', '1' );
// Gizli kaynak hazır olduktan sonra 📚 çıkarımını dene
try { extractLessonMenu(); } catch ( e ) {}
}
function loadSidebar() {
ensureSource();
var wrap = sourceWrap();
if ( !wrap ) { return; }
if ( wrap.getAttribute( 'data-ready' ) === '1' ) { try { extractLessonMenu(); } catch ( e ) {} return; }
var cached = null;
try { cached = sessionStorage.getItem( cacheKey() ); } catch ( e ) {}
if ( cached ) {
applyHiddenSidebar( cached );
return;
}
fetch( timelessUrl(), { credentials: 'same-origin' } )
.then( function ( r ) { return r.text(); } )
.then( function ( html ) {
var doc = new DOMParser().parseFromString( html, 'text/html' );
var out = extractSidebar( doc );
if ( !out ) { return; }
try { sessionStorage.setItem( cacheKey(), out ); } catch ( e ) {}
applyHiddenSidebar( out );
} )
.catch( function () { /* sessiz geç */ } );
}
/* ================= BAŞLAT ================= */
function boot() {
if ( window.jQuery ) {
initFloatingUI();
} else {
// jQuery henüz yoksa DOMContentLoaded'de tekrar dene
document.addEventListener( 'DOMContentLoaded', initFloatingUI, { once: true } );
}
loadSidebar(); // Gezinti'yi önden, görünmez şekilde yükle
}
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', boot );
} else {
boot();
}
}() );