SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Member
    Join Date
    Apr 2005
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Solved] Function pointers and events

    Hey, I'm having some trouble understanding IE's event model. Basically I want to attach a popUpWin() function to onclick in certain anchor tags. I have the anchor tag object...
    Code:
    var anchors = document.getElementsByTagName("a");
    	
      for (var i = 0; i < anchors.length; i++) {
        var anchor = anchors[i];
        ...
    and it works fine in firefox by modifying the onclick attribute:
    Code:
    ...
      // var winAttributes = an intelligent list of window.open attributes.
      var linkDest = anchor.getAttribute("href");
      var tOnClick = "popupWin('" + linkDest + "','" + winAttributes + "');";
      tOnClick += "return false;";
      anchor.setAttribute("onclick", tOnClick);
    but IE isn't having any, of course, so I spent two days googling, trying to understand DOM and IE event handling to no avail.
    If I try to attach an event to the anchor tag in IE I have to use a (so-called) function pointer:
    Code:
    ...
    if (ie4) {
      anchor.attachEvent("onclick", popUpWin);
    } else {//do the above
    ...
    } // end if
    Which means I can't pass the correct href argument to the popUpWin function, right? How can I get the right arguments to the right functions using references?

    TIA,
    Mike
    Last edited by kojiro; May 3, 2005 at 10:36. Reason: Solved

  2. #2
    I'll take mine raw silver trophy MikeFoster's Avatar
    Join Date
    Dec 2002
    Location
    Alabama, USA
    Posts
    2,560
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Mike,

    You've almost got it

    Have a look at example 2 in this demo: accessible_js_links.

  3. #3
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    After writing my answer I decided to split it into three parts, for better understanding.

    Simple stuff.

    You need to assign some function (not string) to object's "onclick" attribute. This is a simplest and most portable way:

    Code:
    function myClick() {
    	alert("hello, " + this.href);
    }
    
    onload = function()
    {
    	var links = document.getElementsByTagName("A");
    	for(var i = 0; i < links.length; i++)
    		links.item(i).onclick = myClick;
    }
    Advanced stuff.

    In javascript, "function" can be everything that has type "Function". Along with function names, this includes function expressions and function literals, also known as "anonymous functions". Thus, there is no need to declare "myClick", you can just assign it directy:

    Code:
    onload = function()
    {
    	var links = document.getElementsByTagName("A");
    	for(var i = 0; i < links.length; i++)
    		links.item(i).onclick = function() {
    			alert("hello, " + this.href);
    		}
    }
    Even more advanced stuff.

    Iterators are better than loops. Javascript has no builtin support for iterators, but this language is extremely easy to extend.

    Code:
    // tell all Functions how they should iterate
    
    Function.prototype.forEach = function(aCollection) {
    	for(var i = 0; i < aCollection.length; i++)
    		this.apply(aCollection.item(i));
    }
    
    // Combine iterators with an anonymous function approach
    
    onload = function()
    {
    	(function() {
    		this.onclick = function() {
    			alert("hello, " + this.href);
    		}
    	}).forEach(
    		document.getElementsByTagName("A")
    	);
    }
    HTH...

  4. #4
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Your problem is this line:
    Code:
    anchor.setAttribute("onclick", tOnClick);
    Event handlers are not considered html attributes, so setAttribute() doesn't work.

    If I try to attach an event to the anchor tag in IE I have to use a (so-called) function pointer...
    Which means I can't pass the correct href argument to the popUpWin function, right?
    Don't use attachEvent()--it's not cross browser. Instead, there is another method that is cross browser that allows you to assign event handler functions. With the cross browser method, inside the event handler function the 'this' keyword will refer to the html element. Therefore, inside the event handler function, you can get the href using the reference: this.href, and you can use that in your popup window.

    Here is a cross browser method for assigning onclick event handlers:
    Code:
    var anchors = document.getElementsByTagName("a");
    
    for (var i = 0; i < anchors.length; i++) 
    {
    	anchors[i].onclick = somefunc;
    }	
    
    function somefunc()
    {
    	alert(this.href);
    }
    Typically, that code would be in the <head> section of the page. However, the js in the <head> of a page is executed before the rest of the page has been parsed, so at that time no html elements exist, e.g your <a> tags, and if you refer to them, you will get an undefined error. So, to remedy that, you have to wrap the code in a window onload event handler:
    Code:
    window.onload=function()
    {
    	
    };
    Anything inside there will be executed right after the page loads, so you can refer to html elements inside those braces. Putting it together looks like this:
    Code:
    window.onload=function()
    {
    	var anchors = document.getElementsByTagName("a");
    
    	for (var i = 0; i < anchors.length; i++) 
    	{
    		anchors[i].onclick = somefunc;
    	}	
    };
    
    function somefunc()
    {
    	alert(this.href);
    }
    Furthermore, suppose you need to pass some additional parameters to your onclick event handler that are not part of the html element and therefore are not accessible using 'this'. You can always do something like this:
    Code:
        ...
        anchors[i].onclick = intermediateFunc;
    };
    
    intermediateFunc()
    {
          someFunc(this, 50, "some text");
    }
    
    someFunc(elmt, num, text)
    {
        alert(elmt.href);
        alert(num);
        alert(text);
    }
    Last edited by 7stud; May 3, 2005 at 11:11.

  5. #5
    SitePoint Member
    Join Date
    Apr 2005
    Posts
    8
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Solution

    Gentlemen (or ladies, as the case may be),

    Thank you so much!

    I've got the solution now. I won't post it because it's just some slight modifications to what stereofrog wrote. It's working now, and my website is 100% tableless xhtml strict and css, with links that work whether you have javascript enabled or not.

    7stud, this reflects what I don't understand about IE's "event handling," but when you say events are not attributes, you are just referring to IE, right? modifying the "onclick" attribute works fine for firefox.

    I read in O'Reilly's JavaScript: The Definitive Guide that IE doesn't "capture events". Does that have something to do with the fact that IE doesn't allow you to modify "onclick" as an attribute?

  6. #6
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    7stud, this reflects what I don't understand about IE's "event handling," but when you say events are not attributes, you are just referring to IE, right? modifying the "onclick" attribute works fine for firefox.
    Ok. I probably knew that at one time, but since it's so much easier to use one crossbrowser method, I don't use setAttribute() for event handlers. You should also be wary of using setAttribute() for regular attributes if you need it to work in all browsers. It's also much easier to set attributes like this:

    elmt.src = "something";
    elmt.href = "a url";

    I read in O'Reilly's javascript: The Definitive Guide that IE doesn't "capture events". Does that have something to do with the fact that IE doesn't allow you to modify "onclick" as an attribute?
    I don't think so. I don't know why it would since "capturing" or "bubbling" just describe the direction the event travels.

    In O'Reilly, this method for assigning event handlers:

    anchors[i].onlclick = somefunc;

    is referred to as "Event Handlers as Properties" or the Level 0 DOM event registration model. It's crossbrowser, and the problem with sending parameters can be overcome in several different ways(see the bottom of my previous post for one way.).

  7. #7
    SitePoint Wizard
    Join Date
    Mar 2001
    Posts
    3,537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    7stud, this reflects what I don't understand about IE's "event handling,"
    If you use the method:

    anchors[i].onclick = somefunc;

    it works the same in all browsers.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •