views:

428

answers:

3

I was trying to make a javascript gallery script by my own. When i have done with it i was pretty happy, until i noticed, that it doesn't work in IE6. In FireFox everything looks fine. So i started debugging.

I noticed, that setAttribute is one of the problems for sure. Maybe even the biggest. So after viewing an interetsing article about setting onclick property with parameters i was kind of happy, but one thing stayed unsolved for me. Using callback method is tricky, but i just don't know how to pass event object that way. Here is the old code sample:

    var miniatury = document.getElementsByTagName ("a");
function zoom (){
    for (l = 0; l < miniatury.length; l++) {
       if (miniatury[l].className.match("zoom") != null  ) {
        var href = miniatury[l].href;
        if (document.images) {
         preImg[l] = new Image();
         preImg[l].src = href;
         miniatury[l].setAttribute("onclick", "przybliz(preImg["+[l]+"].src, event); event.returnValue=false; return false;");
        }
        else {
        miniatury[l].setAttribute("onclick", "przybliz(href, event); event.returnValue=false; return false;");}
        }
    }
}
function przybliz(adres, event) {   
pojemnik.style.display = 'block';
if (navigator.appName == "Microsoft Internet Explorer") {
    pozycjaX= window.event.clientX + document.documentElement.scrollLeft
      + document.body.scrollLeft;
    pozycjaY= window.event.clientY + document.documentElement.scrollTop
      + document.body.scrollTop;
  }
  if (navigator.appName != "Microsoft Internet Explorer") {
    pozycjaX = event.clientX + window.scrollX;
    pozycjaY = event.clientY + window.scrollY;
  }
pojemnik.style.top = pozycjaY+'px';
pojemnik.style.left = pozycjaX+'px';

Question is: How to change the code into

onclick = callback(f, arguments)

with passing event object values, and having the luxury to use them later ?

+1  A: 

The best way is to just append a handler to it. eg:

if (minitury.attachEvent) {
     minitury.attachEvent("onclick", callback);
} else {
     minitury.addEventListener("click", callback, false);
}

Where callback is a function with a single parameter. Like below:

function callback(evt) {
     if (! evt) evt = window.event;
     <insert other code here>
}

This should be what you're looking to do.

EDIT: I realized you were asking how to send parameterized callbacks. I doubt there is a good cross-browser method of doing this, but you could get around that by adding a custom attribute to the element in question which holds your data and through the event object (either evt.target or evt.srcElement) you can access the element. Make sure to follow the guidelines set by the w3c for custom attributes. w3c custom attributes

Myles
Adding a custom attribute is one way, yes. But be careful about storing a reference to a JavaScript object in a custom attribute (storing text is fine), because that can leak memory in IE (until browser close in IE6, until page unload in IE7, not sure in IE8) because you might have a reference to the DOM in JS and a reference to a JS object in that DOM object, creating a circular reference that the IE garbage collector doesn't know it can break.
Anthony Mills
+1  A: 

Well, doing it with jQuery:

$(miniatury[l]).bind("click", preImg[l], przybliz);

After which you could retrieve it in the function:

function przybliz(evt) {
    var adres = evt.data;
    //...
}

Without jQuery it becomes a bit more difficult, since you might have to store the value in a closure, which unless you're careful can force the whole scope chain to stay in memory (not a good thing).

Anthony Mills
This is one of those areas where doing it yourself is very tricky to get right (like, say, writing a multithreaded queue). Use a library's function to get it right since there are a lot more people bugtesting jQuery than will be bugtesting your app.
Anthony Mills
Thanks Anthony. Your answer was helpful. I mean it doesn't work now, but i guess that since basic javascript doesn't have a clear and simple solution for my problem... now is the right time for me to learn more about jQuery or other libraries. Shortly after i shall return to this problem with a difrent view.
Luigi
+1  A: 

IE6 is pretty bad that way. Getting familiar with raw JS is essential, but ultimately you won't want to be bothered with making all kinds of accommodations for the little differences between browsers.

Antony Mills shows you how easy a framework (like jQuery or prototype) can make your life. Another key thing about frameworks is that they have usually thought long and hard about all of these cross browser issues so that you don't have to.

Ewan Todd