Varun
Varun

Reputation: 5061

Attaching event in muliple browser

I had a function in which I had to attach event on an element newElement I checked the condition whether its IE or Firfox based on attachEvent property (works only in IE).

if ( typeof(newElement.attachEvent) != "undefined" )
{               
    newElement.attachEvent("onclick", deleteRow) ;  
    newElement.attachEvent("onclick", customDeleteScript) ;
}else
{   

    newElement.addEventListener("click", deleteRow, false) ;    
    newElement.addEventListener("click", customDeleteScript, false) ;               
} 

The required flow was deleteRow to execute first followed by customDeleteScript It is working fine in Firefox/Chrome but the flow changes in IE customDeleteScript executes before deleteRow in IE. So I had to do as follows:

if ( typeof(newElement.attachEvent) != "undefined" )
{               
    newElement.attachEvent("onclick", customDeleteScript) ;
    newElement.attachEvent("onclick", deleteRow) ;  
}else
{   

    newElement.addEventListener("click", deleteRow, false) ;    
    newElement.addEventListener("click", customDeleteScript, false) ;               
} 

The question here lies is this property of IE or it is just a random hit and trial kind of scenario for IE always?

EDIT: What in case my function contains some parameters like this and others and I don't know which function takes which parameters.

Upvotes: 0

Views: 105

Answers (4)

The Alpha
The Alpha

Reputation: 146191

If you want to execute the customDeleteScript() function after deleteRow() has been executed than you can simply add a return true statement at the end of the deleteRow() function like

function deleteRow()
{
    // other code
    return true;
}

and call customDeleteScript() like

if(deleteRow()) customDeleteScript();

You can use jfriend00's answer for event registering, it's more dynamic and registering two separate event handlers for that reason (as you described in your question) is not an appropriate way.

Update: After some research I've found that IE fires registered event handlers "last in first out(in reverse order)" for an element which has multiple events. Try this fiddle in both IE and Chrome/FF. For example

function addEventHandler(to_element,event,handler)
{
    if (to_element.addEventListener) to_element.addEventListener(event,handler,false);
    else if (to_element.attachEvent) to_element.attachEvent("on"+event,handler);
    else return false;
}


function function1()
{
    alert("first alert");
}

function function2()
{
    alert("second alert");
}

var obj=document.getElementById('obj');
addEventHandler(obj,"click",function1);
addEventHandler(obj,"click",function2);​

In Chrome function1 will be fired first and then function2 will be fired but in IE function2 will be fired first and then function1 (reverse order). So according to the question I think only one event should be registered and call both functions in the same handler like

function deleteRow()
{
    // other code here
    return true;
}
function customDeleteScript()
{
    // code here
}
addEventHandler(obj,"click",myHandler);
function myHandler()
{
    if(deleteRow()) customDeleteScript();
}

Upvotes: 1

kennebec
kennebec

Reputation: 104770

the order of events attached with attachEvent to the same element and type is not guaranteed to be the order in which they are declared. This is not the behavior of addEventListener, which does execute in the declared order. If the order is important, you may have to call the second function from the first, or combine them into one.

Another difference is attachEvent will attach the same handler as many times as it is called, so that the same function can be called many times instead of only once. addEventListener only assigns it once, no matter how many times you call it with the same arguments.

Since IE9+ does support addEventListener, change the order of your assignment, and account for multiple assignments (it does no harm to attempt to delete a nonexistant handler):

if (newElement.addEventListener ){
    newElement.addEventListener("click", deleteRow, false) ;    
    newElement.addEventListener("click", customDeleteScript, false) ;  
}
else if(newElement.attachEvent){   
    newElement.detachEvent("onclick", customDeleteScript) ; 
    newElement.detachEvent("onclick", deleteRow);   
    newElement.attachEvent("onclick", customDeleteScript) ;
    newElement.attachEvent("onclick", deleteRow) ;  
}

Upvotes: 0

jfriend00
jfriend00

Reputation: 707288

If order is important, you should not use separate event handlers. Call both functions in the desired order from one event handler like this:

function delete() {
    deleteRow();
    customDeleteScript();
}

if ( typeof(newElement.attachEvent) != "undefined" )
{               
    newElement.attachEvent("onclick", delete) ;  
}else
{   

    newElement.addEventListener("click", delete, false) ;    
} 

FYI, a generic event handler function that you can reuse works like this:

function addEvent(elem, event, fn) {
    if (elem.addEventListener) {
        elem.addEventListener(event, fn, false);
    } else {
        elem.attachEvent("on" + event, function() {
            // set the this pointer same as addEventListener when fn is called
            return(fn.apply(elem, arguments));   
        });
    }
}

Note, it's better to check for addEventListener first so if both methods exist (like in IE9), your code will use the standard way.

So, your code can work like this:

addEvent(newElement, 'click', function() {
    deleteRow();
    customDeleteScript();
});

Upvotes: 1

Tom
Tom

Reputation: 4180

you can solve it by putting those two handlers in one function and set that one function as the handler:

function handler() {
    deleteRow();
    customDeleteScript();
}

if (typeof(newElement.attachEvent) != "undefined") {               
    newElement.attachEvent("onclick", handler) ;  
} else {   
    newElement.addEventListener("click", handler, false) ;               
} 

Upvotes: 0

Related Questions