youtube-llt

Von $1

  • Sie haben keine Berechtigung, die Beschränkungen auf dieser Seite zu ändern.
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 :-)