Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Add - NOT REPLACE - event handler?

70 views
Skip to first unread message

Matt Kruse

unread,
Apr 23, 2001, 9:42:25 AM4/23/01
to
I have an external JS file containing reusable code. I would like for it to
add an event handler for onmouseup, to perform certain actions. I would also
like to add an action to the onLoad() of the page.

I'd like to do this in a way that won't wipe out any event handler that the
user has already defined, though. Is there any way to "chain" these together
transparently, which works in NN4.x, IE, and NN6? Or am I stuck with giving
the user instructions on how to manually add the event handlers?

I can't seem to find any information about this, so any tips would be
appreciated.
Thanks

--
Matt Kruse
http://www.mattkruse.com/

Lee

unread,
Apr 23, 2001, 10:27:45 AM4/23/01
to

Save a reference to the old handler in a variable.
Have your new handler invoke the old handler either
before or after performing the new procedure:


<html>
<head>
<script language="JavaScript">
function addClick(target){
prevAction=target.onclick;
target.onclick=new Function("alert('new Action');prevAction();");
}
</script>
</head>
<body onload="addClick(window.document.frank.bob)">
<form name="frank">
<input type="button"
name="bob"
value="myButton"
onclick="alert('old Action')">
</form>
</body>
</html>

Jim Ley

unread,
Apr 23, 2001, 12:03:57 PM4/23/01
to
On 23 Apr 2001 07:27:45 -0700, Lee <leedoesno...@earthlink.net>
wrote:

>"Matt said:
>>
>>I have an external JS file containing reusable code. I would like for it to
>>add an event handler for onmouseup, to perform certain actions. I would also
>>like to add an action to the onLoad() of the page.
>>
>
>

><html>
><head>
><script language="JavaScript">
> function addClick(target){
> prevAction=target.onclick;

prevAction will be local to the addClick function won't it?

in anycase it may be nicer to add it to the target in anycase

target.onclickOld=target.onclick
target.onclick=new Function("alert('new');this.onclickOld()");

Jim.

--
FAQ: http://jibbering.com/faq/
Old FAQs: http://jibbering.com/faq/old/

Matt Kruse

unread,
Apr 23, 2001, 1:56:52 PM4/23/01
to
Lee <leedoesno...@earthlink.net> wrote:
> Save a reference to the old handler in a variable.
> Have your new handler invoke the old handler either
> before or after performing the new procedure:

This won't work as a general case, however.

What if I have two include files, each of which wants to add its own handler
for onmouseup?
For example, the following code results in a stack overflow:

<SCRIPT LANGUAGE="JavaScript">
function a1() { alert("a1"); }
function a2() { alert("a2"); }
function a3() { alert("a3"); }
if (document.layers) { document.captureEvents(Event.MOUSEUP); }
document.onmouseup=a1;
var old;
if (document.onmouseup) {
old = document.onmouseup;
document.onmouseup = new Function("old(); a2();");
}
if (document.onmouseup) {
old = document.onmouseup;
document.onmouseup = new Function("old(); a3();");
}
</SCRIPT>

Handling onclick event handlers may a simpler task, but if you can provide
an example for chaining onmouseup or onload handlers, that would be
excellent. I can't seem to get anything to work successfully in my tests.

Matt Kruse
http://www.mattkruse.com/

Matt Kruse

unread,
Apr 23, 2001, 2:20:13 PM4/23/01
to
Matt Kruse <mkr...@netexpress.net> wrote:
> What if I have two include files, each of which wants to add its own
handler
> for onmouseup?
> For example, the following code results in a stack overflow:

Okay, I changed the code around a bit and now it functions correctly (see
below).

However, it's still vulnerable to one thing...
If a user includes my .js file at the top of his page, then down below it
does "document.onmouseup=func" or something like that, my definition will be
wiped out. Same thing with the body's onLoad. Sure, I can instruct people to
include my .js file *after* all their code, but people are generally not
good at following directions :)

For now, I'll be happy with this solution. However, if anyone has ideas for
solutions that are less open to user error, I'd love to see them!!

My (working) code:

<SCRIPT LANGUAGE="JavaScript">
function a1() { alert("a1"); }
function a2() { alert("a2"); }
function a3() { alert("a3"); }
if (document.layers) { document.captureEvents(Event.MOUSEUP); }
document.onmouseup=a1;

