Michael Winter wrote:
Derek Basch wrote: oFilterAdd = this.document.c reateElement("b utton");
The this operator seems unnecessary here, and elsewhere, in this
function (unless you have a document member, of course).
Yes, there was a document member. I have removed it though because it
was redundant.
this.removeChil d(window.oFilte rAddText);
this.appendChil d(window.oFilte rRemoveText);
Why do you feel the need to use the window global? Simply
oFilterAddText or oFilterRemoveTe xt will be sufficient (unless you
have variables with those names higher in the scope chain, which I
doubt is true).
Right again. I had already declared them as global variables so it was
also redundant.
I realize i could pass the addOnClick function by reference such
as:
oFilterAdd.addE ventListener("c lick", this.addOnclick (), false);
That would be a function call, not a reference. In any case, it
wouldn't matter: addOnclick would be called as a member of
oFilterAdd.
Right again. It should have read:
oFilterAdd.addE ventListener("c lick", this.addOnclick , false);
A completely different approach would be to use a closure, avoiding
globals altogether (which is arguably better):
After reading all I could stomach about closure I worked up an example
that uses your example of using closure to reference properties and an
example of what I would like to do using prototyping.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
</head>
<body>
<form id="form">
</form>
<script type="text/javascript">
function SortableTable() {
var filter = document.create Element('button ');
var filter_2 = document.create Element('button ');
var form = document.getEle mentById("form" );
var addText = document.create TextNode('Add') ;
var removeText = document.create TextNode('Remov e');
var addText_2 = document.create TextNode('Add') ;
var removeText_2 = document.create TextNode('Remov e');
filter.type = 'button';
filter_2.type = 'button';
form.appendChil d(filter);
form.appendChil d(filter_2);
filter.appendCh ild(addText);
filter_2.append Child(addText_2 );
//listener function reference is obtained as a private method using
closure
filter.addEvent Listener('click ', listener, false);
//proto_listener is a public method of SortableTable and a reference
// cannot be obtained using closure.
filter_2.addEve ntListener('cli ck', this.proto_list ener, false);
function listener(e) {
//this references button object
//addText/removeText are accesable as private properties
// via closure
this.removeChil d(addText);
this.appendChil d(removeText);
}
}
SortableTable.p rototype.proto_ listener = function (e) {
//this references button object
//addText_2/removeText_2 are not accesable as private properties
//via closure so an error is generated
this.removeChil d(addText_2);
this.appendChil d(removeText_2) ;
}
st = new SortableTable() ;
</script>
</body>
</html>
It seems that I will need to pass the scope of the SortableTable
instance to the proto_listener function.
I found this:
http://jibbering.com/faq/faq_notes/closures.html#clObjI
which seems to be an excellent solution to the scoping issues. It is a
bit of a mind bender (for me at least) but here is my own workup of the
authors example.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
</head>
<body>
<script type="text/javascript">
function associateObjWit hEvent(obj, methodName){
//obj is the SortableTable instance
return (function(e){
e = e||window.event ;
//this refers to the event object
//when onclick occurs obj and methodName
//are still available because of closure
return obj[methodName](e, this);
});
}
function SortableTable(e lementId){
this.property = "foo"
var el = document.getEle mentById(elemen tId);
if(el){
el.onclick = associateObjWit hEvent(this, "doOnClick" );
}
}
SortableTable.p rototype.doOnCl ick = function(event, element){
//this scope has not changed so this.property is available
alert(this.prop erty);
alert(element);
element.id = "new_text"
alert(element.i d);
}
p = document.create Element("p");
p.id = "text";
text = document.create TextNode("text" );
document.body.a ppendChild(p);
p.appendChild(t ext);
obj = new SortableTable(" text");
</script>
</body>
</html>
Thanks for all the help and feel free to rip apart my logic and
terminology.
Derek Basch