Mit jQuery ein Element verändern

16. Mai 2008 Bisher 10 Kommentare

Wenn im DOM ein Element exisitert, möchte ich damit gewisse Dinge anstellen. Zum Beispiel die Breite anpassen, es animieren, oder was auch immer. Doch wie spreche ich das Element mit jQuery eigentlich an, sofern ich nicht draufklicke oder irgendeine Aktion ausführe? Die Lösung anbei.

Szenario: Ich möchte einem DIV eine Breite geben, und zwar die Summe der Breite seiner Kinderelemente. Also unser DIV hat fünf DIVs, die gefloatet sind. Dessen Breite in Summe möchte ich dem Elternelement mitgeben. Doch wie spreche ich nun mein DIV in jQuery an? Bisher habe ich das so gemacht:

  1. $('#meinDiv').each(function(){
  2.     alert('Ja, mich gibt es, stell was mit mir an.');
  3. });
  4.  

Wie oben bereits erwähnt, möchte ich, dass das Element sich beim Aufbau der Seite schon verändert, nicht erst, wenn ich darauf rumdrücke (event “click”). Mit der Methode “each” konnte ich es ansprechen. Doch mein DIV gibt es auf der Seite nur einmal, also fand ich die Anwendung von “each” (gehe jedes Element durch) etwas zu viel des guten – unpassend.

Dank Dirk Jesse, der mir ein paar Tipps gab, habe ich ein jQuery-Plugin geschrieben, was mir analog zu “each” eine Funktion zur Verfügung stellt, mit dem ich mein Element, sofern es im DOM auftaucht, ansprechen kann – ohne Interaktion.

Packt dazu außerhalb von $(document).ready(); folgenden Code in eure Javascript-Datei:

  1. (function($) {
  2.    $.fn.found = function(myFunction) {
  3.       if(this.length) {
  4.          myFunction.call(this);
  5.       }
  6.    };
  7. })(jQuery);
  8.  

Mit meiner neuen Funktion “found” kann ich nun das Element ansprechen. Und die Funktion, die ich ihm dabei mit auf dem Weg gebe, führt meine “found”-Funktion aus.

$('#meinDIv').found(function(){
    alert('Ja, mich gibt es, stell was mit mir an.');
});
 

In der neuesten jQuery-Version 1.2.6 gibt es nun die Funktion, die ich hier konstruiert habe: .index(). Somit ist mein Add-On quasi hinfällig.

Kommentare

