2

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?

2
  • 2
    document.body.onclick = func don't use setAttribute it's not an attribute, well it can be an HTML one but you don't do that from JS. Commented May 14, 2015 at 22:52
  • are there any drawbacks of document.body.onclick? I remember using someelement.setattribute("onclick", "func(...);"), because someelement.onclick did not always set the onclick event properly or was it just some error of mine? Commented May 14, 2015 at 23:20

1 Answer 1

2

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); 
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.