jQuery hace clic / alterna entre dos funciones
Estoy buscando una manera de ejecutar dos operaciones/funciones/"bloques de código" separados cuando se hace clic en algo y luego un bloque totalmente diferente cuando se vuelve a hacer clic en lo mismo. Yo armé esto. Me preguntaba si había una forma más eficiente/elegante. Conozco jQuery .toggle() pero no funciona como se desea.
Trabajando aquí: http://jsfiddle.net/reggi/FcvaD/1/
var count = 0;
$("#time").click(function() {
count++;
//even odd click detect
var isEven = function(someNumber) {
return (someNumber % 2 === 0) ? true : false;
};
// on odd clicks do this
if (isEven(count) === false) {
$(this).animate({
width: "260px"
}, 1500);
}
// on even clicks do this
else if (isEven(count) === true) {
$(this).animate({
width: "30px"
}, 1500);
}
});
jQuery tiene dos métodos llamados .toggle()
. El otro [docs] hace exactamente lo que desea para los eventos de clic.
Nota: Parece que al menos desde jQuery 1.7 , esta versión .toggle
está obsoleta , probablemente exactamente por esa razón, es decir, que existen dos versiones. Usar .toggle
para cambiar la visibilidad de los elementos es solo un uso más común. El método se eliminó en jQuery 1.9 .
A continuación se muestra un ejemplo de cómo se podría implementar la misma funcionalidad que un complemento (pero probablemente expone los mismos problemas que la versión integrada (consulte el último párrafo de la documentación)).
(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));
MANIFESTACIÓN
(Descargo de responsabilidad: ¡no digo que esta sea la mejor implementación! Apuesto a que se puede mejorar en términos de rendimiento)
Y luego llámalo con:
$('#test').clickToggle(function() {
$(this).animate({
width: "260px"
}, 1500);
},
function() {
$(this).animate({
width: "30px"
}, 1500);
});
Actualización 2:
Mientras tanto, creé un complemento adecuado para esto. Acepta un número arbitrario de funciones y puede usarse para cualquier evento. Se puede encontrar en GitHub .
MANIFESTACIÓN
.one() documentación.
Llegué muy tarde para responder, pero creo que es el código más corto y podría ayudar.
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 con código de operación
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);
Complemento MicrojQuery
Si desea su propio método jQuery clickToggle encadenable , puede hacerlo de la siguiente manera:
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>
Alternador de funciones simples
DEMO EN VIVO
function a(){ console.log('a'); }
function b(){ console.log('b'); }
$("selector").click(function() {
return (this.tog = !this.tog) ? a() : b();
});
Si lo desea aún más corto (¿ por qué lo haría, verdad? ) puede usar el operador Bitwise XOR *Docs como:
DEMO
return (this.tog^=1) ? a() : b();
Eso es todo.
El truco consiste en establecer this
una boolean
propiedad para el objeto tog
, alternarla usando negación ( tog = !tog
)
y colocar las llamadas a funciones necesarias en un operador condicional. ?:
En el ejemplo de OP (incluso con varios elementos) podría verse así:
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);
});
TAMBIÉN : También puedes almacenar -toggle como:
DEMO :
$("selector").click(function() {
$(this).animate({width: (this.tog ^= 1) ? 260 : 30 });
});
pero no fue la solicitud exacta del OP para él.looking for a way to have two separate operations / functions
Usando Array.prototype.reverse :
Nota : esto no almacenará el estado de alternancia actual, sino que simplemente invertirá las posiciones de nuestras funciones en Array (tiene sus usos...)
Simplemente almacena sus funciones a,b dentro de una matriz, al hacer clic simplemente invierte el orden de la matriz y ejecuta la array[1]
función:
DEMO EN VIVO
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"...
});
¡UNA MEZCLA!
DEMOSTRACIÓN de jQuery DEMOSTRACIÓN
de JavaScript
Cree una buena función toggleAB()
que contendrá sus dos funciones, colóquelas en Array y al final de la matriz simplemente ejecute la función [ 0 // 1
] respectivamente dependiendo de la tog
propiedad que se pasa a la función desde la this
referencia:
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 );
Haría algo como esto para el código que mostraste, si todo lo que necesitas hacer es alternar un valor:
var oddClick = true;
$("#time").click(function() {
$(this).animate({
width: oddClick ? 260 : 30
},1500);
oddClick = !oddClick;
});