我正在写一个GreaseMonkey脚本,我正在迭代一堆元素.对于每个元素,我需要一个字符串ID,以后我可以用它来引用该元素.元素本身没有id
属性,我不能修改原始文档给它一个(虽然我可以在我的脚本中进行DOM更改).我无法在我的脚本中存储引用,因为当我需要它们时,GreaseMonkey脚本本身将超出范围.例如,有没有办法获得浏览器使用的"内部"ID?只有Firefox的解决方案很好; 可以在其他场景中应用的跨浏览器解决方案非常棒.
编辑:
如果GreaseMonkey脚本超出范围,您以后如何引用这些元素?他们GreaseMonkey脚本正在向DOM对象添加事件.我无法将引用存储在数组或其他类似的机制中,因为当事件触发时,数组将会消失,因为GreaseMonkey脚本将超出范围.因此,事件需要某种方式来了解脚本在附加事件时所具有的元素引用.并且所讨论的元素不是它所附着的元素.
你不能只在元素上使用自定义属性吗?是的,但问题在于查找.我不得不求助于遍历所有元素,寻找将自定义属性设置为所需id的元素.那肯定会有用,但在大型文档中它可能非常耗时.我正在寻找浏览器可以执行查找工作的东西.
等等,你能否或不能修改文件?我无法修改源文档,但我可以在脚本中进行DOM更改.我会在问题中澄清一下.
你能不能使用封口?尽管我最初认为他们不会这样做,但Closuses确实有效.见我后来的帖子.
这听起来像是问题的答案:"我可以使用一些内部浏览器ID吗?" 没有."
答案是否定的,没有可以访问的内部ID.Opera和IE(可能是Safari?)支持.sourceIndex
(如果DOM有所改变),但Firefox没有这种类型.
您可以通过生成给定节点的Xpath或查找document.getElementsByTagName('*')
将始终按源顺序返回元素的节点的索引来模拟源索引.
所有这些当然需要一个完全静态的文件.对DOM的更改将破坏查找.
我不明白的是你如何放松对节点的引用而不是(理论上的)内部id?关闭和分配工作或他们不工作.或者我错过了什么?
你的问题的措辞有点混淆 - 你说你需要一个[你]可以用来引用该元素的字符串ID,"但你"不能在[你的]脚本中存储引用,因为当[你需要它们,GreaseMonkey脚本本身就会超出范围."
如果脚本超出范围,那你以后如何引用它们?!
我将忽略这样一个事实,即我对你所得到的东西感到困惑,并告诉你我经常编写Greasemonkey脚本,并且可以修改我访问的DOM元素,为它们提供ID属性.这是可用于获取临时使用的伪唯一值的代码:
var PseudoGuid = new (function() { this.empty = "00000000-0000-0000-0000-000000000000"; this.GetNew = function() { var fourChars = function() { return (((1 + Math.random()) * 0x10000)|0).toString(16).substring(1).toUpperCase(); } return (fourChars() + fourChars() + "-" + fourChars() + "-" + fourChars() + "-" + fourChars() + "-" + fourChars() + fourChars() + fourChars()); }; })(); // usage example: var tempId = PseudoGuid.GetNew(); someDomElement.id = tempId;
这对我有用,我自己用Greasemonkey脚本测试了它.
更新:闭包是要走的路 - 个人而言,作为一个核心的JavaScript开发人员,我不知道你怎么没有立即想到这些.:)
myDomElement; // some DOM element we want later reference to someOtherDomElement.addEventListener("click", function(e) { // because of the closure, here we have a reference to myDomElement doSomething(myDomElement); }, false);
现在,myDomElement
从您的描述中可以看出,其中一个元素已经存在(因为您正在考虑向其中添加ID,或者其他任何内容).
也许如果你发布一个你想要做的事情的例子,它会更容易帮助你,假设没有.
关闭是要走的路.这样你就可以准确地引用那些甚至可以在DOM的一些改组中存活的元素.
那些不知道闭包的例子:
var saved_element = findThatDOMNode(); document.body.onclick = function() { alert(saved_element); // it's still there! }
如果你必须将它存储在一个cookie中,那么我建议为它计算XPath(例如,沿着DOM计算前一个兄弟姐妹,直到找到带有ID的元素,你最终会得到类似的东西[@id=foo]/div[4]/p[2]/a
).
XPointer是W3C解决该问题的方法.
更新:闭包确实是答案.所以在摆弄它之后,我想出了为什么闭包最初有问题以及如何修复它.关闭闭包的棘手问题是,在遍历元素时必须小心,不要以所有闭包引用相同的元素结束.例如,这不起作用:
for (var i = 0; i < elements.length; i++) { var element = elements[i]; var button = document.createElement("button"); button.addEventListener("click", function(ev) { // do something with element here }, false) }
但这样做:
var buildListener = function(element) { return function(ev) { // do something with event here }; }; for (var i = 0; i < elements.length; i++) { var element = elements[i]; var button = document.createElement("button"); button.addEventListener("click", buildListener(element), false) }
无论如何,我决定不选择一个答案,因为这个问题有两个答案:1)不,你可以使用没有内部ID; 2)你应该使用闭包.所以我只是向第一个人投票说出是否有内部ID或谁建议生成ID,以及提到闭包的人.谢谢您的帮助!