Einen eigenen Kommentar schreiben

  1. 1 macx schrieb am 16. Mai 2008 (14:05 Uhr)

    Manueller Trackback von “Mr. YAML”. :D

  2. 2 Alexander schrieb am 16. Mai 2008 (15:05 Uhr)

    Hallo David,

    1. dein this ist bereits das jQuery-Objekt. Du musst also nicht erst eines mit $(this) erstellen. (Es ändert sich dadurch nicht wirklich, sondern kostet nur).

    2. Zahlen, die nicht 0 sind, werden in JS bei Kontrollstrukturen automatisch in true umgewandelt, 0 dagegen in false. Du kannst dir also den Vergleichsoerator sparen.

    3. Wenn du jQuery schon das DOM durchsuchen lässt, wäre es schön, wenn man dann in der übergebenen Funktion Zugriff auf die Elemente hat. Hier könnte man mit der Methode call arbeiten:

    Verbesserungsvorschlag:
    $.fn.found = function(myFunction) {
    if(this.length) {
    myFunction.call(this);
    }
    };

    Grüsse
    alex

  3. 3 2meter3 schrieb am 16. Mai 2008 (15:05 Uhr)

    [re-posted aus dirks blog]

    Hm, vielleicht ist jQuery nicht zu einfach, sondern ihr denkt zu kompliziert? Oder versteh ich das Problem nicht?

    Alles, was in einem $(document).ready() {} Block steht, kann unmittelbar ausgeführt werden.

    $( ’#meinDiv’ ).jQueryFunktion(“bla”, “blubb”);

    #meinDiv muss in diesem Fall nicht mit einem Ereignis verknüpft werden.

    Alle jQuery-Funktionen “arbeiten” auch auf dem leeren jQuery-Objekt. Wenn #meinDiv nicht im DOM existiert, gibts somit keinen Fehler, sondern es passiert einfach gar nichts.

    Oder gehts darum, in Abhängigkeit von der Existenz eines DOM-Elements nicht-jQuery-Funktionalität auszuführen? In dem Fall reicht ein einfache Bedingung, die die length-Eigenschaft des jQuery-Objekts prüft:

    if($( ’#meinDiv’ ).length) {}

  4. 4 macx schrieb am 16. Mai 2008 (16:05 Uhr)

    @2meter3: Dein Beispiel passt nicht, denn du führst nur eine (!) Funktion aus. Ich möchte aber, dass du beliebig viele ausführen kannst, ohne dass ich dafür eine extra Funktion schreiben muss, also ähnlich wie es mit each() funktioniert. Die Lösung gibts ja auf meiner Seite.

    @Alexander: Danke für deinen Vorschlag.

  5. 5 2meter3 schrieb am 16. Mai 2008 (17:05 Uhr)

    Mehrere jQuery-Funktionen? Alle jQuery-Funktionen können verkettet werden (chaining), da sie das jQuery-Objekt (also die gefundenen Elemente) selbst zurückgeben.

    $( ’#meinDiv’ ).css( ‘backgroundColor’, ’#F00’ ).text( ‘foo’ ).hide().slideIn( 500 );

    Ansonsten wird in der vorgeschlagenen $.fn.found auch nichts anderes gemacht, als die length-eigenschaft zu prüfen. eine einfache if-abfrage (mein zweites beispiel) reicht aber vollkommen aus. warum sollte dafür eine eigene funktion definiert werden?

  6. 6 macx schrieb am 16. Mai 2008 (18:05 Uhr)

    Ich fürchte, ich habe mich blöd ausgedrückt. Natürlich kannst du jQuery-Funktionen aneinanderketten. Doch du kannst da mal keine Mathefunktionenausführen, ein bisschen Voddozauber machen und und und.
    Mit meiner Variante ist das nun möglich. Du könntest sogar reines Javascript da einbinden und was weiß ich programmieren. Ist das so schlimm, oder warum suchst du immer neue Beispiele? ;-)

  7. 7 2meter3 schrieb am 16. Mai 2008 (18:05 Uhr)

    keine neuen beispiele, immer dasselbe. :-) meine einzige frage ist, warum ein

    $( ’#meinDiv’ ).found(function(){ // beliebiges javascript }

    eleganter sein soll als ein einfaches

    if($( ’#meinDiv’ ).length) { // beliebiges javascript }
    – es muss eine zusätzliche funktion definiert werden – jeder funktionsaufruf ist ein zusätzlicher indirektionsschritt – es ist länger!

    einen vorteil bietet meiner meinung nach allein alexanders verbesserungsvorschlag, weil hier innerhalb des blocks direkt mit this auf das überprüfte objekt zugrtriffen werden kann.

    so, das solls jetzt aber gewesen sein. jQuery rockt!

  8. 8 macx schrieb am 03. Juni 2008 (12:06 Uhr)

    In der jQuery 1.2.6 hat (siehe oben im Artikel) nun die Funktion .index() Einzug gehalten, die genau das macht, was ich haben wollte und hier konstruiert hatte.

  9. 9 alexander farkas schrieb am 01. September 2008 (00:09 Uhr)

    Hallo David,

    das mit der index-Methode stimmt nicht ganz. Die index-Methode schaut an welcher Stelle innerhalb einer Auswahl von Elementen ein bestimmtes Element vorkommt. Dies ist sehr sinnvoll, wenn man zum Beispiel das Highlighting für eine Pagination macht und den agezeigten Teaser kennt ($(’#mypagination li:eq(‘$(’#current-teaser’).index()’)’).addClass(‘current’);) oder (‘Teaser ’+String($(’#current-teaser’).index() + 1)+’ von ’$(’#teasers’).length).

    Wenn man wissen möchte, ob ein Element überhaupt vorkommt, ist die Methode zwar schnell geschrieben, aber extrem ineffizient:
    if($(’*’).index(’#foo’) != -1){
    //tu was
    }
    Dieser Code sagt folgendes: Hole dir – egal ob du #foo findest – erstmal alle elemente im dokument, hole dir nun #foo und gebe #foo eine eindeutige id. danach gehe bitte alle elemente durch und sage mir an wievielter stelle #foo dort vorkommt.

    und was macht der scripter in dem beispiel mit dieser aufwendig berechneten information? nichts. er wollte nur wissen, ob foo im dokument vorkommt… (if($(’#foo’)[0]){})

    mehr zum thema ineffizienter jquery-code: http://www.protofunc.com/2008/07/27/ineffizienter-jquery-code/

    P.S.: Leider wurde der Beispiel-Code etwas umformatiert, so dass er nicht lauffähig ist, aber es dürfte klar sein, was ich meinte.

Kommentare anderer Blogger zu diesem Artikel

Antwort schreiben

Kommentare neuer Teilnehmer werden auf Grund von hohem SPAM-Aufkommen zunächst von mir freigeschaltet, bis sie online erscheinen. Textile kann benutzt werden.

(wird nicht veröffentlicht)