473,385 Members | 1,546 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Problems with dynamically adding events to new DOM objects

I am trying to add an event listener to the keyup event for some text
inputs that I am creating dynamically. I have no problems getting it
to work in Firefox, but IE just ignores them. I have created a few
functions to aid in making this process work semi-cross-browser. (I
develop in FF, but everyone who uses it will be using IE6.)

function attachEvent(_obj, _evt, _fnc) {
_evt = _evt.toLowerCase();

if (_obj.attachEvent) {
_obj.attachEvent('on' + _evt, _fnc);
} else {
eval('_obj.on' + _evt + ' = ' + _fnc);
}
}

function generateFunction(_name, _params) {
var func;
if (navigator.userAgent.toLowerCase().indexOf('gecko' ) != -1) {
func = eval('function(){' + _name + '(' + _params + ');}');
} else {
func = function(){eval(_name + '(' + _params + ')');};
}
return func;
}

function attachValidator(_obj, _validatorName) {
if (navigator.userAgent.toLowerCase().indexOf('gecko' ) != -1) {
attachEvent(_obj, 'keyup', generateFunction(_validatorName, 'this'));
} else {
var eventAttr = document.createAttribute('onkeyup');
eventAttr.value = _validatorName + '(this);';
_obj.setAttributeNode(eventAttr);
}
}

function createTextField(_base, _id, _value, _validatorName, _class) {
var input = document.createElement('input');
var inputID = document.createAttribute('id');
inputID.value = _base + _id;
var inputType = document.createAttribute('type');
inputType.value = 'text';
var inputValue = document.createAttribute('value');
inputValue.value = _value;

input.setAttributeNode(inputID);
input.setAttributeNode(inputType);
input.setAttributeNode(inputValue);

if (_validatorName) {
attachValidator(input, _validatorName);
//attachEvent(input, 'keyup', generateFunction(_validatorName,
'this'));
}

if (_class) {
var inputClass = document.createAttribute('class');
inputClass.value = _class;

input.setAttributeNode(inputClass);
}

return input;
}

Sorry about the browser sniffing using the userAgent string, but since
I am the only non-IE6 user in the building, it shouldn't really matter
in the long run.

Thanks in advance,

Chris

Jun 23 '06 #1
5 2210
"Chris Lieb" <ch********@gmail.com> writes:
I am trying to add an event listener to the keyup event for some text
inputs that I am creating dynamically. I have no problems getting it
to work in Firefox, but IE just ignores them.
Let's quote out of context:
function attachValidator(_obj, _validatorName) {
if (navigator.userAgent.toLowerCase().indexOf('gecko' ) != -1) {
attachEvent(_obj, 'keyup', generateFunction(_validatorName, 'this'));
} else {
var eventAttr = document.createAttribute('onkeyup');
eventAttr.value = _validatorName + '(this);';
_obj.setAttributeNode(eventAttr);
}
}
So, Gecko based browsers take the first branch and IE will take the
second. If they act differently, this is as good a place to look as
any.

Indeed it seems the second branch doesn't work in IE.

