[jQuery] doppelte Abfragen verhindern

09/20/2014 13:18 Mr.Tr33#1
Moin,
mir ist folgendes aufgefallen:
Wenn ich nach einem "Klick" abfrage, dann funktioniert diese Abfrage nur für bereits existierende Elemente. Wenn ich dann ein neues hinzufüge, dann muss ich nochmal danach abfragen.
Also habe ich einfach meine Abfrage in eine Funktion getan und nach jedem "neuen" Element rufe ich diese Funktion auf. Leider werden dann die bereits existierenden Elemente doppelt abgefragt.
Wie kann ich da jetzt entgegen kommen, sodass trotzdem nur jedes Element 1x abfrage?

Beispiel:
Code:
$(document).ready(function() {
    $('input[name="addKategorie"]').click(function(){
        if ($('input[name="nameKategorie"]').val() != ""){
            sendFormular (".addKategorie", "kategorie_add", "addKategorie", function(data){
                if (isFinite(data)){
                    $('.kategorien div.add').before('<div class="" data-id="'+data+'">'+$('input[name="nameKategorie"]').val()+'</div>')
                    checkKategorie();
                }else if (data != ""){
                    alert(data);
                }
                $(".addKategorie").slideUp(function(){
                    $('.kategorien div.add').html("+");
                });
            });
        }else{
            $(".addKategorie").slideUp(function(){
                $('.kategorien div.add').html("+");
            });
        }
        
        return false;
    });
    checkKategorie();
    
    
    function checkKategorie(){
        $('.kategorien div').click(function(){
            alert($(this).html());
            if ($(this).attr("class") != "add"){
                $(this).toggleClass("aktiv", function(){
                    var kategorie = "";
                    $('.kategorien div').each(function(){
                        if ($(this).attr("class") == "aktiv") kategorie += $(this).attr("data-id")+",";
                    });
                    $(".kategorien input").val(kategorie);
                });
            }else{
                if ($(this).html() == "+"){
                    $(".addKategorie").slideDown(function(){
                        $('.kategorien div.add').html("-");
                    });
                }else{
                    $(".addKategorie").slideUp(function(){
                        $('.kategorien div.add').html("+");
                    });
                }
            }
        });
    }
});
MfG,
Mr.Tr33
09/20/2014 13:22 snow#2
Als ich mal in jQuery reingeschnuppert habe, habe ich gelernt, dass $('yourobject(s)').on('click', function() { }); bei dynamisch erzeugten Elementen funktioniert, .click() nicht.

Ist es das, wonach du suchst?
09/20/2014 13:33 Mr.Tr33#3
Ja das habe ich auch mal gelernt, aber mir wurde mal gesagt, dass es "falsch" wäre. Also es funktioniert, aber nicht dem Sinne gedacht. Ebenfalls würde es bei größeren Seiten die Seite verlangsammern (konnte ich noch nicht wirklich testen).
09/20/2014 17:29 Hyukisawa#4
Benutzte es aber ebenfalls so.
vllt hilft dir delegate ?

[Only registered and activated users can see links. Click Here To Register...]
09/20/2014 17:38 ThinSmoke#5
Quote:
Originally Posted by Mr.Tr33 View Post
Ja das habe ich auch mal gelernt, aber mir wurde mal gesagt, dass es "falsch" wäre. Also es funktioniert, aber nicht dem Sinne gedacht. Ebenfalls würde es bei größeren Seiten die Seite verlangsammern (konnte ich noch nicht wirklich testen).
Doch, es funktioniert genau so wie es soll. Das Ding ist, dass wenn du ein Klick-Event bindest, es nur an bereits vorhandene Elemente gebunden wird. Alles was danach erzeut wird bekommt das Klick Event nicht, einfach weil du den Aufruf nicht nochmal gibst. JqueryUI (ich übrigens auch) macht das z.B. so, dass gebundene Elemente eine Klasse mitbekommen. Alles was danach erzeugt wird hat diese Klasse nicht und bekommt das Event dann neu gebunden, so wie du es jetzt machst. Hab dir mal schnell nen kleines Beispiel gebaut:

[Only registered and activated users can see links. Click Here To Register...]

Das Elegante daran ist, dass sobald ein Element mehrere Events bekommt, bzw. mehrere Attribute mitbekommt, du Sie einfach im DOM erkennst. Macht das Debugging sehr einfach.
09/21/2014 16:48 Mr.Tr33#6
Quote:
Originally Posted by ci40pg View Post
Benutzte es aber ebenfalls so.
vllt hilft dir delegate ?

[Only registered and activated users can see links. Click Here To Register...]
Und wo ist jetzt der große Unterschied zwischen on und delegate?
Quote:
Originally Posted by ThinSmoke View Post
Doch, es funktioniert genau so wie es soll. Das Ding ist, dass wenn du ein Klick-Event bindest, es nur an bereits vorhandene Elemente gebunden wird. Alles was danach erzeut wird bekommt das Klick Event nicht, einfach weil du den Aufruf nicht nochmal gibst. JqueryUI (ich übrigens auch) macht das z.B. so, dass gebundene Elemente eine Klasse mitbekommen. Alles was danach erzeugt wird hat diese Klasse nicht und bekommt das Event dann neu gebunden, so wie du es jetzt machst. Hab dir mal schnell nen kleines Beispiel gebaut:

[Only registered and activated users can see links. Click Here To Register...]

Das Elegante daran ist, dass sobald ein Element mehrere Events bekommt, bzw. mehrere Attribute mitbekommt, du Sie einfach im DOM erkennst. Macht das Debugging sehr einfach.
Was du gemacht hat ist einfach zusätzliche Abfrage. Auf sowas könnte ich auch kommen :D
Aber gehts da nicht etwas "simpler" und besser?
09/21/2014 16:50 Hyukisawa#7
Habe dir nur eine alternative genannt :) wie gesagt ich selbst benutzte es so wie du
09/21/2014 18:00 RecK#8
Quote:
Originally Posted by Mr.Tr33 View Post
Moin,
Wenn ich nach einem "Klick" abfrage, dann funktioniert diese Abfrage nur für bereits existierende Elemente. Wenn ich dann ein neues hinzufüge, dann muss ich nochmal danach abfragen.

[...]

Wie kann ich da jetzt entgegen kommen, sodass trotzdem nur jedes Element 1x abfrage?
.click bindet das Event an ein Element.
Da ein dynamisch erzeugtes Element nicht existiert wenn du .click verwendest,
wird das Event nicht gesetzt.

Möglichkeiten:

1.
dynamische Elemente vor document.ready erzeugen.
In document.ready Callback Click-Event via .click binden.

2. (favourisiert)
Vor dem erneuten Binding deiner Funktion ein unbind durchführen.
Dadurch löscht du das alte Binding.
$.each [ ... ]
$('selector').unbind('click');
$('selector').click([...])
[ ... ]

lg, Tim


Ps: .on('click') und .click sind soweit ich weiß das gleiche.
Nur andere Syntax fürs Binding.