jQuery click / toggle between two functions
Solution 1:
jQuery has two methods called .toggle()
. The other one [docs] does exactly what you want for click events.
Note: It seems that at least since jQuery 1.7, this version of .toggle
is deprecated, probably for exactly that reason, namely that two versions exist. Using .toggle
to change the visibility of elements is just a more common usage. The method was removed in jQuery 1.9.
Below is an example of how one could implement the same functionality as a plugin (but probably exposes the same problems as the built-in version (see the last paragraph in the documentation)).
(function($) {
$.fn.clickToggle = function(func1, func2) {
var funcs = [func1, func2];
this.data('toggleclicked', 0);
this.click(function() {
var data = $(this).data();
var tc = data.toggleclicked;
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % 2;
});
return this;
};
}(jQuery));
DEMO
(Disclaimer: I don't say this is the best implementation! I bet it can be improved in terms of performance)
And then call it with:
$('#test').clickToggle(function() {
$(this).animate({
width: "260px"
}, 1500);
},
function() {
$(this).animate({
width: "30px"
}, 1500);
});
Update 2:
In the meantime, I created a proper plugin for this. It accepts an arbitrary number of functions and can be used for any event. It can be found on GitHub.
Solution 2:
DEMO
.one() documentation.
I am very late to answer but i think it's shortest code and might help.
function handler1() {
alert('First handler: ' + $(this).text());
$(this).one("click", handler2);
}
function handler2() {
alert('Second handler: ' + $(this).text());
$(this).one("click", handler1);
}
$("div").one("click", handler1);
DEMO With Op's Code
function handler1() {
$(this).animate({
width: "260px"
}, 1500);
$(this).one("click", handler2);
}
function handler2() {
$(this).animate({
width: "30px"
}, 1500);
$(this).one("click", handler1);
}
$("#time").one("click", handler1);
Solution 3:
Micro jQuery Plugin
If you want your own chainable clickToggle jQuery Method you can do it like:
jQuery.fn.clickToggle = function(a, b) {
return this.on("click", function(ev) { [b, a][this.$_io ^= 1].call(this, ev) })
};
// TEST:
$('button').clickToggle(function(ev) {
$(this).text("B");
}, function(ev) {
$(this).text("A");
});
<button>A</button>
<button>A</button>
<button>A</button>
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
Simple Functions Toggler
LIVE DEMO
function a(){ console.log('a'); }
function b(){ console.log('b'); }
$("selector").click(function() {
return (this.tog = !this.tog) ? a() : b();
});
If you want it even shorter (why would one, right?!) you can use the Bitwise XOR *Docs operator like:
DEMO
return (this.tog^=1) ? a() : b();
That's all.
The trick is to set to the this
Object a boolean
property tog
, and toggle it using negation (tog = !tog
)
and put the needed function calls
in a Conditional Operator ?:
In OP's example (even with multiple elements) could look like:
function a(el){ $(el).animate({width: 260}, 1500); }
function b(el){ $(el).animate({width: 30}, 1500); }
$("selector").click(function() {
var el = this;
return (el.t = !el.t) ? a(el) : b(el);
});
ALSO: You can also store-toggle like:
DEMO:
$("selector").click(function() {
$(this).animate({width: (this.tog ^= 1) ? 260 : 30 });
});
but it was not the OP's exact request for he's looking for a way to have two separate operations / functions
Using Array.prototype.reverse:
Note: this will not store the current Toggle state but just inverse our functions positions in Array (It has it's uses...)
You simply store your a,b functions inside an array, onclick you simply reverse the array order and execute the array[1]
function:
LIVE DEMO
function a(){ console.log("a"); }
function b(){ console.log("b"); }
var ab = [a,b];
$("selector").click(function(){
ab.reverse()[1](); // Reverse and Execute! // >> "a","b","a","b"...
});
SOME MASHUP!
jQuery DEMO
JavaScript DEMO
Create a nice function toggleAB()
that will contain your two functions, put them in Array, and at the end of the array you simply execute the function [0 // 1
] respectively depending on the tog
property that's passed to the function from the this
reference:
function toggleAB(){
var el = this; // `this` is the "button" Element Obj reference`
return [
function() { console.log("b"); },
function() { console.log("a"); }
][el.tog^=1]();
}
$("selector").click( toggleAB );
Solution 4:
I would do something like this for the code you showed, if all you need to do is toggle a value :
var oddClick = true;
$("#time").click(function() {
$(this).animate({
width: oddClick ? 260 : 30
},1500);
oddClick = !oddClick;
});