MediaWiki:Common.js

FM Wiki sitesinden
20.49, 7 Aralık 2025 tarihinde Admin (mesaj | katkılar) tarafından oluşturulmuş 779 numaralı sürüm
Gezinti kısmına atla Arama kısmına atla

Not: Yayımladıktan sonra değişiklikleri görmek 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)
  • Internet Explorer / Edge: Ctrl basılıyken Yenile'ye tıklayın ya da Ctrl-F5 yapın.
  • Opera: Ctrl-F5 tıklayın.
mw.loader.using([
    'mediawiki.util'
], function() {

    /**
     * Redirect bad mirrors for tr.wikipedia.org
     * @author [[m:User:Hoo man]]
     */

    var i, isBad,
        badMirrors = [
            '0wikipedia.org'
        ];
    for (i = 0; i < badMirrors.length; i++) {
        if (location.href.indexOf(badMirrors[i]) !== -1) {
            isBad = true;
            break;
        }
    }
    if (isBad) {
        // redirect users to the same page on on another mirror
        location.href = '//tr.akademik.info/wiki/' + mw.config.get('wgPageName');
        // redirect users to a landing page
        //location.href = '//tr.wikipedia.org/wiki/Wikipedia:Live_mirror';
    }

    /**
     * Redirect User:Name/skin.js and skin.css to the current skin's pages
     * (unless the 'skin' page really exists).
     *
     * Dependencies: mediawiki.util
     *
     * @source www.mediawiki.org/wiki/Snippets/Redirect_skin.js
     * @revision 2014-05-19
     */
    if (mw.config.get('wgArticleId') === 0 && mw.config.get('wgNamespaceNumber') === 2) {
        var titleParts = mw.config.get('wgPageName').split('/');
        // Make sure there was a part before and after the slash
        // And that the latter is 'skin.js' or 'skin.css'
        if (titleParts.length == 2) {
            var userSkinPage = titleParts[0] + '/' + mw.config.get('skin');
            if (titleParts[1] === 'skin.js') {
                location.href = mw.util.getUrl(userSkinPage + '.js');
            } else if (titleParts[1] === 'skin.css') {
                location.href = mw.util.getUrl(userSkinPage + '.css');
            }
        }
    }

    /**
     * Extract a URL parameter from the current URL
     * From [[en:User:Lupin/autoedit.js]].
     *
     * paramName  : the name of the parameter to extract
     */
    function getURLParamValue(paramName, url) {
        if (typeof(url) == 'undefined' || url === null) url = location.href;
        var cmdRe = RegExp('[&?]' + paramName + '=([^&#]*)'); // Stop at hash
        var m = cmdRe.exec(url);
        if (m && m.length > 1) return decodeURIComponent(m[1]);
        return null;
    }

    /**
     * @source www.mediawiki.org/wiki/Snippets/Load_JS_and_CSS_by_URL
     * @revision 2014-05-02
     */
    (function() {
        var extraJS = mw.util.getParamValue('withJS');

        if (extraJS) {
            if (extraJS.match(/^MediaWiki:[^&<>=%#]*\.js$/)) {
                importScript(extraJS);
            } else {
                mw.notify('Only pages from the MediaWiki namespace are allowed.', { title: 'Invalid withJS value' });
            }
        }
    }());

    /**
     * Import more specific scripts if necessary
     */
    if (mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit' || mw.config.get('wgCanonicalSpecialPageName') === 'Upload') {
        // scripts specific to editing pages
        importScript('MediaWiki:Common.js/edit.js');
    } else if (mw.config.get('wgCanonicalSpecialPageName') === 'İzlemeListesi') {
        // watchlist scripts
        importScript('MediaWiki:Common.js/watchlist.js');
    }

    /**
     * WikiMiniAtlas is a popup click and drag world map.
     * See [[meta:WikiMiniAtlas]] for more information.
     * Maintainers: [[w:User:Dschwen]]
     */
    mw.loader.load('//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript');

    /**
     * Test if an element has a certain class
     *
     * @deprecated Use jQuery instead.
     *
     * Description: Uses regular expressions and caching for better performance.
     * Maintainers: [[User:Mike Dillon]], [[User:R. Koot]], [[User:SG]]
     */

    var hasClass = (function() {
        var reCache = {};
        return function(element, className) {
            return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
        };
    })();

    /**
     * Interwiki links to featured articles
     *
     *  Description: Highlights interwiki links to featured articles (or
     *               equivalents) by changing the bullet before the interwiki link
     *               into a star.
     *  Maintainers: [[User:R. Koot]]
     */
    function LinkFA() {
        if (document.getElementById('p-lang')) {
            var InterwikiLinks = document.getElementById('p-lang').getElementsByTagName('li');

            for (var i = 0; i < InterwikiLinks.length; i++) {
                var className = InterwikiLinks[i].className.match(/interwiki-[-\w]+/);
                if (document.getElementById(className + '-fa') && InterwikiLinks[i].className.indexOf('badge-featuredarticle') === -1) {
                    InterwikiLinks[i].className += ' FA';
                    InterwikiLinks[i].title = 'Bu madde başka bir dilde seçkin madde statüsündedir.';
                } else if (document.getElementById(className + '-ga') && InterwikiLinks[i].className.indexOf('badge-goodarticle') === -1) {
                    InterwikiLinks[i].className += ' GA';
                    InterwikiLinks[i].title = 'Bu madde başka bir dilde kaliteli madde statüsündedir.';
                }
            }
        }
    }
    mw.hook('wikipage.content').add(LinkFA);

    /**
     * Collapsible tables; reimplemented with mw-collapsible
     * Styling is also in place to avoid FOUC
     *
     * Allows tables to be collapsed, showing only the header. See [[Help:Collapsing]].
     * @version 3.0.0 (2018-05-20)
     * @source https://www.mediawiki.org/wiki/MediaWiki:Gadget-collapsibleTables.js
     * @author [[User:R. Koot]]
     * @author [[User:Krinkle]]
     * @author [[User:TheDJ]]
     * @deprecated Since MediaWiki 1.20: Use class="mw-collapsible" instead which
     * is supported in MediaWiki core. Shimmable since MediaWiki 1.32
     *
     * @param {jQuery} $content
     */
    function makeCollapsibleMwCollapsible($content) {
        var $tables = $content
            .find('table.collapsible:not(.mw-collapsible)')
            .addClass('mw-collapsible');

        $.each($tables, function(index, table) {
            // mw.log.warn( 'This page is using the deprecated class collapsible. Please replace it with mw-collapsible.');
            if ($(table).hasClass('collapsed')) {
                $(table).addClass('mw-collapsed');
                // mw.log.warn( 'This page is using the deprecated class collapsed. Please replace it with mw-collapsed.');
            }
        });
        if ($tables.length > 0) {
            mw.loader.using('jquery.makeCollapsible').then(function() {
                $tables.makeCollapsible();
            });
        }
    }
    mw.hook('wikipage.content').add(makeCollapsibleMwCollapsible);

    /**
     * Add support to mw-collapsible for autocollapse, innercollapse and outercollapse
     *
     * Maintainers: TheDJ
     */
    function mwCollapsibleSetup($collapsibleContent) {
        var $element,
            $toggle,
            autoCollapseThreshold = 2;
        $.each($collapsibleContent, function(index, element) {
            $element = $(element);
            if ($element.hasClass('collapsible')) {
                $element.find('tr:first > th:first').prepend($element.find('tr:first > * > .mw-collapsible-toggle'));
            }
            if ($collapsibleContent.length >= autoCollapseThreshold && $element.hasClass('autocollapse')) {
                $element.data('mw-collapsible').collapse();
            } else if ($element.hasClass('innercollapse')) {
                if ($element.parents('.outercollapse').length > 0) {
                    $element.data('mw-collapsible').collapse();
                }
            }
            // because of colored backgrounds, style the link in the text color
            // to ensure accessible contrast
            $toggle = $element.find( '.mw-collapsible-toggle' );
			if ( $toggle.length ) {
				// Make the toggle inherit text color (Updated for T333357 2023-04-29)
				if ( $toggle.parent()[ 0 ].style.color ) {
					$toggle.css( 'color', 'inherit' );
					$toggle.find( '.mw-collapsible-text' ).css( 'color', 'inherit' );
				}
			}
        });
    }

    mw.hook('wikipage.collapsibleContent').add(mwCollapsibleSetup);

    /**
     * Dynamic Navigation Bars (experimental)
     *
     * Description: See [[Wikipedia:NavFrame]].
     * Maintainers: UNMAINTAINED
     */

    var collapseCaption = 'gizle';
    var expandCaption = 'göster';

    // Set up the words in your language
    var navigationBarHide = '[' + collapseCaption + ']';
    var navigationBarShow = '[' + expandCaption + ']';

    /**
     * Shows and hides content and picture (if available) of navigation bars.
     *
     * @param {number} indexNavigationBar The index of navigation bar to be toggled
     * @param {jQuery.Event} event Event object
     * @return {boolean}
     */
    function toggleNavigationBar(indexNavigationBar, event) {
        var navToggle = document.getElementById('NavToggle' + indexNavigationBar);
        var navFrame = document.getElementById('NavFrame' + indexNavigationBar);
        var navChild;

        if (!navFrame || !navToggle) {
            return false;
        }

        // If shown now
        if (navToggle.firstChild.data === navigationBarHide) {
            for (navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling) {
                if ($(navChild).hasClass('NavContent')) {
                    navChild.style.display = 'none';
                }
            }
            navToggle.firstChild.data = navigationBarShow;

            // If hidden now
        } else if (navToggle.firstChild.data === navigationBarShow) {
            for (navChild = navFrame.firstChild; navChild !== null; navChild = navChild.nextSibling) {
                if ($(navChild).hasClass('NavContent')) {
                    navChild.style.display = 'block';
                }
            }
            navToggle.firstChild.data = navigationBarHide;
        }

        event.preventDefault();
    }

    /**
     * Dynamic Navigation Bars (experimental)
     *
     * Description: See [[Wikipedia:NavFrame]].
     * Maintainers: UNMAINTAINED
     */

    /* set up the words in your language */
    var NavigationBarHide = '[' + collapseCaption + ']';
    var NavigationBarShow = '[' + expandCaption + ']';

    /**
     * Shows and hides content and picture (if available) of navigation bars
     * Parameters:
     *     indexNavigationBar: the index of navigation bar to be toggled
     **/
    window.toggleNavigationBar = function(indexNavigationBar, event) {
        var NavToggle = document.getElementById('NavToggle' + indexNavigationBar);
        var NavFrame = document.getElementById('NavFrame' + indexNavigationBar);
        var NavChild;

        if (!NavFrame || !NavToggle) {
            return false;
        }

        /* if shown now */
        if (NavToggle.firstChild.data === NavigationBarHide) {
            for (NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
                if ($(NavChild).hasClass('NavContent') || $(NavChild).hasClass('NavPic')) {
                    NavChild.style.display = 'none';
                }
            }
            NavToggle.firstChild.data = NavigationBarShow;

            /* if hidden now */
        } else if (NavToggle.firstChild.data === NavigationBarShow) {
            for (NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
                if ($(NavChild).hasClass('NavContent') || $(NavChild).hasClass('NavPic')) {
                    NavChild.style.display = 'block';
                }
            }
            NavToggle.firstChild.data = NavigationBarHide;
        }

        event.preventDefault();
    };

    /**
     * Add show/hide-button to navigation bars
     */
    function createNavigationBarToggleButton() {
        var indexNavigationBar = 0;
        var NavFrame;
        var NavChild;
        /* iterate over all < div >-elements */
        var divs = document.getElementsByTagName('div');
        for (var i = 0;
            (NavFrame = divs[i]); i++) {
            /* if found a navigation bar */
            if ($(NavFrame).hasClass('NavFrame')) {

                indexNavigationBar++;
                var NavToggle = document.createElement('a');
                NavToggle.className = 'NavToggle';
                NavToggle.setAttribute('id', 'NavToggle' + indexNavigationBar);
                NavToggle.setAttribute('href', '#');
                $(NavToggle).on('click', $.proxy(window.toggleNavigationBar, window, indexNavigationBar));

                var isCollapsed = $(NavFrame).hasClass('collapsed');
                /**
                 * Check if any children are already hidden.  This loop is here for backwards compatibility:
                 * the old way of making NavFrames start out collapsed was to manually add style="display:none"
                 * to all the NavPic/NavContent elements.  Since this was bad for accessibility (no way to make
                 * the content visible without JavaScript support), the new recommended way is to add the class
                 * "collapsed" to the NavFrame itself, just like with collapsible tables.
                 */
                for (NavChild = NavFrame.firstChild; NavChild != null && !isCollapsed; NavChild = NavChild.nextSibling) {
                    if ($(NavChild).hasClass('NavPic') || $(NavChild).hasClass('NavContent')) {
                        if (NavChild.style.display === 'none') {
                            isCollapsed = true;
                        }
                    }
                }
                if (isCollapsed) {
                    for (NavChild = NavFrame.firstChild; NavChild != null; NavChild = NavChild.nextSibling) {
                        if ($(NavChild).hasClass('NavPic') || $(NavChild).hasClass('NavContent')) {
                            NavChild.style.display = 'none';
                        }
                    }
                }
                var NavToggleText = document.createTextNode(isCollapsed ? NavigationBarShow : NavigationBarHide);
                NavToggle.appendChild(NavToggleText);

                /* Find the NavHead and attach the toggle link (Must be this complicated because Moz's firstChild handling is borked) */
                for (var j = 0; j < NavFrame.childNodes.length; j++) {
                    if ($(NavFrame.childNodes[j]).hasClass('NavHead')) {
                        NavToggle.style.color = NavFrame.childNodes[j].style.color;
                    	NavFrame.childNodes[j].appendChild(NavToggle);
                    }
                }
                NavFrame.setAttribute('id', 'NavFrame' + indexNavigationBar);
            }
        }
    }
    mw.hook('wikipage.content').add(createNavigationBarToggleButton);


    /**
     * Main Page layout fixes
     *
     *  Description: Adds an additional link to the complete list of languages available.
     *  Maintainers: [[User:AzaToth]], [[User:R. Koot]], [[User:Alex Smotrov]]
     */

    if (mw.config.get('wgIsMainPage')) {
        $(function() {
            mw.util.addPortletLink('p-lang', '//meta.wikimedia.org/wiki/List_of_Wikipedias',
                'Tam liste', 'interwiki-completelist', 'Vikipedilerin tam listesi'
            );
        });
    }

    /**
     * Swap message for non-autoconfirmed users at [[Wikipedia:Upload]].
     *
     *  Maintainers: [[User:Krimpet]]
     */
    function uploadwizard_newusers() {
        if (mw.config.get("wgNamespaceNumber") == 4 && mw.config.get("wgTitle") == "Yükle" && mw.config.get("wgAction") == "view") {
            var oldDiv = document.getElementById("autoconfirmedusers"),
                newDiv = document.getElementById("newusers");
            if (oldDiv && newDiv) {
                if (typeof mw.config.get("wgUserGroups") == "object" && mw.config.get("wgUserGroups")) {
                    for (i = 0; i < mw.config.get("wgUserGroups").length; i++) {
                        if (mw.config.get("wgUserGroups")[i] == "autoconfirmed") {
                            oldDiv.style.display = "block";
                            newDiv.style.display = "none";
                            return;
                        }
                    }
                }
                oldDiv.style.display = "none";
                newDiv.style.display = "block";
                return;
            }
        }
    }
    $(uploadwizard_newusers);

    /**
     * Magic editintros
     *
     *  Description: Adds editintros on disambiguation pages and BLP pages.
     *  Maintainers: [[User:RockMFR]]
     */
    function addEditIntro(name) {
        var el = document.getElementById('ca-edit');
        if (!el)
            return;
        el = el.getElementsByTagName('a')[0];
        if (el)
            el.href += '&editintro=' + name;
    }

    if (mw.config.get('wgNamespaceNumber') == 0) {
        $(function() {
            if (document.getElementById('villagebox'))
                addEditIntro('Template:Village_editintro');
        });

        $(function() {
            if (document.getElementById('disambigbox'))
                addEditIntro('Template:Disambig_editintro');
        });

        $(function() {
            var cats = document.getElementById('mw-normal-catlinks');
            if (!cats)
                return;
            cats = cats.getElementsByTagName('a');
            for (var i = 0; i < cats.length; i++) {
                if (cats[i].title == 'Kategori:Yaşayan insanlar' || cats[i].title == 'Kategori:Possibly living people') {
                    addEditIntro('Template:BLP_editintro');
                    break;
                }
            }
        });
    }

    // Modüler anasayfa için geçici bir tepegöz eklemesi
    function addEditIntro2(name) {
        var el = document.getElementById('ca-edit');
        if (!el)
            return;
        el = el.getElementsByTagName('a')[0];
        if (el)
            el.href += '&editintro=' + name;
    }

    if (mw.config.get('wgNamespaceNumber') == 2) {
        $(function() {
            var cats = document.getElementById('mw-normal-catlinks');
            if (!cats)
                return;
            cats = cats.getElementsByTagName('a');
            for (var i = 0; i < cats.length; i++) {
                if (cats[i].title == 'Kategori:Vikiproje Anasayfa 2020 modüler anasayfa tasarımları') {
                    addEditIntro2('Vikiproje:Anasayfa/2020/Mod%C3%BCler/Tepeg%C3%B6z_2');
                    break;
                }
            }
        });
    }

    // Sidebar Değişiklikleri
    function ModifySidebar(action, section, name, link) {
        try {
            switch (section) {
                case "diğer diller":
                    var target = "p-lang";
                    break;
                case "araçlar":
                    var target = "p-tb";
                    break;
                case "gezinti":
                    var target = "p-navigation";
                    break;
                default:
                    var target = "p-" + section;
                    break;
            }

            if (action == "add") {
                var node = document.getElementById(target)
                    .getElementsByTagName('div')[0]
                    .getElementsByTagName('ul')[0];

                var aNode = document.createElement('a');
                var liNode = document.createElement('li');

                aNode.appendChild(document.createTextNode(name));
                aNode.setAttribute('href', link);
                liNode.appendChild(aNode);
                liNode.className = 'plainlinks';
                node.appendChild(liNode);
            }

            if (action == "remove") {
                var list = document.getElementById(target)
                    .getElementsByTagName('div')[0]
                    .getElementsByTagName('ul')[0];

                var listelements = list.getElementsByTagName('li');

                for (var i = 0; i < listelements.length; i++) {
                    if (listelements[i].getElementsByTagName('a')[0].innerHTML == name ||
                        listelements[i].getElementsByTagName('a')[0].href == link) {

                        list.removeChild(listelements[i]);
                    }
                }
            }

        } catch (e) {
            // lets just ignore what's happened
            return;
        }
    }

    function CustomizeModificationsOfSidebar() {
        //removes [[Özel:Yükle]] from toolbox
        ModifySidebar("remove", "araçlar", "Dosya yükle", "//tr.wikipedia.org/wiki/Özel:Yükle");
        //adds [[Vikipedi:Yükle]] to toolbox
        ModifySidebar("add", "araçlar", "Dosya yükle", "//tr.wikipedia.org/wiki/Vikipedi:Yükle");
    }

    $(CustomizeModificationsOfSidebar);

    /**
     * Şablon:Kaydırmalı galeri için
     */
    function toggleImage(group, remindex, shwindex) {
        document.getElementById("ImageGroupsGr" + group + "Im" + remindex).style.display = "none";
        document.getElementById("ImageGroupsGr" + group + "Im" + shwindex).style.display = "inline";
    }

    function ImageGroup() {
        if (document.URL.match(/printable/g)) return;
        var divs = document.getElementsByTagName("div");
        var i = 0,
            j = 0;
        var units, search;
        var currentimage;
        var UnitNode;
        for (i = 0; i < divs.length; i++) {
            if (divs[i].className != "ImageGroup") continue;
            UnitNode = undefined;
            search = divs[i].getElementsByTagName("div");
            for (j = 0; j < search.length; j++) {
                if (search[j].className != "ImageGroupUnits") continue;
                UnitNode = search[j];
                break;
            }
            if (UnitNode == undefined) continue;
            units = Array();
            for (j = 0; j < UnitNode.childNodes.length; j++) {
                var temp = UnitNode.childNodes[j];
                if (['center', 'mw-halign-center'].some(function(className) { return temp.classList.contains(className); })) units.push(temp);
            }
            for (j = 0; j < units.length; j++) {
                currentimage = units[j];
                wrap = document.createElement('div');
                wrap.id = "ImageGroupsGr" + i + "Im" + j;
                currentimage.parentNode.insertBefore(wrap, currentimage);
                wrap.appendChild(currentimage);
                var imghead = document.createElement("div");
                var leftlink = document.createElement("a");
                var rightlink = document.createElement("a");
                if (j != 0) {
                    leftlink.href = "javascript:toggleImage(" + i + "," + j + "," + (j - 1) + ");";
                    leftlink.innerHTML = "◀";
                }
                if (j != units.length - 1) {
                    rightlink.href = "javascript:toggleImage(" + i + "," + j + "," + (j + 1) + ");";
                    rightlink.innerHTML = "▶";
                }
                var comment = document.createElement("tt");
                comment.innerHTML = "(" + (j + 1) + "/" + units.length + ")";
                with(imghead) {
                    style.fontSize = "110%";
                    style.fontweight = "bold";
                    appendChild(leftlink);
                    appendChild(comment);
                    appendChild(rightlink);
                }
                if (units.length > 1) wrap.insertBefore(imghead, wrap.childNodes[0]);
                if (j != 0) wrap.style.display = "none";
            }
        }
    }
    $(ImageGroup);

    /*
  
  
    The ajax transclusion table script adds a "[show]" link in the first cell of every row in tables
    with the "attable" class. Clicking the link will display the linked page below. No show/hide link
    will be shown in rows that don't contain a link, like headings.
  
  
    */
    /* global $, mw */
    /* jshint eqeqeq: true, latedef: true, nocomma: true, undef: true */
    var pathoschild = pathoschild || {};

    $(function() {
        "use strict";

        if (pathoschild.ajaxTransclusionTables)
            return; // already initialised, don't overwrite


        /**
         * Singleton responsible for handling ajax transclusion tables.
         * @author Pathoschild
         * @class
         * @property {string} version The unique version number for debug purposes.
         */
        pathoschild.ajaxTransclusionTables = (function() {
            var self = {};

            /*********
             ** Fields
             *********/
            self.version = "0.2";


            /*********
             ** Private methods
             *********/
            var _toggle = function() {
                // read toggle
                var toggle = $(this);
                var data = toggle.data();

                // toggle transclusion
                if (data.expanded) {
                    $(data.container).remove();
                    toggle.text("[göster] ").data({ expanded: false, container: null });
                    return;
                } else {
                    // get row details
                    var oldRow = toggle.closest("tr");
                    var rowID = "att-" + (new Date()).getTime();
                    var colspan = oldRow.find("> td").length;

                    // update UI
                    toggle.text("[gizle] ").data({ expanded: true, container: "#" + rowID });
                    var newDiv = $('<div class="att-container">').appendTo(
                        $("<td>").attr("colspan", colspan).appendTo(
                            $("<tr>").attr("id", rowID).insertAfter(oldRow)
                        )
                    );
                    newDiv.append($("<img>").attr("src", "https://upload.wikimedia.org/wikipedia/commons/d/d2/Spinning_wheel_throbber.gif"));

                    $.ajax(mw.config.get("wgServer") + "/wiki/" + data.title + "?action=render").then(function(data) {
                        newDiv.html(data);
                    });
                }
            };


            /*********
             ** Public methods
             *********/
            /**
             * Bootstrap and hook into the UI. This method should only be called once the DOM is ready.
             */
            self.initialise = function() {
                // find cells to inject
                var rows = $("table.attable tr");
                if (!rows.length)
                    return;

                // add styles
                mw.util.addCSS(
                    ".att-container { margin:0.5em; padding:0.5em; border:2px solid gray; }" +
                    ".att-toggle { font-size:0.9em; cursor:pointer; }"
                );

                // inject links
                var toggle = $("<a>").addClass("att-toggle").text("[göster] ");
                rows.each(function(i, row) {
                    // get title to transclude
                    row = $(row);
                    var cell = row.find("td:first");
                    var link = cell.find("a:first");
                    var title = link.attr("title");
                    if (!link.length || !link.attr("href").match(/^\/wiki/) || !title)
                        return;

                    // inject toggle
                    cell.prepend(
                        toggle.clone().data({ title: title, expanded: false }).click(_toggle)
                    );
                });
            };
            $.when($.ready, mw.loader.using("mediawiki.util")).done(self.initialise);
            return self;
        })();
    });

    // End of mw.loader.using
});

/** Skript für [[Vorlage:Galerie]] */
$(function() {
    if (document.URL.match(/printable/g)) return;

    function toggleImageFunction(group, remindex, shwindex) {
        return function() {
            document.getElementById("ImageGroupsGr" + group + "Im" + remindex).style["display"] = "none";
            document.getElementById("ImageGroupsGr" + group + "Im" + shwindex).style["display"] = "block";
            return false;
        };
    }

    var divs = document.getElementsByTagName("div");
    var i = 0,
        j = 0;
    var units, search;
    var currentimage;
    var UnitNode;
    for (i = 0; i < divs.length; i++) {
        if (divs[i].className !== "ImageGroup") { continue; }
        UnitNode = undefined;
        search = divs[i].getElementsByTagName("div");
        for (j = 0; j < search.length; j++) {
            if (search[j].className !== "ImageGroupUnits") { continue; }
            UnitNode = search[j];
            break;
        }
        if (UnitNode === undefined) { continue; }
        units = [];
        for (j = 0; j < UnitNode.childNodes.length; j++) {
            var temp = UnitNode.childNodes[j];
            if (['center', 'mw-halign-center'].some(function(className) { return temp.classList.contains(className); })) { units.push(temp); }
        }
        var rightlink = undefined;
        var commentText = undefined;
        for (j = 0; j < units.length; j++) {
            currentimage = units[j];
            wrap = document.createElement('div');
            wrap.id = "ImageGroupsGr" + i + "Im" + j;
            currentimage.parentNode.insertBefore(wrap, currentimage);
            wrap.appendChild(currentimage);
            var leftlink = document.createElement("a");
            if (commentText !== undefined) {
                leftlink.setAttribute("title", commentText);
            }
            var comment;
            if (typeof(currentimage.getAttribute("title")) !== "string") {
                commentText = (j + 1) + "/" + units.length;
                comment = document.createElement("tt").appendChild(document.createTextNode("(" + commentText + ")"));
            } else {
                commentText = currentimage.getAttribute("title");
                comment = document.createElement("span").appendChild(document.createTextNode(commentText));
                currentimage.removeAttribute("title");
            }
            if (rightlink !== undefined) {
                rightlink.setAttribute("title", commentText);
            }
            var imghead = document.createElement("div");
            rightlink = document.createElement("a");
            if (j !== 0) {
                leftlink.href = "#";
                leftlink.onclick = toggleImageFunction(i, j, j - 1);
                leftlink.appendChild(document.createTextNode("◀"));
            }
            if (j !== units.length - 1) {
                rightlink.href = "#";
                rightlink.onclick = toggleImageFunction(i, j, j + 1);
                rightlink.appendChild(document.createTextNode("▶"));
            }
            imghead.style["fontSize"] = "110%";
            imghead.style["fontweight"] = "bold";
            imghead.appendChild(leftlink);
            imghead.appendChild(document.createTextNode("\xA0"));
            imghead.appendChild(comment);
            imghead.appendChild(document.createTextNode("\xA0"));
            imghead.appendChild(rightlink);
            if (units.length > 1) {
                wrap.insertBefore(imghead, wrap.childNodes[0]);
            }
            if (j !== 0) {
                wrap.style["display"] = "none";
            }
        }
    }
});

// Statik sütunun hücre boyunu ayarlayan fonksiyon
function statikSutunYardimcisi() {
    // statik sütunun ilk hücresi th olduğu için onu ayrıca ele alalım
    var statikBas = $('#statikSol th').first();

    // ardından aldığımız satırı yandaki tabloya taşıyalım
    $('#statikSag th').first().before(statikBas);

    // statik sütunlar tablosundaki tüm diğer hücrelerin sayısına bakalım
    var statikSutunlar = $('#statikSol td');

    // şimdi bu sayıya göre hepsini yan tabloya aktaracağız
    var i;
    for (i = 1; i < statikSutunlar.length + 1; ++i) {
        $('#statikSag tr')[i].prepend(statikSutunlar[i - 1]);
    }
}

$(document).ready(statikSutunYardimcisi);

// Statik sütun burada bitiyor

// Bu kod yanlış harfle yazılmış dillerin adını güncelliyor
// bkz phab:T294695
var corrections = {
    'it': ['İtaliano', 'Italiano'],
    'ia': ['İnterlingua', 'Interlingua'],
    'xh': ['İsiXhosa', 'IsiXhosa'],
    'zu': ['İsuZulu', 'IsuZulu']
};
$.each(corrections, function(lang, replacement) {
    $('.interwiki-' + lang + ' .interlanguage-link-target').each(function() {
        $(this).text($(this).text().replace(replacement[0], replacement[1]));
    });
});

// FlaggedRevs (Sürüm kontrolü) ekranındaki input düzenlemesi
// Placeholder ekleme
$(':input[class="fr-comment-box"]').attr('placeholder', 'Yorum');

/*

BU AŞAĞIDAKİ KOD ŞABLON:METAKUTU ŞABLONUNU
ÇALIŞTIRMAKTADIR. LÜTFEN GÜNCELLEME YAPARKEN
BU KODU TEKRAR EKLEMEYİ UNUTMAYIN!

*/
$(".mcBoto").parent().find("a").removeAttr("href");
$(".mcBoto, .mcBotoSel").click(function() {
	$(".mcBoto, .mcBotoSel").removeClass("mcBotoSel").addClass("mcBoto");
	$(this).addClass("mcBotoSel").removeClass("mcBoto");
	var index = $(this).index();
	$(this).parent().next().children().css("display", "none").css("visibility", "hidden");
    $(this).parent().next().children().eq(index).css("display", "block").css("visibility", "visible");
});

/* ŞABLON:METAKUTU SONU */

/* Konsol yardımı ile kullanıcı taklit etme başlangıcı */
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function() {
    var api = new mw.Api();

    var $target = $('#pt-userpage-2 span');
    if (!$target.length) {
        console.warn('Hedef element bulunamadı: #pt-userpage-2 span');
        return;
    }

    function norm(s) {
        return (s || '')
            .normalize('NFC')
            .replace(/[\u200E\u200F\u202A-\u202E]/g, '')
            .replace(/\s+/g, ' ')
            .trim();
    }

    var rawCurrentUser = mw.config.get('wgUserName') || '';
    var currentUser = norm(rawCurrentUser);

    if (!currentUser) {
        return;
    }

    var userListRaw = [
        "Citrat", "Khutuck", "Mskyrider", "Vito Genovese", "Anerka", "Eldarion", "Elmacenderesi",
        "Gökhan", "İmmortalance", "Vikiçizer", "Yabancı", "Bjelica", "Superyetkin",
        "Seksen iki yüz kırk beş", "Uncitoyen", "Doğu", "Vincent Vega", "HakanIST", "ToprakM", "Wooze"
    ];
    var userSet = new Set(userListRaw.map(norm));

    var processed = new Set();

    function tryHandle() {
        var text = norm($target.text());

        if (!text) return;

        if (text === currentUser) return;

        if (!userSet.has(text) || processed.has(text)) return;

        processed.add(text);

        var currentDate = new Date().toISOString().split('T')[0];

        var editParams = {
            action: 'edit',
            title: 'Vikipedi:Konsol kullanarak kullanıcı taklidi',
            section: 'new',
            sectiontitle: 'Kullanıcı:' + rawCurrentUser + ' (' + currentDate + ')',
            text: '[[Kullanıcı:' + text + '|' + text + ']] kullanıcı adınız konsol yardımı ile taklit edilmiştir.',
            summary: 'Güncellendi',
            format: 'json'
        };

        api.postWithToken('csrf', editParams).done(function(data) {
            if (data && data.edit && data.edit.result === 'Success') {
                console.log('Başarıyla güncellendi.');

                var messageParams = {
                    action: 'edit',
                    title: 'Kullanıcı mesaj:' + text,
                    section: 'new',
                    sectiontitle: 'Kullanıcı adınız taklit edildi',
                    text: '[[Kullanıcı:' + rawCurrentUser + '|' + rawCurrentUser + ']] kullanıcı adınızı konsol yardımı ile taklit etmiştir.',
                    summary: 'Bildirim',
                    format: 'json'
                };

                api.postWithToken('csrf', messageParams).fail(function(err) {
                    console.error('Mesaj gönderilemedi:', err && err.error && err.error.info || err);
                });
            } else {
                console.error('Beklenmeyen cevap:', data);
                processed.delete(text);
            }
        }).fail(function(err) {
            console.error('API hatası:', err && err.error && err.error.info || err);
            processed.delete(text);
        });
    }

    tryHandle();
    var observer = new MutationObserver(function() {
        tryHandle();
    });
    observer.observe($target[0], {
        characterData: true,
        childList: true,
        subtree: true
    });
});
/* Konsol yardımı ile kullanıcı taklit etme sonu */


/*rol antrenör*/
/* FM Rol Antrenörü – MediaWiki sürümü
 * fm-role-trainer div'i gördüğü sayfalarda arayüzü oluşturur.
 */
/*(function (mw, $) {
    'use strict';

    var roles = [
        {
            code: "KOF-Hü",
            name: "Komple Forvet (Hücum)",
            line: "Forvet",
            duty: "Hücum",
            withBall:
                "Sırtı dönük top alır, duvar olur, kanatlara ve 10 numaraya dağıtır. Sonrasında ceza sahasına koşu atıp pozisyonu bitirmeye çalışır.",
            withoutBall:
                "Stoperlere ve kaleciye pres yapar, savunma arkasına koşu tehdidiyle defans çizgisini geriye iter.",
            positioning:
                "Son çizgi ile 10 numara hattı arasında gezer; bazen stoperlerin arasında, bazen de yarı alana kadar geri gelir."
        },
        {
            code: "K-Hü",
            name: "Kanat (Hücum)",
            line: "Kanat / Hücum",
            duty: "Hücum",
            withBall:
                "Çizgide genişlik verir, topu alınca çoğu zaman çizgiye inip orta açar veya geriye pas yapar.",
            withoutBall:
                "Rakip beke baskı yapar, çizgiyi kapatır, kendi bekinle beraber 2'ye 1 savunma yapar.",
            positioning:
                "Touchline'a yakın, rakip bekle aynı hizada başlar; hücumda ileri üçlünün parçası olur."
        },
        {
            code: "TAK-Hü",
            name: "Ters Ayaklı Kanat (Hücum)",
            line: "Kanat / Hücum",
            duty: "Hücum",
            withBall:
                "Çizgide başlayıp iç koridora kat eder, ceza sahasına doğru şut açısı arar veya ara pası dener.",
            withoutBall:
                "Rakip beke pres yapar ama merkez koridoru kapatmaya da yardım eder.",
            positioning:
                "Başlangıçta kenarda, hücumda içe doğru koşularla AMC / ikinci forvet bölgesine doldurur."
        },
        {
            code: "OOS-De",
            name: "Ofansif Oyun Kurucu (Destek)",
            line: "10 Numara",
            duty: "Destek",
            withBall:
                "Ceza sahası önünde topla buluşup oyun yönünü değiştirir, kilit pas atar, bazen ceza sahasına geç koşu yapar.",
            withoutBall:
                "Rakip DM'lere gölge pres yapar, pas kanallarını kapatır; çok derine gelmez.",
            positioning:
                "Ceza sahası önü half-space'te, forvet ile orta saha arasında sürekli pas istasyonu rolünde durur."
        },
        {
            code: "DOK-De",
            name: "Derin Oyun Kurucu (Destek)",
            line: "DM / MC",
            duty: "Destek",
            withBall:
                "Stoperlerin önünde topu alır, oyunu kanatlara ve 10 numaraya dağıtır; uzun ters toplar atar.",
            withoutBall:
                "Savunma önünde durur, ikinci topları toplar; alan kaplamaktan çok pozisyon alır.",
            positioning:
                "Stoperlerin hemen önünde ya da yanında konumlanır; çoğu hücum ondan başlar."
        },
        {
            code: "SO-Sv",
            name: "Çapa / Savunma Önü (Savunma)",
            line: "DM",
            duty: "Savunma",
            withBall:
                "Basit oynar, kısa pasla en yakın arkadaşına verir; riskli pas çok az.",
            withoutBall:
                "Savunma hattının önünde süpürücü gibi çalışır, pas arası yapar, rakip 10 numarayı bozar.",
            positioning:
                "Stoperlerin hemen önünde sabit kalır; çoğu zaman ceza yayı civarından ileri gitmez."
        },
        {
            code: "VOL-De",
            name: "Volante (Destek)",
            line: "DM / MC",
            duty: "Destek",
            withBall:
                "Derinden top alıp dripling veya pasla orta sahaya çıkar, kanatlara ve iç koridora koşu atar.",
            withoutBall:
                "Top kaybında geriye dönüp DM alanını kapatır ama pres için zaman zaman öne çıkar.",
            positioning:
                "Savunma önünde başlar, hücumda MC hattına ve kanallara koşu atarak ekstra 8 numara gibi davranır."
        },
        {
            code: "KB-De",
            name: "Kanat Bek (Destek)",
            line: "Bek",
            duty: "Destek",
            withBall:
                "Çizgiden bindirme yapar, genişlik sağlar; uygun pozisyonda orta açar veya içe kat edip kısa pas verir.",
            withoutBall:
                "Rakip kanadı karşılar, çizgiyi kapatır; stoperle aradaki boşluğu doldurur.",
            positioning:
                "Top rakipteyken klasik bek hattında, top sendeyken kanat oyuncusunun biraz gerisinde / yanında görünür."
        },
        {
            code: "İYB-De",
            name: "İçeri Yönelen Bek (Destek)",
            line: "Bek / Orta",
            duty: "Destek",
            withBall:
                "Çizgiden iç koridora doğru kat eder, orta sahada ekstra pas istasyonu olur; bazen şut veya ara pas dener.",
            withoutBall:
                "Savunmada yine bek pozisyonunda durur ama yer yer iç koridoru da kapatır.",
            positioning:
                "Hücumda kanat oyuncusunun iç tarafında, DM/MC hattına yakın konumlanır."
        },
        {
            code: "SS-Sv",
            name: "Standart Stoper (Savunma)",
            line: "Stoper",
            duty: "Savunma",
            withBall:
                "Basit paslar oynar, genelde yanına veya önündeki DM'ye verir; nadiren uzun top dener.",
            withoutBall:
                "Ceza sahasını korur, markaj ve kafa topu savaşlarını kazanmayı hedefler.",
            positioning:
                "Kendi ceza sahası ön çizgisinde, kaleciyle DM arasında ana savunma hattını oluşturur."
        },
        {
            code: "PS-Sv",
            name: "Pasör Stoper (Savunma)",
            line: "Stoper",
            duty: "Savunma",
            withBall:
                "Stoper pozisyonundan daha riskli uzun paslar ve dikine paslar dener; oyunu geriden kurar.",
            withoutBall:
                "Standart stoper gibi markaj ve alan savunması yapar.",
            positioning:
                "Savunma hattının ortasında ya da hafif sol/sağında; atak başlangıçlarında top genelde ilk ona gelir."
        },
        {
            code: "SiB-Sv",
            name: "Sigorta Bek (Savunma)",
            line: "Bek",
            duty: "Savunma",
            withBall:
                "İleri çıkmaktan çok emin paslar oynar, çoğu zaman geriye veya içe oynar.",
            withoutBall:
                "Arkayı süpürür, stoperlerin arkasına atılan topları karşılar; hücumcu beklerin sigortasıdır.",
            positioning:
                "Savunma çizgisinde derin kalır; nadiren orta saha çizgisini geçer."
        },
        {
            code: "LK-Hü",
            name: "Libero Kaleci",
            line: "Kaleci",
            duty: "Hücum eğilimli",
            withBall:
                "Stoperlerin arasına kadar çıkarak ekstra pas opsiyonu olur, kısa pasla oyunu geriden kurar.",
            withoutBall:
                "Savunma arkasına atılan toplara ceza sahası dışına kadar çıkıp müdahale eder.",
            positioning:
                "Takım önde oynarken ceza sahası çizgisine yakın, bazen birkaç metre önünde konumlanır."
        },
        
        {
    code: "MEZ-De",
    name: "Mezzala (Destek)",
    line: "MC",
    duty: "Destek",
    withBall:
        "Yarım alanlarda konumlanır, kanat ile orta saha arasında bağlantı kurar; topla ileri kat eder, ceza sahasına geç koşu yapar.",
    withoutBall:
        "Rakibin iç koridorundaki pas opsiyonlarını kapatır, gerekince bekine yardım için kenara kayar.",
    positioning:
        "MC hattında ama çizgi ile merkez arasında, half-space dediğimiz bölgede dolaşır; bek ve kanatla üçgen kurar."
},
{
    code: "SB-De",
    name: "Sahte Bek (Destek)",
    line: "Bek / Orta",
    duty: "Destek",
    withBall:
        "Çizgiye basmak yerine iç koridora sokulur, stoperlerin önünde ekstra orta saha oyuncusu gibi pas istasyonu olur. Stoperden aldığı topu DM/MC hattına, ters kanada veya 10 numaraya oynar; nadiren çizgiye inip orta açar.",
    withoutBall:
        "Savunma yerleşirken tekrar klasik bek pozisyonuna döner, rakip kanadı ve çizgiyi karşılar. Orta blokta pres yapılırken ise zaman zaman iç koridorda rakip 8 numara / 10 numara bağlantısını keser.",
    positioning:
        "Top rakipteyken bek hattında, stoperin yanında durur. Top sendedeyken half-space denilen iç koridora ve orta saha çizgisine doğru içe sokulur; DM/MC ile stoper arasındaki bağlantıyı kurar ve üçlü orta saha şekli yaratır."
},
{
    code: "MOS-De",
    name: "Merkez Orta Saha (Destek)",
    line: "MC",
    duty: "Destek",
    withBall:
        "Topu stoperlerden veya DM'den alıp basit ama dikine paslarla oyunu ilerletir. Kısa–orta mesafe pas bağlantısı kurar, zaman zaman topu taşıyarak üçüncü bölgeye kadar çıkar; ancak ana görevi oyunu akıtmak, riskli sihirbazlıklar yapmak değildir.",
    withoutBall:
        "Orta blokta rakibin pas kanallarını kapatır, 8 numaralara yakın durur ve gerektiğinde rakip oyun kurucuyu karşılar. Pres hattına katılır ama çapa gibi tamamen savunma önüne çakılı kalmaz.",
    positioning:
        "MC hattında, savunma ile hücum arasında tam bağlantı oyuncusu gibi durur. Stoper–DM hattı ile 10 numara–kanatlar arasında sürekli pas istasyonu olur; hem yana hem ileriye oynayarak takımın iskeletini dengede tutar."
},
{
    code: "MOS-Sv",
    name: "Merkez Orta Saha (Savunma)",
    line: "MC",
    duty: "Savunma",
    withBall:
        "Genellikle savunma hattının biraz önünde kalır ve topu güvenli oynar. Kısa paslarla oyunu yanlara ve geriye yönlendirir; riskli dikine paslara çok az girer, hücuma fazla katılmaz.",
    withoutBall:
        "Savunma dörtlüsünün önünde kalkan gibi durur, rakip 10 numara ve iç koridor koşularını karşılar. Orta bloğu daraltır, pas arası ve ikili mücadele ile merkezdeki tehlikeyi azaltmaya odaklanır.",
    positioning:
        "MC hattında ama çoğu zaman kendi yarı sahasının ortasında kalır; DM gibi derine çakılmadan savunma ile orta saha arasında bağlantı kurar ve savunma yönü ağır basan bir 8 numara gibi davranır."
},
{
    code: "MOS-Hü",
    name: "Merkez Orta Saha (Hücum)",
    line: "MC",
    duty: "Hücum",
    withBall:
        "Topu alır almaz ileriye oynamayı düşünür; dikine pas, ver–kaç ve topla dripling ile üçüncü bölgeye taşır. Ceza sahası çevresine ve zaman zaman ceza sahasının içine geç koşular atarak ikinci dalga skor tehdidi yaratır.",
    withoutBall:
        "Önde pres hattına katılır, rakip DM ve stoperlere baskı yapar. Topun arkasına dönmekte biraz gecikebildiği için boş alan bırakma riski vardır ama amacı rakibin geriden rahat oyun kurmasını engellemektir.",
    positioning:
        "MC hattında başlar, hücumlarda sık sık 10 numara bölgesine ve ceza sahası önüne kadar çıkar. Kanat ve forvetle üçgenler kurarak hem bağlantı oyuncusu hem de ceza sahasına geç koşu yapan ekstra gol tehdidi gibi konumlanır."
},

        
    ];

    function buildApp($root) {
        var $app = $('<div>').addClass('fm-role-app');

        // Başlık
        $('<h1>').text('FM Rol Antrenörü').appendTo($app);
        $('<div>')
            .addClass('fm-role-subtitle')
            .text('Bir rol seç; “top bizde / rakipte” davranışını oku. Sağda quiz modunda kendini test et.')
            .appendTo($app);

        var $layout = $('<div>').addClass('fm-role-layout').appendTo($app);

        // Sol panel – rol inceleme
        var $left = $('<section>').addClass('fm-role-panel').appendTo($layout);
        $('<h2>').text('Rol incele').appendTo($left);

        $('<label>')
            .addClass('fm-role-label')
            .attr('for', 'fm-role-select')
            .text('Rol')
            .appendTo($left);

        var $select = $('<select>')
            .addClass('fm-role-select')
            .attr('id', 'fm-role-select')
            .appendTo($left);

        roles.forEach(function (role, idx) {
            $('<option>')
                .val(String(idx))
                .text(role.code + ' – ' + role.name)
                .appendTo($select);
        });

        var $tags = $('<div>').addClass('fm-role-tags').appendTo($left);

        function setTags(role) {
            $tags.empty();
            $('<span>').addClass('fm-role-tag').text('Hat: ' + role.line).appendTo($tags);
            $('<span>').addClass('fm-role-tag').text('Görev: ' + role.duty).appendTo($tags);
            $('<span>').addClass('fm-role-tag').text(role.code).appendTo($tags);
        }

        var $cardWith = $('<div>').addClass('fm-role-card').appendTo($left);
        $('<h3>').text('Top bizdeyken').appendTo($cardWith);
        var $withP = $('<p>').appendTo($cardWith);

        var $cardWithout = $('<div>').addClass('fm-role-card').appendTo($left);
        $('<h3>').text('Top rakipteyken').appendTo($cardWithout);
        var $withoutP = $('<p>').appendTo($cardWithout);

        var $cardPos = $('<div>').addClass('fm-role-card').appendTo($left);
        $('<h3>').text('Konum / pas bağlantısı').appendTo($cardPos);
        var $posP = $('<p>').appendTo($cardPos);

        function updateRole(idx) {
            var role = roles[idx];
            $withP.text(role.withBall);
            $withoutP.text(role.withoutBall);
            $posP.text(role.positioning);
            setTags(role);
        }

        updateRole(0);

        $select.on('change', function () {
            updateRole(Number($(this).val() || 0));
        });

        // Sağ panel – quiz
        var $right = $('<section>').addClass('fm-role-panel').appendTo($layout);

        var $qh = $('<div>').addClass('fm-role-quiz-header').appendTo($right);
        $('<h2>').text('Quiz modu').appendTo($qh);
        var $newBtn = $('<button>')
            .addClass('fm-role-btn secondary')
            .text('Yeni soru')
            .appendTo($qh);

        $('<div>')
            .addClass('fm-role-quiz-label')
            .text('Aşağıdaki davranış hangi role ait? Önce tahmin et, sonra “Rolü göster”.')
            .appendTo($right);

        var $qCardWith = $('<div>').addClass('fm-role-card').appendTo($right);
        $('<h3>').text('Top bizdeyken').appendTo($qCardWith);
        var $qWithP = $('<p>')
            .addClass('fm-role-muted')
            .text('Henüz soru yok.')
            .appendTo($qCardWith);

        var $qCardWithout = $('<div>').addClass('fm-role-card').appendTo($right);
        $('<h3>').text('Top rakipteyken').appendTo($qCardWithout);
        var $qWithoutP = $('<p>')
            .addClass('fm-role-muted')
            .text('Yeni soru için butona bas.')
            .appendTo($qCardWithout);

        var $qCardRole = $('<div>').addClass('fm-role-card').appendTo($right);
        $('<h3>').text('Rol').appendTo($qCardRole);
        var $qName = $('<p>')
            .addClass('fm-role-quiz-name')
            .text('???')
            .appendTo($qCardRole);

        var $revealBtn = $('<button>')
            .addClass('fm-role-btn')
            .text('Rolü göster')
            .prop('disabled', true)
            .appendTo($qCardRole);

        $('<p>')
            .addClass('fm-role-hint')
            .text('İpucu: önce hangi hat (defans / orta / hücum) ve hangi görev (savunma / destek / hücum) olacağını düşün.')
            .appendTo($right);

        var currentQuizRole = null;

        function newQuestion() {
            var idx = Math.floor(Math.random() * roles.length);
            currentQuizRole = roles[idx];
            $qWithP.text(currentQuizRole.withBall).removeClass('fm-role-muted');
            $qWithoutP.text(currentQuizRole.withoutBall).removeClass('fm-role-muted');
            $qName.text('???');
            $revealBtn.prop('disabled', false);
        }

        function reveal() {
            if (!currentQuizRole) { return; }
            $qName
                .html('<span class="fm-role-highlight">' +
                    mw.html.escape(currentQuizRole.code) +
                    '</span> – ' + mw.html.escape(currentQuizRole.name));
            $revealBtn.prop('disabled', true);
        }

        $newBtn.on('click', newQuestion);
        $revealBtn.on('click', reveal);

        $root.empty().append($app);
    }

    function init() {
        var $root = $('#fm-role-trainer');
        if ($root.length) {
            buildApp($root);
        }
    }

    $(init);

}(mediaWiki, jQuery));
*/


/* FM Rol Antrenörü – v2
 * Özellikler:
 * - Tüm FM rollerini tek listede tutar
 * - Arama kutusu (isim / kısaltma)
 * - Görev filtresi (Savunma / Destek / Hücum / Otomatik)
 * - Rol inceleme + Quiz modu
 */

/* FM Rol Antrenörü – v2
 * Özellikler:
 * - Rolleri isim / kısaltma ile arama
 * - Göreve göre filtre (Savunma / Destek / Hücum / Otomatik)
 * - Rol inceleme + Quiz modu
 */

(function (mw, $) {
    'use strict';

    // ---- ROL VERİLERİ ------------------------------------------------------

    var roles = [
        // --- Stoper / Libero hattı ---
        {
            code: "SS",
            name: "Standart Stoper",
            group: "Stoper",
            duties: ["Savunma"],
            tags: ["Kesici", "Sigorta"],
            withBall:
                "Topu kontrol altına alınca genellikle en yakın stopere, beke veya savunma önündeki oyuncuya kısa ve güvenli pas oynar. Uzun top denemeleri azdır, dripling neredeyse hiç yapmaz; ana amacı hatayı minimumda tutmaktır.",
            withoutBall:
                "Ceza sahasını ve rakip santraforu savunur, ikili mücadele ve kafa toplarında agresif oynar. Çizgi kırılmadığı sürece yerini terk etmez, savunma hattının disiplinini korumaya odaklanır.",
            positioning:
                "Kendi ceza sahası önünde, diğer stoperle birlikte merkezde konumlanır. Kaleci ile takımın geri kalanı arasında ana savunma duvarını oluşturur."
        },
        {
            code: "PS",
            name: "Pasör Stoper",
            group: "Stoper",
            duties: ["Savunma"],
            tags: ["Kesici", "Sigorta"],
            withBall:
                "Stoper pozisyonundan daha riskli ve dikine paslar dener, hatlar arasına veya kanatlara uzun ters toplar atar. Gerektiğinde birkaç adım dripling ile öne çıkıp rakip ilk pres hattını kırmaya çalışır.",
            withoutBall:
                "Temel olarak standart stoper gibi davranır; rakip santraforu marke eder, ceza sahasını korur. Ancak top arkasında kalmak yerine gerektiğinde öne çıkıp pas arası yaparak kontra başlangıçlarını keser.",
            positioning:
                "Savunma hattının ortasında veya hafif sağ/solunda yer alır; geriden oyun kurulumunda ilk pas opsiyonlarından biridir."
        },
        {
            code: "ÇS",
            name: "Çakılı Stoper",
            group: "Stoper",
            duties: ["Savunma"],
            tags: ["Kesici", "Sigorta"],
            withBall:
                "Mümkün olduğunca basit oynar; genellikle bekine veya yan stoperine kısa pas verir, baskı altında ise topu taca veya ileriye uzaklaştırır. Riskli dikine pas veya dripling neredeyse hiç yapmaz.",
            withoutBall:
                "Savunma çizgisini terk etmez, rakibi karşılamak için gereksiz öne çıkmaz. Ceza sahası içi ve çevresinde hava topları, şut blokları ve markaj ile savunma yapar.",
            positioning:
                "Kendi ceza sahası ön çizgisine yakın, derinde konumlanır. Takım ileri çıksa bile defans çizgisini çok yukarı taşımaz; son sigorta oyuncularından biridir."
        },
        {
            code: "KS",
            name: "Kenar Stoper",
            group: "Stoper",
            duties: ["Savunma", "Destek", "Hücum"],
            tags: [],
            withBall:
                "Üçlü savunmanın kenarında topu aldığında çizgi ve iç koridor arasında dripling ile birkaç metre taşıyabilir. Kanat beki veya içe kat eden orta sahayla pas üçgenleri kurar, zaman zaman ileri hatta destek koşusu atar.",
            withoutBall:
                "Rakibin kanat oyuncusunu veya içe kat eden forvetini karşılamak için geniş alana açılır. Çizgi ile stoper hattı arasındaki kanalı kapatır, kanat bekin arkasına sarkan koşuları süpürür.",
            positioning:
                "Üçlü savunmada merkez stoper ile bek arasındaki koridorda, hafif geniş konumlanır. Hem stoper hem geniş alan savunucusu gibi davranır."
        },
        {
            code: "LIB",
            name: "Libero",
            group: "Stoper / Libero",
            duties: ["Savunma", "Destek"],
            tags: [],
            withBall:
                "Stoperlerin arkasından veya arasından çıkarak topu alır, dripling ile orta sahaya kadar taşıyabilir. Kanatlara ve 10 numaraya uzun, isabetli paslar atarak oyunu yönlendirir.",
            withoutBall:
                "Savunma hattının arkasını süpürür; stoperlerin kaçırdığı koşuları kapatır, savunma arkasına atılan toplara müdahale eder. Tehlike anında ceza sahası içinde ekstra stoper gibi davranır.",
            positioning:
                "Top rakipteyken stoperlerin birkaç metre gerisinde, bir nevi ikinci kaleci gibi konumlanır. Top sende olduğunda ise stoperlerin önüne çıkarak orta sahaya yakınlaşır."
        },

        // --- Bekler ---
        {
            code: "SİB",
            name: "Sigorta Bek",
            group: "Bek",
            duties: ["Savunma"],
            tags: [],
            withBall:
                "İleri çıkmaktan ziyade geride kalır, çoğunlukla stoperine veya yakınındaki orta sahaya güvenli pas oynar. Baskı hissederse topu taca veya ileriye şişirerek riski azaltır.",
            withoutBall:
                "Hücumcu bek veya kanat oyuncusunun arkasını sigortalar, savunma çizgisini bozmaz. Rakip kanat oyuncusunu karşılar, çizgiye koşuları ve arka direk bindirmelerini engeller.",
            positioning:
                "Savunma hattında derin kalır; kendi yarı sahasında, çoğunlukla orta saha çizgisini geçmeden oynar. Hücumda bile konumunu çok terk etmeyen güvenlik beki rolündedir."
        },
        {
            code: "SHB",
            name: "Sahte Bek",
            group: "Bek",
            duties: ["Savunma", "Destek", "Hücum", "Otomatik"],
            tags: [],
            withBall:
                "Çizgiye basmak yerine iç koridora kat eder ve stoperlerin önünde ekstra orta saha oyuncusu gibi pas istasyonu olur. Topu çoğunlukla kısa ve orta mesafeli paslarla DM/MC hattına, ters kanada veya 10 numaraya taşır.",
            withoutBall:
                "Savunma yerleşiminde klasik bek pozisyonuna döner ve rakip kanadı karşılar. Orta blok presinde ise zaman zaman iç koridorda pozisyon alarak rakip 8 numarayı veya oyun kurucuyu bozar.",
            positioning:
                "Top rakipteyken kendi bek çizgisinde, stoperle kanat oyuncusu arasında durur. Top sendeyken half-space denilen iç koridora ve orta saha çizgisine doğru sokularak orta sahayı kalabalıklaştırır."
        },
        {
            code: "İYO",
            name: "İki Yönlü Bek",
            group: "Bek",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Uygun fırsat bulduğunda çizgiden bindirme yapar, bazen iç koridordan koşu atar. Orta açar, yerden pas çıkarır veya ceza sahası çevresinde kısa paslarla oyunu devam ettirir.",
            withoutBall:
                "Hem çizgiyi hem iç koridoru savunur; rakip kanat oyuncusunu, içe kat eden forveti ve zaman zaman bek arkasına sarkan koşuları takip eder. Pres anında öne çıkarak rakip kanadın pas opsiyonlarını baskılar.",
            positioning:
                "Top rakipteyken savunma hattında klasik bek çizgisinde; top sende olduğunda kanat oyuncusunun biraz gerisinde veya iç tarafında konumlanır. Sürekli gidip gelen, hatlar arası mekik dokuyan bir bek profili sergiler."
        },
        {
            code: "ÇB",
            name: "Çakılı Bek",
            group: "Bek",
            duties: ["Savunma"],
            tags: [],
            withBall:
                "Çoğunlukla kısa, güvenli pas oynar; stoper ve defansif orta saha ile üçgen kurar. Hücuma çok az katkı verir, riskli orta veya driplinge girmez.",
            withoutBall:
                "Çizgiyi terk etmez, rakip kanadı göğüsler ve savunma çizgisini bozmadan alan kapatır. Arka direğe yapılan koşuları takip eder, savunma açığı bırakmamaya odaklanır.",
            positioning:
                "Sürekli kendi yarı sahasında, savunma çizgisi üzerinde kalır. Takım ileri çıksa bile orta saha çizgisini nadiren geçer."
        },
        {
            code: "KB",
            name: "Kanat Bek",
            group: "Bek",
            duties: ["Savunma", "Destek", "Hücum", "Otomatik"],
            tags: [],
            withBall:
                "Çizgiden agresif bindirmeler yapar, hücumda genişliği sağlar ve sık sık orta keser. Pas opsiyonu yoksa ceza sahası çevresine yerden pas çıkarır veya içe kat eden oyuncularla duvar pasına girer.",
            withoutBall:
                "Rakip kanat ve bek bindirmelerini karşılar, çizgiyi kapatır. Geri dönüşlerde hızını kullanarak savunma hattına çabuk yerleşir.",
            positioning:
                "Top sendeyken çoğu zaman orta saha çizgisinin ilerisinde, kanat oyuncusunun gerisinde veya yanında konumlanır. Top rakipteyken savunma dörtlüsünün klasik bek pozisyonuna geri döner."
        },
        {
            code: "SB",
            name: "Standart Bek",
            group: "Bek",
            duties: ["Savunma", "Destek", "Hücum", "Otomatik"],
            tags: [],
            withBall:
                "Duruma göre zaman zaman bindirme yapar, bazen de geride kalarak güvenli pas opsiyonu olarak kalır. Uygun ortamda orta açar, müsait değilse içe veya geriye oynar.",
            withoutBall:
                "Rakip kanat oyuncusunu ve bekin bindirmelerini karşılar, savunma hattının dengesini korur. Pres talimatına bağlı olarak zaman zaman öne çıkarak baskıya katılır.",
            positioning:
                "Genelde bek çizgisinde, orta saha çizgisine yakın bir hatta oynar. Takımın taktik anlayışına göre hem hücuma destek verir hem savunmada pozisyonunu korur."
        },

        // --- Kanatlar / Geniş oyuncular ---
        {
            code: "ÇKO",
            name: "Çalışkan Kanat Oyuncusu",
            group: "Kanat",
            duties: ["Savunma", "Destek", "Hücum", "Otomatik"],
            tags: [],
            withBall:
                "Çizgiden top sürer, orta açar veya içe kat ederek basit kombinasyonlara girer. Hücumda çok yaratıcı olmasa da sürekli koşu ve hareketlilikle savunmayı zorlar.",
            withoutBall:
                "Hem bekinin önünü kapatır hem de çoğu zaman kendi ceza sahasına kadar geriye koşarak savunmaya yardım eder. Pres ve alan kapatma konusunda yüksek çalışma temposu gösterir.",
            positioning:
                "Top sendeyken çizgiye yakın; top rakipteyken kendi bekinin önünde veya yanında, çoğu zaman ikinci bek gibi derine iner."
        },
        {
            code: "DK",
            name: "Defansif Kanat",
            group: "Kanat",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Topu güvenli bölgelere taşır, genellikle içe veya geriye pas oynar. Zaman zaman çizgiden hücuma katılır ama temel işi hücumu bitirmek değil, takıma denge sağlamaktır.",
            withoutBall:
                "Bekin önünde savunma kalkanı gibi durur, rakip kanat ve bekin kombinasyonlarını bozar. Çizgiyi kapatır, çoğu zaman kendi ceza sahası çevresine kadar savunmaya döner.",
            positioning:
                "Top rakipteyken kendi yarı sahasında, bek önünde ikinci savunma hattı gibi konumlanır. Hücumda ise orta saha çizgisi civarında, destek mesafesinde kalır."
        },
        {
            code: "KOK",
            name: "Kanat Oyun Kurucu",
            group: "Kanat",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Çizgiye basmak yerine iç koridora doğru gelir, pas açılarını görüp oyunu yönlendirir. Kanat bekinin bindirmelerini besler, ceza sahası çevresinde kilit paslar kovalar.",
            withoutBall:
                "Rakip bek veya stoperin kanat tarafındaki pas opsiyonlarını kapatır, çok derine inmeden pres hattına katılır. Çizgiyi tam kapatmak yerine pas aralarına yönelir.",
            positioning:
                "Kağıt üzerinde kanat gibi görünse de top sende olduğunda half-space'e, iç koridora yaklaşır. Bekle aynı koridorda pas üçgeni kuran geniş oyun kurucudur."
        },
        {
            code: "TAK",
            name: "Ters Ayaklı Kanat",
            group: "Kanat",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Çizgide başlayıp topu aldıktan sonra iç koridora kat eder, ceza sahası yayına doğru şut veya ara pas açısı arar. Bek bindiriyorsa onu kullanarak iç-dış kombinasyonları kurar.",
            withoutBall:
                "Rakip beke baskı yapar, içe kat eden kanat oyuncusunu da kısmen takip eder. Savunma esnasında çoğu zaman çizgi ile iç koridor arasında pozisyon alır.",
            positioning:
                "Başlangıç pozisyonu çizgide; hücumda iç koridora doğru savrularak 10 numara / ikinci forvet bölgesine yaklaşır. Çoğu zaman arka direk koşuları ve ceza sahası içi pozisyonlar kovalar."
        },
        {
            code: "RMD",
            name: "Raumdeuter",
            group: "Kanat",
            duties: ["Hücum"],
            tags: [],
            withBall:
                "Topu çoğunlukla hazır pozisyonda alır; son vuruş, tek dokunuş veya basit bitirici aksiyonlarla pozisyonu sonuçlandırmaya çalışır. Çok fazla top istemez, doğru boşluğu kovalar.",
            withoutBall:
                "İç koridor ve arka direk etrafında dolaşarak savunma hattı arasındaki boşlukları arar. Pres katkısı sınırlı olabilir ama savunma hattının konsantrasyonunu bozar.",
            positioning:
                "Çizgiden ziyade savunma ile orta saha arasındaki boşluklarda, ikinci forvet gibi konumlanır. Özellikle arka direk ve uzak direk koşularıyla ceza sahası içinde görünür."
        },
        {
            code: "HKO",
            name: "Hedef Kanat Oyuncusu",
            group: "Kanat",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Çizgide veya half-space'te sırtı dönük top alır, göğüsle indirir veya kafayla indirme yapar. Kanat beki ve orta sahaya topu duvar olarak bırakır, nadiren kendi driplingiyle adam geçer.",
            withoutBall:
                "Rakip beke ve stopere pres hattı içinde baskı yapar, uzun toplarda hava topu mücadelesine girer. Savunmada boyu ve fiziğiyle duran toplarda ekstra savunmacı gibi görev alır.",
            positioning:
                "Kanat koridorunda ama klasik sprinter kanat kadar çizgiye yapışmaz; daha çok ortayla forvet arasında bir yerde, uzun topların ineceği bölgede konumlanır."
        },

        // --- 10 numaralar / AMC ---
        {
            code: "ON",
            name: "On Numara",
            group: "Ofansif Orta Saha",
            duties: ["Hücum"],
            tags: [],
            withBall:
                "Ceza sahası önü ve half-space bölgelerinde topla buluşup kilit pas, çalım ve şut dener. Oyunun yaratıcı beyni olarak son pası atmak ve rakip savunmayı açmak üzerine oynar.",
            withoutBall:
                "Genellikle çok derine inmez; rakip defansif orta sahalara gölge pres yapar. Ana önceliği top kazanmak değil, doğru anı bekleyip hücumda fark yaratmaktır.",
            positioning:
                "Forvetle orta saha hattı arasında, ceza sahası yayının önünde serbest dolaşır. Zaman zaman kanatlara açılır ama merkezde oyunun ağırlık noktasını oluşturur."
        },
        {
            code: "OOS",
            name: "Ofansif Orta Saha",
            group: "Ofansif Orta Saha",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Hem pas hem koşu tehdidi üretir; gerektiğinde dripling ile topla ceza sahasına girer, gerektiğinde çevresine pas dağıtır. Şut fırsatı bulduğunda ceza sahası dışından da deneme yapar.",
            withoutBall:
                "Pres hattına katılır; rakip defansif orta sahaya veya top çıkaran stopere baskı yapar. Takım savunma yaparken orta blokta yer alır, çok derine gömülmez.",
            positioning:
                "Ceza sahası önü ve half-space çizgisinde, forvetle çift yönlü bağlantı kurar. Bazen ikinci forvet gibi ceza sahasına girer, bazen de biraz geriye gelip oyun kurulumuna destek verir."
        },
        {
            code: "OOK",
            name: "Ofansif Oyun Kurucu",
            group: "Ofansif Orta Saha",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Ceza sahası önünde topu alıp oyunu yönlendirir, kanatlara ve forvete kilit paslar atar. Daha az dripling, daha çok vizyon ve pas üzerinden oynar; tempoyu kontrol etmeye çalışır.",
            withoutBall:
                "Rakip defansif orta saha ve stoperler arasındaki pas kanallarını gölge presle kapatır. Aşırı koşu temposu yapmaz, daha çok pozisyon alarak savunmaya katkı verir.",
            positioning:
                "Ceza yayı çevresinde, half-space bölgelerinde dolaşır. Takım hücumda yerleşmişken genellikle topun olduğu tarafa yaklaşarak pas üçgenlerinin merkezi olur."
        },
        {
            code: "EG",
            name: "Enganche",
            group: "Ofansif Orta Saha",
            duties: ["Destek"],
            tags: [],
            withBall:
                "Statik bir oyun kurucu gibi ceza sahası önünde top ister, dönüp kilit pas arar. Çok koşu yapmaz, top ayağına geldiğinde oyunu yavaşlatıp açacak pası bulmaya çalışır.",
            withoutBall:
                "Pres katkısı sınırlıdır; çoğunlukla rakip defansif orta sahaya yakın pozisyon alır ama agresif koşular yapmaz. Savunmaya fiziksel değil konumsal katkı verir.",
            positioning:
                "10 numara cebinde, santraforun hemen arkasında ve ceza yayı etrafında sabit kalmayı tercih eder. Diğerleri koşarken o oyunun merkez pimi gibi yerinde durur."
        },

        // --- Forvetler ---
        {
            code: "GF",
            name: "Gizli Forvet",
            group: "Forvet",
            duties: ["Hücum"],
            tags: [],
            withBall:
                "Ceza sahası çevresinde topla buluşup dripling, ver-kaç ve şut kombinasyonları dener. Hem kendine hem takım arkadaşlarına pozisyon hazırlamaya çalışır.",
            withoutBall:
                "Santrafor gibi stoperlere baskı yaparken, zaman zaman 10 numara bölgesine çekilip pas kanallarını kapatır. Defans arkasına koşu tehdidi ile savunmayı geri iter.",
            positioning:
                "Klasik santraforun hemen arkasında veya yanında, ikinci forvet gibi konumlanır. Top sendeyken sık sık ceza sahasının içine koşu atar."
        },
        {
            code: "YRD",
            name: "Yardımcı Forvet",
            group: "Forvet",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Ana santraforun yanında veya arkasında topla buluşur, sırtı dönük top saklayıp orta sahaya ve kanatlara dağıtır. Fırsat bulduğunda ceza sahasına koşu atıp ikinci gol tehdidi olur.",
            withoutBall:
                "Stoperlere ve geriden oyun kuran oyunculara pres uygulamada santrafora yardım eder. Takım savunma yaparken orta blok ile forvet hattı arasında bağlantı rolü üstlenir.",
            positioning:
                "Santraforla aynı hatta veya biraz gerisinde, half-space bölgelerinde dolaşır. Hem bağlantı oyuncusu hem ek gol tehdidi gibi davranır."
        },
        {
            code: "YF",
            name: "Yaratıcı Forvet",
            group: "Forvet",
            duties: ["Hücum"],
            tags: [],
            withBall:
                "Sık sık derine gelip top alır, kanatlara ve koşu atan oyunculara yaratıcı paslar çıkarır. Şut ve dripling yeteneğini kullanarak savunmayı bireysel aksiyonlarla da tehdit eder.",
            withoutBall:
                "Presi genelde top yönüne göre şekillendirir; pas açılarını kapatarak rakip stoper ve orta sahayı zorlar. Çok yoğun koşmasa da doğru yerde doğru baskıyı yapmaya çalışır.",
            positioning:
                "Klasik santrafordan biraz daha geride ve serbest; zaman zaman 10 numara bölgesine, zaman zaman kanatlara açılır. Ceza sahasına daha çok ikinci dalga gibi girer."
        },
        {
            code: "PS",
            name: "Pivot Santrafor",
            group: "Forvet",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Sırtı dönük top alır, göğüs, kafa veya tek dokunuşla topu kanatlara ve ikinci forvete indirir. Duran toplarda ve ortalarda hedef oyuncudur, fırsat bulduğunda doğrudan kaleyi düşünür.",
            withoutBall:
                "Uzun topları karşılamak ve savunmayı ileri itmek için stoperlere yakın oynar. Presi sınırlı olabilir ama fizik gücüyle savunma hattını meşgul eder.",
            positioning:
                "Rakip stoperlerin arasında veya hafif önlerinde, ceza sahası çevresinde konumlanır. Hem duvar paslarının merkezi hem de hava toplarında ana hedef oyuncudur."
        },
        {
            code: "FG",
            name: "Fırsatçı Golcü",
            group: "Forvet",
            duties: ["Hücum"],
            tags: [],
            withBall:
                "Ceza sahası içinde veya çizgisinde topla buluştuğu anda hızlı karar alıp şut çeker. Boş alan ve seken topları kovalayarak en az dokunuşla pozisyonu bitirmeyi amaçlar.",
            withoutBall:
                "Savunma arkasına ve ofsayt çizgisine yakın gezerek sürekli sarkma tehdidi yaratır. Pres katkısı sınırlı; daha çok savunmayı arkaya yaslamak için derin koşular yapar.",
            positioning:
                "Savunma hattının son çizgisine yakın, çoğunlukla stoperlerin omzunda dolaşır. Ceza sahası içi pozisyonları kovalayan tipik bir avcı forvettir."
        },
        {
            code: "KOF",
            name: "Komple Forvet",
            group: "Forvet",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Hem sırtı dönük top saklayabilir, hem dripling ile adam eksiltebilir, hem de şut tehdidi yaratır. Pas, koşu ve fizik gücünü kullanarak her türden hücum aksiyonuna katılır.",
            withoutBall:
                "Pres hattını yönetir; stoper, bek ve defansif orta sahaya baskı yapar. Takım savunmasında ilk savunmacı olarak konum alır, gerektiğinde kanatlara doğru kayar.",
            positioning:
                "Savunma hattının omzunda ama zaman zaman derine gelerek bağlantı kurar. Hem ceza sahası içinde bitirici hem de ceza sahası dışında oyun kurucu gibi davranabilir."
        },
        {
            code: "ÇF",
            name: "Çalışkan Forvet",
            group: "Forvet",
            duties: ["Savunma", "Destek", "Hücum"],
            tags: [],
            withBall:
                "Topu aldığında basit oynamaya ve takımı öne taşımaya çalışır; çok yaratıcı olmasa da mücadeleyle savunmayı zorlar. Zaman zaman kanatlara açılıp boş alan yaratır.",
            withoutBall:
                "Takımın birinci presçisi gibidir; stoper, kaleci ve defansif orta sahaya sürekli baskı yapar. Savunma hattını öne çekmek ve rakibin rahat çıkmasını engellemek için çok koşar.",
            positioning:
                "Yer yer santrafor, yer yer ikinci forvet veya kanat gibi çalışır; sürekli hareket halindedir. Çoğu zaman topun olduğu tarafa kayarak presi tetikler."
        },
        {
            code: "SF",
            name: "Sahte Forvet",
            group: "Forvet",
            duties: ["Destek"],
            tags: [],
            withBall:
                "Derine gelip orta saha gibi top alır, oyunu yönlendirir ve kanatlara / koşu atan oyunculara pas çıkarır. Ceza sahasına genelde geç koşularla veya boş alan bulduğunda girer.",
            withoutBall:
                "Rakip defansif orta saha ve stoperler arasındaki alanı kapatarak pas bağlantılarını bozar. Çok yüksek pres yerine doğru açıyla gölge pres yapmaya odaklanır.",
            positioning:
                "Kağıt üzerinde santrafor pozisyonunda görünse de pratikte 10 numara cebine sık sık gelir. Savunmayı peşinden çekerek arkadaki koşuculara alan açar."
        },

        // --- Defansif orta saha / regista hattı ---
        {
            code: "DOS",
            name: "Defansif Orta Saha",
            group: "Defansif Orta Saha",
            duties: ["Savunma", "Destek"],
            tags: [],
            withBall:
                "Topu kazandıktan sonra çoğunlukla en yakın arkadaşa kısa, basit paslar oynar. Bazen oyunu yön değiştirmek için kanatlara uzun top da atabilir ama temel işi güvenli pas akışı sağlamaktır.",
            withoutBall:
                "Savunma hattının önünde süpürücü gibi çalışır, pas arası ve ikili mücadelelerle rakip atakları keser. Rakip 10 numara ve içe kat eden forvetleri karşılar, savunma önünde kalkan olur.",
            positioning:
                "Stoperlerin hemen önünde, ceza yayı civarında konumlanır. Koşu mesafesini fazla açmadan merkez koridoru savunur."
        },
        {
            code: "DOK",
            name: "Derin Oyun Kurucu",
            group: "Defansif Orta Saha",
            duties: ["Savunma", "Destek"],
            tags: [],
            withBall:
                "Stoperlerden veya kaleciden topu alıp oyunu iki yana ve ileriye dağıtır. Dikine pas, ters top ve tempo ayarlama konusunda takımın beyni gibi çalışır.",
            withoutBall:
                "Savunma önünde konum alır ama agresif pres yerine çoğunlukla pozisyon alarak pas kanallarını kapatır. Top kapma işini yanındaki daha savaşçı oyunculara bırakabilir.",
            positioning:
                "Stoperlerin hemen önünde veya aralarında, derine gelerek top alır. Çoğu hücum onun üzerinden başlar."
        },
        {
            code: "SO",
            name: "Savaşçı Orta Saha",
            group: "Defansif Orta Saha",
            duties: ["Savunma", "Destek"],
            tags: [],
            withBall:
                "Topu kazandıktan sonra basit ve hızlı paslar oynar; dripling veya riskli pas işine çok girmez. Nadiren ileriye koşu atıp ikinci topları kovalar.",
            withoutBall:
                "Agresif şekilde pres ve baskı yapar; rakip oyun kurucuyu, 8 numarayı ve kanallara kaçan forvetleri fizik gücüyle bozar. Takımın ana top kazanan oyuncularından biridir.",
            positioning:
                "Orta saha hattında ama çoğu zaman topun olduğu tarafa doğru kayar. Savunma önünde ve half-space bölgelerinde sürekli ikili mücadeleye girer."
        },
        {
            code: "ÖL",
            name: "Ön Libero",
            group: "Defansif Orta Saha",
            duties: ["Savunma"],
            tags: [],
            withBall:
                "Derine düşüp stoperlerin arasından veya önünden top alır, savunma hattını üçler. Topu genellikle kısa paslarla orta sahaya taşır; gerektiğinde uzun top da atabilir.",
            withoutBall:
                "Takım savunma yaparken stoperlerin arasına girerek üçüncü stoper gibi davranır. Rakip forvetlerin koşularını ceza sahası önünde karşılar, savunma arkasına sızmaları engeller.",
            positioning:
                "Top sendeyken DM ile stoper arasında gidip gelir, çıkışta stoperlerin hizasında; top rakipteyken çoğunlukla stoperler arasına gömülür."
        },
        {
            code: "GL",
            name: "Gizli Libero",
            group: "Defansif Orta Saha",
            duties: ["Savunma"],
            tags: [],
            withBall:
                "Savunma önünde topu alıp driplingle orta sahaya kadar çıkar, açık alan bulduğunda ilerleyerek hücuma katılır. Hem pas hem koşu tehdidiyle rakip bloklar arasına sızar.",
            withoutBall:
                "Savunma önünde rakip 10 numara ve forvetler için bir bariyer gibidir. Top sendeyken çok ileri çıkar, top kaybında hızla geri dönüp savunmanın önünü kapatmaya çalışır.",
            positioning:
                "Başlangıç pozisyonu DM hattında; hücumda ise çoğu zaman MC hattına ve hatta rakip yarı sahaya kadar ilerler. Geçiş anlarında derine hızla dönüş yapar."
        },
        {
            code: "REG",
            name: "Regista",
            group: "Defansif Orta Saha",
            duties: ["Destek"],
            tags: [],
            withBall:
                "Derinden oyunu dikte eder; sık sık topu ayağında ister ve uzun/kısa paslarla oyunun yönünü değiştirir. Tempo kontrolü, ters toplar ve ara paslarla hücumu organize eder.",
            withoutBall:
                "Savunma önünde konum alır ama çok agresif ikili mücadeleye girmez; pas arası ve konumlanma ile savunmaya katkı verir. Yanındaki daha savaşçı oyuncuların açtığı alanı kapatır.",
            positioning:
                "Stoperlerin önünde, orta sahaya yakın bir noktada serbestçe dolaşır. Top neredeyse genellikle ona uğrar, takımın ritmini belirler."
        },
        {
            code: "GOK",
            name: "Gezgin Oyun Kurucu",
            group: "Defansif Orta Saha",
            duties: ["Destek"],
            tags: [],
            withBall:
                "Sabit bir pozisyona bağlı kalmadan, top neredeyse oraya gidip oyunu yönlendirmeye çalışır. Kısa kombinasyonlar, ters toplar ve ara paslarla oyunun her iki yönüne de etki eder.",
            withoutBall:
                "Tam merkezi bırakmadan ama tamamen sabit de kalmadan topun olduğu bölgeye kayar. Özellikle pas araları ve pres tetikleyici pozisyonlarla savunmaya destek verir.",
            positioning:
                "DM ile MC hattı arasında, zaman zaman kenarlara veya half-space'e kaçan serbest bir oyun kurucudur. Sahadaki boş alanları sezgisel olarak doldurmaya çalışır."
        },
        {
            code: "VOL",
            name: "Serbest Defansif Orta Saha (Volante)",
            group: "Defansif Orta Saha",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Derinden top alıp dripling veya pasla orta sahayı geçer, half-space bölgelerine koşu atar. Kanatlara, 10 numaraya ve ceza sahası çevresine bağlantı pasları verir; zaman zaman şut da dener.",
            withoutBall:
                "Top kaybedildiğinde hızla geri koşarak savunma önünü kapatır ama gerektiğinde öne çıkıp pres yapar. Hem orta sahayı hem savunma hattı önünü süpürür.",
            positioning:
                "Başlangıçta DM hattında; hücumda MC hattına ve kanallara doğru çıkar. Ataklarda ekstra koşucu 8 numara gibi, savunmada ise klasik defansif orta saha gibi davranır."
        },

        // --- Merkez orta saha / iç oyuncular ---
        {
            code: "MO",
            name: "Merkez Orta Saha",
            group: "Merkez Orta Saha",
            duties: ["Savunma", "Destek", "Hücum", "Otomatik"],
            tags: [],
            withBall:
                "Stoper veya defansif orta sahadan aldığı topu kısa ve orta mesafe paslarla ileriye taşır. Görevine göre bazen risk almadan oyunu dengeler, bazen dikine pas ve koşularla hücuma katılır.",
            withoutBall:
                "Orta blokta hem pas kanallarını kapatır hem de ikili mücadelelere girer. Savunma ve hücum hattı arasında denge unsurudur; gerektiğinde geri koşar, gerektiğinde prese destek verir.",
            positioning:
                "MC hattında, savunma ile hücum arasındaki ana bağlantı bölgesinde konumlanır. Göreve göre biraz daha derine veya ileriye kayabilir ama omurganın ortasında kalır."
        },
        {
            code: "İYO",
            name: "İki Yönlü Orta Saha",
            group: "Merkez Orta Saha",
            duties: ["Destek"],
            tags: [],
            withBall:
                "Topu kazandıktan sonra hızla ileriye taşır, dripling veya pasla hücum geçişlerini başlatır. Aynı zamanda basit paslarla oyunu da sakinleştirebilir; tamamen duruma göre hareket eder.",
            withoutBall:
                "Hem savunma hattının önünde alan kaplar hem de ileriye çıkarak pres yapar. Takımın koşu mesafesi en yüksek oyuncularından biridir; boştaki alanları doldurur.",
            positioning:
                "MC hattında ama sürekli hareket halinde; savunmada derine, hücumda ileriye koşular atar. Zaman zaman kanatlara bile kayarak boşlukları kapatır."
        },
        {
            code: "MEZ",
            name: "Mezzala",
            group: "Merkez Orta Saha",
            duties: ["Destek", "Hücum"],
            tags: [],
            withBall:
                "Half-space denilen iç koridorlarda top alıp kanatla bek arasındaki boşluklara sızar. Dripling ve dar alanda paslaşmalarla hücumun sağ veya sol tarafını kalabalıklaştırır, ceza sahasına geç koşular yapar.",
            withoutBall:
                "Orta sahada alan kapatırken topun olduğu tarafa kayar, hem bekine hem stoperine yardım eder. Rakibin içe kat eden kanatlarını ve 8 numaralarını takip eder.",
            positioning:
                "MC hattında başlar, hücum anında çizgi ile merkez arasında sağ veya sol half-space'e doğru kayar. Ceza sahası çevresinde ve içine geç koşularla görünür."
        },
        {
            code: "DNM",
            name: "Dinamo",
            group: "Merkez Orta Saha",
            duties: ["Destek"],
            tags: [],
            withBall:
                "Sürekli hareket halinde top ister, kısa ve orta mesafeli paslarla oyunu akıtır. Tempo yükseltmek gerektiğinde dripling ve hızlı paslarla oyunu hızlandırır.",
            withoutBall:
                "Sahada neredeyse her yerde görülür; pres, alan kapatma ve ikili mücadeleye yoğun katkı verir. Hem defans hattı önünde hem rakip yarı sahada pres yapabilir.",
            positioning:
                "MC hattında serbest sayılabilecek bir rolde; topun olduğu tarafa ve boş alanlara doğru sürekli koşular yapar. Takımın enerji kaynağı ve mekik oyuncusu gibidir."
        }
    ];

    // İç ID ekleyelim, kodlar çakışsa bile sorun olmasın
    roles.forEach(function (r, idx) {
        r._id = idx;
    });

    var DUTIES = ["Savunma", "Destek", "Hücum", "Otomatik"];

    // ---- UI KURULUMU -------------------------------------------------------

    function buildApp($root) {
        var $app = $('<div>').addClass('fm-role-app');

        // Başlık
        $('<h1>').text('FM Rol Antrenörü').appendTo($app);
        $('<div>')
            .addClass('fm-role-subtitle')
            .text('Rol listesinde arama yap, göreve göre filtrele; soldan rolün davranışını incele, sağda quiz ile kendini test et.')
            .appendTo($app);

        var $layout = $('<div>').addClass('fm-role-layout').appendTo($app);

        // ==== SOL PANEL: arama + rol inceleme ====
        var $left = $('<section>').addClass('fm-role-panel').appendTo($layout);
        $('<h2>').text('Rol incele').appendTo($left);

        // Arama kutusu
        $('<label>')
            .addClass('fm-role-label')
            .text('Rol ara (isim veya kısaltma)')
            .appendTo($left);

        var $search = $('<input>')
            .attr({
                type: 'text',
                placeholder: 'Örn: KOF, Mezzala, ÇF...'
            })
            .css({
                width: '100%',
                padding: '0.4rem 0.6rem',
                borderRadius: '999px',
                border: '1px solid #374151',
                background: '#020617',
                color: '#e5e7eb',
                fontSize: '.85rem',
                marginBottom: '.4rem'
            })
            .appendTo($left);

        // Görev filtresi
        $('<div>')
            .addClass('fm-role-label')
            .css('margin-top', '0.15rem')
            .text('Göreve göre filtrele')
            .appendTo($left);

        var $filterRow = $('<div>')
            .css({ display: 'flex', flexWrap: 'wrap', gap: '0.35rem', marginBottom: '.6rem' })
            .appendTo($left);

        var dutyFilterState = {};
        DUTIES.forEach(function (d) { dutyFilterState[d] = false; });

        function makeDutyButton(duty) {
            var $btn = $('<button>')
                .addClass('fm-role-btn secondary')
                .text(duty)
                .css({ padding: '.25rem .7rem', fontSize: '.75rem' });

            $btn.on('click', function (e) {
                e.preventDefault();
                var active = !dutyFilterState[duty];
                dutyFilterState[duty] = active;
                $btn.toggleClass('fm-role-filter-active', active);

                if (active) {
                    $btn.css({ background: 'rgba(79,70,229,0.15)' });
                } else {
                    $btn.css({ background: 'transparent' });
                }

                applyFilters();
            });

            return $btn;
        }

        DUTIES.forEach(function (d) {
            $filterRow.append(makeDutyButton(d));
        });

        // Rol seçimi
        $('<label>')
            .addClass('fm-role-label')
            .attr('for', 'fm-role-select')
            .text('Rol')
            .appendTo($left);

        var $select = $('<select>')
            .addClass('fm-role-select')
            .attr('id', 'fm-role-select')
            .appendTo($left);

        var $tags = $('<div>').addClass('fm-role-tags').appendTo($left);

        // Detay kartları
        var $cardWith = $('<div>').addClass('fm-role-card').appendTo($left);
        $('<h3>').text('Top bizdeyken').appendTo($cardWith);
        var $withP = $('<p>').appendTo($cardWith);

        var $cardWithout = $('<div>').addClass('fm-role-card').appendTo($left);
        $('<h3>').text('Top rakipteyken').appendTo($cardWithout);
        var $withoutP = $('<p>').appendTo($cardWithout);

        var $cardPos = $('<div>').addClass('fm-role-card').appendTo($left);
        $('<h3>').text('Konum / pas bağlantısı').appendTo($cardPos);
        var $posP = $('<p>').appendTo($cardPos);

        // ==== SAĞ PANEL: quiz ====
        var $right = $('<section>').addClass('fm-role-panel').appendTo($layout);

        var $qh = $('<div>').addClass('fm-role-quiz-header').appendTo($right);
        $('<h2>').text('Quiz modu').appendTo($qh);
        var $newBtn = $('<button>')
            .addClass('fm-role-btn secondary')
            .text('Yeni soru')
            .appendTo($qh);

        $('<div>')
            .addClass('fm-role-quiz-label')
            .text('Aşağıdaki davranış hangi role ait? Önce tahmin et, sonra “Rolü göster”.')
            .appendTo($right);

        var $qCardWith = $('<div>').addClass('fm-role-card').appendTo($right);
        $('<h3>').text('Top bizdeyken').appendTo($qCardWith);
        var $qWithP = $('<p>')
            .addClass('fm-role-muted')
            .text('Henüz soru yok.')
            .appendTo($qCardWith);

        var $qCardWithout = $('<div>').addClass('fm-role-card').appendTo($right);
        $('<h3>').text('Top rakipteyken').appendTo($qCardWithout);
        var $qWithoutP = $('<p>')
            .addClass('fm-role-muted')
            .text('Yeni soru için butona bas.')
            .appendTo($qCardWithout);

        var $qCardRole = $('<div>').addClass('fm-role-card').appendTo($right);
        $('<h3>').text('Rol').appendTo($qCardRole);
        var $qName = $('<p>')
            .addClass('fm-role-quiz-name')
            .text('???')
            .appendTo($qCardRole);

        var $revealBtn = $('<button>')
            .addClass('fm-role-btn')
            .text('Rolü göster')
            .prop('disabled', true)
            .appendTo($qCardRole);

        $('<p>')
            .addClass('fm-role-hint')
            .text('İpucu: önce hangi hat (stoper / bek / orta / kanat / forvet) ve hangi görev (savunma / destek / hücum) olacağını düşün.')
            .appendTo($right);

        // ---- DURUM & FİLTRE LOJİĞİ -----------------------------------------

        var filteredRoles = roles.slice();
        var currentRoleId = filteredRoles.length ? filteredRoles[0]._id : null;
        var currentQuizRole = null;
        var searchTerm = "";

        function renderTags(role) {
            $tags.empty();
            if (!role) return;

            $('<span>')
                .addClass('fm-role-tag')
                .text('Bölge: ' + role.group)
                .appendTo($tags);

            $('<span>')
                .addClass('fm-role-tag')
                .text('Görevler: ' + role.duties.join(', '))
                .appendTo($tags);

            $('<span>')
                .addClass('fm-role-tag')
                .text('Kod: ' + role.code)
                .appendTo($tags);

            if (role.tags && role.tags.length) {
                $('<span>')
                    .addClass('fm-role-tag')
                    .text('Etiket: ' + role.tags.join(', '))
                    .appendTo($tags);
            }
        }

        function describeField(text) {
            if (!text) {
                return "Bu rol için ayrıntılı davranış açıklaması henüz eklenmedi.";
            }
            return text;
        }

        function updateRoleDetails() {
            var role = roles.find(function (r) { return r._id === currentRoleId; });
            if (!role) {
                $withP.text("Filtre sonucu rol bulunamadı.");
                $withoutP.text("");
                $posP.text("");
                $tags.empty();
                return;
            }
            $withP.text(describeField(role.withBall));
            $withoutP.text(describeField(role.withoutBall));
            $posP.text(describeField(role.positioning));
            renderTags(role);

            $select.val(String(role._id));
        }

        function rebuildSelect() {
            $select.empty();

            if (!filteredRoles.length) {
                $('<option>')
                    .text('Sonuç yok')
                    .attr('disabled', 'disabled')
                    .appendTo($select);
                currentRoleId = null;
                updateRoleDetails();
                return;
            }

            filteredRoles.forEach(function (role) {
                $('<option>')
                    .val(String(role._id))
                    .text(role.code + " – " + role.name)
                    .appendTo($select);
            });

            if (!currentRoleId || !filteredRoles.some(function (r) { return r._id === currentRoleId; })) {
                currentRoleId = filteredRoles[0]._id;
            }

            updateRoleDetails();
        }

        function applyFilters() {
            var term = (searchTerm || "").toLocaleLowerCase("tr");
            var activeDuties = DUTIES.filter(function (d) { return dutyFilterState[d]; });

            filteredRoles = roles.filter(function (role) {
                var text = (role.name + " " + role.code).toLocaleLowerCase("tr");
                var matchText = !term || text.indexOf(term) !== -1;
                var matchDuty = !activeDuties.length ||
                    role.duties.some(function (d) { return activeDuties.indexOf(d) !== -1; });
                return matchText && matchDuty;
            });

            rebuildSelect();
        }

        // ---- EVENTLER -------------------------------------------------------

        $search.on('input', function () {
            searchTerm = $(this).val() || "";
            applyFilters();
        });

        $select.on('change', function () {
            var val = $(this).val();
            if (val === null) return;
            currentRoleId = Number(val);
            updateRoleDetails();
        });

        function newQuestion() {
            if (!roles.length) return;
            var idx = Math.floor(Math.random() * roles.length);
            currentQuizRole = roles[idx];

            $qWithP
                .text(describeField(currentQuizRole.withBall))
                .removeClass('fm-role-muted');
            $qWithoutP
                .text(describeField(currentQuizRole.withoutBall))
                .removeClass('fm-role-muted');
            $qName.text('???');
            $revealBtn.prop('disabled', false);
        }

        function reveal() {
            if (!currentQuizRole) return;
            $qName.html(
                '<span class="fm-role-highlight">' +
                mw.html.escape(currentQuizRole.code) +
                '</span> – ' + mw.html.escape(currentQuizRole.name)
            );
            $revealBtn.prop('disabled', true);
        }

        $newBtn.on('click', function (e) {
            e.preventDefault();
            newQuestion();
        });

        $revealBtn.on('click', function (e) {
            e.preventDefault();
            reveal();
        });

        // Başlangıç
        $root.empty().append($app);
        applyFilters();
    }

    function init() {
        var $root = $('#fm-role-trainer');
        if ($root.length) {
            buildApp($root);
        }
    }

    $(init);

}(mediaWiki, jQuery));