Kais bewegtes Web 11.01.12
Vor einigen Tagen wollte ich eine auf den ersten Blick einfache Interaktion mit HTML und jQuery erstellen. Es handelte sich um ein Formular innerhalb eines mobilen Interfaces (mit jQuery Mobile), bestehend aus zwei Eingabefeldern für Betreff und Text einer zu versendenden Nachricht.
Die Anforderung war: Wenn das Senden erfolgreich war, wir uns im success-Handler des AJAX-Aufrufs befinden, soll die versendete Nachricht ins DOM aufgenommen, gleichzeitig das Betreff-Feld von einem <input type="text"...> in ein <input type="hidden"> geändert und mit dem existierenden und versandten Wert des Betreff-Feldes belegt werden.
Das ist auch alles ganz einfach – bis auf die Tatsache, dass der Aufruf von .attr("type", "hidden") zu einer JavaScript-Exception auf der Konsole mit der Meldung "type property can't be changed" führt. Die hier betroffene Anwendung nutzt jQuery 1.6.4, und eine kurze Suche im Quelltext der Bibliothek führt zu:
// We can't allow the type property to be changed (since it causes problems in IE)
if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
jQuery.error( "type property can't be changed" );
} ...
Aha, Problem erkannt – IE-Kompatibilität. Die hier entwickelte Anwendung (bzw. ihr View) wird allerdings niemals auf IE laufen, sondern mehr oder weniger exklusiv auf iOS-Geräten. Man kann nun dieser jQuery-Einschränkung auf mehrere Arten ausweichen:
marker = $"('<span />').insertBefore($subject);
$subject.detach().attr('type','hidden').insertAfter(marker);
marker.remove();$subject.prop("type","hidden");.
Ich habe mich am Ende für die dritte Option entschieden – letztlich weil sie mir am saubersten erschien. Das Änderen des type-Attributs im Zustand "detached" ist auf jeden Fall auch schon mit jQuery 1.4.2 möglich – mit älteren Versionen habe ich das Verhalten nicht getestet (.prop() aus Option 4 wird übrigens seit jQuery 1.6 unterstützt).
Warum aber nicht Option 4? Von einem rein funktionalen Standpunkt aus gesehen spricht nichts dagegen – sie scheint tadellos den Anforderungen zu genügen. Das Problem ist, dass .attr() und .prop() eine deutlich unterschiedliche Semantik haben. Kurz gefasst: .attr() sollte verwendet werden, um auf Tag-Attribute zuzugreifen, .prop(), um auf DOM-Eigenschaften zuzugreifen, die kein äquivalentes Tag-Attribut haben. Die oben verlinkten API-Dokumentationen beider Funktionen erklären den Unterschied (und damit ggf, verbundene Probleme) anhand einiger Beispiele genauer.
Kai lebt in seiner Wahlheimat Wellington in Neuseeland und arbeitet dort als Director und Software Solutions Architect für das von ihm mitbegründete Unternehmen Ventego Creative Ltd.