if (document.onmouseup) {
var olda2 = document.onmouseup;
document.onmouseup = new Function("olda2(); a2();");
}
if (document.onmouseup) {
var olda3 = document.onmouseup;
document.onmouseup = new Function("olda3(); a3();");
}
</SCRIPT>

Matt Kruse
http://www.mattkruse.com/

Lee

unread,
Apr 23, 2001, 1:31:29 PM4/23/01
to
j...@jibbering.com said:
>
>On 23 Apr 2001 07:27:45 -0700, Lee <leedoesno...@earthlink.net>
>wrote:
>
>>"Matt said:
>>>
>>>I have an external JS file containing reusable code. I would like for it to
>>>add an event handler for onmouseup, to perform certain actions. I would also
>>>like to add an action to the onLoad() of the page.
>>>
>>
>>
>><html>
>><head>
>><script language="JavaScript">
>> function addClick(target){
>> prevAction=target.onclick;
>
>prevAction will be local to the addClick function won't it?
>
>in anycase it may be nicer to add it to the target in anycase
>
> target.onclickOld=target.onclick
> target.onclick=new Function("alert('new');this.onclickOld()");

prevAction is global, and can even be safely reused,
but your method is clearly tidier.

Jim Ley

unread,
Apr 23, 2001, 8:04:09 PM4/23/01
to
On Mon, 23 Apr 2001 13:20:13 -0500, "Matt Kruse"
<mkr...@netexpress.net> wrote:

>Matt Kruse <mkr...@netexpress.net> wrote:

>For now, I'll be happy with this solution. However, if anyone has ideas for
>solutions that are less open to user error, I'd love to see them!!
>
>My (working) code:
>
><SCRIPT LANGUAGE="JavaScript">
>function a1() { alert("a1"); }
>function a2() { alert("a2"); }
>function a3() { alert("a3"); }
>if (document.layers) { document.captureEvents(Event.MOUSEUP); }
>document.onmouseup=a1;
>if (document.onmouseup) {
> var olda2 = document.onmouseup;
> document.onmouseup = new Function("olda2(); a2();");
> }
>if (document.onmouseup) {
> var olda3 = document.onmouseup;
> document.onmouseup = new Function("olda3(); a3();");
> }
></SCRIPT>

This is flexible enough to cope with any practical number of functions
being added without a stack overflow

function AddHandler(element,strEvent,fnName) {
ref='a'+new Date().valueOf()
while (typeof element[ref]!='undefined')
ref='a'+Number(ref.substr(1,100))+1
element[ref]=element[strEvent]
element[strEvent]=new Function("this['"+ref+"']();"+fnName+"()")
}

function a1() { alert('a1') }
function a2() { alert('a2') }

AddHandler(window,'onload','a1')
AddHandler(window,'onload','a2'); // etc. etc.

To attempt to overcome your problem of users overriding, how about
this?

<script>
function AddHandler(element,strEvent,fnName) {
var ref='a'+new Date().valueOf()
while (typeof element[ref]!='undefined')
ref='a'+Number(ref.substr(1,100))+1
element[ref]=element[strEvent]
element[strEvent]=new Function("this['"+ref+"']();"+fnName+"()")
element[strEvent+'cache']=new
Function("this['"+ref+"']();"+fnName+"()")
}

setInterval('CheckEvent(document,"onmouseup")',5000);

function CheckEvent(element,strEvent) {
if (String(element[strEvent])!=
String(element[strEvent+'cache'])) {
var ref='a'+new Date().valueOf()
while (typeof element[ref]!='undefined')
ref='a'+Number(ref.substr(1,100))+1
element[ref]=element[strEvent+'cache']
element['b'+ref]=element[strEvent]
element[strEvent]=new
Function("this['"+ref+"']();this['b"+ref+"']();")
element[strEvent+'cache']=new
Function("this['"+ref+"']();this['b"+ref+"']();")
}
}


//to test:
function a1() { alert('a') }


function a2() { alert('a2') }

AddHandler(document,'onmouseup','a1')
setTimeout('document.onmouseup=a2',7000);
</script>

Which checks every 5 seconds that your function is still there if it's
not then it adds the old version, and remembers the new one - only
tested in IE6 beta, but no reason why it should cause problems in
others that I can see.

Jim.

Fox

unread,
Apr 24, 2001, 2:02:11 AM4/24/01
to
Matt--

It seems to me that once a page has finished loading, we can pretty much
be sure the user has already installed all the Event handlers they are
going to use, and it would be safe to install your handlers programmatically.

Problem is, they may have installed an onload handler as well.

There is another way...

In Netscape, the document.height property is zero until the page has
finished loading, at which time it is set.

In Internet Explorer, the document.body object is null until the page
has loaded (at that point you could, if needed, check the document
height with document.body.clientHeight).

Your script could initiate a timer that would check for either one of
these conditions, then call a routine to install the Event handlers. I'd
recommend a delay of 100. "Catching" the event within a tenth of a
second seems reasonable enough.

Anyway, I'm not aware of anybody else using this technique for
establishing an onload event that bypasses the actual onload event, so
you could probably use it to solve your problems.

Hope this helps,


Fox
**************

Fox

unread,
Apr 24, 2001, 3:19:18 AM4/24/01
to
Here's something else you might find useful:

****
This example installs or removes event handlers at the user's
whim via form buttons (3 of each type). The "add buttons
install mousedown and mouseup handlers that write text to the
corresponding text box. The "rem" buttons remove the corresponding
handlers. After adding and/or removing the handlers, click on the
document's content area to test.

The following creates a global Event manager.
Events are subscribed to the manager (or removed)
All events are registered to gEventMgr.handler
the handler determines the type of event
and executes ALL functions registered

Requires convincing the user to install handlers via EventMgr
add() method
-- arguments: event type and method's name
event type examples: "mousedown", "mouseup" [as in event.type]
handler method's name is assumed to take an event object
as argument, so only the name is required. See example.

Not recommended for non-document events unless modified
to handle different targets [this is just an example]

This shouldn't interfere with non-document events.

This example is designed for Netscape, as written
Mods for IE should be easy enough [just skip the
document.captureEvents/releaseEvents, I think]

****
<xmp><!-- remove this line to run -->
<script language = javascript>

// a better version of the pop method --
// it allows you to pop an element from any part of the array
// not just the last entry
// method returns the element popped, if required
Array.prototype.pop = function(index)
{

if(this.length == 0) return;

if(index == null) index = this.length - 1;

var elem = this[index];

for (var i = index; i < this.length - 1; i++)
this[i] = this[i+1];

this[this.length - 1] = null;
this.length--;
return elem;

}

function
EventMgr()
{
this.methodList = [];

this.add = function(evtType,evtMethod)
{

if(!this.methodList[evtType]) this.methodList[evtType] = [];

var m = this.methodList[evtType];
var alreadyInstalled = false;

// do NOT want duplicates!
for(var i = 0; i < m.length; i++)
{
if(m[i].toString().indexOf(evtMethod) != -1){
alreadyInstalled = true;
break;}
}
if(!alreadyInstalled)
this.methodList[evtType][this.methodList[evtType].length] = eval(evtMethod);
}

this.remove = function(evtType, methodName)
{
if(this.methodList[evtType])
{
var m = this.methodList[evtType];

for(var i = 0; i < m.length; i++)
{
if(m[i].toString().indexOf(methodName) != -1)
m.pop(i);
}
}
}

this.handler = function(e)
{
// no method installed? then back off
if(!gEventMgr.methodList[e.type]) return;

// get shortcut
var evts = gEventMgr.methodList[e.type];

for(var i = 0; i < evts.length; i++)
{
evts[i](e); // make sure you pass the event obj.
}
}

}

var gEventMgr = new EventMgr();

onload = function() // set up required events
{
document.captureEvents(Event.MOUSEUP | Event.MOUSEDOWN);
document.onmousedown = gEventMgr.handler;
document.onmouseup = gEventMgr.handler;
}

onunload = function()
{

document.releaseEvents(Event.MOUSEUP | Event.MOUSEDOWN);
}

function
alert_user0(e)
{
document.info.evt_1.value = e.type + " 1";
}

function
alert_user1(e)
{
document.info.evt_2.value = e.type + " 2";
}

function
alert_user2(e)
{
document.info.evt_3.value = e.type + " 3";
}

function
remEvt(n)
{
gEventMgr.remove("mousedown", "alert_user" + n);
gEventMgr.remove("mouseup", "alert_user" + n);

// this is just for this demo -- it clears the
// form textbox associated with these events
var elem = eval("document.info.evt_" + (n + 1));
elem.value = "";
}

function
addEvt(n)
{
gEventMgr.add("mousedown", "alert_user" + n);
gEventMgr.add("mouseup", "alert_user" + n);
}


</script>

<body>
<center>
<form name = info>
Event 1: <input type = text name = evt_1><br>
Event 2: <input type = text name = evt_2><br>
Event 3: <input type = text name = evt_3><br>
<br>
<input type = button value= Add_Evt1 onclick = "addEvt(0)"><br>
<input type = button value= Add_Evt2 onclick = "addEvt(1)"><br>
<input type = button value= Add_Evt3 onclick = "addEvt(2)"><br>
<input type = button value= Rem_Evt1 onclick = "remEvt(0)"><br>
<input type = button value= Rem_Evt2 onclick = "remEvt(1)"><br>
<input type = button value= Rem_Evt3 onclick = "remEvt(2)"><br>
<br>
<br>
</form>


</center>
</body>

</xmp><!-- remove this line to run -->


If this can't be modified to run in IE -- scrap it -- I don't care to
get involved with IE at this level (too much of a headache -- and I
already spent too much time tonight getting setTimeout to work in IE
[which is incorrectly implemented]).


Fox
*************

Jim Ley

unread,
Apr 25, 2001, 6:24:16 AM4/25/01
to
On Tue, 24 Apr 2001 02:19:18 -0500, Fox <mah...@eatel.net> wrote:

>Here's something else you might find useful:

>Not recommended for non-document events unless modified


>to handle different targets [this is just an example]

I think my AddHandler method is a lot nicer than that, already handles
any event on any object, doesn't use eval, doesn't need the other user
to do change the way code at all.

Franz Figl

unread,
Apr 29, 2001, 5:25:50 PM4/29/01
to
Hi all,

I want to do a complex dia show loading files via refresh undefinetely.

<meta http-equiv="Refresh" content="20;URL=Identity-Produkte03.html;
charset=iso-8859-1">

The 20 seconds is too static, IE stops any other action and loads the new
file.
Is there a "not idle" or so, I mean load the file after 20 sec. only when
nothing other happens?

Franz


Jim Ley

unread,
Apr 29, 2001, 7:20:55 PM4/29/01
to
On Sun, 29 Apr 2001 23:25:50 +0200, "Franz Figl" <fr...@augusta.de>
wrote:

how do you define nothing happens? no mousemovement, no clicks, no
..?

count=0
setInterval("Moomin()",2000)
function Moomin() {
if (++count==20) location.href="Indentity-Produkte03.html"
}

document.onmousemove=new Function("count=0")

Should do it on the mouse not moving.

Jim.

Message has been deleted

Jim Ley

unread,
May 18, 2001, 5:13:59 AM5/18/01
to
On 18 May 2001 01:52:56 -0700, ro...@sjdd43.posting.google.com (root)
wrote:

>j...@jibbering.com (Jim Ley) wrote in message news:<3ae4b661...@west.usenetserver.com>...
>>
>> setTimeout('document.onmouseup¢',7000);

Google seems to have mangled the quoted material, don't trust the
script in the previous post, go back to the original with the above
message id!

>> Which checks every 5 seconds that your function is still there if it's
>> not then it adds the old version, and remembers the new one - only
>> tested in IE6 beta, but no reason why it should cause problems in
>> others that I can see.
>>
>> Jim.
>

>This solution works, even though I don't totally understand how it
>works since I'm newbie to Javascript. Can you explain how these
>statement work?
>
>element[ref]= element[strEvent]
>element[strEvent]= new Function("this['"+ref+"']();"+fnName+"()")

element contains a reference to the object you're adding the handler
too, say document or window, or whatever.

strEvent is the name of the event you wish to add, e.g. onmouseup

element["onmouseup"] is equivalent to element.onmouseup

ref is a generated id, made up of a and the current time, then
processed to be forced unique (the while loop - 101 references added
in under 1 millisecond would cause problems for the script)

element[ref] then stores the old reference to the strEvent.
then a new function is created for the strEvent which first calls
element[ref], then calls the new function you add.

so it's the same as doing:
document.a23321=document.onmouseup
document.onmouseup=new Function("document.a23321;newfn()")

but you don't need to keep track of the a23321 etc.

>Also, how would you remove an event handler (say a1) from the event
>after it is being added?

Well, the above script doesn't keep track of the scripts it adds in
any way, all you would do if you knew it was a3 (the script above
doesn't store them like this, if you remove the ref="a"+new Date() and
make ref="a1" you'll get that effect, with the limitation of only
being able to add 100 event handlers.)
then
document.a3=null
would remove it, however that would also remove document.a2 from the
list so what you actually would want to to remove the a'n'th one is

element['a'+n]=new Function("this['a"+n+"']")

so it just calls the previous one. Not sure what the best approach to
tracking n would be though.

Kevin Ly

unread,
May 18, 2001, 5:28:33 AM5/18/01
to
j...@jibbering.com (Jim Ley) wrote in message news:<3ae4b661...@west.usenetserver.com>...
> On Mon, 23 Apr 2001 13:20:13 -0500, "Matt Kruse"
> <mkr...@netexpress.net> wrote:
>
> >Matt Kruse <mkr...@netexpress.net> wrote:
>
> >For now, I'll be happy with this solution. However, if anyone has ideas for
> >solutions that are less open to user error, I'd love to see them!!
> >
> >My (working) code:
> >
> ><SCRIPT LANGUAGE"JavaScript">

> >function a1() { alert("a1"); }
> >function a2() { alert("a2"); }
> >function a3() { alert("a3"); }
> >if (document.layers) { document.captureEvents(Event.MOUSEUP); }
> >document.onmouseup¡;
> >if (document.onmouseup) {
> > var olda2 document.onmouseup;
> > document.onmouseup new Function("olda2(); a2();");
> > }
> >if (document.onmouseup) {
> > var olda3 document.onmouseup;
> > document.onmouseup new Function("olda3(); a3();");

> > }
> ></SCRIPT>
>
> This is flexible enough to cope with any practical number of functions
> being added without a stack overflow
>
> function AddHandler(element,strEvent,fnName) {
> ref'a'+new Date().valueOf()
> while (typeof element[ref]!'undefined')
> ref'a'+Number(ref.substr(1,100))+1
> element[ref]element[strEvent]
> element[strEvent]new Function("this['"+ref+"']();"+fnName+"()")

> }
>
> function a1() { alert('a1') }
> function a2() { alert('a2') }
>
> AddHandler(window,'onload','a1')
> AddHandler(window,'onload','a2'); // etc. etc.
>
> To attempt to overcome your problem of users overriding, how about
> this?
>
> <script>
> function AddHandler(element,strEvent,fnName) {
> var ref'a'+new Date().valueOf()
> while (typeof element[ref]!'undefined')
> ref'a'+Number(ref.substr(1,100))+1
> element[ref]element[strEvent]
> element[strEvent]new Function("this['"+ref+"']();"+fnName+"()")
> element[strEvent+'cache']new

> Function("this['"+ref+"']();"+fnName+"()")
> }
>
> setInterval('CheckEvent(document,"onmouseup")',5000);
>
> function CheckEvent(element,strEvent) {
> if (String(element[strEvent])!
> String(element[strEvent+'cache'])) {
> var ref'a'+new Date().valueOf()
> while (typeof element[ref]!'undefined')
> ref'a'+Number(ref.substr(1,100))+1
> element[ref]element[strEvent+'cache']
> element['b'+ref]element[strEvent]
> element[strEvent]new

> Function("this['"+ref+"']();this['b"+ref+"']();")
> element[strEvent+'cache']new
> Function("this['"+ref+"']();this['b"+ref+"']();")
> }
> }
>
>
> //to test:
> function a1() { alert('a') }
> function a2() { alert('a2') }
> AddHandler(document,'onmouseup','a1')
> setTimeout('document.onmouseup¢',7000);

> </script>
>
> Which checks every 5 seconds that your function is still there if it's
> not then it adds the old version, and remembers the new one - only
> tested in IE6 beta, but no reason why it should cause problems in
> others that I can see.
>
> Jim.

This solution works, even though I don't totally understand how it


works since I'm newbie to Javascript. Can you explain how these
statement work?

element[ref]= element[strEvent]

element[strEvent]= new Function("this['"+ref+"']();"+fnName+"()")

Also, how would you remove an event handler (say a1) from the event
after it
is being added?

Thanks, Kevin

0 new messages