webentwicklung-frage-antwort-db.com.de

So teilen Sie das Browser-Ansichtsfenster in zwei horizontale Bereiche

Bis zu HTML 4 war es möglich, Layouts mit Frames zu erstellen, in denen verschiedene HTML-Dateien in verschiedenen Bereichen geladen wurden.

Ich möchte ein ähnliches Ergebnis erzielen, aber zwei unterschiedliche Teile desselben Dokuments laden und auf dem Bildschirm anzeigen .

Mein ideales Paradigma ist MS Word, das es ermöglicht, das Fenster in zwei horizontale Teile zu unterteilen, um jeweils verschiedene Abschnitte desselben Dokuments anzuzeigen (äußerst nützlich, wenn Sie verschiedene Teile des Dokuments vergleichen oder Teile lange von einer entfernten Seite zur anderen verschieben möchten) Dokumente) oder MS Excel (sogar LibreOffice oder OpenOffice Calc haben eine ähnliche Funktion), die es ermöglicht, den Bereich des Blattes aus dem gleichen Grund in zwei (oder sogar vier) Abschnitte zu teilen oder einige Zeilen oben oder einige Spalten an sichtbar zu halten rechts (z. B. Zeilen- oder Spaltenüberschrift).

Das folgende Bild zeigt es:  Split same window document example.png

Der rote Pfeil zeigt die Rinne an, die das Fensterdokument in zwei Teile aufteilt, sodass jeder Teil separat gescrollt werden kann. Sie sehen, wie die Nummer der Zeile im oberen Bereich 3 und im unteren Bereich 21 lautet. Auch die Dachrinne ist in der Größe veränderbar.

Ist es möglich, dies mit Vanilla JS mit HTML & CSS zu tun (bitte keine jQuery oder ein anderes Framework)?

Einschränkungen:

  1. Das Dokument muss für alle 2 Bereiche (oben und unten) gleich sein (altes Frameset muss zwei verschiedene Dokumente oder dasselbe Dokument zweimal laden: Ich verwende dies bereits, aber ich möchte einen saubereren Ansatz, wenn möglich!)
  2. Der Separator (Dachrinne?) Muss in der Größe verändert werden
  3. Die zwei verschiedenen Teile des Dokuments sind in dem Sinne perfekt synchron, dass, wenn ich etwas (mit der Eigenschaft contenteditable) im oberen (oder unteren) Bereich ändere, der untere (oder obere) Bereich sofort die gerade durchgeführte Bearbeitung anzeigt, wie dies auch bei MS der Fall ist Word oder Excel ... Wenn ich also etwas in einer unteren Tabellenzelle lösche, wird auch der obere Inhalt entsprechend angepasst (auch die Spaltengröße), wie dies bei MS Word, Excel, Calc usw. der Fall ist.
  4. Die geteilte Ansicht wird beim Klicken auf eine bestimmte Schaltfläche ein- und ausgeschaltet
  5. Alte Browser interessieren mich nicht, nur ECMA-Skript 2015 oder neuere
  6. Die HTML-Datei enthält viele Ereignis-Listener mit addEventListener()-Methode für verschiedene HTML-Elemente wie Schaltflächen, Textfelder, Kontrollkästchen, Auswahlfelder usw.: Dies bedeutet, dass die beantwortete Lösung in der Lage sein muss, sie intakt zu halten und in beiden Bereichen zu funktionieren. .

Wo werde ich das verwenden?

Ich habe eine Reihe von Tabellen in einer lokalen HTML-Datei (kein Webserver beteiligt), die Daten aus einer CSV-Datei oder aus dem Sitzungsspeicher des Browsers laden, und ich muss häufig Daten von verschiedenen Punkten vergleichen oder den Header währenddessen festhalten Scrollen Sie durch den Rest einer bestimmten Tabelle oder während Sie neue Daten einfügen oder alte Daten in einer von ihnen aktualisieren, um fortlaufend zu sehen, in welche Tabellenzelle ich Daten einfüge oder aktualisiere.

Situation:

Im Moment benutze ich den folgenden Code:

function splitView()
{
    var tgtSrc = location.href;
    var frameset =  '<frameset rows="*,*">' +
                        '<frame name="' + upFrame + '" src="' + tgtSrc + '">' +
                        '<frame name="' + dwFrame + '" src="' + tgtSrc + '">' +
                    '</frameset>';
    document.write(frameset);   
}

Die obige Funktion teilt das aktuelle Fenster horizontal in zwei Frames mit den Namen upFrame und dwFrame (das sind zwei Variablen). Nach dem Aufteilen wird eine veränderbare Rinne zwischen den beiden Rahmen platziert.

Dazu kommt der Algorithmus zum Synchronisieren beider Instanzen der Dokumentdaten: Er speichert bei jeder Datenbearbeitung in einem Frame die Daten im Sitzungsspeicher dieses Frames und lädt dieselben Daten erneut in den anderen Frame.

Es funktioniert ein bisschen, aber Frames sind nicht der richtige Weg. Ich möchte die Notwendigkeit beseitigen, das Dokument zweimal zu laden und jede Instanz mit allen damit verbundenen relativen Nachteilen zu synchronisieren. Leider ist dies nicht die ultimative Antwort, die ich suche, da sie einige Nachteile hat:

  1. Die Tags frame und frameset werden in modernen HTML5-kompatiblen Dateien nicht unterstützt, auch wenn sie von Browsern weiterhin unterstützt werden
  2. Die Datei muss zweimal geladen werden (einmal pro Frame). Dies führt zu einer spürbaren Leistungsminderung und zu einer Schwierigkeit, Änderungen in einem Frame mit dem anderen Frame in Echtzeit zu synchronisieren (möglicherweise ist eine bidirektionale Synchronisierung erforderlich, sodass Änderungen in beiden gezeigten Teilen vorgenommen werden können des Dokuments). Leider bedeutet selbst der erforderliche Synchronisierungsprozess, dass die Leistung nachlässt, wodurch die Benutzeroberfläche bei jeder Synchronisierungsschleife für einen Moment gesperrt wird
  3. Der Synchronisierungsvorgang läuft nicht in Echtzeit ab, sondern hat eine gewisse Verzögerung (einige Sekunden): Wenn ich ihn kürzer mache, mangelt es mir an Leistung, einschließlich Browser-Freezing

Deshalb bin ich offen für bessere Antworten mit saubereren und effizienteren Lösungen. (Ich habe sogar Chrome-Entwicklern vorgeschlagen, eine Funktion für diesen Browser zu implementieren, da dies meiner Meinung nach ein Muss ist, insbesondere angesichts der wachsenden Online-Datenverwaltungssysteme.)

Was ich suche:

Die Verwendung des obigen Codes, den ich bereits verwende, ist überhaupt nicht obligatorisch: Die Antworten können auch einen völlig anderen Ansatz vorschlagen.

Die ultimative Lösung, nach der ich suche, ist ähnlich wie bei der von Google Spreadsheet verwendeten Aufteilungsfunktion (wenn möglich, hoffen wir auch). Hier ist ein Bild mit dem Beispiel

 enter image description here

Schauen Sie es sich genau an: Es gibt eine Dachrinne, die sich horizontal bewegen lässt (es gibt auch eine vertikale Dachrinne, aber die vertikale Aufteilung interessiert mich nicht wirklich, nur die horizontale), und wenn das Arbeitsblatt nach unten rollt, verschwinden die Zeilen darunter: in Tatsächlich ist die erste Reihe über der Rinne die n. 1 Die erste Reihe in der Rinne ist n. 45.

Beachten Sie auch den kleinen doppelköpfigen weißen Pfeil, der durch den großen roten Pfeil ganz links im Bild angezeigt wird.

Ich habe versucht, die Google-Tabellenkalkulation zu studieren, um sie rückzuentwickeln und zu extrahieren die herausragenden Funktionen und die gleiche "Philosophie" an meine lokale Anwendung anzupassen, aber ich bin nicht gut genug, um zu verstehen, was sie genau taten: mein Verdächtiger ist, dass, wenn eine "Tischreihe trifft die Rinne" versteckt sich nur dahinter, aber ich bin nicht sicher.

IMHO ist dies eine Funktion, die jeder Browser (auch für tragbare Geräte) nativ implementiert haben muss und ohne die alte Technologie von Frames zu verwenden, die in HTML 5 nicht mehr unterstützt werden. Leider ist diese Möglichkeit dasselbe Dokument zu teilen um verschiedene Teile davon anzuzeigen und zu bearbeiten (z. B. eine sehr lange Tabelle), wobei jedes Fenster wechselseitig aktualisiert wird, ist (noch) keine Browserfunktion. In der Zwischenzeit ist also eine Problemumgehung erforderlich.

Beachten:

Die CSS-Eigenschaft

position: sticky;

es wäre auch nützlich, um einen Teil des Problems zu lösen (um den Kopf beim Bearbeiten oder beim Einfügen von Daten in den Körper hängen zu lassen), aber leider scheint es auf Thead-Elementen nicht wie erwartet zu funktionieren, zumindest in einigen Browsern. Außerdem wird nur ein Teil des Problems gelöst: Wenn Daten aus verschiedenen Teilen derselben Tabelle oder verschiedener Tabellen mit demselben Dokument verglichen werden müssen, ist diese Lösung überhaupt nicht geeignet. Also wird noch etwas benötigt.

18
willy wonka

Nur neugierig, wenn es sich um lokale Dateien auf Ihrem Computer handelt, warum versuchen Sie, Tabellendaten aus CSV-Dateien in einem Browser zu bearbeiten, anstatt nur die nativen Fähigkeiten eines Programms wie Excel zu verwenden, das Sie oben erwähnt haben? Oder wenn Sie es in einem Browser tun möchten, erlaubt Google Sheets die Split-Screen-Sache? Keine Respektlosigkeit Ich verstehe einfach nicht, warum Sie kein Programm verwenden, das für diese Art von Arbeit bestimmt und optimiert ist.

wenn Sie weiterhin Frames verwenden möchten, sollten Sie die Datei wieder in einen Frame laden und die innerHTML einfach von einem Frame in einen anderen kopieren, etwa wie folgt. Wenn Sie Sitzungsspeicher verwenden, sollte es zwar schneller sein, Änderungen an dieser Datei und der CSV-Datei zu speichern, sie sollte jedoch aus dem Sitzungsspeicher anstelle der Datei geladen werden.

window.frames[upFrame].document.body.innerHTML = window.frames[dwFrame].document.body.innerHTML;

Anstelle von Frames können Sie DIVs als Container verwenden, in den lokalen Speicher laden und von dort beide DIVs auffüllen. Speichern würden sowohl in die CSV-Datei als auch in den lokalen Speicher gehen, wie die Frames-Lösung. Javascript kann den Bildlauf nachverfolgen, sodass Sie die beiden Abschnitte nach dem Laden aus dem lokalen Speicher in die Zeilen "einklappen" können, in denen sie sich befanden.

Eine schnellere Lösung könnte jedoch darin bestehen, dass die CSV-Daten im Speicher (Array) gespeichert und in der CSV gespeichert werden. Das Aktualisieren aus dem Speicher wäre jedoch in der Theorie viel schneller als eine Datei. :)

3
Viking NM

ich denke, das kann man mit divs erreichen.

erstellen Sie zuerst zwei Divs, um die oberen und unteren Ansichten zu speichern.

klonen Sie dann den Hauptinhalt auf jedes div.

durch Anpassen der Abmessungen und der Position für jedes div können Sie die Ansicht eines div in zwei Teile spalten

sie können auch ein Größenänderungsskript erstellen, um die Höhe der einzelnen Ansichten zu verwalten

für kaskadierte Aktionen über mehrere Ansichten hinweg. Sie können Ereignisse in der oberen Ansicht verwenden, um die Änderungen in der unteren Ansicht vorzunehmen. und in der unteren Ansicht, um die Änderungen in der oberen Ansicht vorzunehmen.

endlich entschuldige mich für schlechte Erklärung.

ich habe jsfiddle gemacht, um den ansatz zu erklären

[1]: https://jsfiddle.net/EmadElpurgy/r9w93zo7/sample code

2
Emad Elpurgy

Es gibt wahrscheinlich bessere Lösungen als den Hack, den ich mir ausgedacht habe, aber versuchen wir es mal.

Wenn Sie die gesamte - Seite nehmen und nur teilen möchten, können Sie Ihre Frameset-Lösung verwenden. Statt jedoch die Ressource des Browsers zweimal laden zu müssen, können Sie deren HTML-Code kopieren und in die Frames schreiben:

<html>
  <head>
    <style type="text/css">
        body { color: red; } /* Only used to test if CSS is copied as well
    </style>
  </head>
  <body>
      Hello world!
  </body>

  <script type="text/javascript">
    function inFrame () {
      try {
    return window.self !== window.top;
      } catch (e) {
        return true;
      }
    }


    function buildFrames() {
      const documentHTML = document.documentElement.innerHTML;

      const frameset = document.createElement('frameset');
      frameset.rows = '*,*';

      const frame1 = document.createElement('frame');
      const frame2 = document.createElement('frame');

      document.documentElement.innerHTML = '<html><body></body></html>';

      frameset.appendChild(frame1);
      frameset.appendChild(frame2);

      document.body.appendChild(frameset);

      frame1.src = 'data:text/html;charset=utf-8,' + encodeURI(documentHTML);
      frame2.src = 'data:text/html;charset=utf-8,' + encodeURI(documentHTML);
    }

    if (!inFrame()) {
        buildFrames();
    }
  </script>
</html>

Sie müssen jedoch vorsichtig mit dem Javascript-Code sein, der auf Ihren Seiten ausgeführt wird. Wie Sie sehen, musste ich auch überprüfen, ob sich die Seite nicht bereits in einem Frame befindet. Andernfalls wird Framesets für immer an das Dokument angehängt (oder zumindest so lange, bis der Browser dies verhindert).

2
samu

Ich werde Ihre Frage nur teilweise beantworten, da ich keine vollständige Lösung habe.

Die Frame- und Frameset-Tags werden in modernen HTML5-kompatiblen Dateien nicht unterstützt, auch wenn sie noch von Browsern unterstützt werden

Der Frame wurde zugunsten von iframe nicht mehr empfohlen. Dies sollte sich ziemlich ähnlich verhalten.

Um die Synchronisierung zwischen den beiden Bereichen mit den von Ihnen festgelegten Abhängigkeiten zu gewährleisten, müssen Sie benutzerdefinierte JS schreiben, vor allem, weil Sie Framework/Package-abgeneigt sind.

0
Samir