JQuery ... der erste Versuch
heinetz
- javascript
Hallo Forum,
vor einiger Zeit habe ich daimt begonnen, mich mit dem Gedanken,
JS-Framework: Ja/Nein, Welches überhaupt?, Warum überhaupt?
... auseinanderzusetzen und eine mächtige Diskussion losgetreten.
Danke nochmal an alle Beteiligten für eine lebhafte Diskussion,
die mir sehr geholfen hat !
Jetzt kommt meine Einstieg:
Anlass für mich, mich mit dem Thema auseinanderzusetzen war
dass ich in meinem sehr umfangreichen Projekt entdeckt habe,
dass ich schonmal prototype eingebunden hatte ... und nicht
so recht wusste, wo ich das verwendet hatte. Natürlich hätte
ich das zu dem Zeitpunkt genau untersuchen können, empfand es
aber als nicht so wichtig, weil ich eh über kurz oder lang
damit konfrontiert werden würde ... und das ist jetzt passiert.
Ich hatte das Framework eingebunden, um einen Ajax.Request
umzusetzen. Ich weiss, dafür das ganze umfassende Framework
zu laden, bedeutet mit Kanonen auf Spatzen zu schiessen,
weil ich aber nicht wusste, wie ich das sonst machen sollte
und weil ich die Funktionalität eh für das Backend der Site
brauchte, spielt die LAdezeit keine grosse Rolle.
Da ich mich nach dieser Diskussion erstmal dafür entschieden
hatte, mich mit JQuery vertraut zu machen, habe ich eben die
Funktion umgeschrieben und setzen den Ajax.Request nun mit
JQuery ab, was genauso unproblematisch ging.
... und dann habe ich versucht, in meinem Skript etwas
handgeschriebes in JQuery-Systax umzuschreiben:
In einem zuvor geladenen Script Wird die Funktion
'ieinputonfocus()' onload aufgerufen. Die sorgt
dafür, dass für jedes input type="text" auf der
Site ein Event onfocus definiert wird, der onfocus
den ClassName des Input ändert, um das was FF mit:
input:focus{
}
... für IE zu simulieren. In einem anderen, später
geladenen Skript muss onfocus bei einem Input etwas
anderes ZUSÄTZLICHES passieren. Ich dachte mir, das
müsse doch mit JQUERY recht einfach gehen und habe
mal ausprobiert diese Zeile:
formObj.elements[e].onfocus = function (){lA[this.name].className = "";}
... in JQuery-Syntax umzuschreiben:
formObj.elements[e].focus(function (){lA[this.name].className = "";});
Das funktioniert wie erwartet erstmal nicht.
Warum nicht? Ich glaube, mir fehlt ein Grundgedanke.
danke für Tipps und
beste gruesse,
hienetz
Warum nicht? Ich glaube, mir fehlt ein Grundgedanke.
Ja, irgendwie ist da nicht viel von jQuery zu sehen :)
Du benötigst idR. einen Selektor - wie in CSS - der in der jQuery-Funktion aufgerufen wird
z.B.
$('input');
damit selektierst du alle input-Element auf der Seite
dann benötigst du einen Handler - bind() oder live() sind gut geeignet um einen anzuhängen - wenn es nur um einen handler geht, gibts auch eigene Methoden dafür. focus(), mouseover() usw
$('input').bind(
'focus',
function() {
}
);
Dann muss die Funktion noch irgendetwas tun.
$('input').bind(
'focus',
function() {
$(this).addClass('focus');
}
);
dein css ergänzt du dann um die Klasse focus, um damit die Pseudoklasse zu simulieren.
input:focus,
input.focus {
}
Nicht vergessen: wenn das Element den focus verliert, muss die Klasse natürlich wieder entfernt werden.
Warum nicht? Ich glaube, mir fehlt ein Grundgedanke.
Ja, irgendwie ist da nicht viel von jQuery zu sehen :)
Du benötigst idR. einen Selektor - wie in CSS - der in der jQuery-Funktion aufgerufen wird
... langsam steig ich dahinter, wie das ganze zu verstehen ist!
Ich vermute, der Verständnisfehler, der hinter meinem Versuch:
formObj.elements[e].focus(function(){lA[this.name].className = "";})
... steckt, ist dass ich versucht habe, ein JQ-Methode auf ein
DOM-Objekt anzuwenden. Dass das hier funktioniert, habe ich
herausgefunden:
$(':input').focus(function(){lA[this.name].className = "";});
Damit wird der für die Inputs ursprünglich mal definierte
onfocus-Event nicht mal überschrieben. Diesem kleinen
Erfolgserlebnis folgt aber leider eine möglicherweise
schwerwiegende Erkenntnis.
Nochmal zurück zur Ausganssituation:
var eA =[];
function init_form ()
{//alert("init_form()");
formObj = document.forms['adminForm'];
for (e=0; e<formObj.elements.length; e++)
{
if(formObj.elements[e].type!="hidden") eA[formObj.elements[e].name] = formObj.elements[e];
formObj.elements[e].onfocus = function (){lA[this.name].className = "";}
}
...
}
...
Hieran probiere ich also, ob ich mit JQuery meinen Code sauberer
und übersichtlicher hinbekomme. Und das hier:
$(':input').focus(function(){lA[this.name].className = "";});
... funktionierte ja auch schon sehr gut. Mein Versuch, die erste
Anweisung im Schleifenblock zu erstzen:
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
... scheitert aber. Der Selektor scheint korrekt zu sein. Aber
mein Umgang mit oder vielmehr mein Verständnis für globale
Variablen scheint mir hier in die jQuere zu kommen. Ich weiss,
globale Variablen sind evil aber ich weiss garnicht so genau
warum und wie ich das anders machen soll ;(
Meine Logik (verkürzt):
1. in init_form() fülle ich das global defnierte Array 'eA' mit
allen Form.elements die nicht vom Typ hidden sind.
2. das ich an verschiednenen Stellen in anderen Funktionen
beeinflusse und greife u.U. auf die Elemente zu
(z.B. eA['title'].disabled=true)
3. in check_form() verwende ich das u.U. veränderte globale 'eA'
um Inhalte vor dem Abschicken auf Richtigkeit zu prüfen.
Jetzt frage ich mich, ob es grundsätzlich ein Fehler ist,
das Array 'eA' zu definieren um mit mehreren Funktioneen
darauf zuzugreifen, weil global evil ist, oder ich nur
wissen muss, wie ich hier:
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
... dafür sorge, dass jQuery weiss, dass ich das global definierte
Array 'eA' füllen möchte.
vielen dank für Tipps uns
beste gruesse,
heinetz
Hi,
formObj.elements[e].focus(function(){lA[this.name].className = "";})
... steckt, ist dass ich versucht habe, ein JQ-Methode auf ein
DOM-Objekt anzuwenden.
richtig. Das Prototype-Framework basiert darauf, die Prototypen von Objekten zu verändern; jQuery hingegen erzeugt Objekte eines eigenen Typs, anstatt den gesamten JavaScript-Kosmos zu manipulieren. Die jQuery-Basisfunktion (also "$()") nimmt jedoch auch beliebige DOM-Nodes entgegen und liefert sie als jQuery-Objekt zurück, d.h. aus Deinem "formObj.elements[e].irgendwas()" kannst Du einfach "$(formObj.elements[e]).jQueryAequivalent()" machen.
Mein Versuch, die erste Anweisung im Schleifenblock zu erstzen:
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
... scheitert aber. Der Selektor scheint korrekt zu sein.
Du hast hiernach, genau wie bisher, die DOM-Nodes in Deinem Array. jQuery-Objekte machst Du daraus wie oben beschrieben.
Jetzt frage ich mich, ob es grundsätzlich ein Fehler ist,
das Array 'eA' zu definieren um mit mehreren Funktioneen
darauf zuzugreifen, weil global evil ist,
Der globale Scope sollte möglichst sauber gehalten werden, das stimmt. Du kannst Dein Array als Eigenschaft eines günstig gewählten Objektes abspeichern, wenn Du magst; für den Anfang kannst Du window dieses Objekt sein lassen.
oder ich nur wissen muss, wie ich hier:
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
... dafür sorge, dass jQuery weiss, dass ich das global definierte
Array 'eA' füllen möchte.
jQuery erfährt nicht mal, dass Du da ein Array füllen willst. Das ist handelsübliches JavaScript.
Cheatah
hi,
oder ich nur wissen muss, wie ich hier:
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
... dafür sorge, dass jQuery weiss, dass ich das global definierte
Array 'eA' füllen möchte.jQuery erfährt nicht mal, dass Du da ein Array füllen willst. Das ist handelsübliches JavaScript.
Nachdem mir nun klar ist, wann in JS Variablen global und wann
lokal definiert sind (Schande.Warum eigentlich erst jetzt?)
habe ich meine Variablen mal aufgeräumt und dachte, dann müsse
das ja auch funktionieren. Tat es nicht. Konnte aber nicht sein.
Jetzt hab ich's gefunden:
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
... belegt tatsächlich wie erwartet das Array 'eA' als
assoziatives Array mit den DOM-Objekten alá:
eA['title'] = Object HtmlInput
Dass es nicht beim ersten Versuch funktionierte, lag aber nicht
an unsauber deklarierten Variablen, sondern daran, dass mein
Input name="title" zwar vom Typ="text" war, aber per css mit
display:none versteckt wird und aufgrund dessen nicht von
$(':input:not(:hidden)') erfasst wurde, weil "not(:hidden)"
sich garnicht auf type="hidden", sondern auf alles, was nicht
angezeigt wird bezieht ;)
gruesse,
heinetz
Mahlzeit heinetz,
$(':input:not(:hidden)').each(function(){eA[this.name]=this;});
Was genau soll eigentlich der Doppelpunkt vor dem "input"?
MfG,
EKKi
hallo ekki,
Was genau soll eigentlich der Doppelpunkt vor dem "input"?
der meint nicht nur input sondern auch textarea usw. wie hier
beschrieben.
Ich bin allerdings gerade über meinen (glaube ich) nächsten
grundsätzlichen Denkfehler gefallen. So sah mein funktionierender
Code mal aus:
formObj = document.forms['adminForm'];
for (var i=0; i<formObj.elements.length; i++)
{
if(formObj.elements[i].type!="hidden") eA[formObj.elements[i].name] = formObj.elements[i];
formObj.elements[i].onfocus = function (){lA[this.name].className = "";}
}
eA['site_id'] = formObj.elements['site_id'];
Damit hatte ich zum Einen einen Event für alle elements in
meinem Form definiert und, was für meine Logik wesentlicher
war, alle elements, die nicht vom type="hidden" waren in
mein Array eA geschrieben. Und zusätzlich das element mit
dem namen 'site_id', was eben doch vom type="hidden" war.
Mit JQuery habe ich das ganze so versucht:
$(':input').focus(function(){lA[this.name].className = "";});
$(":input:not(input[type='hidden'])").each(function(){eA[this.name]=this;});
eA['site_id'] = $("input[name='site_id']");
... und mit der letzten Zeile konnte nicht das gewünschte
bewirken. Ich glaube, ich habe verstanden warum:
Ich schreibe nicht das DOM-Objekt in mein Array, sondern
das JQuery-Objekt!
Die Lösung liegt sicher darin, den Selektor noch weiter
zu verfeinern:
1. Alle :input
2. ausser type=hidden
3. wenn nicht name=site_id
Was dann noch fehlt ist die Verfeinerung:
1. Alle :input im form name="adminForm"
beste gruesse,
heinetz
hi,
Die Lösung liegt sicher darin, den Selektor noch weiter
zu verfeinern:
- Alle :input
- ausser type=hidden
- wenn nicht name=site_id
Was dann noch fehlt ist die Verfeinerung:
- Alle :input im form name="adminForm"
ich habe etwas gefunden, was zu gehen scheint:
$("form[name='adminForm'] :input:not(input[type='hidden']), input[name='site_id']")
... spricht:
1. alle INPUT, TEXTAREA usw.
2. in dem FORM name="adminForm"
3. ausser sie sind vom type="hidden"
4. und das INPUT mit name="site_id" an
Ich habe allerdings erst folgendes versucht:
$("form[name='adminForm'] :input:not(input[type='hidden']),form[name='adminForm'] input[name='site_id']")
Das erschien mir logischer, weil die Notation CSS-Syntax eher
entspricht, führt aber zum Fehler.
Gilt der Parent vor dem Komma nun tatsächlich auch für den
Teil hinter dem Komma oder ist in dem Teil nach dem Komma
nun garkein parent für mein INPUT definiert ?
danke für Tipps und
beste gruesse,
heinetz
... steckt, ist dass ich versucht habe, ein JQ-Methode auf ein
DOM-Objekt anzuwenden.richtig. Das Prototype-Framework basiert darauf, die Prototypen von Objekten zu verändern; jQuery hingegen erzeugt Objekte eines eigenen Typs, anstatt den gesamten JavaScript-Kosmos zu manipulieren.
Das kann man so nicht sagen. Auch bei Prototype kann man nicht ohne weiteres Methoden der Bibliothek auf Elementobjekten aufrufen. Sie müssen vorher manuell durch $() bzw. $$() erweitert werden. Das ist also keine prototypische Erweiterung, sondern vielmehr ein Mixin. Prototype erweitert ECMAScript-Kernobjekte prototypisch, aber nicht DOM-Objekte. Das geht nämlich erst in neueren Browsern, deshalb ist für Elementobjekte das manuelle Erweitern nötig.
jQuery setzt m.E. ein Facade-Pattern um, welches einzelne DOM-Elementknoten zu Elementlisten kapselt. Andere nennen es in Anlehnung an Haskell Monade.
Disclaimer: IANA computer scientist.
Mathias
jedes input type="text"
input:focus{
}
Das ist natürlich unsinn ;)
input[type=text]:focus wäre vermutlich wohl der Selektor der Wahl.