Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement unobtrusive javascript with dynamic content generation?

I write a lot of dynamically generated content (developing under PHP) and I use jQuery to add extra flexibility and functionality to my projects.

Thing is that it's rather hard to add JavaScript in an unobtrusive manner. Here's an example:

You have to generate a random number of div elements each with different functionality triggered onClick. I can use the onclick attribute on my div elements to call a JS function with a parameter but that is just a bad solution. Also I could generate some jQuery code along with each div in my PHP for loop, but then again this won't be entirely unobtrusive.

So what's the solution in situations like this?

like image 256
Brayn Avatar asked Sep 24 '08 10:09

Brayn


People also ask

What is the practical application of unobtrusive JavaScript?

Introduction. Unobtrusive JavaScript is the way of writing JavaScript language in which we properly separate Document Content and Script Content thus allowing us to make a clear distinction between them. This approach is useful in so many ways as it makes our code less error prone, easy to update and to debug.

How do you bind a click event to dynamically created elements?

You can use the live() method to bind elements (even newly created ones) to events and handlers, like the onclick event.

How do you add an event dynamic to an element?

Attaching the event dynamically className = 'dynamic-link'; // Class name li. innerHTML = dynamicValue; // Text inside $('#links'). appendChild(li); // Append it li. onclick = dynamicEvent; // Attach the event!


3 Answers

You need to add something to the divs that defines what type of behaviour they have, then use jQuery to select those divs and add the behaviour. One option is to use the class attribute, although arguably this should be used for presentation rather than behaviour. An alternative would be the rel attribute, but I usually find that you also want to specify different CSS for each behaviour, so class is probably ok in this instance.

So for instance, lets assume you want odd and even behaviour:

<div class="odd">...</div>
<div class="even">...</div>
<div class="odd">...</div>
<div class="even">...</div>

Then in jQuery:

$(document).load(function() {
$('.odd').click(function(el) {
// do stuff
});
$('.even').click(function(el) {
// dostuff
});
});

jQuery has a very powerful selector engine that can find based on any CSS based selector, and also support some XPath and its own selectors. Get to know them! http://docs.jquery.com/Selectors

like image 126
roryf Avatar answered Oct 20 '22 00:10

roryf


I would recommend that you use this thing called "Event delegation". This is how it works.

So, if you want to update an area, say a div, and you want to handle events unobtrusively, you attach an event handler to the div itself. Use any framework you prefer to do this. The event attachment can happen at any time, regardless of if you've updated the div or not.

The event handler attached to this div will receive the event object as one of it's arguments. Using this event object, you can then figure which element triggered the event. You could update the div any number of times: events generated by the children of the div will bubble up to the div where you can catch and handle them.

This also turns out to be a huge performance optimization if you are thinking about attaching multiple handlers to many elements inside the div.

like image 23
Rakesh Pai Avatar answered Oct 20 '22 01:10

Rakesh Pai


I would recommend disregarding the W3C standards and writing out HTML-properties on the elements that need handlers attached to them:

Note: this will not break the rendering of the page!

<ul>
    <li handler="doAlertOne"></li>
    <li handler="doAlertTwo"></li>
    <li handler="doAlertThree"></li>
</ul>

Declare a few functions:

function doAlertOne() { }
function doAlertTwo() { }
function doAlertThree() { }

And then using jQuery like so:

$("ul li").each(function ()
{
    switch($(this).attr("handler"))
    {
        case "doAlertOne":
            doAlertOne();
            break;

        case ... etc.
    }
});

Be pragmatic.

like image 41
cllpse Avatar answered Oct 20 '22 00:10

cllpse