Avoiding inline event handlers in Javascript

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

I am trying to fix my javascript so it does not use event handlers within the HTML code. Instead, I am trying to get the script to trigger the events within the script, but I can't seem to get it to work. This is what my inline function looks like:
onblur="validate('residence');"'

So how do I write that in javascript alone? I think it should be something like this:
document.residence.onblur = validate('residence');'

or document.getElementbyID('residence').onblur = validate('residence');'

but neither of those work. Any help??

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Update: i found this page which says that I need to load the event handler parts in an onload event. That seems to have helped but it's still not working right. The function works but the event handler doesn't, if that makes any sense. You can see it here, on the residence field:

http://www.housing.uwaterloo.ca/profiles/individual.php

(I took out that code now so don't bother with that last link).

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Come on, please? Anyone? I need to have this working by the end of the week (preferably tomorrow!)

He has: 1,758 posts

Joined: Jul 2002

I wish I could help meg, but I know crap all about javascript. It's next on my 'stuff to learn list'. Laughing out loud

timjpriebe's picture

He has: 2,667 posts

Joined: Dec 2004

If I understand correctly what you are trying to do, your logic is fundamentally flawed. JavaScript events must be triggered by HTML code, or simply executed as your browser loads the page.

All that onload does is allows you to execute a specific function when the code loads. The same thing can be accomplished by simply not placing the code within an actual function. The code would then simply execute as your browser rendered the page, more or less.

EDIT: Scratch that, hang on...

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

timjpriebe;214319 wrote: If I understand correctly what you are trying to do, your logic is fundamentally flawed. JavaScript events must be triggered by HTML code, or simply executed as your browser loads the page.

Right, but you're supposed to do this outside of the HTML code, by detecting the event inside the script, separating behaviour from structure in the same way that we separate presentation from structure using CSS. But, I can't find a simple way to do that. All of the code samples I've come across are complicated and confusing.

Quote: All that onload does is allows you to execute a specific function when the code loads. The same thing can be accomplished by simply not placing the code within an actual function. The code would then simply execute as your browser rendered the page, more or less.

I know that. The page I linked above included instructions for detecting the events after the page is loaded ... or something, I'm still really confused.

I've given up on this for now. Too hard for me.

timjpriebe's picture

He has: 2,667 posts

Joined: Dec 2004

Okay, I was wrong. I read through that guy's page that you linked to, then through a JavaScript book's 1 page on the subject.

It turns out that you can't pass any variables when you create an event handler like that. Here's what the book says...

Quote: Note that there are no parentheses after the function name. That is because we don't want to invoke the function here; we just want to assign a reference to it.

A workaround might be to call a different function, say validateresidence. Then that function would be assigned to the event handler, and would itself call validate, passing the string 'residence' to validate.

Make any sense?

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Okay, that's helpful. Will try again after lunch.

I can't believe the lack of basic information avialable about this. All the expert type people say not to do it but I wasn't able to find any basic instructions.. They debate the finer points and have snippets of code that depend on you knowing other parts of the process or trying to do something much more complicated.

JeevesBond's picture

He has: 3,956 posts

Joined: Jun 2002

Well I found out how to do this a couple of years ago so have no idea where I learnt it! Probably from http://www.quirksmode.org that bloke knows what he's talking about.

Attached is a very small Javascript library with just a couple of functions I use every time I want to get Javascript code hooked onto an HTML event.

What you'll need to do is include that file into the html page code along with your own Javascript:

<script src="event.js" type="text/javascript"></script>
<script src="yourcode.js" type="text/javascript"></script>
'

Ending up with something like this in your declaration. In your yourcode.js file you should have some functions that will be associated with events, the library defines a function called eventCallBack for that purpose. The yourcode.js file should look something like:

var objloadHandler = new eventHandler();
var objblurHandler = new eventHandler();

objblurHandler.eventCallBack = function() {
  alert('Our sublair is under attack!');
}

objloadHandler.eventCallBack = function() {
  objBlur = document.getElementById('residence');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);
}

objloadHandler.addEventHandler(window,'load', objloadHandler.eventCallBack);
'

Note: the sublair thing is from a game called Savage. Play it, works on Linux and it's free (as in beer). Smiling Other than wanting to support a great game, it was the first thing that popped into my head.

Back to the code: this seems a bit backwards, but the code is in this order so functions are always available when loading: preventing errors. This makes more sense when broken down:

var objloadHandler = new eventHandler();
var objblurHandler = new eventHandler();
'

Firstly new event handler objects are created. These are defined in the library, one new object is required per event. They don't do anything at the moment as they haven't been hooked onto an event.

objblurHandler.eventCallBack = function() {
  alert("Our sublair is under attack!");
}
'

Then the eventCallBack function is added to our new objblurHandler object. Note that it is just added at this point (well the correct term is overloaded, but am not about to explain that!), not called or used at all. In fact this is the last function that will be called, when the 'residence' element blur event occurs.

objloadHandler.eventCallBack = function() {
  objBlur = document.getElementById('residence');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);
}
'
Like the eventCallBack function added to objblurHandler an eventCallBack is added to the objloadHandler, to be triggered after the page has finished loading. The 'residence' element cannot be accessed before the page has loaded, which is why this step is required.

The code within this function tells the objblurHandler object that when/if the 'residence' element blur event happens it should call the [incode]objblurHandler.eventCallBack[/incode] function.

objloadHandler.addEventHandler(window,'load', objloadHandler.eventCallBack);'
Finally we tell the objloadHandler that when the page load event happens the [incode]objloadHandler.eventCallBack[/incode] function should be called. This does all the blur event stuff just discussed.

Hope this makes sense, event handling isn't always the easiest of subjects. Smiling

