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);
    }
})();