Code-Verbesserung u.Test gewünscht
Kai345
- javascript
0 Paul0 Kai3450 Patrick Andrieu0 Kai345
0 Kai345
Grütze .. äh ... Grüße!
Ich habe mir letzte Nacht ein kleines Popup-Script -> popup.js auf div-Basis zur universellen Anwendung gebaut.
Eine minimalistische Testumgebung habe ich ebenfalls erstellt. Bei mir läuft es bisher auch soweit in Op9, IE6 und FF2.
Leider bin ich noch eher Anfänger, daher würde ich mich freuen, wenn die Experten mir ein paar Tipps zu potentiellen Fehlern, Effizienzsteigerung und auch Codeverbesserung/schönerung geben würden. Nur wenn sie das wollen natürlich ;)
Cü
Kai
Hallo Kai,
nur zur Info: Im IE 7, Netscape 8 und Safari 3 läuft's auch.
Paul
Grütze .. äh ... Grüße!
Ich habe mir letzte Nacht ein kleines Popup-Script -> popup.js auf div-Basis zur universellen Anwendung gebaut.
Mir ist gerade ein unschönes Problem aufgefallen: Wenn mehrere Popups geöffnet sind, kann ich
die einzelnen Popups nicht gezielt in den Vordergrund bringen. Theoretisch müßte das folgendermaßen ablaufen:
Bei Klick auf ein Popup aktuellen z-index auslesen, um eins erhöhen und allen anderen Popups den Default-Wert zuweisen.
Das gibt zwei Probleme:
1. Ich weiß nicht, wie viele Popups existieren
2. Wenn ein neues Popup hinzukommt, muß das zuletzt im Vordergrund (also mit höherem z-index)
versehene auch wieder auf Normalwert gesetzt werden.
Also müßte die Funktion irgendwie ihre erzeugten Objekt-Instanzen verwalten. Nun könnte ich diese jeweils in ein globales Array pushen, aber das ist bestimmt nicht der richtige Ansatz.
Cü
Kai
Hallo,
Hab's mir mal kurz angesehen. Der Code scheint mir soweit ok. In meinem IE 6.0 verschwindet aber der Seiteninhalt hinter einem großen, dünn umrahmten und leeren "Feld", sobal ein Popup geöffnet ist, d.h man kann gar kein zweites Popup öffen. Wenn man es wieder schießt, erscheint der normale Inhalt mit den Buttons wieder.
- Ich weiß nicht, wie viele Popups existieren
- Wenn ein neues Popup hinzukommt, muß das zuletzt im Vordergrund (also mit höherem z-index)
versehene auch wieder auf Normalwert gesetzt werden.Also müßte die Funktion irgendwie ihre erzeugten Objekt-Instanzen verwalten. Nun könnte ich diese jeweils in ein globales Array pushen, aber das ist bestimmt nicht der richtige Ansatz.
Denkbar wäre ein übergeordnetes Popups-Objekt, das die einzelnen Popups erzeugt und jeweils seine z-index-Eigenschaft erhöht. Der z-index jedes neuen Popups ist dann einfach immer um 1 größer, als der letzte, und wenn eins von mehreren Popups angeklickt wird, wird der z-index einfach weiter erhöht und als neuer z-index für das geklickte Popup verwendet. Die anderen z-indizes kannst du ja in Ruhe lassen. Statt eines übergeordneten Objekts würde es auch eine einzige globale Variable tun (wenn man dagegen nicht allergisch ist), die einfach immer den größten z-index enthält und immer nur erhöht wird.
Gruß, Don P
Grütze .. äh ... Grüße!
Hab's mir mal kurz angesehen. Der Code scheint mir soweit ok. In meinem IE 6.0 verschwindet aber der Seiteninhalt hinter einem großen, dünn umrahmten und leeren "Feld", sobal ein Popup geöffnet ist, d.h man kann gar kein zweites Popup öffen. Wenn man es wieder schießt, erscheint der normale Inhalt mit den Buttons wieder.
Ja, das ist der dumme iframe, den der IE braucht, um divs auch über Formularelementen zu öffnen. Bisher war der ein separates Element direkt unterhalb von body, genau wie mein div-container und daher verschob er nicht mit dem popup mit. Also hab ich ihn erst mal auf width/height 100% gesetzt, was dem body entspricht. Ist aber nur ein Workaround, ich bin zur Zeit dabei, das Script so zu ändern, daß der iframe innerhalb des Popup-Containers sitzt und so mitverschoben wird. Als ich die Funktion schrieb, habe ich die ganze Nacht durchgemacht und war dann einfach zu müde, mich auch noch darum zu kümmern. Früher, als ich noch jung war, war das kein Problem, aber jetzt? ;)
Was ich nur nicht verstehe ist, daß du den iframe zu sehen scheinst, er sollte eigentlich durchsichtig sein.
oIframe.style.filter = "Alpha(style=0,opacity=0)";
Auch ich habe IE 6.
Denkbar wäre ein übergeordnetes Popups-Objekt, das die einzelnen Popups erzeugt und jeweils seine z-index-Eigenschaft erhöht. Der z-index jedes neuen Popups ist dann einfach immer um 1 größer, als der letzte, und wenn eins von mehreren Popups angeklickt wird, wird der z-index einfach weiter erhöht und als neuer z-index für das geklickte Popup verwendet. Die anderen z-indizes kannst du ja in Ruhe lassen. Statt eines übergeordneten Objekts würde es auch eine einzige globale Variable tun (wenn man dagegen nicht allergisch ist), die einfach immer den größten z-index enthält und immer nur erhöht wird.
Ich glaube, daß ich weiß, wie du das meinst. Werde ich versuchen. Danke.
Cü
Kai
Grütze .. äh ... Grüße!
Hab's mir mal kurz angesehen. Der Code scheint mir soweit ok.
Dazu noch eine Frage, die mir schon beim Schreiben des Codes eingefallen ist:
Ich habe sämtliche Operationen erst einmal mit lokalen Variablen durchgeführt und erst ganz zum Schluß "public" gemacht. Hat das irgendwelche Vor/Nachteile gegenüber Operationen an einer public variable (z.B. daß erst jedes Mal nachgesehen werden müßte, was z.B. "this" ist
also
function Konstruktor() {
var foo1 = document.createElement("div");
foo1.style.irgendwas = "irgendwas";
foo1.id = "bar";
this.foo = foo1;
}
oder
function Konstruktor() {
var xy = this;
var foo1 = document.createElement("div");
foo1.style.irgendwas = "irgendwas";
foo1.id = "bar";
xy.foo = foo1;
}
oder
function Konstruktor() {
this.foo = document.createElement("div");
this.foo.style.irgendwas = "irgendwas";
this.foo.id = "bar";
}
oder
function Konstruktor() {
var xy = this;
xy.foo = document.createElement("div");
xy.foo.style.irgendwas = "irgendwas";
xy.foo.id = "bar";
}
oder ist das mehr oder weniger akademisch?
Cü
Kai
Hallo,
Ich habe sämtliche Operationen erst einmal mit lokalen Variablen durchgeführt und erst ganz zum Schluß "public" gemacht. Hat das irgendwelche Vor/Nachteile gegenüber Operationen an einer public variable (z.B. daß erst jedes Mal nachgesehen werden müßte, was z.B. "this" ist
[...]
oder ist das mehr oder weniger akademisch?
Naja, ich denke das ist mehr oder weniger akademisch. Es sind ja ohnehin nur Referenzen, mit denen der Compiler jeweils hantiert.
Aufpassen muss man aber mit Closures, weil da u.U. 'this' wider Erwarten auch mal das globale Objekt (window im Browser-DOM) sein kann, z.B. statt
var diesUndDas = function() {
var etwas = this;
function nochwas() {
etwas.mehr = "viel";
}
nochwas();
}
könnte man nicht einfach schreiben:
var diesUndDas = function() {
function nochwas() {
this.mehr = "viel";
}
nochwas();
}
weil etwas() im zweiten Fall nicht die Objekteigenschaft 'diesUndDas.mehr' erzeugen würde, sondern eine globale Variable 'window.mehr', obwohl eigentlich zu erwarten wäre, das sich 'this' dort ebenfalls auf das Objekt diesUndDas() bezieht, genau wie im ersten Fall.
Die Zeilen
var dummy = new diesUndDas();
alert( dummy.mehr );
alert( window.mehr );
beweisen das jeweils. Leider :-(.
Gruß, Don P
function Konstruktor() {
var foo1 = document.createElement("div");
foo1.style.irgendwas = "irgendwas";
foo1.id = "bar";
this.foo = foo1;
}
Das ist im Prinzip gut. fool ist nur im Objekt sichtbar und sollte es auch sein, nach den Paradigmen der OOP. Aber in JS ist es durchaus üblich Objekte "public" zu machen. z.b. for(attribut in window).
D.h. du musst Wissen ob du fool public machen willst oder nicht, im ersten Fall machst du `this.foo1 = document.createElement("div");`{:.language-javascript} im zweiten `var foo1 = document.createElement("div");`{:.language-javascript} und den Umweg über this.foo kannst du sparen.
> oder
>
> ~~~javascript
function Konstruktor() {
> var xy = this;
> var foo1 = document.createElement("div");
> foo1.style.irgendwas = "irgendwas";
> foo1.id = "bar";
> xy.foo = foo1;
> }
Der Umweg über xy ist hier überflüssig, wann er nicht überflüssig ist, hat dir ja schon Don gezeigt.
function Konstruktor() {
this.foo = document.createElement("div");
this.foo.style.irgendwas = "irgendwas";
this.foo.id = "bar";
}
siehe oben.
> ~~~javascript
function Konstruktor() {
> var xy = this;
> xy.foo = document.createElement("div");
> xy.foo.style.irgendwas = "irgendwas";
> xy.foo.id = "bar";
> }
>
egal.
oder ist das mehr oder weniger akademisch?
Nicht ganz. Im Prinzip brauchst du nur this und solltest public Variabeln vermeiden. this kann aber fehlschlagen, wenn du closures benutzt, weil dort u.U. this nicht mehr das gleiche ist, wie ausserhalb. Dann kommt der Umweg über xy zum tragen (ich nenn es immer self). Und die Entscheidung ob du lieber eine public Variabel oder Objekt benutzt ist in JS akademisch
Struppi.
P.S. ich bastel auch grad an so nem Ding http://javascript.jstruebig.de/test/js-popup/, wurd mir aber dann irgendwann zu kompliziert.
gruss Kai,
...
Mir ist gerade ein unschönes Problem aufgefallen: Wenn mehrere Popups
geöffnet sind, kann ich die einzelnen Popups nicht gezielt in den
Vordergrund bringen. ......
...Also müßte die Funktion irgendwie ihre erzeugten Objekt-Instanzen
verwalten. Nun könnte ich diese jeweils in ein globales Array pushen,
aber das ist bestimmt nicht der richtige Ansatz.
var Popup = (function () { // legt einen weiteren funktionsstack an, ...
var popupList = []; // ... der diese liste von popup-referenzen kapselt, ...
var defragment = (function () {
for (var obj, i=0, len=popupList.length; i<len; ++i) {
obj = popupList[i];
if ((obj && !obj.pop_container) || !obj) {
delete obj;
//popupList.splice(i--, 1);
popupList.splice(i, 1);
--len;
--i;
}
}
});
var Popup = (function (def) { // [1]... den konstruktor initialisiert, ...
/* http://www.kaichen.in/code/popup.js */ /*
code*/
var oNewpop = this;/*
code*/
/* ----- public ----- */
oNewpop.pop_container = oContainer;
oNewpop.pop_titlebar = oTitlebar;
oNewpop.pop_closeme = oClImg;
oNewpop.pop_content = oContent;
oNewpop.pop_iframe = oIframe;
popupList.push(oNewpop);
return oNewpop;
});
Popup.prototype.show = (function (w) {/*
code*/
defragment();
popupList.forEach(function (obj/*, idx, arr*/) {
obj.pop_container.style.zIndex = 0;
});
this.pop_container.style.zIndex = 99;
});
Popup.prototype.initQMDrag = (function () {/*
code*/
});
return Popup; // ... und genau den in [1] genannten zurueckgibt.
})();/*
[popupList] und [defragment] lassen sich jetzt nur noch ueber den
konstruktor einer jeden [[Popup]]-instanz adressieren.
fuer die generische/prototypische array-methode [forEach] siehe auch:
[link:http://developer.mozilla.org/en/docs/New_in_JavaScript_1.6#Array_extras]
[link:http://forum.de.selfhtml.org/archiv/2007/3/t149403/#m970590]
*/
so long - peterS. - pseliger@gmx.net
Hallo peterS,
Interessante Übung, aber ist das nicht eigentlich viel zu viel des Guten?
Ich meine, es reicht doch prinzipiell eine einzige Variable, meinetwegen z-popup genannt, die jedesmal um 1 erhöht wird, sobald irgend ein Popup den Fokus erhält bzw. angeklickt oder auch neu erzeugt wird. Dieser erhöhte Wert wird dann immer sofort dem fokussierten bzw. angeklickten bzw. neu erzeugten Popup zugewiesen und schwupps - ist es im Vordergrund. Da muss man doch eigentlich keine Arrays bemühen und pflegen.
Klar: ein z-popup Wert, der immer nur wachsen kann, und das auch noch manchmal unnötigerweise (wenn z.B. dasselbe Popup mehrfach hintereinander angeklickt wird), könnte theoretisch irgenwann einmal zu groß werden... aber praktisch sollte das doch nie zum Problem werden, schätze ich.
Gruß, Don P
gruss Don P,
Interessante Übung, aber ist das nicht eigentlich viel zu viel des Guten?
meinst Du die *defragmentierung* der [Popup]-objekt-referenz-liste, oder
ueberhaupt die verwendung einer solchen, oder deren kapselung, oder gar
den gesamtansatz?
Ich meine, es reicht doch prinzipiell eine einzige Variable, meinetwegen
z-popup genannt, die jedesmal um 1 erhöht wird, sobald irgend ein Popup
den Fokus erhält bzw. angeklickt oder auch neu erzeugt wird. ...
ahh ... alles klar. ich denke, mein ansatz ist einfach sehr sauber. auch
wenn geringfuegig mehr code geschrieben werden muss, ist die die art der
implementierung sehr gut nachzuvollziehen. egal, wie die gesamtanwendung
spaeter auch belastet wird - dieser ansatz verpflichtet sich dem ziel,
keine leichen im keller zurueckzulassen.
so long - peterS. - pseliger@gmx.net
Hallo peterS.,
meinst Du die *defragmentierung* der [Popup]-objekt-referenz-liste, oder
ueberhaupt die verwendung einer solchen, oder deren kapselung, oder gar
den gesamtansatz?
Ja, irgendwie alles...
ich denke, mein ansatz ist einfach sehr sauber.
Es macht durchaus den Eindruck, obwohl ich Schwierigkeiten habe, alles zu durchschauen (s.u.).
auch wenn geringfuegig mehr code geschrieben werden muss, ist die art der
implementierung sehr gut nachzuvollziehen.
Naja... Was ich z.B. nicht ganz verstehe ist, dass in der .show()-Methode anscheinend alle z-Indizes auf 0 gesetzt werden, außer dem aktuellen, welches 99 wird (deine Lieblingszahl?):
Popup.prototype.show = (function (w) {/*
code*/
defragment();
popupList.forEach(function (obj/*, idx, arr*/) {
obj.pop_container.style.zIndex = 0;
});this.pop_container.style.zIndex = 99;
});
Der von dir oben hier weggelassene Code zeigt doch, dass die .show-Methode nicht nur anzeigen, sondern auch verstecken kann, je nach übergebenem Parameter:
var dis = (w === true) ? "block" : "none";
if (typeof this.pop_iframe === "object") {
this.pop_iframe.style.display = dis;
}
this.pop_container.style.display = dis;
Wenn wir abgesehen davon einmal annehmen, dass immer angezeigt wird (und nicht versteckt), dann leuchtet mir trotzdem nicht ein, warum hier überhaupt alle anderen zIndizes angefasst werden. Was haben denn die zIndizes der anderen Popups untereinander mit dem aktuellen PopUp zu tun? Landen die dann nicht immer wieder alle auf der gleichen Ebene, wenn doch alle zu 0 werden? Und falls ja, warum willst du sie immer dorthin zwingen? Das würde doch eine evtl. vom Benutzer eingestellte Überlappung vorhandener Popups wieder zerstören. Oder sehe ich das falsch?
egal, wie die gesamtanwendung
spaeter auch belastet wird - dieser ansatz verpflichtet sich dem ziel,
keine leichen im keller zurueckzulassen.
Das sehe ich ein. Mein beschriebener Vorschlag wäre dagegen ein bisschen "quick and dirty", weil theoretisch ein unendlich großer zIndex auftreten könnte. Allerdings kann man da auch mit wenig Aufwand eine Obergrenze definieren, ab der dann halt mal aufgeräumt wird, wenn es jemals soweit kommen sollte, dass diese Obergrenze erreicht wird. Die läge ja dann so bei 2^30 Klicks!
Auch die Sache mit dem Array und der Defragmentierung scheint mir ziemlich teuer. Arrays sind ja in JavaScript performance- und speichermäßig nicht gerade vorteilhaft implementiert...
Gruß, Don P
gruss Don P,
auch wenn geringfuegig mehr code geschrieben werden muss, ist die
art der implementierung sehr gut nachzuvollziehen.Naja... Was ich z.B. nicht ganz verstehe ist, dass in der .show()-
Methode anscheinend alle z-Indizes auf 0 gesetzt werden, außer dem
aktuellen, welches 99 wird (deine Lieblingszahl?):
welche werte den z-indizes schlussendlich zugewiesen werden, bleibt dem
anwender ueberlassen. vielleicht gibt es fuer die popups default-werte,
um in den vorder- bzw. hintergrund zu treten.
da es auf der hand liegt, die steuerung der z-indizes der [show]-methode
zuzuschlagen, ergibt es sich genauso zwingend, vor dem komplett-durchlauf
der referenzliste, diese erst mal aufzuraeumen - man kann ja nie wissen,
was den popups in der zwischenzeit so alles widerfahren ist.
Der von dir oben hier weggelassene Code zeigt doch, dass die .show-
Methode nicht nur anzeigen, sondern auch verstecken kann, je nach
übergebenem Parameter:
da hast Du natuerlich recht. das habe ich glatt uebersehen. da es mich
bei dem verlinkten beispiel stoerte, dass ein geoeffnetes fokusiertes
popup nicht wieder in den vordergrund trat, habe ich beispielhaft gleich
mal einen moeglichen loesungsansatz dafuer implementiert, ohne auf den
die display-eigenschaften steuerenden block zu achten.
aber eine vernuenftige [show]-methode muss sowiso die faelle "anzeigen",
"verstecken" sowie eine "vorder-/hintergrund"-steuerung implementieren.
Auch die Sache mit dem Array und der Defragmentierung scheint mir
ziemlich teuer. Arrays sind ja in JavaScript performance- und
speichermäßig nicht gerade vorteilhaft implementiert...
schon wenn nur bei jedem aufruf von [show] unter den popup-referenzen
aufgeraeumt wird, fallen diese faktoren nicht mehr ins gewicht, da die
liste durch das permanente saeuberungs-management immer schoen kurz
gehalten wird.
so long - peterS. - pseliger@gmx.net
Grüße!
[code lang=javascript]var Popup = (function () { // legt einen weiteren funktionsstack an, ...
etc.
Vielen Dank für deine Mühe. Ich habe deinen Beitrag gedruckt und abgespeichert, um auf jeden Fall darauf wieder zurückgreifen zu können, wenn ich das Prinzip wenigstens ansatzweise verstehe. Für jemanden, der gerade mal seinen ersten Konstruktor geschrieben hat und dem die OOP Grundlagen in weiten Teilen noch fehlen, ist das erst mal noch etwas zu viel. Ich merke immer mehr, wie weit der Weg noch ist ...
Cü
Kai
Hallo Kai345!
ein paar Tipps zu potentiellen Fehlern, Effizienzsteigerung und auch Codeverbesserung/schönerung geben würden. Nur wenn sie das wollen natürlich ;)
Zum JavaScript-Code und mögliche Verbesserungen haben viel kompetentere Leute sich bereits geäußert. Ich beschränke mich auf Tipps, was das Aussehen der Fenster angeht.
Den maussensitiven Bereich für die Titelleisten (Drag&Drop) solltest Du vor dem X aufhören lassen. Es sollte nicht möglich sein, die Box zu draggen, wenn man auf X geklickt hat aber noch nicht losgelassen.
Letztens hatte hier ein gewisser »wiberg« einen auch sehr interessanten Ansatz gepostet, ist noch im Archiv, der Link geht noch - sieht nur so aus, als wäre der Ansatz nicht weiter verfolgt worden (sieht genauso aus, wie damals):
Archiv-Posting
Window-Manager von »wiberg«
Eiboxen (hier wird nichts mittels JavaScript generiert, die DIVs sind im Seitenquelltext hartcodiert und nur als Popup dargestellt).
Viele Grüße aus Frankfurt/Main,
Patrick
Grüße!
Zum JavaScript-Code und mögliche Verbesserungen haben viel kompetentere Leute sich bereits geäußert. Ich beschränke mich auf Tipps, was das Aussehen der Fenster angeht.
Fein. Das gehört schließlich auch dazu.
Den maussensitiven Bereich für die Titelleisten (Drag&Drop) solltest Du vor dem X aufhören lassen. Es sollte nicht möglich sein, die Box zu draggen, wenn man auf X geklickt hat aber noch nicht losgelassen.
Das ist eine gute Idee, auch wenn ich persönlich wohl nie auch nur auf die Idee gekommen wäre, ausgerechnet in diesem Bereich draggen zu wollen. Habe ich jetzt behoben, indem ich dem "X"-Bereich einfach ein onmousedown statt onclick verpasst habe.
Archiv-Posting
Window-Manager von »wiberg«
Eiboxen (hier wird nichts mittels JavaScript generiert, die DIVs sind im Seitenquelltext hartcodiert und nur als Popup dargestellt).
Schau ich mir auch mal an. Danke.
Cü
Kai
Grütze .. äh ... Grüße!
Ich habe mir letzte Nacht ein kleines Popup-Script -> popup.js auf div-Basis zur universellen Anwendung gebaut.
Die (inzwischen erweiterte) Testumgebung ist umgezogen, das Popup-Script in vielen Punkten verbessert.
Ich scheine keine _einfache_ Lösung gefunden zu haben, den unsichtbaren iframe innerhalb des Hauptcontainers auf volle Höhe zu bringen. Daher habe ich jetzt in der show() funktion erst den Hauptcontainer angezeigt und dann mit offsetHeight den iframe "nachberechnet".
Leider hat der IE irgendwie noch keine Freundschaft mit einem der Test-Beispiele schließen könne, aber das wird wohl ein CSS-Problem sein (das ich allerdings zur Zeit [wahrscheinlich wegen Müdigkeit] nicht erkenne, 8:30Uhr .. hmm es wird nun wirklich mal Zeit fürs Bett ; )
Die Sache mit dem z-Index ist mir zur Zeit dann doch zu viel, komme nicht dazu, ich bin schon froh, daß ich zwei ziemlich üble Fehler, die nur beim IE auftraten, gefunden habe. IE ick liebe dir, besonders deine aussagekräftige Debug-Hilfen. Firebug ist nix dagegen *wg*
Cü
Kai