jQuery Klicken / Umschalten zwischen zwei Funktionen

72

Ich suche nach einer Möglichkeit, zwei separate Operationen / Funktionen / "Codeblöcke" auszuführen, wenn auf etwas geklickt wird, und dann einen völlig anderen Block, wenn dasselbe erneut angeklickt wird. Ich habe das zusammengestellt. Ich habe mich gefragt, ob es einen effizienteren / eleganteren Weg gibt. Ich weiß über jQuery .toggle () Bescheid, aber es ist irgendwie beschissen .

Arbeiten hier: 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
quelle
14
toggle()saugt nicht, es tut einfach nicht das, was du brauchst;)
Felix Kling
1
Überprüfen Sie meine Antwort stackoverflow.com/questions/4911577/…
Tushar Gupta - curioustushar
1
Dieser Code hat ziemlich geholfen. VIELEN DANK!
nholloway4

Antworten:

70

In jQuery werden zwei Methoden aufgerufen .toggle(). Der andere [docs] macht genau das, was Sie für Klickereignisse wollen.

Hinweis: Es scheint , dass zumindest seit jQuery 1.7 , ist diese Version von .toggleist veraltet , wahrscheinlich genau aus diesem Grund, nämlich dass zwei Versionen existieren. Die Verwendung .togglezum Ändern der Sichtbarkeit von Elementen ist nur eine häufigere Verwendung. Die Methode wurde in jQuery 1.9 entfernt .

Im Folgenden finden Sie ein Beispiel dafür, wie Sie die gleiche Funktionalität wie ein Plugin implementieren können (wahrscheinlich jedoch dieselben Probleme wie bei der integrierten Version (siehe den letzten Absatz in der Dokumentation)).


(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

(Haftungsausschluss: Ich sage nicht, dass dies die beste Implementierung ist! Ich wette, sie kann in Bezug auf die Leistung verbessert werden.)

Und dann nenne es mit:

$('#test').clickToggle(function() {   
    $(this).animate({
        width: "260px"
    }, 1500);
},
function() {
    $(this).animate({
        width: "30px"
    }, 1500);
});

Update 2:

In der Zwischenzeit habe ich ein passendes Plugin dafür erstellt. Es akzeptiert eine beliebige Anzahl von Funktionen und kann für jedes Ereignis verwendet werden. Es kann auf GitHub gefunden werden .

Felix Kling
quelle
@ ThomasReggi: Danke für das Update. Es war sehr spät, als ich dies schrieb;) Es ist jedoch nicht notwendig, es zu verwenden this.each, zumal dies ein funcsArray und eine neue Ereignishandlerfunktion für jedes Element erzeugt. Es wurde behoben und Demo hinzugefügt.
Felix Kling
Ich verstehe es nicht ... warum nicht einfach api.jquery.com/toggle-event verwenden ? Sie haben es sogar in Ihrer Antwort erwähnt ... Vielleicht sollten Sie diesen Teil hervorheben, da es sich um eine native jQuery-Methode handelt.
dmmd
@jlcd: Deshalb habe ich es am Anfang der Antwort gesetzt. Ich habe meine Antwort bearbeitet, um sie stärker zu betonen. Glaubst du, es ist jetzt besser? TBH, ich habe den Code geschrieben und später die andere .toggleMethode entdeckt. Ich wollte diesen Code aber nicht wegwerfen ...
Felix Kling
1
Überprüfen Sie meine Antwort stackoverflow.com/questions/4911577/…
Tushar Gupta - curioustushar
1
@Syed: Sicher, setzen Sie data.toggleclickeddas Element einfach auf den Index, auf den Sie zurücksetzen möchten.
Felix Kling
66

DEMO

.one () Dokumentation.

Ich bin sehr spät zu antworten, aber ich denke, es ist der kürzeste Code und könnte helfen.

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 Mit 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);
Tushar Gupta - Curioustushar
quelle
@urjitonrails Ich bin froh, dass es hilft :)
Tushar Gupta - Curioustushar
1
So eine saubere Lösung. Prost Kumpel!
Carl Papworth
2
Das ist perfekt, bis heute!
Eckstein
Erstaunliche Lösung !!! Ich wusste nie über die .one()Methode Bescheid , aber sie ist sehr nützlich. Danke
Si8
49

Micro jQuery Plugin

Wenn Sie Ihre eigene verkettbare clickToggle jQuery-Methode möchten , können Sie dies wie folgt tun:

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>


Einfache Funktionen Toggler

LIVE DEMO

function a(){ console.log('a'); }
function b(){ console.log('b'); }

$("selector").click(function() { 
  return (this.tog = !this.tog) ? a() : b();
});

Wenn Sie es noch kürzer haben möchten ( warum sollte es eines geben, oder?! ), Können Sie den Bitwise XOR * Docs- Operator wie folgt verwenden :
DEMO

  return (this.tog^=1) ? a() : b();