a Padded Cell our articles site!

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Oooh, thanks for that sweetie! I think I might have to work on that tomorrow. Looks like a lot to do Smiling

JeevesBond's picture

He has: 3,956 posts

Joined: Jun 2002

Well all you need to worry about are the first two blocks of code: the first goes in your HTML Head block. The second goes in a javascript file of your choice. Should work out of the box, then you can customise at your leisure! Smiling

The rest of all that is just an explanation.

a Padded Cell our articles site!

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

You should write a tutorial for the new site about this. I had a really hard time finding anything useful on a search.

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Yay, it works! No, what would be the best thing to do when I have 4 fields I need to validate? Three of them get the same function, one gets a different function. I'll see what I can do with that but help would be appreciated Smiling

I tried wrapping the event creator part into a function and calling that for each field but it only works on the last one, so this isn't right:

var onloadHandler = new eventHandler();
var onblurHandler = new eventHandler();

function makeBlurEvent(event) {
onblurHandler.eventCallBack = function() {
  validate(event); // testing to make sure it works
}

onloadHandler.eventCallBack = function() {
  onBlur = document.getElementById(event);
  onblurHandler.addEventHandler(event, 'blur', onblurHandler.eventCallBack); // adds event to the function in the eventHandlers.js file
}
}

makeBlurEvent('name');
makeBlurEvent('residence');
makeBlurEvent('year');
makeBlurEvent('email');

onloadHandler.addEventHandler(window,'load', onloadHandler.eventCallBack);
'

Oh, and I changed your obj to on because the obj made it more confusing to me. That's another problem with all these samples - abbreviations in the variable and function names and no commenting make it much harder to understand.

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Now I have this code, which allows me to use different event handlers and pass different functions. It still only works on the last makeEvent call:

var onloadHandler = new eventHandler();
var onblurHandler = new eventHandler();

function makeEvent(element, event, func) {
onblurHandler.eventCallBack = function() {
  func(element); // testing to make sure it works
}

onloadHandler.eventCallBack = function() {
  onBlur = document.getElementById(element);
  onblurHandler.addEventHandler(element, event, onblurHandler.eventCallBack); // adds event to the function in the eventHandlers.js file
}
}


makeEvent('name', 'blur', validate);
makeEvent('residence', 'blur', validate);
makeEvent('year', 'blur', validate);
makeEvent('email', 'blur', validate_email);
makeEvent('photopath', 'blur', validate_photopath);

onloadHandler.addEventHandler(window,'load', onloadHandler.eventCallBack);
'

Oh, and one question: is it better to have a lot of separate .js files or to keep all my script in a few files?

JeevesBond's picture

He has: 3,956 posts

Joined: Jun 2002

Megan wrote: Oh, and one question: is it better to have a lot of separate .js files or to keep all my script in a few files?

Just seperate things logically as you see fit. Like I knew when creating 'event.js' that I'd need to plug it into lots of projects so I seperated it. It also does one thing (and hopefully does it well) so that made it a good thing to keep by itself too.

There're no real rules for this, just make sure you're consistent. Smiling

Will look at your code now... What have you done to it?! Laughing out loud

a Padded Cell our articles site!

JeevesBond's picture

He has: 3,956 posts

Joined: Jun 2002

var objloadHandler = new eventHandler();
var objblurHandler = new eventHandler();

objblurHandler.eventCallBack = function() {
  alert('Our sublair is under attack!');
}

objloadHandler.eventCallBack = function() {
  objBlur = document.getElementById('residence');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);

  objBlur = document.getElementById('name');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);

  objBlur = document.getElementById('year');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);

  objBlur = document.getElementById('email');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);

  objBlur = document.getElementById('photopath');
  objblurHandler.addEventHandler(objBlur, 'blur', objblurHandler.eventCallBack);
}

objloadHandler.addEventHandler(window,'load', objloadHandler.eventCallBack);
'

Here's how you can re-use the same eventHandler object with multiple HTML elements. Sorry for the delay but I wanted to test this with an actual HTML form to see if it works. It seems fine.

I suspect your code wasn't working because it was trying to add the handlers before the page loaded, don't worry about getting it wrong: events can cause headaches! Nothing works in sequence, so they're confusing to programmers who expect to see everything running line by line. Smiling

My naming conventions (like prefixing everything with 'obj' or 'str') come from my VB background. The first three letters always denote the type of variable (or object) being used. Feel free to change it to suit yourself, there are no comments because I wrote all this off the top of my head in a hurry. Smiling

a Padded Cell our articles site!

JeevesBond's picture

He has: 3,956 posts

Joined: Jun 2002

Looking at the code of that library, this should also work:

var objloadHandler = new eventHandler();
var objblurHandler = new eventHandler();

objblurHandler.eventCallBack = function() {
  alert('Our sublair is under attack!');
}

objloadHandler.eventCallBack = function() {
  objblurHandler.addEventHandler('name', 'blur', objblurHandler.eventCallBack);
  objblurHandler.addEventHandler('residence', 'blur', objblurHandler.eventCallBack);
  objblurHandler.addEventHandler('year', 'blur', objblurHandler.eventCallBack);
  objblurHandler.addEventHandler('email', 'blur', objblurHandler.eventCallBack);
  objblurHandler.addEventHandler('photopath', 'blur', objblurHandler.eventCallBack);
}

objloadHandler.addEventHandler(window,'load', objloadHandler.eventCallBack);
'

Cuts doon on the code a bit, eh?

I haven't tested this, but it should work. Smiling

a Padded Cell our articles site!

Megan's picture

She has: 11,421 posts

Joined: Jun 1999

Okay, that seems to work, but how do I tell it what function to run? Before I had:

objblurHandler.eventCallBack = function() {
validate('residence');
}
'

but I can't do that anymore. I need to pass the value to the validate() function...

Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.