Passing objects to onClick methods in document.write()
I'm trying to dynamically create js objects which can also "write" themselves into the document using Foo.write()
. The write method is just a bunch of document.write()
calls which pulls variables from Foo
to populate elements. So essentially, write()
contains the template for all Foo
s.
This works great. However, I'm running into a problem when I want to set an onClick
to one of the template elements (an anchor
). The line that writes the link is:
document.write( "<a href='javascript:" +this+ "close()'><img src='layout_img/button_close.png' /></a> ");
So when called, the Foo
inserts itself and Foo.close()
should be called on that specific Foo
. But when I click the link I get a js error: "missing ] after element list"
. In the status bar, when I hover the link, it shows javascript:[Object object].close()
which I'm assuming is a good thing.
Why isn't this working?
Here's more of my code to help. This is how I'd like to create/write my objects:
<script type="text/javascript">
new Foo( 'any_id_i_want', {
title: "any_title",
icon: "any_image",
is开发者_如何学运维Minimized: false,
top: 400,
left: 500
}).write().setContents( "Hello <a href='http://google.com'>google</a>" );
</script>
write()
uses document.write()
to create a template and uses things like Foo.title
to customize the object's appearance.
setContents()
finds the written code by document.getElementById(Foo.id)
and uses Element.innerHTML
to fill the Foo
with a custom message, in this case text and a link.
So I'd like to keep this method of creating the objects as it's very convenient. I just can't figure out how to use the template to make calls on the Foo
.
When you concatenate this
with the other strings, you will get the string representation of the object (i.e. this.toString()
). For a complex object that is not useful at all. As you see you get the text [Object object]
instead of anything that you can use to access the object.
If you want to be able to use the object like that, the object has to know the name of a variable that it can use to access itself.
Example:
// create object
var x = new Foo();
// set variable name
x.name = 'x';
Now you can use that property to create code that accesses the object:
document.write(
'<a href="javascript:' + this.name + '.close();">' +
'<img src="layout_img/button_close.png" />' +
'</a>'
);
If you instead would create the element as an object and append to an element in the page, you could simply put this
in a local variable and use in an anonymous function, without the need of a global variable name:
var e = document.createElement('a');
var t = this;
e.onclick = function(){
t.close();
};
(The need ot the local variable t
is so that you get it in a closeure for the anonymous function. When the onclick
event runs, this
doesn't refer to your object, but the HTML element.)
this
is an object. There is an implicit call to the object's toString()
when you concatenate it to a string. This is why you're seeing [Object object].close()
. What is the output that you're expecting?
There is a number of things that are not optimal here:
- You are converting Foo, which is an object, to a String. This calls
Foo.toString()
which returns the string[Object object]
. - You are assigning an event listener via a string. You should create your link and call
addEventListener
or evenlink.onclick = function() { Foo.close() }
. this
changes its value depending on context. At the time ofwrite()
it will be something different then when you call the onclick handler. A simple solution is to usevar that = this; that.close()
.- Using
document.write
is probably the worst method of adding stuff to your document. Use the DOM apis to create stuff in JavaScript.
Saying that this is how I would tackle that:
Foo.write = function() {
var link = document.createElement('a');
link.innerHTML = "<img src='layout_img/button_close.png' />";
var that = this;
link.onclick = function() { that.close(); };
document.body.appendChild(link);
}
In your situation it might also be a good idea to look into using a templating library.
精彩评论