Das ist alles.
Der Trick besteht darin, für das thisObjekt eine booleanEigenschaft togfestzulegen, diese mit negation ( tog = !tog) umzuschalten
und die erforderlichen Funktionsaufrufe in einen bedingten Operator einzufügen ?:




Im Beispiel von OP (auch mit mehreren Elementen) könnte es so aussehen:

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

AUCH : Sie können -toggle auch wie folgt speichern :
DEMO :

$("selector").click(function() {
  $(this).animate({width: (this.tog ^= 1) ? 260 : 30 });
}); 

aber es war nicht die genaue Anfrage des OP für ihn looking for a way to have two separate operations / functions


Verwenden von Array.prototype.reverse :

Hinweis : Dadurch wird nicht der aktuelle Umschaltstatus gespeichert, sondern nur unsere Funktionspositionen im Array umgekehrt (es hat seine Verwendung ...).

Sie speichern einfach Ihre a, b- Funktionen in einem Array. Klicken Sie einfach auf, um die Array-Reihenfolge umzukehren, und führen Sie die folgende array[1]Funktion aus:

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"...
});

EINIGES MASHUP!

jQuery DEMO
JavaScript DEMO

Erstellen Sie eine nette Funktion toggleAB(), die Ihre beiden Funktionen enthält, fügen Sie sie in das Array ein und führen Sie am Ende des Arrays einfach die Funktion [ 0 // 1] aus, abhängig von der togEigenschaft, die aus der this Referenz an die Funktion übergeben wird :

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
quelle
2
Fantastische Antwort! Vielen Dank
Alex Holsgrove
Ich verstehe das meiste davon. Aber ich verstehe nicht, woher "tog" kommt? und wie geht el.tog ^ = 1 alternativ zwischen 0 und 1? Vielen Dank
koz
@koz .togist nur eine Eigenschaft, die wir dem thisObjekt hinzufügen . Genau wie in " Person.name = "koz"Person ist ein Objekt" weisen Sie eine nameEigenschaft und dann einen Wert zu. Mehr zum XOR-Operator ^finden Sie hier: stackoverflow.com/a/22061240/383904 (Sie können den gleichen Link in meiner Antwort finden;))
Roko C. Buljan
@ RokoC.Buljan Danke für die Antwort, sehr geschätzt. Ich habe mir den Link angesehen, aber er erklärt nicht die Mathematik, die ich gerne verstehe. Ich verstehe, es gibt 0, 1, 0, 1 zurück ... aber wie macht es das? Was bedeutet "^ = 1" in der Mathematik eigentlich, um alternativ 0,1,0,1 zu entsprechen? thnx
koz
@koz Denken Sie binär, Nullen und Einsen. Der XOR-Operator Gibt onean jeder Bitposition ein zurück, für die die entsprechenden Bits eines der Operanden, jedoch nicht beider Operanden sind ones. Wie Sie bemerkt haben, gehen wir immer gegen die Einsen ( 1) -Operatoren vor: operand^1Hier ist eine Ergebnistabelle : 0^1 =1und 1^1 =0. So weit so gut - die Ergebnisse wechseln! Aber um unseren Operator tatsächlich zu ändern, müssen el.togSie den Assignment-Operator ( =) verwenden - und los geht's! el.tog^=1. Wenn Sie nun auf die kleine Tabelle zurückgreifen, werden Sie verstehen, welche Werte der el.togEigenschaft jetzt zugewiesen sind .
Roko C. Buljan
24

Ich würde so etwas für den Code tun, den Sie gezeigt haben, wenn Sie nur einen Wert umschalten müssen:

var oddClick = true;
$("#time").click(function() {
    $(this).animate({
        width: oddClick ? 260 : 30
    },1500);
    oddClick = !oddClick;
});
dom
quelle
Dies funktioniert nur für eindeutige Elemente. Ich schlage vor , die oddClick-Teil und ersetzen Sie die entfernen width:-Linie mit width: $(this).width() == 30 ? 260 : 30.
mgutt
15

Ich habe dies verwendet, um einen Umschalteffekt zwischen zwei Funktionen zu erzeugen.

var x = false;
$(element).on('click', function(){
 if (!x){
  //function
  x = true;
 }
 else {
  //function
  x = false;
 }
});
metamlkshk
quelle
Danke :) Sehr nützlich!
Emil Gurbanov
5

Ich denke nicht, dass Sie die Umschaltmethode implementieren sollten, da es einen Grund gibt, warum sie aus jQuery 1.9 entfernt wurde.

Verwenden Sie stattdessen toggleClass, das von jQuery vollständig unterstützt wird:

function a(){...}
function b(){...}   

