96

I have a button:

<button id="a" onclick="Foo()">Button A</button>

When I click this button the first time, I want it to execute Foo (which it does correctly):

function Foo() {
  document.getElementById("a").onclick = Bar();
}

What I want to happen when I click the button the first time is to change the onclick function from Foo() to Bar(). Thus far, I've only been able to achieve an infinite loop or no change at all. Bar() would look something like this:

function Bar() {
  document.getElementById("a").onclick = Foo();
}

Thus, clicking this button is just alternating which function gets called. How can I get this to work? Alternatively, what's a better way to show/hide the full text of a post? It originally starts shorted, and I provide a button to "see the full text." But when I click that button I want users to be able to click the button again to have the long version of the text go away.

Here's the full code, if it helps:

function ShowError(id) {
    document.getElementById(id).className = document.getElementById(id).className.replace(/\bheight_limited\b/, '');
    document.getElementById(id+"Text").className = document.getElementById(id+"Text").className.replace(/\bheight_limited\b/, '');
    document.getElementById(id+"Button").innerHTML = "HIDE FULL ERROR";
    document.getElementById(id+"Button").onclick = HideError(id);
}

function HideError(id) {
    document.getElementById(id).className += " height_limited";
    document.getElementById(id+"Text").className += " height_limited";
    document.getElementById(id+"Button").innerHTML = "SHOW FULL ERROR";
    document.getElementById(id+"Button").onclick = "ShowError(id)";
}
5
  • 2
    I'm not making this an answer since you are specifically asking about vanilla JavaScript, but you may want to look into jQuery. It's a JavaScript library that can help you do what you are looking to do in your question. Commented Mar 14, 2011 at 20:12
  • Know about JQuery, can only use Javascript in this case. Thanks. Commented Mar 14, 2011 at 20:13
  • 1
    The onclick property should be in all lowercase. developer.mozilla.org/en/DOM/element.onclick Commented Mar 14, 2011 at 20:15
  • Aren't event handlers added by using += ? And perhaps you might even need to do this: myobject.onclick += function() { Foo(); } Commented Mar 14, 2011 at 20:16
  • 1
    Turns out I didn't need the +=. I think += wouldn't remove the existing onclick function, right? Commented Mar 14, 2011 at 20:22

8 Answers 8

136

Your code is calling the function and assigning the return value to onClick, also it should be 'onclick'. This is how it should look.

document.getElementById("a").onclick = Bar;

Looking at your other code you probably want to do something like this:

document.getElementById(id+"Button").onclick = function() { HideError(id); }
Sign up to request clarification or add additional context in comments.

3 Comments

Just wanted to add that Ryan does not include the parentheses after Bar because it is not a function call.
... you probably want to do something like this: .onclick = HideError; // if this won't work, why not. What's the diff from above answer?
@pashute The difference is that .onclick = HideError is going to invoke HideError(event: MouseEvent) whereas the above answer invokes HideError(id). If you don't care about parameters, then you can do the shorter version and ignore the event that gets passes in.
88
var Foo = function(){
    document.getElementById( "a" ).setAttribute( "onClick", "javascript: Boo();" );
}

var Boo = function(){
    alert("test");
}

5 Comments

This seems to be the best way to do it. Though others work, adding a function directly to onclick may not work in some scenarios. I faced an issue in a case where creating multiple buttons in a loop and assigning a function for onclick for each button in the loop was not working. It would assign the function for the last button to all the buttons. Using this method works like a charm. Thanks Hor!
Should be onclick, not onClick.
@user66001 it doesn't matter, HTML is not case sensitive
@Calne - camel case'ng it might make people think it needs to be.
Is this still true? 'onClick' did not work for me, but 'onclick' did.Using Chrome 47 on Windows 7 64-bit.
26

Do not invoke the method when assigning the new onclick handler.

Simply remove the parenthesis:

document.getElementById("a").onclick = Foo;

UPDATE (due to new information):

document.getElementById("a").onclick = function () { Foo(param); };

6 Comments

Unfortunately, i have a parameter that needs to be there. Does that change your answer?
@hatorade: use onclick = function () { Foo(params); };
@hatorade - Yes document.getElement... function() { Foo(param);};
Thank you all for the help. I'd give you the answer if I could, but Ryan got it a few mins sooner. Sorry :(. I did +1 though!
should that be .onclick not .onClick?
|
16

Thanks to João Paulo Oliveira, this was my solution which includes a variable (which was my goal).

document.getElementById( "myID" ).setAttribute( "onClick", "myFunction("+VALUE+");" );

Comments

11

I recommend this approach:

Instead of having two click handlers, have only one function with a if-else statement. Let the state of the BUTTON element determine which branch of the if-else statement gets executed:

HTML:

<button id="a" onclick="toggleError(this)">Button A</button>

JavaScript:

function toggleError(button) { 
    if ( button.className === 'visible' ) {
        // HIDE ERROR
        button.className = '';
    } else {
        // SHOW ERROR
        button.className = 'visible';
    }
}

Live demo: http://jsfiddle.net/simevidas/hPQP9/

1 Comment

I personally like this solution because it keeps the code for the button together (and being a toggle, if you update one side, usually you want to update the other side), but I was also working with Vue and using v-on:click, so the top answer didn't seem to be working for me. Thanks Sime!
7

You could try changing the button attribute like this:

element.setAttribute( "onClick", "javascript: Boo();" );

Comments

4

What might be easier, is to have two buttons and show/hide them in your functions. (ie. display:none|block;) Each button could then have it's own onclick with whatever code you need.

So, at first button1 would be display:block and button2 would be display:none. Then when you click button1 it would switch button2 to be display:block and button1 to be display:none.

1 Comment

Perfect answer! For someone not really familiar with javascript, this is a very helpful method.
1

For anyone, like me, trying to set a query string on the action and wondering why it's not working-

You cannot set a query string for a GET form submission, but I have found you can for a POST.

For a GET submission you must set the values in hidden inputs e.g.

an action of: "/handleformsubmission?foo=bar" would have be added as the hidden field like: <input type="hidden" name="foo" value="bar" />

This can be done add dynamically in JavaScript as (where clickedButton is the submitted button that was clicked:

var form = clickedButton.form;
var hidden = document.createElement("input");
hidden.setAttribute("type", "hidden");
hidden.setAttribute("name", "foo");
hidden.setAttribute("value", "bar");
form.appendChild(hidden);

See this question for more info submitting a GET form with query string params and hidden params disappear

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.