Setting properties of anonymous DOM elements via JavaScript?

Let's say I generate markup via server side code. I am generating a bunch of HTML tags but want to add custom client side behavior.

With JavaScript (if I had a DOM node reference), I could write:

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

      

Now the problem is that I don't want to qualify each item with a unique ID just to initialize the data. And it's really strange to me that there is no easier and more unobtrusive way to enforce client-side behavior.

If I get myself right this is really IE stuff.

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

      

If I could do that, I could access it by the "data context" though the identifier is "myCustomAttribute", which is really what I want.

+1


source to share


10 replies


I am doing apricate input, but I finally figured it out and this is how I am doing initialization, which was a thorn in my side.

What you never do is pollute your global namespace with a bunch of short identifiers. Every time you put id=""

on an element you are doing exactly this (same for any top-level function). Relying on jQuery, HTML5 data and CSS is a solution to my problem, which I think is pretty nifty.

What I do is that I reserve a CSS class for a specific behavior and then use the HTML5 data to parameterize the behavior. When the document is ready, I query the document (using Query) for a CSS class that represents the behavior and initializes the client-side behavior.

I've done a lot of ASP.NET, and in this context both tags id=""

and name=""

are both ASP.NET and pretty useless for anything other than ASP.NET internals. What you usually do is to get a server side property called ClientID

that you can reference it from the client side JavaScript is a lot of hassle. They made things easier in 4.0, but basically I think it broke a lot.

Using this hybrid of CSS, HTML5 data and jQuery solves this problem altogether. Here's an example of attached behavior where regular expressions are used to validate the input of a text field.



<input type="text" class="-input-regex" data-regex="^[a-z]+$" />

      

And here's the script:

$(function () {

    function checkRegex(inp) {
        if (inp.data("regex").test(inp.val()))
            inp.data("good-value", inp.val());
        else
            inp.val(inp.data("good-value"));
    }

    $(".-input-regex")
        .each(function () {
            // starting with jQuery 1.5 
            // you can get at HTML5 data like this
            var inp = $(this);
            var pattern = inp.data("regex");
            inp.data("regex", new RegExp(pattern));
            checkRegex(inp);
        })
        .keyup(function (e) {
            checkRegex($(this));
        })
        .change(function (e) {
            checkRegex($(this));
        })
        .bind("paste", undefined, function (e) {
            checkRegex($(this));
        })
        ;

});

      

Completely clean, no lag id=""

or compulsive addiction.

+1


source


The following will work, but not confirm:

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

      



But if you're injecting it into HTML with Javascript, then it might not concern 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');
});

      

+1


source


You must first access custom attributes using methods getAttribute

and setAttribute

if you want your code to work in browsers other than IE.

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

.

If you are using IE attachEvent you cannot use this

, you can access the element that generated the event using event.srcElement

, but it could be a child of a div. Hence, you will need to check for the existence of myCustomAttribute and look for ancestors until you find it.

+1


source


In the HTML5 the HTML5 data attributes introduced exactly for this case.

<!DOCTYPE html>
<div data-my-custom-attribute='Hi!'></div>

      

is now the corect validator html. You can use any name starting with data-

any number.

There is a jQuery.data

method to interact with them. Use .data( key )

to get .data(key, value)

, to set an attribute data-key

. For example,

$('div').each(function () {
     $(this).html($(this).data('myCustomAttribute')).data('processed', 'OK');
});

      

+1


source


How about this?

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

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

      

not tested btw

0


source


Since you are trying to do this for multiple elements, you can try attributes name

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 a selector using libraries (such as jQuery and Prototype) and their respective iterators. It will also allow you to search for other attributes (for example class

).


Be careful with the terminology though:

obj.property = value;

<tag attribute="value">

      

0


source


<div style="width:100px;height:100px;border:solid black 1px" myCustomAttribute='Hi!' onclick="alert(myCustomAttribute);"></div>

      

0


source


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

0


source


Take a look at the following functions (especially on 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, we can now 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 I now find searching for that particular element (which has an attribute dreas

) without using the name or class name ... or even the tag name

0


source


It looks like jQuery is the best bet for this based on my search. You can link an object to a DOM node with:

var domNode = ...
var myObject = { ... }
$(domNode).data('mydata', mymyObj);

      

then you can call the data in the same way using your key.

var myObect = $(domNode).data('mydata');

      

I assume you can also store a reference to this inside this object, but that might be more information than you really want. Hope I can help.

0


source







All Articles