3

Javascript is pretty shaky for me, and I can't seem to find the answer to this. I have some code along the lines of

var Scheduler = function(divid,startDate,mode){

    this.setHeader = function(){
          header.innerHTML = '<a href="#" onclick="this.showScheduler(1);">Show</a>';

    }

   this.showScheduler = function period(){

        ...
   }

};

My problem is, how do I put the onclick into the HTML so that it properly calls the showScheduler function for the appropriate instance of the current scheduler object that I'm working with?

Amy Anuszewski
  • 1,843
  • 17
  • 30

6 Answers6

4

I wouldn't do whatever it is you're doing the way you're doing it, but with the code the way you have it, I would do this (lots ofdo and doing :) ):

var Scheduler = function(divid, startDate, mode){
    var that = this;

    this.setHeader = function(){
          header.innerHTML = '<a href="#">Show</a>';
          header.firstChild.onclick = function() { that.showScheduler(1); };
    }

   this.showScheduler = function period(){

        ...
   }
};
nickytonline
  • 6,855
  • 6
  • 42
  • 76
  • 1
    I'm surprised by the lack of clarity around ol' school event handlers and DOM elements in the answers so far. Yours is the first to get it. – Crescent Fresh Sep 03 '09 at 20:02
  • @crescentfresh - I like to kick it old school ;) – nickytonline Sep 03 '09 at 20:03
  • To all, you can obviously use cross-browser frameworks for attaching the events, but in the spirit of Old School (I drink Diet Pepsi) I thought it was more appropriate, especially since Amy didn't specify she was using a client-side framework. – nickytonline Sep 03 '09 at 20:06
  • True, but you don't have to include a whole framework to use peices of it. YUI is once such, you include two javascript files and voila, you got a whole robust cross environment solution to event handling. – Zoidberg Sep 03 '09 at 20:07
  • @Zoidberg - you can do a check for either click or onclick. Or just go with a client-side framework. – nickytonline Sep 03 '09 at 20:07
  • 1
    @Zoidberg: it works in Firefox just fine. Actually it works in every browser made since 1998. – Crescent Fresh Sep 03 '09 at 20:08
  • @crescentfresh - my bad I was thinking of something else. Please disregard... since 1998 like you said. I think I'm going to go fire up a copy of NCSA Mosaic. – nickytonline Sep 03 '09 at 20:11
  • I find it hard to believe it works in both firefox and IE. Firefox requires you put a string in there such as 'that.showScheduler(1);' while IE requires the function declaration as you have shown it. I have had this exact problem and I know for certain that it does not work in IE 6, and I am pretty sure it does not in IE 7 – Zoidberg Sep 03 '09 at 20:12
  • 1
    @Zoidberg - If you set the onclick attribute yes, but not the onclick property. They are two different things. header.firstChild.onclick = function() { that.showScheduler(1); }; is not the same thing as header.firstChild.setAttribute("onclick", "function() { that.showScheduler(1); };"); – nickytonline Sep 03 '09 at 20:16
  • 1
    @Zoidberg: You're thinking of `setAttribute` and event handlers (which you are right, would fail in all IEs). See http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html. However the `onclick` attribute takes a `function` object as it's value and works in all browsers. See – Crescent Fresh Sep 03 '09 at 20:17
  • Okay... NOT withstanding that, how can setting a global variable of your object be a good idea? The framework approach, offered by both JQuery and YUI offer a cleaner, safter, less globalized approach. – Zoidberg Sep 03 '09 at 20:18
  • 1
    @Zoidberg: `that` is not a global variable. nickyt simply used a closure to capture the instance of `Scheduler`. It's a well known JavaScript idiom. – Crescent Fresh Sep 03 '09 at 20:21
  • @Zoidberg: The answer *starts* with "I wouldn't do whatever it is you're doing the way you're doing, but...". In *this case*, setting the handler directly is fine. Since the element is getting constructed and the handler added in the same function, it seems it's not likely to have other event handlers added (although it's impossible to know for certain without seeing the rest of the code). – Daniel Pryden Sep 03 '09 at 20:22
  • @Daniel: reminds me of that simpsons episode: "don't do what Donny Don't does". Wait, what? – Crescent Fresh Sep 03 '09 at 20:28
  • @crescentfresh Okay, I see that and it makes sense. Its only limitation is the ability to add more listeners to that click. Again, a neat trick I forgot about. – Zoidberg Sep 03 '09 at 20:52
1

You should use a framework for this type of thing. If you don't use one then you gotta declare each instance of schedular as a global object, and you will need the name of the instance in order to call it from the link. Look at the following link

