Javascript Chrome扩展在YouTube中意外隐藏按钮

Javascript Chrome扩展在YouTube中意外隐藏按钮,javascript,google-chrome-extension,youtube,Javascript,Google Chrome Extension,Youtube,我已经构建了一个Chrome扩展,在初始页面加载时故意隐藏缩略图,效果很好。但它也会在单击一次后隐藏“加载更多”按钮,并阻止加载更多缩略图,即使需要加载更多视频/缩略图 以下是单击“加载更多”后执行的扩展代码部分,它隐藏了“加载更多”按钮: 当我在Chrome的调试器中逐步查看代码时,我发现每个新加载的缩略图周围的整个div都被隐藏了,而不仅仅是图像。因此,实际上,附加的拇指正在加载,但是整个div被隐藏,不仅仅是img元素,所有后续div都会一个接一个地向左滑动,直到看起来没有新的加载。最后的

我已经构建了一个Chrome扩展,在初始页面加载时故意隐藏缩略图,效果很好。但它也会在单击一次后隐藏“加载更多”按钮,并阻止加载更多缩略图,即使需要加载更多视频/缩略图

以下是单击“加载更多”后执行的扩展代码部分,它隐藏了“加载更多”按钮:

当我在Chrome的调试器中逐步查看代码时,我发现每个新加载的缩略图周围的整个div都被隐藏了,而不仅仅是图像。因此,实际上,附加的拇指正在加载,但是整个div被隐藏,不仅仅是img元素,所有后续div都会一个接一个地向左滑动,直到看起来没有新的加载。最后的div隐藏实际上也隐藏了按钮,即使该按钮中没有图像。为什么要这样做


我如何改变这一点,使1额外的视频缩略图按预期加载和显示,并且仅隐藏其中的img元素;2“加载更多”按钮保持可见,直到确实没有更多的拇指可加载为止?

MutationObserver回调最可能的问题是jQuery.htmlDOMnode方法将提供的DOMnode从页面文档移动到分离的非呈现节点qHTML

另外,为了不降低页面加载速度,MutationObserver回调必须非常快, 看见 也就是说,只在您想要的元素上使用jQuery,而不是在每个添加的节点上

onElementAdded('div[data-context-item-id]', document, function(elements) {
    elements.forEach(function(element) {
        var vID = element.dataset.contextItemId;
        if (vID) {
            console.log("dynamic vID: " + vID);
            $(element).find('img').hide();
        }
    });
});

FWIW,如果目标只是使用数据上下文项id属性将图像隐藏在div元素中,那么您可以通过简单的一次性CSS样式注入来实现,或者通过手动添加元素:div[data context item id]img{display:none;}

我用下面的方法解决了这个问题,我从wOxxOm的评论中得到了很多帮助,但不是发布的答案。它现在工作得很好,至少效率有所提高。wOxxOm,我对你的答案投了赞成票,我仍然欢迎你的任何评论。我试过你的。观察变化,它似乎不起作用,但我可能做错了

var insertedNodes = [];
var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        // loop through each chunk of html that changes on the page
        for (var i = 0; i < mutation.addedNodes.length; i++){
            newHTMLChunk = mutation.addedNodes[i];

            if (!newHTMLChunk.tagName) 
                continue;

            if(newHTMLChunk.getElementsByTagName('div').length > 0){
                if(newHTMLChunk.getElementsByTagName('div')[0]){
                    var vID = newHTMLChunk.getElementsByTagName('div')[0].getAttribute('data-context-item-id');

                    if(vID){
                        $("div[data-context-item-id='" + vID + "'] img").hide();
                    }
                }
            }
        }
    })
});
observer.observe(document, {
    attributes: true,
    childList: true,
    characterData: true,
    subtree:true
});

