Reputation: 135
Given the following example code I want to set the onclick
event to a function which I declare in the same method (no function in global scope):
<HTML>
<HEAD>
<Title>Title</Title>
</HEAD>
<body>
<img id="img" class="std" src="http://www.free-animated-pictures.com/bug_crawls_on_screen.gif"/>
<script type='text/javascript'>
var i = document.getElementById("img");
var func = function(){
var i = document.getElementById("img");
if(i.className === "std"){
i.className = "hid";
i.style.display = "none";
}
else if(i.className === "hid"){
i.className = "std";
i.style.display = "block";
}
};
//func = func.toString();
//func = func.replace("function ()", "")
document.body.setAttribute("onclick", func);
</script>
</body>
</HTML>
If I use the code as is I only get the following error when the event is fired:
Uncaught SyntaxError: Unexpected token (
If instead I take the string of the function and remove the function part of it, the script works as expected:
func = func.toString();
func = func.replace("function ()", "")
Why is that so? Is there a better way? Obviously I can't declare the function without the function part, so what's the point in removing it again?
Upvotes: 2
Views: 1575
Reputation: 14645
You were setting the actual textual element's attribute string using setAttribute
, which in turn is auto-wrapped in a function!
Also, if it would have worked, there would be no body to click on once the image had disappeared.
Here is a working example you should not use, just intended to explain above statement:
Here is a function func
which is converted to string (and where a string is expected, javascript usually calls the .toString()
method automatically, I put it in to clearly show what happened).
Then, to prevent a quoting problem (you used double-quotes in html and for some (in my opinion, insane) reason some browsers replace single quotes in javascript to double quotes (and I've even witnessed some pre-compiling in some browsers)), I naively (because it was safe for this particular function) replaced all double quotes to single quotes.
Then we still need to remove function(){
and trailing }
.
Now we arrived at the function string, which we can pass.
Finally the browser sets the actual textual attribute and wraps the code again inside a function so that it works.
<img id="img" class="std" src="http://www.free-animated-pictures.com/bug_crawls_on_screen.gif" />
intentional text filler, otherwise body shrinks to 0*0 px leaving nothing to click on...
<script type='text/javascript'>
var func = function(){
var i = document.getElementById('img');
if(i.className === 'std'){
i.className = 'hid';
i.style.display = 'none';
}
else if(i.className === 'hid'){
i.className = 'std';
i.style.display = 'block';
}
};
document.body.setAttribute( 'onclick'
, func.toString()
.replace(/\"/g,'\'')
.replace(/^function *\( *\) *{/,'')
.replace(/} *$/,'')
);
</script>
Solution is obviously to document.body.onclick=func
directly (as gillesc already commented), or use document.body.addEventListener('click',func,false)
(which is what you are probably confused with).
Note that for backward compatibility (notably < IE9) you'd need attachEvent
, here is a basic workaround:
function addEventHandler(elem, eventType, handler) {
if (elem.addEventListener)
elem.addEventListener (eventType,handler,false);
else if (elem.attachEvent)
elem.attachEvent ('on'+eventType,handler);
}
Upvotes: 2