IMDb - Show Current Age

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

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

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