FPL Faces

Replaces player jerseys with faces - Fixed Typos & Layout

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         FPL Faces
// @namespace    http://tampermonkey.net/
// @version      5.0
// @description  Replaces player jerseys with faces - Fixed Typos & Layout
// @author       Luigi
// @match        https://fantasy.premierleague.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    GM_addStyle(`

        button.tm-card-pickteam {
            padding-left: 0 !important;
            padding-right: 0 !important;
            padding-bottom: 0 !important;
        }

        button.tm-card-pickteam > div:first-child {
            display: flex !important;
            flex-direction: column !important;
            justify-content: flex-end !important;
            align-items: center !important;
            padding: 0 !important;
            margin: 0 !important;
            height: 100% !important;
            width: 100% !important;
            position: relative !important;
        }


        .tm-face-pickteam {
            order: 1 !important;
            flex: 1 1 auto !important;
            width: auto !important;
            height: auto !important;
            max-height: 65% !important;
            max-width: 85% !important;
            margin: 0 auto !important;
            margin-bottom: -1px !important;
            object-fit: contain !important;
            object-position: bottom center !important;
            z-index: 1 !important;
            pointer-events: none;
        }


        button.tm-card-pickteam picture + div {
            order: 2 !important;
            flex: 0 0 auto !important;
            width: 100% !important;
            margin: 0 !important;
            max-width: none !important;
            z-index: 20 !important;
            position: relative !important;
            border-radius: 0 0 6px 6px !important;
        }


        button.tm-card-transfer {
            position: relative !important;
        }


        .tm-face-transfer {
            position: absolute !important;
            left: 0 !important;
            right: 0 !important;
            margin: 0 auto !important;
            display: block !important;


            top: 22px !important;
            bottom: 58px !important;
            width: 75% !important;
            max-width: 70px !important;

            object-fit: contain !important;
            object-position: bottom center !important;
            z-index: 0 !important;
            pointer-events: none;
        }

        /* We force the text box to sit at the absolute bottom of the card */
        button.tm-card-transfer > div:first-child > div:last-child {
            position: absolute !important;
            bottom: 0 !important;
            left: 0 !important;
            width: 100% !important;
            z-index: 20 !important;
            margin: 0 !important;
        }


        button[data-pitch-element="true"] picture {
            display: none !important;
        }
    `);

    let playersData = [];
    let teamsData = [];
    let isDataLoaded = false;


    function fetchFPLData() {
        if (isDataLoaded) return;
        GM_xmlhttpRequest({
            method: "GET",
            url: "https://fantasy.premierleague.com/api/bootstrap-static/",
            onload: function(response) {
                if (response.status === 200) {
                    const data = JSON.parse(response.responseText);
                    playersData = data.elements;
                    teamsData = data.teams;
                    isDataLoaded = true;
                    console.log('FPL Faces: Database loaded.');
                    runScript();
                }
            }
        });
    }


    function getPlayerPhoto(webName, teamNameRaw) {
        if (!isDataLoaded || !webName || !teamNameRaw) return null;
        const cleanTeamName = teamNameRaw.trim();
        const teamObj = teamsData.find(t => t.name === cleanTeamName || t.short_name === cleanTeamName);
        if (!teamObj) return null;
        const playerObj = playersData.find(p => p.team === teamObj.id && p.web_name === webName.trim());

        if (playerObj) {
            let code = playerObj.photo.replace('.jpg', '.png');
            return `https://resources.premierleague.com/premierleague25/photos/players/110x140/${code}`;
        }
        return null;
    }


    function runScript() {
        if (!isDataLoaded) return;

        const playerCards = document.querySelectorAll('button[data-pitch-element="true"]');

        playerCards.forEach(card => {
            const shirtImg = card.querySelector('picture img');
            if (!shirtImg) return;
            const teamName = shirtImg.getAttribute('alt');

            const pictureTag = card.querySelector('picture');
            if (!pictureTag) return;

            const nameContainer = pictureTag.nextElementSibling;
            if (!nameContainer) return;

            const nameSpan = nameContainer.querySelector('span');
            if (!nameSpan) return;

            const webName = nameSpan.textContent.trim();
            const innerContainer = pictureTag.parentNode;

            const existingFace = innerContainer.querySelector('.tm-fpl-face');

            if (existingFace) {
                if (existingFace.dataset.assignedPlayer === webName) {
                    return;
                }
                existingFace.remove();
            }

            const parentDiv = innerContainer.parentNode;
            const priceTag = parentDiv ? parentDiv.querySelector('span') : null;
            const innerPriceTag = innerContainer.querySelector('span');
            const hasPrice = (priceTag && priceTag.textContent.includes('£')) || (innerPriceTag && innerPriceTag.textContent.includes('£'));
            const isTransferPage = hasPrice || window.location.href.includes('/transfers');

            const faceUrl = getPlayerPhoto(webName, teamName);

            if (faceUrl) {
                const newImg = document.createElement('img');
                newImg.src = faceUrl;
                newImg.className = 'tm-fpl-face';
                newImg.dataset.assignedPlayer = webName;

                if (isTransferPage) {
                    newImg.classList.add('tm-face-transfer');
                    card.classList.add('tm-card-transfer');
                } else {
                    newImg.classList.add('tm-face-pickteam');
                    card.classList.add('tm-card-pickteam');
                }

                innerContainer.insertBefore(newImg, pictureTag);
                card.classList.add('tm-processed');
            }
        });
    }

    const observer = new MutationObserver(() => {
        runScript();
    });

    fetchFPLData();

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();