Is there a better way of toggling between different functions, on click events ? Something maybe that use "on" "off" methods or simpler alternative ?
(function($) {
$.fn.clickToggle = function(func1, func2, func3) {
var funcs = [func1, func2, func3];
this.data('toggleclicked', 0);
this.click(function() {
var data = $(this).data();
var tc = data.toggleclicked;
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % 3;
});
return this;
};
}(jQuery));
$('#b1').clickToggle(
function() {alert('First handler');},
function() {alert('Second handler');},
function() {alert('Third handler');}
);
1 Answer 1
Your general approach seems sound. But you shouldn't hard-code the number of handlers. Take the functions as a rest-arg, and use funcs.length
in the modulo expression.
You can also use the argument to .data()
to look up the named data element, rather than getting the whole data object.
$.fn.clickToggle = function(...funcs) {
this.data('toggleclicked', 0);
this.click(function() {
var tc = $(this).data("toggleclicked");
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % funcs.length;
});
return this;
};
You might also want to special-case a single function and just bind it the normal way, and completely ignore the call if there are no functions.
$.fn.clickToggle = function(...funcs) {
switch (funcs.length) {
case 0:
break;
case 1:
this.click(funcs[0]);
break;
default:
this.data('toggleclicked', 0);
this.click(function() {
var tc = $(this).data("toggleclicked");
$.proxy(funcs[tc], this)();
$(this).data("toggleclicked", (tc + 1) % funcs.length);
});
}
return this;
};
.off()
and.on()
to change the handler won't work, because when the next handler is added with.on()
, and the old handler returns, it will then run the next handler immediately. \$\endgroup\$