views:

109

answers:

2

Hi guys,

what I'm trying to do here is to associate a DOM object with an instance of a JS object, which will provide some meaningfol methods later on ;) At this point I just want to handle my JS object the click event, whilst keeping it's references intact.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
<script type="text/javascript">
// my object, which will hold a reference to a single DOM object
obj = function(domobj) {
 this.o = domobj;
 my = this;
 var ref = my.click;
 this.o.onclick = ref;

}
// my objects click function
obj.prototype.click =  function() {
  alert(my.o.innerHTML);
}

// create objects with references
$(document).ready(function() {
 o1 = new obj(document.getElementById('b1'));
 o2 = new obj(document.getElementById('b2'));
});
</script>

</head>
<body>
<button id="b1">button 1</button>
<button id="b2">button 2</button>
</body>
</html>

Expected result: when clicking on button 1, the text "button 1" should be alerted.

Current result: when clicking button 1, the text "button 2" is alerted.

What I found out so far is that the wrong instance of obj is triggered from the click event, even though o1 and o2 maintain correct references to their corresponding DOM object.

Any ideas how to solve this?

Thanks for your help!

Best regards, Clemens

+2  A: 

my is a global, so by the time the click event is triggered, it will always refer to the object returned by the last call.

You could make my local and define the click function inside the obj constructor.

Uh Clem
+1  A: 

When you assign a function to a DOM element property like onclick, the this in that function (when invoked) is going to be the DOM element. You can change that, however, by using apply and/or a little closure.

Check this out (it is still pretty much like your example, but see the comments for what is going on now):

<script type="text/javascript">
// Obj with properties of its own, including a cool DOM object
function Obj(domobj, name) {
    this.name = (typeof name==='undefined') ? 'Clemens Prerovsky' : name;
    this.o = domobj;
    // Closure time! Preserve this 'this', using 'that'
    var that = this;
    domobj.onclick = function () {return that.clickHandler();};
}
// Handler of clicks
Obj.prototype.clickHandler = function () {
    alert(this.o.innerHTML+', name:'+this.name);
}

// Create objects with references
$(document).ready(function() {
    var o1 = new Obj(document.getElementById('b1'));
    var o2 = new Obj(document.getElementById('b2'), 'npup');
});
</script>

I urge you not to create global variables by mistake. Take care and declare your variables so you don't get so many nasty surprises. What was left of that in this example were the o1 and o2 objects.

Nasty surprises always lurk when creating circular references, and you run the risk of memory leakage if they are not handled propertly. Are the "custom objects" really needed in this manner?

HTH.

npup
Hi guys - thanks for your help. Obviously I did not understand how to use closures in the right way, despite creating a global variable by accident :-/.The custom objects are needed, as they represent individual instances of an inline editor, with various setups (different formatting buttons etc.).Anyway - now I got the point - thank you very much!
cduke