Unique element ID, even if element doesn't hav

2019-01-22 11:59发布

I'm writing a GreaseMonkey script where I'm iterating through a bunch of elements. For each element, I need a string ID that I can use to reference that element later. The element itself doesn't have an id attribute, and I can't modify the original document to give it one (although I can make DOM changes in my script). I can't store the references in my script because when I need them, the GreaseMonkey script itself will have gone out of scope. Is there some way to get at an "internal" ID that the browser uses, for example? A Firefox-only solution is fine; a cross-browser solution that could be applied in other scenarios would be awesome.

Edit:

  • If the GreaseMonkey script is out of scope, how are you referencing the elements later? They GreaseMonkey script is adding events to DOM objects. I can't store the references in an array or some other similar mechanism because when the event fires, the array will be gone because the GreaseMonkey script will have gone out of scope. So the event needs some way to know about the element reference that the script had when the event was attached. And the element in question is not the one to which it is attached.

  • Can't you just use a custom property on the element? Yes, but the problem is on the lookup. I'd have to resort to iterating through all the elements looking for the one that has that custom property set to the desired id. That would work, sure, but in large documents it could be very time consuming. I'm looking for something where the browser can do the lookup grunt work.

  • Wait, can you or can you not modify the document? I can't modify the source document, but I can make DOM changes in the script. I'll clarify in the question.

  • Can you not use closures? Closuses did turn out to work, although I initially thought they wouldn't. See my later post.

It sounds like the answer to the question: "Is there some internal browser ID I could use?" is "No."

13条回答
Rolldiameter
2楼-- · 2019-01-22 12:12

If you can write to the DOM (I'm sure you can). I would solve this like this:

Have a function return or generate an ID:

//(function () {

  var idCounter = new Date().getTime();
  function getId( node ) {
    return (node.id) ? node.id : (node.id = 'tempIdPrefix_' + idCounter++ );
  }

//})();

Use this to get ID's as needed:

var n = document.getElementById('someid');
getId(n);  // returns "someid"

var n = document.getElementsByTagName('div')[1];
getId(n);  // returns "tempIdPrefix_1224697942198"

This way you don't need to worry about what the HTML looks like when the server hands it to you.

查看更多
\"骚年 ilove
3楼-- · 2019-01-22 12:12

In javascript, you could attach a custom ID field to the node

if(node.id) {
  node.myId = node.id;
} else {
  node.myId = createId();
}

// store myId

It's a bit of hack, but it'll give each and every node an id you can use. Of course, document.getElementById() won't pay attention to it.

查看更多
狗以群分
4楼-- · 2019-01-22 12:14

OK, there is no ID associated to DOM element automatically. DOM has a hierarchycal structure of elements which is the main information. From this perspective, you can associate data to DOM elements with jQuery or jQLite. It can solve some issues when you have to bind custom data to elements.

查看更多
疯言疯语
5楼-- · 2019-01-22 12:15

A bit confused by the wording of your question - you say that you "need a string ID that [you] can use to reference that element later, " but that you "can't store the references in [your] script because when [you] need them, the GreaseMonkey script itself will have gone out of scope."

If the script will have gone out of scope, then how are you referencing them later?!

I am going to ignore the fact that I am confused by what you are getting at and tell you that I write Greasemonkey scripts quite often and can modify the DOM elements I access to give them an ID property. This is code you can use to get a pseudo-unique value for temporary use:

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;

That works for me, I just tested it in a Greasemonkey script myself.


UPDATE: Closures are the way to go - personally, as a hard-core JavaScript developer, I don't know how you didn't think of those immediately. :)

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

Now, myDomElement is one of the elements you apparently, from your description, already have around (since you were thinking of adding an ID to it, or whatever).

Maybe if you post an example of what you are trying to do, it would be easier to help you, assuming this doesn't.

查看更多
虎瘦雄心在
6楼-- · 2019-01-22 12:15

Use mouse and/or positional properties of the element to generate a unique ID.

查看更多
Deceive 欺骗
7楼-- · 2019-01-22 12:23

I 'think' I've just solved a problem similar to this. However, I'm using jQuery in a browser DOM environment.

var objA = $("selector to some dom element"); var objB = $("selector to some other dom element");

if( objA[0] === objB[0]) { //GREAT! the two objects point to exactly the same dom node }

查看更多
登录 后发表回答