Since the attachEvent function is also written to work in more
than one setting, it looks like an error that you only call it
for Gecko browsers.
When working with HTML it's better to use the HTML DOM properties
(e.g., obj.href) instead of Core DOM attribute methodes (e.g.,
obj.setAttribute). IE, for one, often doesn't react to changes
to Core DOM attributes.
I have created a few functions to aid in making this process work
semi-cross-browser. (I develop in FF, but everyone who uses it will
be using IE6.)
Some suggestions (mostly about how to avoid "eval", which only
complicates your life):
function attachEvent(_obj, _evt, _fnc) {
Try:
function attachEvent(_obj, _evt, _fnc) {
_evt = _evt.toLowerCase();
if (_obj.addEventHandler) {
_obj.addEventHandler(_evt, _fnc, false);
} else if (_obj.attachEvent) {
_obj.attachEvent("on" + _evt, fnc);
} else {
_obj["on" + _evt] = fnc;
}
}
function generateFunction(_name, _params) {
I guess this function's job is to create a function that calls another
with specified arguments. It's safer to pass the actual function than
just its name:

function bindParameter(_func, _params) {
_func.apply(this,_params)
}
var func;
if (navigator.userAgent.toLowerCase().indexOf('gecko' ) != -1) {
func = eval('function(){' + _name + '(' + _params + ');}');
} else {
func = function(){eval(_name + '(' + _params + ')');};
}
Why this difference? I can't see any feature that IE and Gecko would
do differently in either branch.
return func;
}
function attachValidator(_obj, _validatorName) {
function attachValidator(_obj, _validatorFunc) {
attachEvent(_obj, "keyup", bindParams(_validatorFunc, _obj));
}

function createTextField(_base, _id, _value, _validatorName, _class) {


Here also pass a validator function, not its name.

I.e., something like:
createTextField(..,..,.., function(_obj){ return _obj.value!=""; }, ...);
(or use a function defined somewhere else).

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jun 23 '06 #2

Lasse Reichstein Nielsen wrote:
"Chris Lieb" <ch********@gmail.com> writes:
I am trying to add an event listener to the keyup event for some text
inputs that I am creating dynamically. I have no problems getting it
to work in Firefox, but IE just ignores them.
Let's quote out of context:
function attachValidator(_obj, _validatorName) {
if (navigator.userAgent.toLowerCase().indexOf('gecko' ) != -1) {
attachEvent(_obj, 'keyup', generateFunction(_validatorName, 'this'));
} else {
var eventAttr = document.createAttribute('onkeyup');
eventAttr.value = _validatorName + '(this);';
_obj.setAttributeNode(eventAttr);
}
}


So, Gecko based browsers take the first branch and IE will take the
second. If they act differently, this is as good a place to look as
any.

Indeed it seems the second branch doesn't work in IE.

Since the attachEvent function is also written to work in more
than one setting, it looks like an error that you only call it
for Gecko browsers.


The code that is in there for IE does not use the attachEvent method
because I had apready determined that the attachEvent function was not
achieving what I wanted.
When working with HTML it's better to use the HTML DOM properties
(e.g., obj.href) instead of Core DOM attribute methodes (e.g.,
obj.setAttribute). IE, for one, often doesn't react to changes
to Core DOM attributes.
I have created a few functions to aid in making this process work
semi-cross-browser. (I develop in FF, but everyone who uses it will
be using IE6.)
Some suggestions (mostly about how to avoid "eval", which only
complicates your life):
function attachEvent(_obj, _evt, _fnc) {


Try:
function attachEvent(_obj, _evt, _fnc) {
_evt = _evt.toLowerCase();
if (_obj.addEventHandler) {
_obj.addEventHandler(_evt, _fnc, false);
} else if (_obj.attachEvent) {
_obj.attachEvent("on" + _evt, fnc);
} else {
_obj["on" + _evt] = fnc;
}
}
function generateFunction(_name, _params) {


I guess this function's job is to create a function that calls another
with specified arguments. It's safer to pass the actual function than
just its name:

function bindParameter(_func, _params) {
_func.apply(this,_params)
}


I've never seen the apply function before. I looked it up in the
Mozilla Developer docs, but I don't understand how this works or how
the bindParameter function would be used comared to the previous
generateFunction function.
var func;
if (navigator.userAgent.toLowerCase().indexOf('gecko' ) != -1) {
func = eval('function(){' + _name + '(' + _params + ');}');
} else {
func = function(){eval(_name + '(' + _params + ')');};
}


Why this difference? I can't see any feature that IE and Gecko would
do differently in either branch.
return func;
}
For some reason, IE choked on creating an anonymous function using eval
and FF evaluated the IE version correctly, meaning that an anonymous
function was created whose body was eval(_name + '(' + _params + ')');
This did not work in FF because the _name and _params variables had
gone out of scope by the time that the function was invoked.

function attachValidator(_obj, _validatorName) {


function attachValidator(_obj, _validatorFunc) {
attachEvent(_obj, "keyup", bindParams(_validatorFunc, _obj));
}

function createTextField(_base, _id, _value, _validatorName, _class) {


Here also pass a validator function, not its name.

I.e., something like:
createTextField(..,..,.., function(_obj){ return _obj.value!=""; }, ...);
(or use a function defined somewhere else).


I thought that events did not pass any parameters. If this is so,
where is this anonymous function (the one passed to createTextField in
the above example) getting the _obj parameter from?
/L
Thanks for the help, but I am slightly confused by some of the things
that you proposed, such as the bindParam function. Could you please
clarify them?

Chris
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'


Jun 23 '06 #3
Chris Lieb wrote:
I am trying to add an event listener to the keyup event for some text
inputs that I am creating dynamically. I have no problems getting it
to work in Firefox, but IE just ignores them. I have created a few
functions to aid in making this process work semi-cross-browser. (I
develop in FF, but everyone who uses it will be using IE6.)

[...]

Aren't you making this much more difficult than it should be? Why
can't you just use:

function createTextField(_base, _id, _value, _validatorName, _class)
{
var oInput = document.createElement('input');
oInput.type = 'text';
oInput.id = _base + _id;
oInput.value = _value;

if ( _validatorName) {
oInput.onkeyup = _validatorName;
}

/* Assuming 'class' is in regard to style, not JScript 'class' */
if (_class && 'string' == typeof _class){
oInput.className = _class;
}

return oInput;
}
Within whatever function is attached to the input, 'this' will refer to
the input that called the function, so if you had:

function showID(){ alert(this.id); }

Then do:

document.body.appendChild(
createTextField( 'foo', 'bar', 'foey', showID, 'brightRed'));
Then you should see a new text input with a value of 'foey' and
displays 'foobar' onkeyup - works in IE, Firefox & Safari at least. If
you want to add multiple functions to a particular handler (which is
rare for onkeyup), use your forking addEventListener/attachEvent for
the _validator.

Sample below:

<html><title>Play</title>

<style type="text/css">
.brightRed {
border: 2px solid red;
background-color: #fdd;
}
</style>

<script type="text/javascript">

function createTextField(_base, _id, _value, _validatorName, _class)
{
var oInput = document.createElement('input');
oInput.type = 'text';
oInput.id = _base + _id;
oInput.value = _value;

if ( _validatorName) {
oInput.onkeyup = _validatorName;
}

/* Assuming 'class' is in regard to style, not JScript 'class' */
if (_class && 'string' == typeof _class){
oInput.className = _class;
}

return oInput;
}

function showID(){ alert(this.id);}

window.onload = function()
{
document.body.appendChild(
createTextField( 'foo', 'bar', 'foey', showID, 'brightRed'));
};

</script>
</html>
--
Rob

Jun 24 '06 #4
"Chris Lieb" <ch********@gmail.com> writes:
Lasse Reichstein Nielsen wrote: The code that is in there for IE does not use the attachEvent method
because I had apready determined that the attachEvent function was not
achieving what I wanted.
Sine no other browser has an attachEvent function (well, maybe some
does by now, but it's a proprietary IE feature), you can safely remove
that code.

function bindParameter(_func, _params) {
_func.apply(this,_params)
}


I've never seen the apply function before. I looked it up in the
Mozilla Developer docs, but I don't understand how this works or how
the bindParameter function would be used comared to the previous
generateFunction function.


Well, since I forgot something, it's not odd that you don't understand
what it does :)

The bind function should ofcourse return a function, so it should be:

function bindParameter(_func, _params) {
return function() {
_func.apply(this,_params)
};
}

What it now does is to return a function that, when called, calls
the _func function with the parameters in the array _params.

The .apply method on function values calls the function as a method
of the object in the first argument and with the parameters in the
array in the second argument.

There is a similar method, "call", that expects the parameters
directly, not as an array.

So, if o is an object, then the following performs the same calls:

o.foo = myFunc;
o.foo(a,b,c)
and
myFunc.call(o,a,b,c)
and
myFunc.apply(o,[a,b,c])
For some reason, IE choked on creating an anonymous function using eval
and FF evaluated the IE version correctly, meaning that an anonymous
function was created whose body was eval(_name + '(' + _params + ')');
This did not work in FF because the _name and _params variables had
gone out of scope by the time that the function was invoked.
The fragility of eval is one of the reasons it's not recommended.
You have to be very careful when you build source strings for eval,
and it's generally not worth it.
Javascript allows you to pass values around, even function values,
so it's unlikely that you ever need to pass around names of
functions or strings representing values.
Thanks for the help, but I am slightly confused by some of the things
that you proposed, such as the bindParam function. Could you please
clarify them?


Generally, don't use eval.
If you need to call an unknown function in some code, don't pass its
name and look it up, just pass the function directly.

If you want to add an event handler, the W3C DOM method is addEventHandler,
IE's metod is attachEvent (which doesn't bind "this" to the attachee when
it executes the function), and the generic fallback is object.onevent
(i.e., object['on'+_evt]), which can only accept one handler per event
type).

Be carefull with using setAttribute on HTML elements, since some browsers,
most notably IE, will not make them take effect the same way assigning
to the W3C HTML DOM properties does (e.g., _obj.style.width='4px',
_link.href='foo.html').

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jun 24 '06 #5

Lasse Reichstein Nielsen wrote:
"Chris Lieb" <ch********@gmail.com> writes:
Lasse Reichstein Nielsen wrote:

The code that is in there for IE does not use the attachEvent method
because I had apready determined that the attachEvent function was not
achieving what I wanted.


Sine no other browser has an attachEvent function (well, maybe some
does by now, but it's a proprietary IE feature), you can safely remove
that code.

function bindParameter(_func, _params) {
_func.apply(this,_params)
}


I've never seen the apply function before. I looked it up in the
Mozilla Developer docs, but I don't understand how this works or how
the bindParameter function would be used comared to the previous
generateFunction function.


Well, since I forgot something, it's not odd that you don't understand
what it does :)

The bind function should ofcourse return a function, so it should be:

function bindParameter(_func, _params) {
return function() {
_func.apply(this,_params)
};
}

What it now does is to return a function that, when called, calls
the _func function with the parameters in the array _params.

The .apply method on function values calls the function as a method
of the object in the first argument and with the parameters in the
array in the second argument.

There is a similar method, "call", that expects the parameters
directly, not as an array.

So, if o is an object, then the following performs the same calls:

o.foo = myFunc;
o.foo(a,b,c)
and
myFunc.call(o,a,b,c)
and
myFunc.apply(o,[a,b,c])
For some reason, IE choked on creating an anonymous function using eval
and FF evaluated the IE version correctly, meaning that an anonymous
function was created whose body was eval(_name + '(' + _params + ')');
This did not work in FF because the _name and _params variables had
gone out of scope by the time that the function was invoked.


The fragility of eval is one of the reasons it's not recommended.
You have to be very careful when you build source strings for eval,
and it's generally not worth it.
Javascript allows you to pass values around, even function values,
so it's unlikely that you ever need to pass around names of
functions or strings representing values.
Thanks for the help, but I am slightly confused by some of the things
that you proposed, such as the bindParam function. Could you please
clarify them?


Generally, don't use eval.
If you need to call an unknown function in some code, don't pass its
name and look it up, just pass the function directly.

If you want to add an event handler, the W3C DOM method is addEventHandler,
IE's metod is attachEvent (which doesn't bind "this" to the attachee when
it executes the function), and the generic fallback is object.onevent
(i.e., object['on'+_evt]), which can only accept one handler per event
type).

Be carefull with using setAttribute on HTML elements, since some browsers,
most notably IE, will not make them take effect the same way assigning
to the W3C HTML DOM properties does (e.g., _obj.style.width='4px',
_link.href='foo.html').

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'


Thanks. That bindParam function has everything working in both FF and
IE.

Chris

Jun 26 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Thomas | last post by:
Hi, I'm having a problem with the dynamically created inputfields in Internet Explorer. The situation is the following: - I have a dynamically created table with a textbox in each Cell. - It...
11
by: Steven D'Aprano | last post by:
Suppose I create a class with some methods: py> class C: .... def spam(self, x): .... print "spam " * x .... def ham(self, x): .... print "ham * %s" % x .......
8
by: Donald Xie | last post by:
Hi, I noticed an interesting effect when working with controls that are dynamically loaded. For instance, on a web form with a PlaceHolder control named ImageHolder, I dynamically add an image...
2
by: JezB | last post by:
I'm adding WebControl objects to a Page dynamically on Page_Load, but I'm having trouble attaching events to these. For example, adding an image button :- ImageButton nb = new ImageButton();...
1
by: bill | last post by:
I'm using VS2005. I am dynamically adding a Textbox control to a Placeholder control in the page_load event of the form, but the event handler isn't firing. What am I doing wrong? Thanks...
7
by: Ron Goral | last post by:
Hello I am new to creating objects in javascript, so please no flames about my coding style. =) I am trying to create an object that will represent a "div" element as a menu. I have written...
9
by: Chris | last post by:
I am dynamically adding a user control to each row in a gridview. The reason I am doing it dynamically is the user control is different depending on certain data in the gridview. The gridview...
3
by: yovalk | last post by:
Hello, I have the following problem, I think it is rather simple, but hard to describe: I created a simple user control which contains a check box and an image - CheckBoxImage. Then I createa a...
10
by: Jess | last post by:
Hello, I have a program that stores dynamically created objects into a vector. #include<iostream> #include<vector> using namespace std;
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.