http://developer.yahoo.com/yui/examples/event/eventsimple.html

They only show a function being applied, but you can also do something like this

YAHOO.util.Event.addListener(myAnchorDom, "click", this.showScheduler,this,true);

Where myAnchorDom is the achor tag dom object. This will have showScheduler function execute within the scope of your scheduler object.

Zoidberg
  • 10,137
  • 2
  • 31
  • 53
  • 2
    You don't need a framework to set `myAnchorElement.onclick = ...`. – Crescent Fresh Sep 03 '09 at 20:06
  • 1
    No, but setting onclick directly is a bad idea and always has been. Which is why everyone who knows what they're doing uses the add/attach pair. – annakata Sep 03 '09 at 20:15
  • You don't need one... but why make life difficult on yourself handling cross browser issues. – Zoidberg Sep 03 '09 at 20:16
  • This may actually be the most useful for me because I am using YUI elsewhere in the script. I'm going to play with this first and see if I can't get it working. Thank you. – Amy Anuszewski Sep 03 '09 at 20:21
  • 3
    @Amy: You should tag your questions with any frameworks you are using. That way answers don't have to be as widely varying as the ones you've gotten so far. – Crescent Fresh Sep 03 '09 at 20:23
  • @annakata - The example she gave was quite trivial and it appears no other events were being added. That was the assumption I went with when I gave my answer (see below), but for more complex widgets or dynamic HTML/AJAX stuff, attaching and detaching events is the way to go. – nickytonline Sep 03 '09 at 20:41
  • @nickyt - sure, me too, but of course it's always advisable to fix the problem asked *and* show a better way – annakata Sep 03 '09 at 20:43
1

Instead of working with innerHTML use the DOM methods.

Try replacing this:

header.innerHTML = '<a href="#" onclick="this.showScheduler(1);">Show</a>';

with this:

var x = this; // create a closure reference
var anchor = document.createElement('a');
anchor.href= '#';
anchor.innerHTML = 'Show';
anchor.onclick = function() { x.showScheduler(1); }; //don't use onclick in real life, use some real event binding from a library
header.appendChild(anchor);

Explanation:

The "this" in the original code refers to the element which fired the event, i.e. the anchor ("this' is notoriously problematic for things like, well, like this). The solution is to create a closure on the correct method (which is why you have to create something like the var x above) which then only leaves the problem of passing in the parameter which is accomplished by wrapping the method in another function.

Strictly speaking it would be much preferable to bind eventhandlers with the addEventListener/attachEvent pair (because direct event assignment precludes the ability to assign multiple handlers to one event) but it's best handled using a library like jquery if you're new to JS anyway.

annakata
  • 74,572
  • 17
  • 113
  • 180
  • Why "use some real event binding from a library"? – Crescent Fresh Sep 03 '09 at 20:10
  • Because for a newbie events are one of the hardest things to wrap your head around. I would strongly advise using something which just works rather than spending time getting it right and/or reinventing wheels. – annakata Sep 03 '09 at 20:17
  • @annakata: very good point. It also avoids this: http://stackoverflow.com/questions/95731/why-does-an-onclick-property-set-with-setattribute-fail-to-work-in-ie – Crescent Fresh Sep 03 '09 at 20:25
  • Well quite, but setAttribute is toxic anyway :) – annakata Sep 03 '09 at 20:41
0

You can add an event handler to the header object directly:

var me = this;

this.setHeader = function(){
          header.innerHTML = '<a href="#" onclick="this.showScheduler(1);">Show</a>';

header.addHandler("click", function(e) { me.showScheduler(1); });
    }

Insite the passed function, this will refer to the header element.

eulerfx
  • 36,769
  • 7
  • 61
  • 83
  • Its a mistake on my part. I am not sure on the exact name, but its a function available without framework, however the call is different for IE and FF. – eulerfx Sep 03 '09 at 20:01
0
var Scheduler = function(divid, startDate, mode)
{
    var xthis = this;

    this.setHeader = function()
    {
          var lnk = document.createElement("a");
          lnk.addEventListener("click", xthis.showScheduler, false);
          lnk.innerText = "Show";
          lnk.setAttribute('href', "#");
          header.appendChild(lnk);
    }

   this.showScheduler = function period(){

        ...
   }
};
andres descalzo
  • 14,887
  • 13
  • 64
  • 115
-1

When using "this" inside the onclick attribute, you're actually referring to the anchor tag object. Try this and see if it works:

this.setHeader = function(){
      header.innerHTML = '<a href="#" onclick="Scheduler.showScheduler(1);">Show</a>';
}
Joe D
  • 3,588
  • 2
  • 19
  • 14