Div ausblenden, wenn man außerhalb klickt
snoot
- javascript
Hi,
ich habe ein Eingabefeld und ein Div. Im Div stehen Links, deren ID bei onclick in das Eingabefeld übergeben werden soll. Das Div soll ausgeblendet werden, wenn man
a) einen Link anklickt, oder
b) neben das Div klickt
Das mit dem Link klappt soweit einwandfrei:
<script type="text/javascript">
function insert_eingabe(id, div_id, txt_id)
{
var div = document.getElementById(div_id)
var txt = document.getElementById(txt_id)
if(txt && div)
{
txt.value = id;
div.style.visibility = 'hidden';
}
}
</script>
<input type="text" id="eingabe">
<div id="div">
<a id="1" href="#" onclick="insert_eingabe(id, 'div', 'eingabe')">Link 1</a><br>
<a id="2" href="#" onclick="insert_eingabe(id, 'div', 'eingabe')">Link 2</a><br>
<a id="3" href="#" onclick="insert_eingabe(id, 'div', 'eingabe')">Link 3</a><br>
</div>
Aber wie frage ich das "Danebenklicken" ab?
Ich dachte ich mache das, sobald das Eingabefeld den Focus verliert (es hat den Focus vorher, bei sichtbarem Div, *immer*):
<script type="text/javascript">
function schliessen(div_id)
{
var div_id = document.getElementById(div_id);
div_id.style.visibility = 'hidden';
}
</script>
<input type="text" id="eingabe" onblur="schliessen('div')">
<div id="div">
<a id="1" href="#" onclick="insert_eingabe(id, 'div', 'eingabe')">Link 1</a><br>
<a id="2" href="#" onclick="insert_eingabe(id, 'div', 'eingabe')">Link 2</a><br>
<a id="3" href="#" onclick="insert_eingabe(id, 'div', 'eingabe')">Link 3</a><br>
</div>
Dummerweise ist das "onblur" schneller als das "onclick", d.h. das Div ist weg, bevor der angeklickte Link registriert wird. Es wird beim Klick also das Div geschlossen und die ID nicht mehr übergeben.
Wie könnte ich sonst noch feststellen, ob irgendwo außerhalb des Divs geklickt wird?
Hi,
Aber wie frage ich das "Danebenklicken" ab?
Du musst zum Zuklappen den Klick im document registrieren, aber verhindern, dass der Klick auch dann im document aufläuft, wenn Du auf die Liste klickst. Dafür gibts cancleBubble (IE's) resp. stopPropagation, Methoden, die das "Hochblubbern" des events in der Dom-Hirarchie verhindern. Schau Dir mal diesen Test an, könnte Dir weiterhelfen: http://www.wendenburg.de/test/listitem_to_input.html
Ist jetzt allerdings nur schnell am FF/Mac gestrickt, hab leider keine Zeit allles durchzutesten. Verbesserungen willkommen...
Gruesse, Joachim
Du musst zum Zuklappen den Klick im document registrieren, aber verhindern, dass der Klick auch dann im document aufläuft, wenn Du auf die Liste klickst. Dafür gibts cancleBubble (IE's) resp. stopPropagation, Methoden, die das "Hochblubbern" des events in der Dom-Hirarchie verhindern. Schau Dir mal diesen Test an, könnte Dir weiterhelfen: http://www.wendenburg.de/test/listitem_to_input.html
Ist jetzt allerdings nur schnell am FF/Mac gestrickt, hab leider keine Zeit allles durchzutesten. Verbesserungen willkommen...
Gruesse, Joachim
Danke, hab jetzt noch was kürzeres gefunden:
document.onclick = function(e)
{
if(!e)
{
e = window.event;
}
var obj = e.target ? e.target : e.srcElement ? e.srcElement : null;
if( div_id != obj )
{
div_id.style.display = 'none';
}
Scheint eigentlich in allen Browsern (IE/FF/Opera/Chrome/Safari) zu laufen.
document.onclick = function(e)
{
if(!e)
{
e = window.event;
}
var obj = e.target ? e.target : e.srcElement ? e.srcElement : null;
if( div_id != obj )
{
div_id.style.display = 'none';
}
>
> Scheint eigentlich in allen Browsern (IE/FF/Opera/Chrome/Safari) zu laufen.
Das kann nicht sein.
Du fragst hier ab, welches Element das Ziel des Klicks ist - und vergleichst, ob dieses Element identisch mit dem div-Container ist.
Wenn ich allerdings auf einen Link im div-Element klicke, so ist der Link das Ziel des Events. D.h. div != Event-Target, also müsste das div versteckt werden. Das war aber nicht Sinn der Sache, oder?
Der Ansatz ist aber schon ganz richtig, aber dich interessiert vielmehr, ob das Zielelement
1\. das div selbst ist
2\. oder ein Element, das im div liegt (halt ein Link)
Dazu bieten die Browser außer Firefox die Methode .contains() an:
if (eventTarget != divContainer && !divContainer.contains(eventTarget)) {
/\* Klick kam nicht vom div oder seinen Kindelementen \*/
}
Für den Firefox bindest du [dieses Script](http://forum.de.selfhtml.org/archiv/2008/7/t173611/#m1140229) ein, sodass er ebenfalls .contains() kennt.
Mathias
--
[JavaScript-Erweiterung für das SELFHTML-Forum](http://forum.de.selfhtml.org/js/doku/)
Du fragst hier ab, welches Element das Ziel des Klicks ist - und vergleichst, ob dieses Element identisch mit dem div-Container ist.
Wenn ich allerdings auf einen Link im div-Element klicke, so ist der Link das Ziel des Events. D.h. div != Event-Target, also müsste das div versteckt werden. Das war aber nicht Sinn der Sache, oder?
Eigentlich schon, ich wollte ja:
div verschwindet bei
a) Klick auf Link, oder
b) Klick neben div
Also macht die Funktion im Grunde alles richtig - wenn auch unbeabsichtigt. Beim Klick auf einen Link würde das div auch verschwinden, weil das dann die onclick-Funktion erledigt.
Also macht die Funktion im Grunde alles richtig - wenn auch unbeabsichtigt. Beim Klick auf einen Link würde das div auch verschwinden, weil das dann die onclick-Funktion erledigt.
Okay. Aber dann verstehe ich ehrlich gesagt den Nutzen nicht so recht.
Bei einem Klick auf das div soll das Feld nicht verschwinden, ansonsten schon. Gut. Aber wieso sollte man auch auf das div klicken? Doch wohl eher aus Zufall? Es wird ja nicht suggeriert, dass da irgendeine Funktionalität hinter läge.
Mathias
Aber wieso sollte man auch auf das div klicken? Doch wohl eher aus Zufall? Es wird ja nicht suggeriert, dass da irgendeine Funktionalität hinter läge.
Mathias
Doch:
Im Div stehen Links, deren ID bei onclick in das Eingabefeld übergeben werden soll
Das div soll im Grunde immer verschwinden (bei einem Klick *ins* div aber erst nachdem die Link-ID übergeben wurde; daher ging mein erster Ansatz mit onblur nicht).
Hier mal die Seite. Bei Texteingabe in einem der beiden Suchfelder erscheint ein div mit Links. Bei Klick auf einen Link oder neben das div, soll sich selbiges wieder schließen.
Im Div stehen Links, deren ID bei onclick in das Eingabefeld übergeben werden soll
Das ist mir schon klar.
Hier mal die Seite. Bei Texteingabe in einem der beiden Suchfelder erscheint ein div mit Links. Bei Klick auf einen Link oder neben das div, soll sich selbiges wieder schließen.
Wie gesagt: Das div hat selbst keine Fläche, die nicht von einem Kindelement, insbesondere von den Links eingenommen wird.
Daher ist die Abfrage, ob nicht das div selbst geklickt wurde (nicht deren Kindelemente!), also letztliches Zielelement des Events ist, ziemlich überflüssig - soweit ich das richtig verstehe.
Mathias
Damit wir uns richtig verstehen: Was wäre daran problematisch?
document.onclick = function () {
document.getElementById("suggest").style.display = 'none';
};
Wenn das div selbst keine eigene Fläche hat, die nicht von einem Kindelement und vor allem den Links eingenommen wird, kann die Abfrage doch wegfallen?
Mathias
Damit wir uns richtig verstehen: Was wäre daran problematisch?
document.onclick = function () {
document.getElementById("suggest").style.display = 'none';
};Wenn das div selbst keine eigene Fläche hat, die nicht von einem Kindelement und vor allem den Links eingenommen wird, kann die Abfrage doch wegfallen?
Ja, es sieht in der Tat so aus. Da hab ich eben viel zu kompliziert gedacht. Das kommt davon, wenn man wenig Ahnung von der Materie hat ;)
Da kann ich nur sagen, herzlichen Dank für die tatkräftige Unterstützung.
Wenn man ohnehin mit Event Delegation arbeitet, kann man auch die Klicks auf oberster Ebene filtern, anstatt das Bubbling auf unterster Ebene bei jedem li-Elemente einzeln herauszufiltern.
Überhaupt leuchtet mir gerade nicht ein, wieso jedes li den cancel_bubble-Handler braucht.
linklist_wrapper.onclick = cancel_bubble;
... sollte doch schon alle Event stoppen, die vom linklist-Wrapper *oder* seinen Kindelementen aufsteigen.
Mathias
Hi,
Wenn man ohnehin mit Event Delegation arbeitet, kann man auch die Klicks auf oberster Ebene filtern.
Auf jeden Fall. Das ist ein C&P-Überbleibsel, Sorry. In Zeile 78 steht ja schon:
linklist_wrapper.onclick = cancel_bubble;
Gruesse, Joachim