jQuery hace clic / alterna entre dos funciones

Resuelto ThomasReggi asked hace 13 años • 10 respuestas

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);
    }
});
ThomasReggi avatar Feb 06 '11 11:02 ThomasReggi
Aceptado

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 .toggleestá obsoleta , probablemente exactamente por esa razón, es decir, que existen dos versiones. Usar .togglepara 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 .

Felix Kling avatar Feb 06 '2011 04:02 Felix Kling

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>
Expandir fragmento


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 thisuna booleanpropiedad 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 togpropiedad 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 );
Roko C. Buljan avatar Feb 03 '2014 05:02 Roko C. Buljan

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;
});
dom avatar Feb 06 '2011 04:02 dom