freies Hilfsfeld beim Tippen andocken, left und top finden
Linuchs
- javascript
Moin,
bei Eingabe von Orten kommen Vorschläge per Ajax zum Anklicken.
Bisher hatte ich das Vorschlags-div HTML-mäßig an das input-Feld geklebt. Nun gibt es aber mehrere input-Felder in einer form und ich möchte die Vorschläge variabel positionieren.
Das Feld parke ich mit position:absolute;display:none
erstmal oben links auf der Seite.
Wenn mehr als 2 Zeichen eingegeben werden, holt sich Ajax die Vorschläge vom Server und das „freie“ Vorschlagsfeld soll an das aktuelle input-Feld angedockt werden.
Irgendwie klappt's nicht mit der Positionierung, es erscheint viel zu weit unten auf der Seite.
Ausgehend vom aktuellen input-Feld (obj) hole ich mir left und top auf diese Weise:
/* *******************************************
* Neues obj, Vorschlagsfeld positionieren
* ******************************************* */
if ( obj.name != getOrteVar.obj.name ) {
getOrteVar.obj = obj; // speichern/merken fuer die UEbername Vorschlagswert
var left = 5; // 5px rechts vom Feldanfang ansetzen
var top = obj.offsetHeight +obj.clientHeight; // unterhalb des Eingabefeldes ansetzen
var obj2 = obj.parentElement;
while ( obj2.tagName != "BODY" && obj2.style.position != "absolute" && obj2.style.position != "relative" ) {
left += obj2.offsetLeft;
top += obj2.offsetTop;
obj2 = obj2.parentElement;
}
getOrteVar.obj_vorschlaege.style.left = left +"px";
getOrteVar.obj_vorschlaege.style.top = top +"px";
}
Weil ich nicht sicher bin, ob BODY standardmäßig absolut/relativ positioniert ist, habe ich body {position: relative;} definiert. Das Problem bleibt, auch wenn ich body klein schreibe.
Vielleicht sieht jemand den Haken sofort?
Gruß, Linuchs
Hi there,
Vielleicht sieht jemand den Haken sofort?
Ich denke, Du addierst in der Schleife zu viele "tops" und "lefts" - warum fragst Du nicht einfach die Koordinaten vom Inputfeld ab, versetzt das Ganze um die Höhe des Inputfelds und gut ist's?
Hallo klawischnigg
warum fragst Du nicht einfach die Koordinaten vom Inputfeld ab?
Wie geht das?
Ich habe einen anderen Fall, da wird bei Mausklick etwas positioniert mit x/y des Mauszeigers.
Aber hier wird z.B. mit der Tab-Taste ins Feld gesprungen und dann per Tastatur eingegeben. Das Feld ist als erstes Feld bei body eingehakt und benötigt die links-oben-Angaben von dort.
Linuchs
Hallo klawischnigg
warum fragst Du nicht einfach die Koordinaten vom Inputfeld ab?
Wie geht das?
Mit der Funktion zum Beispiel:
function getKoordinaten(obj) {
let box = obj.getBoundingClientRect();
return {
top: box.top + pageYOffset,
left: box.left + pageXOffset
};
}
Ich habe einen anderen Fall, da wird bei Mausklick etwas positioniert mit x/y des Mauszeigers.
Ja, da wird die Positionsbestimmung mit einer Event"abfrage" verknüpft. Hat aber im Prinzip mit der Positionsermittlung von Objekten nichts zu tun...
Hallo klawischnigg,
danke, das sieht unkompliziert aus.
Habe es so umgesetzt:
let box = obj.getBoundingClientRect();
getOrteVar.obj_vorschlaege.style.left = box.left + pageXOffset +10 +"px";
getOrteVar.obj_vorschlaege.style.top = box.top + pageYOffset +obj.offsetHeight +"px";
Linuchs
Hallo klawischnigg,
ok, wie genau? getBoundingClientRect hängt am Viewport, d.h. wenn man scrollt, ändert sich der top-Wert.
offsetTop hängt am offsetParent, d.h. es ist relativ zum nächstgelegenen positionierten Parent-Element.
Irgendwie muss man die Elternkette ablaufen, aber wie genau, das ist so trivial nicht. Ich krieg's grad auch nicht hin.
Update: jetzt erst dein Posting gelesen.
Rolf
Hi,
bei Eingabe von Orten kommen Vorschläge per Ajax zum Anklicken.
Bisher hatte ich das Vorschlags-div HTML-mäßig an das input-Feld geklebt.
Per datalist-Element ans jeweilige Input-Feld anbinden?
cu,
Andreas a/k/a MudGuard
Hi there,
bei Eingabe von Orten kommen Vorschläge per Ajax zum Anklicken.
Bisher hatte ich das Vorschlags-div HTML-mäßig an das input-Feld geklebt.
Per datalist-Element ans jeweilige Input-Feld anbinden?
ja, das ist sicher die beste Lösung. Ich weiß nicht warum, aber ich vergeß' dieses Datalist-Element ständig...;)
Moin Andreas,
Per datalist-Element ans jeweilige Input-Feld anbinden?
Sicher auch eine brauchbare Lösung.
Die Klawischnigg-Lösung hat den Vorteil, dass ich im HTML den Input-Feldern, die durch den angeklickten Vorschag gefüllt werden sollen, nur den richtigen Namen verpassen muss:
Alles andere macht getOrte.js. Beginnt damit, das Vorschlagsfeld bei body einzuhängen.
Linuchs
@@Linuchs
Per datalist-Element ans jeweilige Input-Feld anbinden?
Sicher auch eine brauchbare Lösung.
Die Klawischnigg-Lösung hat den Vorteil …
Ich bezweifle, dass du die brauchbar umgesetzt hast. Ist sie tastaturbedienbar?
😷 LLAP
Weil ich nicht sicher bin, ob BODY standardmäßig absolut/relativ positioniert ist, habe ich body {position: relative;} definiert.
In der zentralen CSS-Datei.
Führt dazu, dass die Leaflet-Landkarte nur wenige Pixel hoch ist statt den ganzen Viewport zu füllen. Habe das wieder zurückgenommen.
Im Inspektor der Landkarte kann man anklicken und den Effekt togglen:
Stört nicht mehr, aber wäre wissenswert, warum.
Linuchs
Hallo Linuchs,
ist doch klar.
Die Map ist position:absolute, und du verwendest top, left, right und bottom, um ihre Grenzen festzulegen.
Der Bezugspunkt für diese Werte wird entlang der Elternhierarchie gesucht, er ist das erste positionierte Element (d.h. alles außer dem Defaultwert position:static).
Dein Body hat eine Höhe von 18px. Vermutlich wegen des einsamen darin, das nicht aus dem Flow hinauspositioniert oder versteckt wird.
Ohne position:relative am body orientiert sich die Map am Viewport.
Lösung:
body {
height: calc(100vh - 1em);
}
Minus ein emm wegen des Margins am Body. Sonst ist der Body zu hoch und es gibt rechts einen Scrollbar.
Rolf
@@Rolf B
Lösung:
body { height: calc(100vh - 1em); }
Minus ein emm wegen des Margins am Body. Sonst ist der Body zu hoch und es gibt rechts einen Scrollbar.
Das ist wohl eher ein Hack als eine Lösung.
Der Hack basiert darauf, das body { margin: 8px }
im browserinternen Stylesheet steht und dass 1em 16px entspricht. Das kann gutgehen, muss aber nicht.
Sauberer ist da
body {
margin: 0;
min-height: 100vh;
}
und anderweitig dafür sorgen, dass der Inhalt nicht am Rand klebt.
😷 LLAP
Hallo Gunnar,
nein, das ist kein Hack. Es ist nur unvollständig beschrieben.
Linuchs hat body { margin: 0.5em; }
in seinem Stylesheet stehen. Ich habe unterstellt, dass ein alter Fux wie Linuchs den Zusammenhang zwischen Subtrahend und Margin erkennt, aber natürlich sieht das niemand, der die Seite nicht anschaut.
Rolf
@@Rolf B
Linuchs hat
body { margin: 0.5em; }
in seinem Stylesheet stehen. Ich habe unterstellt, dass ein alter Fux wie Linuchs den Zusammenhang zwischen Subtrahend und Margin erkennt, aber natürlich sieht das niemand, der die Seite nicht anschaut.
Und auch nicht unbedingt jemand, der sich das Stylesheet anschaut. Das ist schlechter Code.
Entweder
body {
--margin: 0.5em;
margin: var(--margin);
min-height: calc(100vh - 2 * var(--margin));
}
oder mit Präprozessor
body {
$margin: 0.5em;
margin: $margin;
min-height: calc(100vh - #{2 * $margin});
}
oder wenigstens in einem Kommentar vermerken, wo das 1em
herkommt, welche Stellen also voneinander abhängen und bei Änderungen gemeinsam berücksichtigt werden müssen.
😷 LLAP
@@Gunnar Bittersmann
Entweder […]
oder mit Präprozessor […]
oder wenigstens in einem Kommentar […]
oder
html {
min-height: 100vh;
display: flex;
}
body {
flex: 1;
margin: 0.5em;
}
oder eine Zeile kürzer
html {
min-height: 100vh;
display: grid;
}
body {
margin: 0.5em;
}
Look Ma, kein calc()
, keine Abhängigkeiten.
😷 LLAP