MediaWiki:CustomItemTracker.js: Difference between revisions

From Roat Pkz
Jump to navigation Jump to search
No edit summary
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 22: Line 22:




     let images = [];
     let images = {};
 
     let searchValue = "";
     let searchValue = "";


Line 119: Line 120:




         $.getJSON(
         $.post(
             "/api.php",
             "/api.php",
             {
             {
Line 131: Line 132:




             if (!data.parse)
             if (!data.parse) {
 
                console.warn(
                    "Image parse failed",
                    data
                );
 
                images = {};
 
                render();
 
                 return;
                 return;
            }




Line 146: Line 159:




             images =
             const parsedImages =
                 Array.from(
                 Array.from(
                     wrapper.querySelectorAll("img")
                     wrapper.querySelectorAll("img")
                 );
                 );
            images = {};
            allItems.forEach(function(item, index) {
                if (parsedImages[index]) {
                    images[item.name] =
                        parsedImages[index];
                }
            });




Line 248: Line 280:




searchBox.addEventListener(
        searchBox.addEventListener(
    "input",
            "input",
    function() {
            function() {
 
                searchValue =
                    this.value.toLowerCase();
 
                render(searchValue);
 
 
                setTimeout(function() {
 
                    const newSearch =
                        container.querySelector(".trackerSearch");


        searchValue =
            this.value.toLowerCase();


        render(searchValue);
                    if (newSearch) {


        setTimeout(function() {
                        newSearch.focus();
            const newSearch =
                container.querySelector(".trackerSearch");


            if (newSearch) {
                        newSearch.setSelectionRange(
                newSearch.focus();
                            newSearch.value.length,
                newSearch.setSelectionRange(
                            newSearch.value.length
                    newSearch.value.length,
                        );
                    newSearch.value.length
 
                );
                    }
            }


        }, 0);
                }, 0);


    }
);


            }
        );
                let globalIndex = 0;




        let globalIndex = 0;
       
         trackerData.tiers.forEach(function(tier) {
         trackerData.tiers.forEach(function(tier) {


Line 295: Line 332:


                 });
                 });
            // Keep index alignment with completed data
            tier.items.forEach(function(item) {
                if (
                    filteredItems.includes(item)
                ) {
                    return;
                }
            });




Line 352: Line 373:




                const index =
const index =
                    globalIndex++;
    trackerData.tiers
    .flatMap(t => t.items)
    .indexOf(item);




Line 405: Line 428:


                 if (
                 if (
                     images[index]
                     images[item.name]
                 ) {
                 ) {


                     const img =
                     const img =
                         images[index]
                         images[item.name]
                         .cloneNode(true);
                         .cloneNode(true);



Latest revision as of 17:12, 30 July 2026

mw.hook('wikipage.content').add(function () {

    const container =
        document.getElementById("customItemTracker");

    if (!container) return;


    const allowedUsers = [
        "Hefner"
    ];


    const currentUser =
        mw.config.get("wgUserName");


    let trackerData = {
        tiers: [],
        completed: {}
    };


    let images = {};

    let searchValue = "";



    function loadData() {


        $.getJSON(
            mw.util.wikiScript("api"),
            {
                action: "query",
                titles: "Module:CustomItemTracker/data.json",
                prop: "revisions",
                rvprop: "content",
                format: "json",
                formatversion: 2
            }

        ).done(function(data) {


            const page =
                data.query.pages[0];


            if (!page.revisions)
                return;



            try {

                trackerData =
                    JSON.parse(
                        page.revisions[0].content
                    );


            } catch(e) {

                console.error(
                    "Invalid tracker JSON",
                    e
                );

                return;

            }



            loadImages();


        });


    }





    function loadImages() {


        const allItems = [];


        trackerData.tiers.forEach(function(tier) {


            tier.items.forEach(function(item) {

                allItems.push(item);

            });


        });



        const templates =
            allItems
            .map(function(item) {

                return "{{plinkp|" +
                    item.name +
                    "}}";

            })
            .join("\n");



        $.post(
            "/api.php",
            {
                action: "parse",
                text: templates,
                format: "json"
            }

        ).done(function(data) {



            if (!data.parse) {

                console.warn(
                    "Image parse failed",
                    data
                );

                images = {};

                render();

                return;

            }



            const wrapper =
                document.createElement("div");



            wrapper.innerHTML =
                data.parse.text["*"];



            const parsedImages =
                Array.from(
                    wrapper.querySelectorAll("img")
                );



            images = {};



            allItems.forEach(function(item, index) {


                if (parsedImages[index]) {

                    images[item.name] =
                        parsedImages[index];

                }


            });



            render();


        });


    }





    function render(searchTerm = "") {


        container.innerHTML = "";



        let total = 0;


        trackerData.tiers.forEach(function(tier) {

            total += tier.items.length;

        });



        let completed = 0;


        Object.keys(
            trackerData.completed
        ).forEach(function(key) {


            if (
                trackerData.completed[key]
            ) {

                completed++;

            }


        });



        const progress =
            document.createElement("div");


        progress.className =
            "trackerProgress";


        progress.innerHTML =
        `
        Completed:
        <strong>${completed}/${total}</strong>
        (${total ? Math.floor((completed / total) * 100) : 0}%)
        `;


        container.appendChild(progress);



        const searchBox =
            document.createElement("input");


        searchBox.type =
            "text";


        searchBox.placeholder =
            "Search items...";


        searchBox.className =
            "trackerSearch";


        searchBox.value =
            searchTerm;


        container.appendChild(searchBox);



        searchBox.addEventListener(
            "input",
            function() {

                searchValue =
                    this.value.toLowerCase();

                render(searchValue);


                setTimeout(function() {

                    const newSearch =
                        container.querySelector(".trackerSearch");


                    if (newSearch) {

                        newSearch.focus();

                        newSearch.setSelectionRange(
                            newSearch.value.length,
                            newSearch.value.length
                        );

                    }

                }, 0);


            }
        );
                let globalIndex = 0;


        trackerData.tiers.forEach(function(tier) {


            const filteredItems =
                tier.items.filter(function(item) {


                    if (!searchTerm)
                        return true;


                    return item.name
                        .toLowerCase()
                        .includes(searchTerm);


                });



            if (filteredItems.length === 0)
                return;



            const heading =
                document.createElement("div");


            heading.className =
                "trackerTierHeading";


            heading.textContent =
                tier.name;


            container.appendChild(heading);



            const grid =
                document.createElement("div");


            grid.className =
                "trackerGrid";


            container.appendChild(grid);





            tier.items.forEach(function(item) {


const index =
    trackerData.tiers
    .flatMap(t => t.items)
    .indexOf(item);



                if (
                    searchTerm &&
                    !item.name
                    .toLowerCase()
                    .includes(searchTerm)
                ) {

                    return;

                }





                const tile =
                    document.createElement("div");


                tile.className =
                    "trackerTile";



                if (
                    trackerData.completed[index]
                ) {

                    tile.classList.add(
                        "completed"
                    );

                }





                const imageBox =
                    document.createElement("div");


                imageBox.className =
                    "itemImage";



                if (
                    images[item.name]
                ) {


                    const img =
                        images[item.name]
                        .cloneNode(true);



                    img.style.maxWidth =
                        "50px";


                    img.style.maxHeight =
                        "50px";


                    img.style.width =
                        "auto";


                    img.style.height =
                        "auto";


                    img.style.objectFit =
                        "contain";



                    imageBox.appendChild(img);

                }



                tile.appendChild(imageBox);





                const name =
                    document.createElement("div");


                name.className =
                    "itemName";


                name.textContent =
                    item.name;



                tile.appendChild(name);





                tile.onclick =
                function() {



                    if (
                        !allowedUsers.includes(
                            currentUser
                        )
                    ) {

                        return;

                    }



                    trackerData.completed[index] =
                        !trackerData.completed[index];



                    saveData();


                };



                grid.appendChild(tile);


            });


        });


    }





    function saveData() {


        $.post(
            mw.util.wikiScript("api"),
            {

                action: "edit",

                title:
                "Module:CustomItemTracker/data.json",


                token:
                mw.user.tokens.get(
                    "csrfToken"
                ),


                format: "json",


                text:
                JSON.stringify(
                    trackerData,
                    null,
                    4
                )

            }

        ).done(function() {


            render(searchValue);


            console.log(
                "Custom Item Tracker updated"
            );


        });


    }





    loadData();


});