Jarod Thornton
Jarod Thornton

Reputation: 401

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.

Upvotes: 0

Views: 12885

Answers (6)

FriendsKenny
FriendsKenny

Reputation: 150

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);

Upvotes: 0

Yuriy Yakym
Yuriy Yakym

Reputation: 3911

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>

Upvotes: 1

castletheperson
castletheperson

Reputation: 33496

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>

Upvotes: 2

Jarod Thornton
Jarod Thornton

Reputation: 401

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 i.e. 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?

Upvotes: 0

castletheperson
castletheperson

Reputation: 33496

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>

Upvotes: 2

napo
napo

Reputation: 869

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!

Upvotes: 0

Related Questions