Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split the browser viewport into two horizontal panes

Until HTML 4 it was possible to create layouts with frames loading different HTML files in different panes.

What I want to do is to achieve a similar result but loading and showing on screen two different part of the same document.

My ideal paradigm is MS Word which allows to split the window in 2 horizontal parts to show in each one different sections of the same document (extremely useful when comparing different parts of the document or when moving parts from one distant side to the other on long documents) or MS Excel (even LibreOffice or OpenOffice Calc have a similar feature) that allows to split the pane of the sheet in 2 (or even in 4) sections for the same reason or to keep visible some rows on top or some columns at the right (row or column header for example).

The following picture shows it: Split same window document example.png

The red arrow indicate the gutter that splits the window document in two allowing to scroll each part separately, as you can see looking at the number of the row that in the upper pane is 3 and 21 the bottom pane. Also the gutter is resizable.

Is it possible to do this using vanilla JS with HTML & CSS (no jQuery or other framework please)?

Constraints:

  1. The document must be the same for all 2 panes (top and bottom) (old frameset needs to load two different documents or the same document twice: I'm using this already but I want a more clean approach if possible!)
  2. The separator (gutter?) has to be resizable
  3. The two different parts of the document are perfectly in sync in the sense that if I modify something (with the contenteditable property) in the top (or bottom) pane the bottom (or the top) pane shows instantly the edit just done as does MS Word or Excel... so if I delete something in any bottom pane table cell even the top content is adjusted accordingly (even the column size), as happens with MS Word, Excel, Calc, etc..
  4. The split view will be switched on and off on click on a specific button
  5. I don't care about old browsers, just ECMA script 2015 or more recent ones
  6. The HTML file has lots of event listeners attached with addEventListener() Method to various HTML elements like buttons, text boxes, checkboxes, selectboxes, etc: this means that the answered solution must be able to keep them intact and working in both panes.

Where will I use this?

I have a bunch of tables in a local HTML file (no web server involved) that loads data from a csv file or from the browser session storage, and I frequently need to compare data from different points or to keep the header fixed on top while scrolling the rest of a specific table or while inserting new data or updating old data in one of them to continuously see in which table cell I'm inserting or updating data in.

Situation:

At the moment I'm using the following 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);   
}

The above function splits horizontally the current window pane in two frames called upFrame and dwFrame (that are two variables). After splitting a resizable gutter is placed between the two frames.

Plus the algorithm to sync both instances of the document's data: it works by saving at each data edit in one frame the data into the session storage of that frame and reloads the same data into the other frame.

It kinda works but frames aren't the way to go, I would like to get rid of the need to load the document twice and sync each instance with all the relative drawback involved. So unfortunately this isn't the ultimate answer I'm looking for because it has some drawbacks:

  1. The frame and frameset tags are not supported in modern HTML5-compliant files even if they are still supported by browsers
  2. The file has to be loaded twice (once per frame) this means a noticeable lack of performance and difficult to sync in real time any edits in one frame with the other frame (possibly bidirectional sync is needed so edits could be done in both shown part of the document). Unfortunately even the sync process needed means loosing performances that lock the UI for some instant every sync loop
  3. The sync process isn't in real time, it has some delay (some seconds): if I make it shorter I have a large lack of performances that includes browser freezing

So I'm open to better answers with cleaner and more efficient solutions. (I have even proposed to Chrome devs to implement a function for it in the browser, because I really think this is a Must Have feature especially considering the expanding online data management systems.)

What I'm looking for:

The use of the above code I'm using already isn't mandatory at all: the answers can propose a complete different approach as well.

So the ultimate solution I'm looking for is something similar to the splitting function used by Google Spreadsheet (if they can, I hope we could too), here's an image with the example

enter image description here

Look carefully at it: there is the gutter that is possible to move horizontally (there is a vertical gutter too, but I don't really care about vertical splitting, just horizontal) and when the spreadsheet scrolls down the rows disappear under it: in fact the first row above the gutter is the n. 1 the first row down the gutter is n. 45.

Also notice the little double headed white arrow indicated by the big red arrow at the extreme left of the picture.

I tried to study the Google spreadsheet approach to reverse engineer it and extract the salient features and adapt the same "philosophy" to my local application but I'm not good enough to understand what they did exactly: my suspect is that when a "table row hits the gutter" just hides behind it, but I'm not sure.

IMHO this is a feature that every browser (even those for portable devices) have to have implemented natively and without using the old technology of frames that are no more supported in html 5. Unfortunately this possibility to split the same document to show and edit different parts of it (as a very long table for example) keeping each pane reciprocally updated, isn't (yet) a browser feature, so in the meanwhile... it is needed a workaround.

Notice:

The CSS property

position: sticky;

would be also usable to solve part of the problem (to keep the thead stuck when editing or when inserting data into the tbody), but unfortunately it doesn't seem to work as expected on thead elements, at least on some browsers. Also it solves just part of the problem: in fact if it is needed to compare data from different parts of the same table or of different tables into the same document this solution isn't good at all. So something else is needed.

like image 486
willy wonka Avatar asked Feb 13 '18 14:02

willy wonka


1 Answers

Just curious, if it's local files on your computer why are you trying to edit table data from csv files in a browser instead of just using the native abilities of a program like Excel you mentioned above? Or if you want to do it in browser does google sheets allow for the split screen thing? No disrespect I just don't understand why not using a program dedicated and optimized for this type of work.

if you want to continue using frames you should be able to load the file back into one frame and just copy the innerHTML from one frame to another, something like the following. If you're using session storage though it should (?) be faster to save edits to that and the csv file but load from session storage instead of the file.

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

Instead of using frames you can use DIVs as containers, load into local storage as you suggest and populate both DIVs from there. saves would go to both csv file and local storage like the frames solution. Javascript can keep track of the scroll top so once reloaded from local storage you can "pop" the two sections to the rows they were on.

A faster solution though might be keeping the csv data in memory (array) and save out to the csv but updating from memory would be much faster than a file in theory right :)

like image 81
Viking NM Avatar answered Sep 20 '22 18:09

Viking NM