Nehmen wir zum Beispiel an, Ihr Ereignisauslöser ist onclick, also:

Erste Wahl:

$('#test').on('click', function (event) {

    $(this).toggleClass('toggled');

    if ($(this).hasClass('toggled')) {
        a();
    } else{
        b();
    }
}

Sie können die Handlerfunktionen auch als Parameter senden:

Zweite Option:

$('#test').on('click',{handler1: a, handler2: b}, function (event) {

    $(this).toggleClass('toggled');

    if ($(this).hasClass('toggled')) {
        event.data.handler1();
    } else{
        event.data.handler2();
    }
}
Dudi
quelle
1

Wenn Sie nur einen Booleschen Wert beibehalten, isEvenkönnen Sie prüfen, ob sich eine Klasse isEvenim Element befindet, und diese Klasse dann umschalten.

Die Verwendung einer gemeinsam genutzten Variablen wie count ist eine schlechte Praxis. Fragen Sie sich, welchen Umfang diese Variable hat. Denken Sie daran, wenn Sie 10 Elemente hätten, die Sie auf Ihrer Seite umschalten möchten, würden Sie 10 Variablen oder ein Array oder Variablen erstellen, um deren Status zu speichern? Wahrscheinlich nicht.

Bearbeiten:
jQuery verfügt über eine switchClass- Methode, mit der in Kombination mit hasClass zwischen den beiden von Ihnen definierten Breiten animiert werden kann. Dies ist günstig, da Sie diese Größen später in Ihrem Stylesheet ändern oder andere Parameter wie Hintergrundfarbe oder Rand zum Übergang hinzufügen können.

nedk
quelle
1

Verwenden Sie einige Funktionen und einen Booleschen Wert. Hier ist ein Muster, kein vollständiger Code:

 var state = false,
     oddONes = function () {...},
     evenOnes = function() {...};

 $("#time").click(function(){
     if(!state){
        evenOnes();
     } else {
        oddOnes();
     }
     state = !state;
  });

Oder

  var cases[] = {
      function evenOnes(){...},  // these could even be anonymous functions
      function oddOnes(){...}    // function(){...}
  };

  var idx = 0; // should always be 0 or 1

  $("#time").click(function(idx){cases[idx = ((idx+1)%2)]()}); // corrected

(Beachten Sie, dass die zweite nicht mehr auf meinem Kopf liegt und ich viele Sprachen mische, sodass die genaue Syntax nicht garantiert ist. Sollte in der Nähe von echtem Javascript liegen.)

Charlie Martin
quelle
Abgesehen von Syntaxfehlern würde der zweite nicht funktionieren. Sie rufen $("#time").click(..)nur einmal auf, wodurch die aufzurufende Funktion festgelegt wird.
Felix Kling
benötigt nur eine andere anonyme Funktion, um den richtigen Fall aufzurufen.
zzzzBov
0

Wenn Sie die erste Antwort ändern, können Sie zwischen n Funktionen wechseln:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus.com®">
<!-- <script src="../js/jquery.js"></script> -->
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
  <title>my stupid example</title>

 </head>
 <body>
 <nav>
 <div>b<sub>1</sub></div>
<div>b<sub>2</sub></div>
<div>b<sub>3</sub></div>
<!-- .......... -->
<div>b<sub>n</sub></div>
</nav>
<script type="text/javascript">
<!--
$(document).ready(function() {
	(function($) {
        $.fn.clickToggle = function() {
          var ta=arguments;
	        this.data('toggleclicked', 0);
          this.click(function() {
				    id= $(this).index();console.log( id );
            var data = $(this).data();
            var tc = data.toggleclicked;
            $.proxy(ta[id], this)();
            data.toggleclicked = id
          });
          return this;
        };
   }(jQuery));

    
	$('nav div').clickToggle(
	    function() {alert('First handler');}, 
        function() {alert('Second handler');},
        function() {alert('Third handler');}
		//...........how manny parameters you want.....
		,function() {alert('the `n handler');}
	);

});
//-->
</script>
 </body>
</html>

Constantin
quelle
0

Einzeilige Lösung: Grundidee:

$('sth').click(function () {
    let COND = $(this).propery == 'cond1' ? 'cond2' : 'cond1';
    doSomeThing(COND);
})

Beispiele auf jsfiddle

Beispiel 1: Ändern von innerHTML eines Elements in einem Umschaltmodus:

$('#clickTest1').click(function () {
    $(this).html($(this).html() == 'click Me' ? 'clicked' : 'click Me');
});

Beispiel 2: Umschalten der Anzeigen zwischen "none" und "inline-block":

$('#clickTest2, #clickTest2 > span').click(function () {
    $(this).children().css('display', $(this).children().css('display') == 'inline-block' ? 'none' : 'inline-block');
});
kia nasirzadeh
quelle