IMDb - Show Current Age

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

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

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

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

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

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

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