设置断点并正确调试代码。顺便说一句,你的MutationObserver回调非常低效。你如何使它更高效?只观察你需要的东西,不要在内部使用jQuery,不要重新创建html块。无论如何,这是一个单独的问题,一旦你修复了主节点,你就可以继续解决。注意,一些添加的节点是文本节点而不是html元素,所以首先检查类型:if!newHTMLChunk.tagName继续;您可能需要额外检查DocumentFragment。谢谢wOxxOm,我已经删除了一行有问题的代码,正在调试。请参阅上面的编辑。不,我需要一次只做一个,因为我还需要为ajax调用捕获youtube id。
<div class="yt-lockup clearfix  yt-lockup-video yt-lockup-grid vve-check" data-context-item-id="n3Qb30awpLs" data-visibility-tracking="QLvJwrX0-4a6nwE=">
<div class="yt-lockup-dismissable">
    <div class="yt-lockup-thumbnail">
        <span class=" spf-link  ux-thumb-wrap contains-addto">
            <a href="/watch?v=n3Qb30awpLs" class="yt-uix-sessionlink" aria-hidden="true" data-sessionlink="ei=PdyEWNiaGozB-AOT64qQCA&amp;feature=c4-videos-u">
                <span class="video-thumb  yt-thumb yt-thumb-196">
                    <span class="yt-thumb-default">
                        <span class="yt-thumb-clip">
                            <img onload=";__ytRIL(this)" alt="" aria-hidden="true" width="196" src="https://i.ytimg.com/vi/n3Qb30awpLs/hqdefault.jpg?custom=true&amp;w=336&amp;…amp;jpg444=true&amp;jpgq=90&amp;sp=68&amp;sigh=CiLl7jzBOIIFewRt-KAOEs-bKwA" data-ytimg="1">
                                <span class="vertical-align"></span>
                            </span>
                        </span>
                    </span>
                </a>
                <span class="video-time" aria-hidden="true">
                    <span aria-label="103 seconds">1:43</span>
                </span>
                <span class="thumb-menu dark-overflow-action-menu video-actions">
                    <button class="yt-uix-button-reverse flip addto-watch-queue-menu spf-nolink hide-until-delayloaded yt-uix-button yt-uix-button-dark-overflow-action-menu yt-uix-button-size-default yt-uix-button-has-icon no-icon-markup yt-uix-button-empty" type="button" aria-haspopup="true" aria-expanded="false" onclick=";return false;">
                        <span class="yt-uix-button-arrow yt-sprite"></span>
                        <ul class="watch-queue-thumb-menu yt-uix-button-menu yt-uix-button-menu-dark-overflow-action-menu hid">
                            <li role="menuitem" class="overflow-menu-choice addto-watch-queue-menu-choice addto-watch-queue-play-next yt-uix-button-menu-item" data-action="play-next" onclick=";return false;" data-video-ids="n3Qb30awpLs">
                                <span class="addto-watch-queue-menu-text">Play next</span>
                            </li>
                            <li role="menuitem" class="overflow-menu-choice addto-watch-queue-menu-choice addto-watch-queue-play-now yt-uix-button-menu-item" data-action="play-now" onclick=";return false;" data-video-ids="n3Qb30awpLs">
                                <span class="addto-watch-queue-menu-text">Play now</span>
                            </li>
                        </ul>
                    </button>
                </span>
                <button class="yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button video-actions spf-nolink hide-until-delayloaded addto-watch-later-button yt-uix-tooltip" type="button" onclick=";return false;" role="button" title="Watch Later" data-video-ids="n3Qb30awpLs"></button>
                <button class="yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button addto-queue-button video-actions spf-nolink hide-until-delayloaded addto-tv-queue-button yt-uix-tooltip" type="button" onclick=";return false;" title="Queue" data-video-ids="n3Qb30awpLs" data-style="tv-queue"></button>
            </span>
        </div>
        <div class="yt-lockup-content">
            <h3 class="yt-lockup-title ">
                <a class="yt-uix-sessionlink yt-uix-tile-link  spf-link  yt-ui-ellipsis yt-ui-ellipsis-2" dir="ltr" title="Josh’s Afterlife Analogy" aria-describedby="description-id-407587" data-sessionlink="ei=PdyEWNiaGozB-AOT64qQCA&amp;feature=c4-videos-u" href="/watch?v=n3Qb30awpLs">Josh’s Afterlife Analogy</a>
                <span class="accessible-description" id="description-id-407587"> - Duration: 103 seconds.</span>
            </h3>
            <div class="yt-lockup-meta">
                <ul class="yt-lockup-meta-info">
                    <li>16,475 views</li>
                    <li>2 months ago</li>
                </ul>
            </div>
        </div>
    </div>
    <div class="yt-lockup-notifications-container hid" style="height:110px"></div>
</div>
onElementAdded('div[data-context-item-id]', document, function(elements) {
    elements.forEach(function(element) {
        var vID = element.dataset.contextItemId;
        if (vID) {
            console.log("dynamic vID: " + vID);
            $(element).find('img').hide();
        }
    });
});
function onElementAdded(selector, baseNode, callback) {
    new MutationObserver(function(mutations) {
        var found = [];
        for (var mutation, i = 0; (mutation = mutations[i++]); ) {
            var addedNodes = mutation.addedNodes[i];
            for (var node, j = 0; (node = addedNodes[j++]); ) {
                // skip non-element nodes
                if (!node.tagName) {
                    continue;
                }
                // does the added node itself match the selector?
                if (node.matches(selector)) {
                    found.push(node);
                    continue;
                }
                // does the added node contain child elements matching the selector?
                // (since qS is much faster than qSA it makes sense to use it first)
                if (node.querySelector(selector)) {
                    var children = node.querySelectorAll(selector);
                    // prevent stack overflow
                    if (children.length < 1000) {
                        Array.prototype.push.apply(found, children);
                    } else {
                        found = found.concat(children);
                    }
                }
            }
        }
        if (found.length) {
            callback(found);
        }
    }).observe(baseNode || document, {
        childList: true,
        subtree: true,
    });
}
var insertedNodes = [];
var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        // loop through each chunk of html that changes on the page
        for (var i = 0; i < mutation.addedNodes.length; i++){
            newHTMLChunk = mutation.addedNodes[i];

            if (!newHTMLChunk.tagName) 
                continue;

            if(newHTMLChunk.getElementsByTagName('div').length > 0){
                if(newHTMLChunk.getElementsByTagName('div')[0]){
                    var vID = newHTMLChunk.getElementsByTagName('div')[0].getAttribute('data-context-item-id');

                    if(vID){
                        $("div[data-context-item-id='" + vID + "'] img").hide();
                    }
                }
            }
        }
    })
});
observer.observe(document, {
    attributes: true,
    childList: true,
    characterData: true,
    subtree:true
});