简体   繁体   中英

Switch onclick Event onclick

I have a function written to open / close a div using a placeholder for a hyperlink.

<a class="button" onclick="show('click-drop')">Open</a>

The onclick event then opens the div.

I have this onclick to close it:

<a class="button" onclick="hide('click-drop')">Close</a>

What I would like to do is have a single placeholder for a hyperlink that switches between the two onclick events. So onclick=show would switch to onclick=hide and vice versa.

I have looked everywhere and cannot find a straightforward solution for my situation.

Revised Question

Here's specifically what I am working with.

function show(target) {
    document.getElementById(target).style.height = '300px';
}
function hide(target) {
    document.getElementById(target).style.height = '0px';
}

<a class="button" onclick="show('click-drop')">Open</a>
<div id="click-drop" style="height:0px">
    <a class="button" onclick="hide('click-drop')">Close</a>
</div>

Click Open and it opens / expands inline height style. Click Close and it closes.

I need to have the onclick toggle, but with Open changing to Close and reverse.

It would be ideal to keep the placement of the links. So the Open link outside the link is hidden until the Close link within the div is clicked.

I appreciate any feedback.

You could dynamically change the onclick event of the button, but it's already awkward enough that you're using HTML to describe functionality. It would do you even better if you kept all functionality in the JavaScript. Something like this:

 var button = document.getElementById("button"); var target = document.getElementById("target"); button.innerHTML = "Close"; button.onclick = function() { hide(target); }; function hide(target) { console.log("hiding"); target.style.display = "none"; console.log(target); button.innerHTML = "Open"; button.onclick = function() { show(target); }; } function show(target) { target.style.display = "block"; button.innerHTML = "Close"; button.onclick = function() { hide(target); }; } 
 <button id="button">Close</button> <div id="target">Hello World!</div> 

Here is another answer in case you want to use toggle on multiple buttons. This solution uses the button to store the state of its target, and so it uses toggle.call() to modify the value of this within toggle .

It's inspired by jQuery.toggle() and Yuriy Yakym's answer .

 for (i = 1; i <= 3; i++) { var button = document.getElementById("button"+i), target = document.getElementById("target"+i); // wrapped in closure because https://stackoverflow.com/q/8909652/5743988 (function(_button, _target) { _button.onclick = function() { toggle.call(_button, _target); } })(button, target); } function toggle(target) { this.func = this.func || hide; // if "func" is undefined, assign "hide" this.func.call(target); // execute "func" this.func = this.func === hide // make "func" call the other thing next time ? (this.innerHTML = "Show", show) : (this.innerHTML = "Hide", hide); } function hide() { this.oldDisplay = window.getComputedStyle(this).display; this.style.display = "none"; // better than "height = 0px" } function show() { this.oldDisplay = this.oldDisplay || "block"; this.style.display = this.oldDisplay; } 
 button, div { display: inline-block; } 
 <button id="button1">Close</button> <div id="target1">Hello World!</div> <br> <button id="button2">Close</button> <div id="target2">Hello Again World!</div> <br> <button id="button3">Close</button> <div id="target3">Hello Again Again World!</div> 

It's possible to save button's state inside its context. And then, depending on its state call appropriate functions.

 function toggle() { this.state = !this.state; // false - open; true - closed; default = false (because is not initialized yet) this.innerHTML = this.state ? 'Close' : 'Open'; if(this.state) { open(); } else { close(); } } function open() { alert("Opened"); } function close() { alert("Closed"); } 
 <a class="button" onclick="toggle.call(this)">Open</a> <a class="button" onclick="toggle.call(this)">Open</a> <a class="button" onclick="toggle.call(this)">Open</a> 

Either the jQuery toggle or the toggleClass methods should the trick for you.

Edit, per requested, an example:

Say you have a CSS class that looks like this, based on the OP:

.info-box { 
    height: 300px;
}

By using $('#myTarget').toggleClass('info-box') , you will be removing that class or adding it. If you don't have it, you'll add it. If you do have it, you'll remove it. Just like that.

So, a working example I just threw together is here, and it implements toggle() by itself without the need to add any classes, which I believe still accomplishes what the OP was seeking resolution for.

https://jsfiddle.net/bbh9m478/1/

Hope that helps!

I figured out a straightforward solution for this.

When the open link is clicked and the div opens I need the open link to disappear and a close link displayed as a separate element. The same event should work in reverse ie close link closes div and displays open link.

While the original code I am working with uses an inline height property to control the open and close, the example below uses display property.

function show(target) {
    document.getElementById(target).style.display = 'block';
}
function hide(target) {
    document.getElementById(target).style.display = 'none';
}
function hideButton() {
    var x = document.getElementById("open");
    x.style.display = "none";
    var x = document.getElementById("close");
    x.style.display = "";
}
function showButton() {
    var x = document.getElementById("open");
    x.style.display = "";
    var x = document.getElementById("close");
    x.style.display = "none";
}

<a class="button" onclick="show('click-drop');hideButton()" id="open">Open</a>

<div id="click-drop" style="display:none">

<a class="button" onclick="hide('click-drop');showButton()" id="close" style="display:none">Close</a>

</div>              

Here it is in the wild - http://iemajen.com/scripts/mssa/

With this in place I have two more questions.

  1. How would I write this so it uses unobtrusive Javascript to attach behaviour to DOM elements from within the JS solely, meaning separate HTML from JS
  2. How can I write this to be used on multiple divs? I have a dozen divs that will be closed initially and each opened individually using the markup I wrote. I could write it up for each div / unique ids and such, but that seems like more bad practice and I would like to learn the best practice.

Should I just open a new topic for the last question?

After you create your element

var elem = document.querySelector('.js-switch'); var init = new Switchery(elem);

Bind your OnClickMetod to init.switcher like this

$(init.switcher).on('click', OnClickMetod);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM