Linuchs: Absolutwert style.top eines Vorschlagsfeldes bestimmen

problematische Seite

Moin,

ich habe mehrere input-Felder für die GEMA-Meldung von Liedern.

Nach Eingabe von mindestens 3 Zeichen sollen Titel vorgeschlagen werden. Dazu ist ein vorhandenes und zu body absolut positioniertes Vorschlagsfeld unter das jeweilge input-Feld zu positionieren und zu öffnen. Der Inhalt kommt später.

Die Position dieses Vorschlagsfeldes ermittle ich, in dem die Links- und Oben-Werte des input und seiner parents aufsummiert werden.

Bei left funktioniert das auch, aber bei top nicht. Wieso meldet ein td, dass er 53px oben-Abstand hat zu seinem tr und der oberste tr auch 53px zu tbody? Habe das per console.log dokumentiert:

  var obj_vorschlaege = document.getElementById( "vorschlaege" );
  function getLieder( obj ) {
    
    // vorschlagsfeld positionieren und oeffnen
    if ( obj.value.length == 3 ) {
      var div   = obj;
      var left  = div.offsetLeft; // im parent-Element
      var top   = div.offsetTop;  // im parent-Element
      while ( div.tagName != "BODY" ) {
        console.log( div.tagName +" left=[" +div.offsetLeft +"] top=[" +div.offsetTop +"]" );
        div    =  div.parentElement;
        left  +=  div.offsetLeft;
        top   +=  div.offsetTop;
      }
      console.log( "left=[" +left +"]" );
      console.log( "top =[" +top  +"]" );
      obj_vorschlaege.style.left      = left            +"px";
      obj_vorschlaege.style.minWidth  = obj.offsetWidth +"px";
      obj_vorschlaege.style.top       = top             +"px";
      obj_vorschlaege.style.display   = "block";
    }
...

Gruß, Linuchs

  1. problematische Seite

    Hallo Linuchs,

    ich bin da nicht der Experte, aber ich weiß, dass im style Attribut dein Wunsch steht, nicht die Wirklichkeit. Du brauchst getComputedStyle.

    Darüber hinaus sollte man wilde Rechnerei mit Koordinaten meiden. Kannst du nicht mit einem position: relative Container um das Input arbeiten? Dann ist das Popup darauf bezogen. Wenn das alles in einem td stattfindet müsste man doch das td als position: relative setzen können, oder?

    Rolf

    --
    sumpsi - posui - clusi
    1. problematische Seite

      Hallo Rolf,

      Kannst du nicht mit einem position: relative Container um das Input arbeiten?

      Das habe ich bisher gemacht, aber nun sind da 20 inputs und ich wollte ein vereinfachtes Verfahren ausprobieren.

      Es muss doch möglich sein, die Position beliebiger Felder gegen body zu ermitteln.

      Linuchs

      1. problematische Seite

        @@Linuchs

        Es muss doch möglich sein, die Position beliebiger Felder gegen body zu ermitteln.

        HTMLElement.offsetTop, HTMLElement.offsetLeft.

        Aber wie Rolf sagte: Wenn man JavaScript zum Positionieren von Elementen verwendet, macht man vermutlich was mit CSS nicht richtig.

        LLAP 🖖

        --
        „Man kann sich halt nicht sicher sein“, sagt der Mann auf der Straße, „dass in einer Gruppe Flüchtlinge nicht auch Arschlöcher sind.“
        „Stimmt wohl“, sagt das Känguru, „aber immerhin kann man sich sicher sein, dass in einer Gruppe Rassisten nur Arschlöcher sind.“

        —Marc-Uwe Kling
        1. problematische Seite

          Hallo Gunnar,

          important detail from MDN:

          offsetTop/Left beziehen sich nicht auf den body, sondern auf den offsetParent (wobei es sich um den body handelt wenn kein position:relative Element, oder td, th oder tsble in der Elternkette ist).

          Dass Tabellenelemente dabei sind hat mich gewundert. Sind die automatisch position:relative?

          Also eigentlich genau das richtige für ein absolut positioniertes Geschwisterlein. Und es erklärt, warum Linuchs sich verrechnet. Er verwendet die offset-Werte und folgt der parentElement Kette.

          Rolf

          --
          sumpsi - posui - clusi
          1. problematische Seite

            Hallo Rolf,

            offsetTop/Left beziehen sich nicht auf den body, sondern auf den offsetParent (wobei es sich um den body handelt wenn kein position:relative Element, oder td, th oder tsble in der Elternkette ist).

            Danke, das ist der entscheidende Hinweis. Man muss aus Sicht des input alle zu durchlaufenden (parent-) Elemente relative setzen:

            body, form, table, tbody, tr, td {
              position: relative;   /* wg. Positionierung Vorschlagsfeld */
            }
            

            Jetzt liegt das Vorschlagsfeld (position:absolute) vor dem betroffenen input und verdeckt es. Also noch einen Zuschlag für left und top.

            Linuchs

            1. problematische Seite

              allerdings bringt der Firefox jetzt in der Konsole diesen Hinweis:

              Relative Positionierung von Tabellenzeilen und Zeilengruppen wird jetzt unterstützt. Diese Website muss möglicherweise aktualisiert werden, weil sie sich darauf verlassen könnte, dass diese Funktion keine Wirkung hat.

              Unterstützen andere Browser das auch?

              Linuchs

              1. problematische Seite

                Hallo Linuchs,

                ich weiß nicht, warum du das so kompliziert machst. Wenn ich etwas relative zu etwas anderem positionieren möchte, mache ich das so:

                #inner { width: 50px; height:50px; background-color: red; position: absolute; top:50px; left: 50px }
                
                #outer { width: 200px; height:200px; background-color: blue; position: relative; margin: 30px 30px 30px 200px }
                
                <div id="outer"><div id="inner"></div></div>
                

                Gruß
                Jürgen

                1. problematische Seite

                  Hallo Jürgen,

                  ich weiß nicht, warum du das so kompliziert machst.

                  Dann ist dir wohl entgangen, dass ich Text-Vorschläge für 20 input-Felder einblende.

                  Der Vorschlags-Container div soll nicht an einer festen Position stehen, sondern unterhalb des fokussierten input-Feldes.

                  Nach deiner Methode müsste ich 20 Vorschlags-Container vorsehen.

                  Linuchs

                  1. problematische Seite

                    Hallo Linuchs,

                    ich wollte dir nur zeigen, wie man relativ zu einem umgebenden Element positionieren kann, ohne die Position des umgebenden Elements zu wissen.

                    Deine Inputs stecken doch in irgendeinem Element. Wenn dieses relativ positioniert ist, kannst du dein Vorschlags-DIV ebenfalls dort ablegen und dann nach Datenlage einblenden, positioniern und mit Inhalt füllen.

                    Gruß
                    Jürgen

                  2. problematische Seite

                    Hallo Linuchs,

                    Dazu ist ein vorhandenes und zu body absolut positioniertes Vorschlagsfeld unter das jeweilge input-Feld zu positionieren und zu öffnen.

                    Ja, wer liest, ist im Vorteil. Du hast ja gesagt, dass Du einen Vorschlagscontainer hast und ihn unter das jeweilige Input-Feld platzierst? Das erklärt die Rechnerei.

                    Du könntest ihn aber auch bei Bedarf im DOM umhängen, so dass er im gleichen Container wie das input Feld steht. Das könnte die Mathematik vereinfachen und es es könnte für die Accessibility nützlich sein (es sei denn, ein Screenreader kann mit solcher Dynamik nicht umgehen). Nur mal so als Idee

                    Rolf

                    --
                    sumpsi - posui - clusi