IMDb - Show Current Age

Shows current age or "would be" age in correct birth-and-death-section (improved date detection)

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name           IMDb - Show Current Age
// @namespace      https://github.com/BlueAG/TamperMonkey/tree/main/IMDb-Show-Current-Age
// @icon           https://www.google.com/s2/favicons?domain=imdb.com
// @version        1.1.3
// @description    Shows current age or "would be" age in correct birth-and-death-section (improved date detection)
// @author         BlueAG
// @license        MIT
// @match          https://www.imdb.com/name/nm*
// @grant          none
// @compatible     chrome
// @compatible     firefox
// @compatible     opera
// @compatible     edge
// @compatible     safari
// ==/UserScript==

(function() {
    'use strict';

    window.addEventListener('load', () => setTimeout(addAgeText, 1500));

    function addAgeText() {
        if (document.getElementById('imdb-age-text')) return;

        console.log("[IMDb Age 1.1.8] Starting...");

        const candidates = document.querySelectorAll('[data-testid="birth-and-death-section"]');
        console.log(`[IMDb Age 1.1.8] Found ${candidates.length} sections`);

        let targetAside = null;
        let birthDiv = null;
        let dateSpan = null;
        let birthText = "";

        // Prefer aside with crfwtP class
        for (const aside of candidates) {
            if (aside.className.includes('crfwtP')) {
                targetAside = aside;
                console.log("[IMDb Age 1.1.8] Selected aside with crfwtP class");
                break;
            }
        }

        // Fallback: first one with birthdate div
        if (!targetAside) {
            for (const aside of candidates) {
                if (aside.querySelector('[data-testid="birth-and-death-birthdate"]')) {
                    targetAside = aside;
                    console.log("[IMDb Age 1.1.8] Fallback to first aside with birthdate div");
                    break;
                }
            }
        }

        if (!targetAside) {
            console.log("[IMDb Age 1.1.8] No suitable aside found");
            return;
        }

        birthDiv = targetAside.querySelector('[data-testid="birth-and-death-birthdate"]');
        if (!birthDiv) {
            console.log("[IMDb Age 1.1.8] birth-and-death-birthdate div missing");
            return;
        }

        // Find date span: check all spans inside birthDiv
        const allSpans = birthDiv.querySelectorAll('span');
        console.log(`[IMDb Age 1.1.8] Found ${allSpans.length} spans inside birth div`);

        for (const span of allSpans) {
            const t = span.textContent.trim().replace(/\s+/g, ' ');
            console.log("[IMDb Age 1.1.8] Checking span text:", t);

            if (/^\d{4}$/.test(t) ||
                /^[A-Za-z]+\s+\d{1,2},\s+\d{4}$/.test(t) ||
                /^[A-Za-z]+\s+\d{1,2}$/.test(t)) {  // also allow month + day only (but we'll skip age calc)
                dateSpan = span;
                birthText = t;
                break;
            }
        }

        if (!dateSpan || !birthText) {
            console.log("[IMDb Age 1.1.8] No valid date/year text found");
            return;
        }

        console.log("[IMDb Age 1.1.8] Selected birth text:", birthText);

        // Skip age if no year
        if (!/\d{4}/.test(birthText)) {
            console.log("[IMDb Age 1.1.8] No year present - skipping age calculation");

            const placeholder = document.createElement('span');
            placeholder.id = 'imdb-age-text';
            placeholder.style.cssText = `
                margin-left: 0px;
                font-size: 1.05em;
                font-weight: 100;
                color: #ffe300;
                font-style: italic;
            `;
            placeholder.textContent = "No birth year found!";

            birthDiv.insertAdjacentElement('afterend', placeholder);
            return;
        }

        // Calculate age
        const today = new Date();
        let age = null;
        const isYearOnly = /^\d{4}$/.test(birthText);

        if (isYearOnly) {
            age = today.getFullYear() - parseInt(birthText);
        } else {
            const birthDate = new Date(birthText);
            if (!isNaN(birthDate.getTime())) {
                age = today.getFullYear() - birthDate.getFullYear();
                const m = today.getMonth() - birthDate.getMonth();
                if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) age--;
            }
        }

        if (age === null || age < 0) {
            console.log("[IMDb Age 1.1.8] Invalid age");
            return;
        }

        // Deceased check
        const isDeceased =
            targetAside.querySelector('[data-testid="birth-and-death-deathdate"]') ||
            targetAside.querySelector('[data-testid="birth-and-death-death-age"]') ||
            targetAside.textContent.includes('Died');

        // Create age element
        const ageEl = document.createElement('span');
        ageEl.id = 'imdb-age-text';
        ageEl.style.cssText = `
            margin-left: 0px;
            font-size: 1.05em;
            font-weight: 500;
            color: ${isDeceased ? '#c62828' : '#2e7d32'};
        `;

        ageEl.textContent = isDeceased
            ? `Current age would be: ${age} years`
            : `Current age: ${age} years${isYearOnly ? ' (approx)' : ''}`;

        // Insert after birth div
        birthDiv.insertAdjacentElement('afterend', ageEl);
        console.log("[IMDb Age 1.1.8] Age inserted:", ageEl.textContent);
    }
})();