tags:

views:

743

answers:

7

Let's say I'm generating markup through server-side code. I'm generating a bunch of HTML tags but I want to add custom attributes (properties).

In JavaScript (if I had a reference to the DOM node I could write):

var myDOMNode = ...
myDOMNode.myCustomAttribute = "Hi!";

The issue here is that I don't want to qualify every element with an unique id just to initialize data.

If I'm remembing this correctly, this is valid IE stuff.

<div onload="this.myCustomAttribute='Hi!'"></div>

If I added an event handler on that element I should be able to access it's "data context" though the identifier 'myCustomAttribute', which is really what I want.

If anyone has a neat trick to make this happen, I'm all ears.

EDIT:

I don't want to go against W3C recommendations or re-purpose attributes in a hackish way and I don't want to depend on IE only stuff.

@AnthonyWJones, a technique I usually go about using is that I tag DOMElements with data when working with JavaScript. To the extent of my knowledge it's perfectly OK to say that even though the property is undefined I can set a property on any object and refer to that later.

var myObj = ...
alert(myObj.someProperty); // undefined
myObj.someProperty = "Hi!";
alert(myObj["someProperty"]); // Hi!

Objects in JavaScript are just name/value dictionaries. When I wrote that attribute thing, this is what I meant. Sorry for that.

It really bothers me that the only purpose these id="" attributes will have is to initialize this data.

For the record, I could be going about this the wrong way but I really want to pursue this idea a bit more, because it's appealing to me.

A: 

How about this?

<script>
    function LoadElement(myDiv)
    {
        alert(this.myCustomAttribute);
    }
</script>

<div onload="LoadElement(this)"></div>

not tested btw

Dan Williams
The onload event is only fired by the IE web browser and it's not standards compliant, but it's exactly what I want to do.
John Leidegren
+1  A: 

The following will work but not validate:

<div myattribute="myvalue"></div>

But if you are injecting it into the HTML with Javascript, then perhaps that's not concern for you. Otherwise, you can use something like jQuery to process the elements before adding them to the DOM:

$(elements).each(function(){
     $(this).attr('myattribute','myvalue');
});
Eran Galperin
Close, but no cigar. How would I reference the DOM elements from JavaScript without giving every element an unique id, that my point. Maybe it's impossible but I'm looking for a really mean and lean way of doing this.
John Leidegren
Not really sure what you are talking about. The second approach I gave you does exactly what you want - it's inside a callback, you are free to give them what attributes you wish.
Eran Galperin
Well, in HTML I have some elements (not all) that I'd like to assign data, but in JavaScript I have no way to reference these elements. I can not assume that the data applies to all elements. I need to isolate a few, but do I really need to put an id="" on every such element? It feels unnecessary.
John Leidegren
A: 

Since you're trying to do this for multiple elements, you may try name attributes and getElementsByName.

<div name="handleonload">...</div>

window.onload = function () {
    var divs = document.getElementsByName('handleonload');
    for (var i = 0; i < divs.length; i += 1) {
        divs[i].foo = 'bar';
    }
};

Alternatively, you can use selectors, using libraries (such as jQuery and Prototype) and their respective iterators. This will also allow for you to search by other attributes (such as class).


Though, be cautious with your terminology:

obj.property = value;

<tag attribute="value">
Jonathan Lonowski
getElementsByName doesn't work in Internet Explorer unless the field officially supports the name attribute. A selector library is probably the better option.
Matthew Crumley
I'd like to avoid re-purposing attributes defined in the standard...
John Leidegren
+1  A: 

First off you should access custom attributes using the getAttribute and setAttribute methods if you want your code to work on other browsers than IE.

As to your event handler question that really depends on how you add the event handler. Assigning a function directly to the elements onXXXX property would allow you access the the element via this.

If you use IE's attachEvent you can't use this, you can access the element that generated the event using event.srcElementbut that may be child element of the div. Hence you will need to test for the existance of myCustomAttribute and search up the ancestors until you find it.

AnthonyWJones
I second the use of getAttribute and setAttribute. Sometimes it works w/ direct property access (object.myCustomAttribute = ...) but it may depend on the property name and the object... (I believe "class" is problematic for setting CSS classes)
Jason S
A: 
<div style="width:100px;height:100px;border:solid black 1px" myCustomAttribute='Hi!' onclick="alert(myCustomAttribute);"></div>
DMKing
A: 

The onload event is used for server side events. Its not part of the standard html element events.

Jobo
No it's not, the onload event is a client side javascript event.
Pim Jager
is it, for html elements? sorry pal, its not.
Jobo
A: 

Take a look at the following functions (especially the *walk_the_dom* one):

// walk_the_DOM visits every node of the tree in HTML source order, starting
// from some given node. It invokes a function,
// passing it each node in turn. walk_the_DOM calls
// itself to process each of the child nodes.
var walk_the_DOM = function walk(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walk(node, func);
        node = node.nextSibling;
    }
};

// getElementsByAttribute takes an attribute name string and an optional
// matching value. It calls walk_the_DOM, passing it a
// function that looks for an attribute name in the
// node. The matching nodes are accumulated in a
// results array.
var getElementsByAttribute = function (att, value) {
    var results = [];

    walk_the_DOM(document.body, function (node) {
        var actual = node.nodeType === 1 && node.getAttribute(att);
        if (typeof actual === 'string' &&
                (actual === value || typeof value !== 'string')) {
            results.push(node);
        }
    });
    return results;
};

With the above two functions at hand, now we can do something like this:

<a href="#" dreas="">some link</a>
<script>
var els = getElementsByAttribute('dreas');
if (els.length > 0) {
    els[0].innerHTML = 'changed text';
}
</script>

Notice how now I am making finding that particular element (which has an attribute called dreas) without using an id or a class name...or even a tag name

Andreas Grech