1

I'm reading through elements on the page (of all kinds) with JavaScript and modifying them if needed. When I do modify one of the elements, I want to leave a marker behind to say that I modified it. Then later, I can read through the elements on the page and if I find that marker, I know it's one of the elements I modified and can restore it. Here's code that's working for me, but it was suggested I should be using setAttribute and getAttribute rather than what I'm doing:

//hide some elements, after first leaving a marker and saving orig. val
for(var i=0; i<elements.length; i++) {
    if(should_i_hide_this_element(elements[i])) {    //external logic unimportant

        elements[i].wasModifiedByMe = true;             //mark element as modified
        elements[i].origViz = elements[i].style.visibility; //save visibility val
        elements[i].style.visibility = "hidden";          //and give it a new val
    }
}

The corresponding code to restore the element values is like this:

for(var i=0; i<elements.length; i++) {
    if(elements[i].wasModifiedByMe) {                 //This is one I modified
        elements[i].style.visibility = elements[i].origViz; //restore original val
        elements[i].wasModifiedByMe = false;          //mark as not modified now
    }
}

The question is, should I be using setAttribute and getAttribute for my wasModifiedByMe boolean and my origViz properties? I don't believe currently that I need to use the attribute functions for my own added properties.

Following thread discussions below, I tried this test:

<!doctype html>
<html>
<body>
<div id="mydiv">DIV</div>
<script>
var elem = document.getElementById("mydiv");
elem.secretproperty = "not_seen_in_elements_tab_in_chrome_dev_tools";
elem.setAttribute("publicproperty","is_visible_in_elements_tab");
</script>
</body>
</html>

and in the elements tab in the chrome dev tools, I saw that mydiv was showing that publicproperty attribute as part of the div. It was NOT showing the secretproperty though.

It's as I thought. Using setAttribute is setting a HTML Attribute that is also reflected in the javascript object, but when NOT using setAttribute and adding a property to the javascript host object, the reflection does not go the other way (TO the HTML attributes). This is what I want. I don't want that every element I've hidden suddenly displays a wasHiddenByMe="true" attribute (although there is merit in that, I see that).

Dee2000
  • 1,641
  • 2
  • 18
  • 21
  • 1
    My advice is to use classes for this, and write CSS based on the class. The presence of the class tells you if it was modified by you. – kapa May 31 '12 at 12:46
  • Good suggestion, but classes aren't appropriate in this case. My code can be added to ANY page and will hide some elements when asked to, and restore them later. – Dee2000 May 31 '12 at 12:55
  • 1
    You can still use classes, but you can keep `style.visibility` then. – kapa May 31 '12 at 13:03
  • I guess I don't know how this would work. I don't venture into the CSS classes world. Presumably this would rely on the fact that an element can inherit/belong to multiple classNames, and I could add/remove when I choose. I'm at risk of something else on the page potentially altering classes on me though. (everything I've just said could be nonsense and really expose how little I know about CSS classes) – Dee2000 May 31 '12 at 13:14
  • 1
    The page can potentially alter your properties as well. Multiple classnames are allowed, you can later query the elements from the DOM, you can style them with CSS, classes give you a lot of options. – kapa May 31 '12 at 13:43

2 Answers2

2

For adding attributes to HTML Elements, the W3C standard is setAttribute. You can't use it for element.style.property.

However, setting attributes by simply doing element.*attribute* still works. It's just not a real standard, so it may be better to use setAttribute, but this is up to your preference.

user2428118
  • 7,935
  • 4
  • 45
  • 72
  • am I wrong in thinking that element.setAttribute("xyz","XYZ") on a div, would show xyz="XYZ" when viewing that element in the browser dev tools? Whereas doing element.xyz="XYZ" would NOT Show it, because it hasn't created an HTML attribute, instead it's just created a property of the element OBJECT. In which case, this is what I want, that it's not a proper HTML attribute. – Dee2000 May 31 '12 at 13:02
  • Confirmed with this test case. var elem = document.getElementById("mydiv"); elem.hello = "world"; elem.setAttribute("rock","roll"); I saw in the chrome dev tool that div properties showed rock="roll" but I never saw hello="world". So using setAttribute is definitely not what I want. I think. – Dee2000 May 31 '12 at 13:05
2

There are some issues with setting your own properties of DOM elements, covered by this article on perfectionkills.com. It talks about extending DOM element prototypes, but the sections

are relevant to you. Yet, if your are aware of the issues I think it is OK - it is the only way to accociate custom objects to DOM elements.

If you can use HTML5 techniques, you also may have a look at data attributes. For simple boolean markers they may be the superior approach.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks. I've looked at your links. It sure seems to me now (after adding my little test page to my original post) that avoiding setAttribute is what I really want. Collision avoidance was definitely a consideration, my variable names are far more unique than in the example code in the original post. Unfortunately can't use HTML5-only properties. Still have to support the legacy browsers. – Dee2000 May 31 '12 at 13:30
  • 2
    If you use data-*attributes* with the setAttribute method, legacy browsers will support it. You just won't be able to access them the HTML5 way, with the [dataset](https://developer.mozilla.org/en/DOM/element.dataset) property. – Bergi May 31 '12 at 13:38
  • 1
    +1 `data-` attributes can be used in older browsers. For those browsers, they are simply HTML attributes. – kapa May 31 '12 at 13:45
  • I've changed my code now to use get/setAttribute and although I've no particular HTML5 use for the dataset, I've anyway prefixed the names with "data-" simply because there's no good reason not to :) Thanks guys. – Dee2000 May 31 '12 at 19:02