youtube-llt

Von $1

    Inhaltsverzeichnis
    keine Gliederung
    /* YOUTUBE LAZY LOAD - Ersetzt iframes durch Thumbnails */
    .yt-lazy {
        position: relative;
        display: block;
        cursor: pointer;
        background: #000000;
        overflow: hidden;
        max-width: 100%;
    }
    
    .yt-lazy img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
        opacity: 0.85;
        transition: opacity 0.2s ease;
    }
    
    .yt-lazy:hover img {
        opacity: 1.0;
    }
    
    .yt-lazy .yt-play {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 72px;
        height: 50px;
        margin-left: -36px;
        margin-top: -25px;
        background: rgba(204, 0, 0, 0.9);
        border-radius: 12px;
        z-index: 10;
        cursor: pointer;
        transition: background 0.2s ease, transform 0.2s ease;
    }
    
    .yt-lazy:hover .yt-play {
        background: rgba(255, 0, 0, 1);
        transform: scale(1.1);
    }
    
    .yt-lazy .yt-play:after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        margin-left: -6px;
        margin-top: -12px;
        border-style: solid;
        border-width: 12px 0 12px 22px;
        border-color: transparent transparent transparent #FFFFFF;
    }
    
    .yt-lazy .yt-title {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        padding: 8px 12px;
        background: rgba(0, 0, 0, 0.7);
        color: #FFFFFF;
        font-size: 13px;
        font-family: Arial, Helvetica, sans-serif;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    
    .yt-lazy.yt-loading .yt-play {
        background: rgba(100, 100, 100, 0.8);
        animation: yt-pulse 1s ease-in-out infinite;
    }
    
    @keyframes yt-pulse {
        0%, 100% { opacity: 1; }
        50% { opacity: 0.5; }
    }
    
    (function () {
        /* ============================================================
         * YOUTUBE LAZY LOADER v2
         * FIX 24.02.2026: Ersetzt YouTube iframes durch Thumbnails
         * FIX 24.02.2026 v2: MutationObserver Loop gefixt
         *   - Geladene iframes werden mit data-yt-lazy="loaded" markiert
         *   - Observer ignoriert markierte iframes
         *   - Observer pausiert waehrend Replacement
         * ============================================================ */
    
        var PREFIX = '[YT-Lazy] ';
        var ATTR = 'data-yt-lazy';
        var initialized = false;
        var isReplacing = false;
    
        function log(msg) {
            if (window.console && console.log) {
                console.log(PREFIX + msg);
            }
        }
    
        function extractVideoId(src) {
            if (!src) return null;
            var patterns = [
                /\/embed\/([a-zA-Z0-9_-]{11})/,
                /\/v\/([a-zA-Z0-9_-]{11})/,
                /[?&]v=([a-zA-Z0-9_-]{11})/
            ];
            for (var i = 0; i < patterns.length; i++) {
                var match = src.match(patterns[i]);
                if (match) return match[1];
            }
            return null;
        }
    
        function isYouTube(iframe) {
            /* Bereits von uns geladen? Finger weg! */
            if (iframe.getAttribute(ATTR)) return false;
    
            var src = iframe.getAttribute('src') || '';
            return src.indexOf('youtube.com') !== -1 ||
                   src.indexOf('youtube-nocookie.com') !== -1 ||
                   src.indexOf('youtu.be') !== -1;
        }
    
        function getEmbedParams(src) {
            var params = '';
            var qIndex = src.indexOf('?');
            if (qIndex !== -1) {
                params = src.substring(qIndex);
            }
            if (params.indexOf('autoplay') === -1) {
                params += (params.indexOf('?') !== -1 ? '&' : '?') + 'autoplay=1';
            }
            return params;
        }
    
        function createPlaceholder(iframe, videoId) {
            var src = iframe.getAttribute('src') || '';
    
            var w = iframe.getAttribute('width') || iframe.style.width || '560';
            var h = iframe.getAttribute('height') || iframe.style.height || '315';
    
            var wStr = (w + '').indexOf('%') !== -1 ? w : w + 'px';
            var hStr = (h + '').indexOf('%') !== -1 ? h : h + 'px';
    
            var container = document.createElement('div');
            container.className = 'yt-lazy';
            container.setAttribute('data-video-id', videoId);
            container.setAttribute('data-embed-params', getEmbedParams(src));
            container.setAttribute('data-width', w);
            container.setAttribute('data-height', h);
            container.style.width = wStr;
            container.style.height = hStr;
    
            if (iframe.style.maxWidth) container.style.maxWidth = iframe.style.maxWidth;
            if (iframe.style.margin) container.style.margin = iframe.style.margin;
    
            var thumb = document.createElement('img');
            thumb.src = 'https://img.youtube.com/vi/' + videoId + '/hqdefault.jpg';
            thumb.alt = 'YouTube Video';
            thumb.style.width = '100%';
            thumb.style.height = '100%';
    
            var playBtn = document.createElement('div');
            playBtn.className = 'yt-play';
    
            container.appendChild(thumb);
            container.appendChild(playBtn);
    
            function onClick(e) {
                if (e && e.preventDefault) e.preventDefault();
                if (e && e.stopPropagation) e.stopPropagation();
    
                container.className += ' yt-loading';
                log('Lade Video: ' + videoId);
    
                var vid = container.getAttribute('data-video-id');
                var params = container.getAttribute('data-embed-params');
                var cw = container.getAttribute('data-width');
                var ch = container.getAttribute('data-height');
                var cwStr = (cw + '').indexOf('%') !== -1 ? cw : cw + 'px';
                var chStr = (ch + '').indexOf('%') !== -1 ? ch : ch + 'px';
    
                var newIframe = document.createElement('iframe');
                newIframe.setAttribute('width', cw);
                newIframe.setAttribute('height', ch);
                newIframe.style.width = cwStr;
                newIframe.style.height = chStr;
                newIframe.setAttribute('frameborder', '0');
                newIframe.setAttribute('allowfullscreen', '');
                newIframe.setAttribute('allow', 'autoplay; encrypted-media');
    
                /* KRITISCH: Markieren damit Observer diesen iframe ignoriert */
                newIframe.setAttribute(ATTR, 'loaded');
    
                newIframe.src = 'https://www.youtube-nocookie.com/embed/' + vid + params;
    
                /* Observer pausieren waehrend Replacement */
                isReplacing = true;
    
                if (container.parentNode) {
                    container.parentNode.replaceChild(newIframe, container);
                    log('Video geladen: ' + vid);
                }
    
                /* Observer nach kurzer Pause wieder aktivieren */
                setTimeout(function () {
                    isReplacing = false;
                }, 500);
    
                return false;
            }
    
            if (container.addEventListener) {
                container.addEventListener('click', onClick, false);
            } else if (container.attachEvent) {
                container.attachEvent('onclick', onClick);
            }
    
            return container;
        }
    
        function processIframes() {
            /* Wenn gerade ein Video geladen wird, nicht eingreifen */
            if (isReplacing) return 0;
    
            var iframes = document.getElementsByTagName('iframe');
            var count = 0;
            var toReplace = [];
    
            for (var i = 0; i < iframes.length; i++) {
                var iframe = iframes[i];
    
                if (iframe.getAttribute(ATTR)) continue;
    
                if (isYouTube(iframe)) {
                    var videoId = extractVideoId(iframe.getAttribute('src'));
                    if (videoId) {
                        toReplace.push({ iframe: iframe, videoId: videoId });
                    }
                }
            }
    
            /* Pausiere Observer waehrend Batch-Replacement */
            if (toReplace.length > 0) {
                isReplacing = true;
            }
    
            for (var j = 0; j < toReplace.length; j++) {
                var item = toReplace[j];
                var placeholder = createPlaceholder(item.iframe, item.videoId);
    
                if (item.iframe.parentNode) {
                    item.iframe.parentNode.replaceChild(placeholder, item.iframe);
                    count++;
                }
            }
    
            if (toReplace.length > 0) {
                setTimeout(function () {
                    isReplacing = false;
                }, 500);
            }
    
            if (count > 0) {
                log(count + ' YouTube iframe(s) durch Thumbnails ersetzt');
            }
    
            return count;
        }
    
        function init() {
            if (initialized) {
                log('SKIP: Bereits initialisiert (Singleton)');
                return;
            }
            initialized = true;
    
            log('Init v2 gestartet...');
            var count = processIframes();
    
            if (count === 0) {
                log('Keine YouTube iframes gefunden');
            }
    
            if (window.MutationObserver) {
                var observer = new MutationObserver(function (mutations) {
                    /* Waehrend Replacement nichts tun */
                    if (isReplacing) return;
    
                    var hasNew = false;
                    for (var i = 0; i < mutations.length; i++) {
                        var nodes = mutations[i].addedNodes;
                        if (!nodes) continue;
                        for (var j = 0; j < nodes.length; j++) {
                            var node = nodes[j];
                            /* Nur reagieren wenn ein unmarkierter iframe hinzugefuegt wurde */
                            if (node.tagName === 'IFRAME' && !node.getAttribute(ATTR)) {
                                hasNew = true;
                                break;
                            }
                            /* Oder ein Container der iframes enthaelt */
                            if (node.getElementsByTagName) {
                                var inner = node.getElementsByTagName('iframe');
                                for (var k = 0; k < inner.length; k++) {
                                    if (!inner[k].getAttribute(ATTR)) {
                                        hasNew = true;
                                        break;
                                    }
                                }
                            }
                            if (hasNew) break;
                        }
                        if (hasNew) break;
                    }
                    if (hasNew) {
                        processIframes();
                    }
                });
                observer.observe(document.body, { childList: true, subtree: true });
                log('MutationObserver aktiv (dynamische iframes)');
            }
    
            log('Fertig!');
        }
    
        if (document.readyState === 'complete') {
            init();
        } else if (document.addEventListener) {
            document.addEventListener('DOMContentLoaded', init, false);
        } else {
            window.onload = init;
        }
    })();
    
    NoElements {}
    Tags: (Schlagworte bearbeiten)
    • No tags
     
    Kommentare (0)
    Um einen Kommentar zu schreiben, müssen Sie sich anmelden.

     
    Use the language selection below for English Utilise le sélecteur de langue ci-dessous pour français Per l'italiano, utilizzare la selezione della lingua qui sotto Schön sprichst du deutsch :-)