IMDb - Show Current Age

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

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

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