2

我有一个奇怪的问题。我尝试编写一个在 Firefox 和 Google Chrome 中运行的 GreaseMonkey 脚本。使用 Chrome,我尝试了 2 个扩展:“TamperMonkey”和“Blank Canvas Script Handler”,主要是因为我的脚本会定期检查外部站点上的新版本,这被认为是跨站点脚本,在 Chrome 中没有授权。

为了向您展示我的问题,我编写了一个简单的测试用例:

// ==UserScript==
// @name        test
// @namespace       http://fgs.ericc-dream.fr.nf
// @description     test gm script
// @include         http://gaia.fallengalaxy.eu/
// @author          ericc
// @version         0.0.1
// ==/UserScript==

/* We attach an event listener to the body tag and trigger the function
 * 'message' each time that an element is inserted in the page */
var el = document.body;
el.addEventListener('DOMNodeInserted', message, false);

var extraFlag = false;

function message(event) {
    /* first we capture the id of the new inserted element
     * (the one who created the event) */
    var objId = event.target.id;

    /* add an event listener on the map container */
    if (objId == "extra") {
        el = document.getElementById('extra');
        el.addEventListener('DOMSubtreeModified',readTest,false);
        GM_log(el.style.display);
    }
}

function readTest() {
    el = document.getElementById('extra');
    GM_log(extraFlag);
    GM_log(el.style.display);
    if ((el.style.display != 'none') && (!extraFlag)) {
        alert('extra');
        extraFlag = true;
    } else if ((el.style.display == 'none')) {
        extraFlag = false;
    }
}

div 元素“额外”由页面修改。问题是 Chrome 无法读取 el.style.display 的值,因此 extraFlag 永远不会再次变为“假”。我使用这个标志来避免多次运行代码,该网站大量使用 JavaScript 驱动此代码在 Firefox 中运行良好!

我试图用谷歌搜索,但找不到正确的答案。更改显示值似乎很容易,但似乎只有我一个尝试阅读它!

我编写此代码是因为 Chrome 不支持“DOMAttrModified”:-(

在此先感谢您的帮助

埃里克

4

2 回答 2

3

我很难准确理解您的问题是什么,但看起来 Chrome 可以.style.display很好地读取属性。我只是将以下代码放入 HTML 模板并在 Chrome 10 中加载:

<div id="div1">
</div>

<div id="div2" style="display: block;">
</div>

<div id="div3" style="display: inline;">
</div>

<div id="div4" style="display: none;">
</div>

<script type="text/javascript">
    alert(document.getElementById("div1").style.display);
    alert(document.getElementById("div2").style.display);
    alert(document.getElementById("div3").style.display);
    alert(document.getElementById("div4").style.display);

    document.getElementById("div1").style.display = "none";

    alert(document.getElementById("div1").style.display);
</script>

该代码生成了 5 个“警报”框,输出如下:

  • 堵塞
  • 排队
  • 没有任何
  • 没有任何

所以看起来 Chome 读这个属性就好了。

也许问题是您运行greasemonkey 脚本的网页在Chrome 中的行为与在Firefox 中的行为不同?可能是元素的 ID 不同,或者元素正在从 DOM 中删除而不是被隐藏?如果你用更多的检查修改你的函数会发生什么,有点像这样?

function readTest() {
    el = document.getElementById('extra');
    if(el)
    {
        GM_log(extraFlag);
        GM_log(el.style.display);
        if (el.style.display && (el.style.display != 'none') && (!extraFlag)) {
            alert('extra');
            extraFlag = true;
        } else if ((el.style.display == 'none') || !el.style.display) {
            extraFlag = false;
        }
    }
    else
    {
        GM_log(extraFlag);
        GM_log("element not present");
        extraFlag = false;
    }
}

这有帮助吗?如果没有,您是否还有其他原因可以想到为什么 el.style.display 无法在 Chrome 中正确评估?

如果我们更多地了解您尝试对脚本执行的操作,以及您尝试在哪个网页或代码上运行它,这可能会有所帮助。

于 2011-03-29T20:30:57.110 回答
1

经过几个小时和大量的测试用例,我终于找到了一个可以接受的解释(但还没有解决方案!)

让我们来解释一下这个场景:
1°)用户点击屏幕上的一个图标
2°)已经存在于页面中的 div#extra 通过删除它的显示属性(.style.display="")变得可见
3°)div#extra 由 AJAX 函数归档,其中一些元素取决于用户单击的图标(在某些情况下超过 200 个元素)
4°)用户单击另一个图标以关闭 div
5° ) div#extra 中的所有元素都被删除
6°) div#extra 通过将显示属性设置为'none' (.style.display="none") 来隐藏

起初,在 Firefox 上,我在 div#extra 上使用“ DOMAttrModified ”事件来检查显示属性何时被修改并做出相应的反应。问题,Chrome 不支持此事件!

所以我将它替换为两个浏览器都支持的“ DOMSubtreeModified ”(附加到 div#extra)......但方式不完全相同:-(
在 Firefox 上,子树中的每个修改都会触发一个事件,但也当元素本身被修改时。
在 Chrome 上,它们更严格一些,并且仅针对子树中的修改触发事件....这是我的问题!

在 Firefox 中,第一个事件在第 2 点(在场景中)触发,最后在第 6 点触发,允许我的函数在 div#extra 隐藏时读取

在 Chrome 中,第一个事件在第 3 点触发,最后在第 5 点触发……所以当 div#extra 被隐藏时,我的函数不会被调用,我也无法修改标志!!!!CQFD

现在,或者我会在页面正文中添加一个事件监听器,在修改显示属性时进行拦截,但是会产生大量对我的函数的调用,或者TamperMonkey的开发者昨天说他的扩展现在支持“ DOMAttrModified "(在 Chrome 上)....

无论如何,感谢您花时间了解我的问题和您提出的解决方案

埃里克

于 2011-03-31T08:06:52.067 回答