tags:

views:

89

answers:

4

Here's what I'm trying to do: I have a bookmarklet that is looking for elements in the current page (which can be any site) and dispatch a click event on the ones that match. I have that part working.

In some cases though, nothing matches automatically and I want to be able to show (by hovering it) what element should be activated and then save some info about it in localStorage. The next time I'm using the bookmarklet on that page, I want to retrieve that info to identify the element in the DOM and then dispatch a click event.

The question is: what information should I save to be able to identify it? (in most cases, since it will always be possible to create a case where it doesn't work)

In the best case, said-element will have an id value and I'm good to go. In some other cases, it won't and I'd like to see your suggestions as to what info and what method I should use to get it back.

So far my idea is to save some of the element's properties and traverse the DOM to find elements that match everything. Not all properties will work (e.g. clientWidth will depend on the size of the browser) and not all types of elements will have all properties (e.g. a div node won't have a src value), which means that on one hand, I can't blindly save all properties, but on the other, I need to either choose a limited list of properties that will work for any kinds of element (at the risk of losing some useful info) or have different cases for different elements (which doesn't sound super great).

Things I was thinking I could use:

  • id of course
  • className, tagName would help, though className is likely to not be a clear match in some cases
  • innerHTML should work in a lot of cases if the content is text
  • src should work in most cases if the content is an image
  • the hierarchy of ancestors (but that can get messy)
  • ...?

So, my question is a bit "how would you go about this?", not necessarily code. Thanks!

+1  A: 

What about finding all elements without an ID and assigning them a unique id. Then you could always use id.

brendan
But how can I make sure that the `id`'s I generate would be the same once the page is reloaded? What would you base the `id`s on: on some kind of hash of other information? If so, it goes back to my question about what info to use.
Timothée Boucher
A: 

an approach would be using name, tagName and className-combination. innerHTML could may be too big.

another approach would be to look for child elements of your choosen element which have an id.

check for id => check for childs with id => check for name, tagName and className-combination (if => tell user to choose a different item :-)

henchman
Interesting idea with going with the children (if any). By default I would have gone with ancestors first (mostly because there are more likely to have ancestors than children), but that's true that if I can find a descendant with an `id`, the ancestor `n` levels up should be pretty safely the one I want. If I were to go with ancestors with `id`, there might be confusion more easily.I'll dig a bit your idea of "fail-over" to less sure methods, from `id`, to `className`.
Timothée Boucher
+1  A: 

You could do what @brendan said. You can also make up a jQuery-style selector string for each element in the DOM by figuring out the element's "index" in terms of its place in its parent's list of child nodes, and then building that up by walking up the DOM to the body tag.

What you'd end up with is something that looks like

body > :nth-child(3) > :nth-child(0) > :nth-child(4)

Of course if the DOM changes that won't work so good. You could add class names etc, but as you said yourself things like this are inherently fragile if you don't have a good "id" to start with, one that's put there at page creation time by whatever logic knows what's supposed to be in the page in the first place.

Pointy
A: 

What about using the index (integer) of the element within the DOM? You could loop through every element on page load and set a custom attribute to the index...

var els = document.getElementsByTagName("*");
for(var i = 0, l = els.length; i < l; i++) {
  els[i].customIndex = i;
}
Josh Stodola