Chrome扩展程序在YouTube中意外隐藏了按钮

时间:2017-01-22 14:44:02

标签: javascript google-chrome-extension youtube

我已经构建了一个Chrome扩展程序,可以在初始页面加载时故意隐藏缩略图,并且效果很好。但它也隐藏了#34;加载更多"单击一次后按钮,可防止加载更多缩略图,即使还有更多视频/缩略图需要加载。

以下是点击加载更多后执行的扩展程序代码部分,然后隐藏加载更多按钮:

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;

            qHTML = $('<div/>').html(newHTMLChunk).contents();
            var vID = qHTML.find('div').attr("data-context-item-id");

            if(vID){
                console.log("dynamic vID: " + vID);
                qHTML.find('img').hide();
            }
        }
    })
});
observer.observe(document, {
    attributes: true,
    childList: true,
    characterData: true,
    subtree:true
});

以下是初始页面加载后的样子,我的扩展程序正在运行: enter image description here

单击“加载更多”按钮后,请注意该按钮消失且不再显示大拇指: enter image description here

以下是YouTube的加载更多按钮的html,它似乎没有任何与img选择器匹配的隐藏内容:

<span class="yt-uix-button-content">
    <span class="load-more-loading hid">
        <span class="yt-spinner">
            <span class="yt-spinner-img  yt-sprite" title="Loading icon"></span>       
            Loading...
        </span>
    </span>
    <span class="load-more-text">
        Load more
    </span>
</span>

以下是newHTMLChunk.innerHTML内容的一个示例(请注意,只有1个img元素,而这是我要隐藏的那个,而不会隐藏“加载更多”按钮并且不会阻止更多的拇指加载):

<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>

当我逐步浏览Chrome调试器中的代码时,我发现每个新加载的缩略图周围的整个div都被隐藏,而不仅仅是图像。所以,事实上,额外的拇指正在加载,但随后整个div被隐藏(不仅仅是img元素),并且所有后续的div一个接一个地向左滑动,直到看起来没有任何新的加载。即使该按钮中没有图像,最后的div hide也会隐藏按钮。为什么要这样做?

如何更改此设置以便(1)其他视频缩略图按预期加载和显示,并且只隐藏内部的img元素; (2)Load more按钮保持可见,直到真正没有更多的拇指加载?

2 个答案:

答案 0 :(得分:1)

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

另外,MutationObserver回调必须非常快,以免减慢页面加载速度 见Performance of MutationObserver to detect nodes in entire DOM
也就是说,仅在您想要的元素上使用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();
        }
    });
});

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,
    });
}

FWIW,如果目标只是使用data-context-item-id属性将图像隐藏在div元素中,那么您可以使用简单的一次性CSS样式注入(在manifest.json中或通过手动执行)添加<style>元素):div[data-context-item-id] img { display: none; }

答案 1 :(得分:0)

我用以下内容解决了这个问题,并得到了wOxxOm评论的帮助(但不是发布的答案)。它现在完美地工作,至少在某种程度上更有效。 wOxxOm,我赞成你的回答,我仍然欢迎你的任何评论。我尝试了你的.observe()更改,它似乎没有用,但我可能做错了。

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
});