Search code examples
javascriptprototypejs

Dynamically add hyperlinks to DOM with pre-wired events?


I have a table where one column includes a hyperlink. On page load, there's a number of rows already populated, and I am enumerating over the array and hooked up the click event on each hyperlink:

$$("a[id^=remove]").each(function (item) {
    item.observe("click", removeDevice);
});

This part works; clicking on the hyperlink runs the removeDevice method, which includes an Event.stop call to prevent the hyperlink from navigating away.

Later, I add new rows to this table and need to have new hyperlinks that work the same. I'm creating these dynamically using Prototype, like this:

var remove = new Element("a", { id: "remove-{SerialNumber}".interpolate(device), href: "/Home/Javascript" })
    .update("Remove")
    .observe("click", removeDevice);

However, I'm now stuck with how to get this element into my table and still have the events wired up. I can get the hyperlink to show up by doing this:

newRow.insert({ bottom: new Element("td").update(remove.outerHTML) });

but, as you might suspect, the events no longer work here. Is there a way to add the element directly, keeping the events I've wired up?


Solution

  • I've done this same thing in the past and had to figure out how to use event propagation to observe the event at the parent so all the elements (dynamic or otherwise) trigger my handler

    using your example of rows of data

    <table id="clickablerows">
        <tr><td><a href="javascript:void(0);" class="clickme">Click Me</a></td></tr>
        <tr><td><a href="javascript:void(0);" class="clickme">Click Me</a></td></tr>
        <tr><td><a href="javascript:void(0);">Don't Click Me</a></td></tr>
    </table>
    

    you can observe the table element but watch for the event that bubbles up from the link

    $('clickablerows').on('click','.clickme',function(e,target){
        // e is the Event object
        // `this` is the <table> element
        // target is the element that matches the CSS selector (2nd parameter)
    
    });
    

    with it wired up this way you only have one observer vs lots of observers from doing $$().each() and no matter what elements are added to the table if they match the CSS selector it fires the handler. Sometimes I will be lazy and do document.on('click','.clickme',function(e,target){}) which watches for clicks at the root document object

    Caveat : some events do not bubble like focus or blur, check on MDN to see if the event you want to use will bubble up to parent elements.