如何将浏览器视口拆分为两个水平窗格

时间:2018-02-13 14:48:18

标签: javascript html css window

在HTML 4之前,可以使用在不同窗格中加载不同HTML文件的框架来创建布局。

我想要做的是获得类似的结果,但加载并在屏幕上显示同一文档的两个不同部分

我理想的范例是MS Word,它允许将窗口分成2个水平部分,以显示同一文档的每个不同部分(在比较文档的不同部分或将部件从一个远端移动到其他在长文档上)或MS Excel(甚至LibreOffice或OpenOffice Calc具有相似的功能)允许在相同的原因下将工作表的窗格分成2个(甚至4个)部分,或者在顶部保持可见的某些行或右边的一些列(例如行或列标题)。

下图显示: Split same window document example.png

红色箭头表示将窗口文档分成两部分的装订线,允许分别滚动每个部分,如您所见,可以看到上部窗格中的行数为3,底部窗格中的行数为21。天沟也可以调整大小。

是否可以使用带有HTML&amp ;;的vanilla JS来做到这一点CSS(请不要jQuery或其他框架)?

约束:

  1. 所有2个窗格(顶部和底部)的文档必须相同(旧框架集需要加载两个不同的文档或同一文档两次:我已经使用过这个了但是我想要一个更干净的方法,如果可能的话!)
  2. 分离器(排水沟?)必须可调整大小
  3. 文档的两个不同部分完全同步,因为如果我在顶部(或底部)窗格中修改某些内容(具有contenteditable属性),则底部(或顶部)窗格会立即显示编辑刚刚完成,如MS Word或Excel ...所以,如果我删除任何底部窗格表格单元格中的内容甚至顶部内容相应调整(甚至列大小),如MS Word,Excel,Calc等所发生的那样。
  4. 点击特定按钮
  5. 将打开和关闭拆分视图
  6. 我不关心旧浏览器,只关注ECMA脚本2015或更新的浏览器
  7. HTML文件有许多事件监听器附加addEventListener()方法到各种HTML元素,如按钮,文本框,复选框,选择框等:这意味着应答解决方案必须能够保留它们完整并在两个窗格中工作
  8. 我将在哪里使用它?

    我在本地HTML文件(不涉及Web服务器)中有一堆表,它们从csv文件或浏览器会话存储器加载数据,我经常需要比较来自不同点的数据或保持标头固定在滚动特定表格的其余部分或在插入新数据或更新其中一个数据的同时连续查看我在哪个表格单元格中插入或更新数据时。

    情况:

    目前我正在使用以下代码:

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

    上面的函数将当前窗口窗格水平分割为两个帧,称为upFrame和dwFrame(这是两个变量)。拆分后,可调整大小的排水沟放置在两个框架之间。

    另外算法同步文档数据的两个实例:它通过在一帧中的每个数据编辑中将数据保存到该帧的会话存储中并将相同的数据重新加载到另一帧中。 / p>

    它有点工作,但框架不是要走的路,我想摆脱两次加载文档的需要,并同步每个实例所涉及的所有相对缺点。所以不幸的是,这并不是我寻找的最终答案,因为它有一些缺点:

    1. 现代HTML5兼容文件不支持框架和框架集标记,即使浏览器仍然支持它们
    2. 文件必须加载两次(每帧一次),这意味着明显缺乏性能,并且难以实时同步一帧中与另一帧的任何编辑(可能需要双向同步,因此编辑可以在两者都显示了文件的一部分)。不幸的是,即使是同步过程也意味着失去了在每个同步循环中锁定UI的性能
    3. 同步过程不是实时的,它有一些延迟(几秒钟):如果我把它缩短,我的表现很大,包括浏览器冻结
    4. 因此,我可以通过更清晰,更有效的解决方案获得更好的答案。 (我甚至建议Chrome开发人员在浏览器中实现它的功能,因为我真的认为这是一个必备功能,特别是考虑到不断扩展的在线数据管理系统。)

      我正在寻找:

      上面使用的代码我已经不是强制性的了:答案也可以提出完全不同的方法。

      所以我正在寻找的最终解决方案是类似于Google电子表格使用的分割功能(如果可以,我希望我们也可以),这里是一个带有示例的图像

      enter image description here

      仔细观察它:有可能水平移动的排水沟(也有垂直的排水沟,但我不太关心垂直分割,只是水平),当电子表格向下滚动行时消失在它下面:实际上排水沟上方的第一排是n。 1排水沟的第一排是n。 45。

      还要注意图片最左边的大红色箭头指示的小双头白色箭头。

      我尝试研究Google电子表格方法对其进行逆向工程,并提取显着特征,并采用相同的&#34;哲学&#34;在我当地的申请表中,但我还不够理解他们的确切做法:我的怀疑是,当一排表排在排水沟上时#34;只是隐藏在它背后,但我不确定。

      恕我直言,这是一个功能,每个浏览器(甚至是便携式设备的浏览器)都必须本机实现,而不使用html 5中不再支持的旧技术。不幸的是,这种可能性将它分开文档显示和编辑它的不同部分(例如,作为一个很长的表)保持每个窗格相互更新,不是(还)一个浏览器功能,所以同时...它是需要的解决方法。

      注意:

      CSS属性

      position: sticky;
      

      也可用于解决部分问题(在编辑或将数据插入到tbody时保持thead卡住),但不幸的是,它似乎并没有按照预期在thead元素上工作,至少在一些浏览器。它也解决了问题的一部分:事实上,如果需要将同一个表或不同表的不同部分的数据与同一个文档进行比较,这个解决方案根本不是很好。所以还需要别的东西。

4 个答案:

答案 0 :(得分:3)

只是好奇,如果你的计算机上有本地文件,为什么你试图在浏览器中编辑csv文件中的表数据,而不是仅使用上面提到的Excel程序的本机功能?或者,如果你想在浏览器中这样做,google工作表是否允许拆分屏幕?没有不尊重我只是不明白为什么不使用专门为这类工作而优化的程序。

如果你想继续使用框架,你应该能够将文件加载到一个框架中,只需将innerHTML从一个框架复制到另一个框架,如下所示。如果您正在使用会话存储,虽然它应该(?)更快地保存对该文件和csv文件的编辑,但是从会话存储而不是文件加载。

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

您可以使用DIV作为容器,而不是使用框架,按照您的建议加载到本地存储中,并从那里填充DIV。保存将转到csv文件和本地存储,如帧解决方案。 Javascript可以跟踪滚动顶部,因此一旦从本地存储重新加载,您可以将这两个部分“弹出”到它们所在的行。

更快的解决方案可能是将csv数据保存在内存(数组)中并保存到csv但是从内存更新比理论上的文件快得多:)

答案 1 :(得分:2)

可能有比我提出的黑客更好的解决方案,但让我们试一试。

如果您想要获取整个页面并将其拆分,您可以使用框架集解决方案,但不是让浏览器加载资源两次,您只需复制其HTML并将其写入框架:

<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>

您需要注意在页面内执行的javascript代码。正如您所看到的,我还必须检查页面是否已经在一个框架内,否则它将永久地将框架集附加到文档中(或者至少在浏览器阻止它之前)。

答案 2 :(得分:2)

我认为你可以通过div实现这一点。

首先创建两个div来保存上下视图。

然后将主要内容克隆到每个div。

通过调整每个div的尺寸和位置,您可以将一个div的视图分成两部分

您也可以创建重新调整大小的脚本来管理每个视图div的高度

用于跨多个视图的级联操作。您可以使用上部视图上的事件在下部视图上进行更改。 并在较低的视图上进行上部视图的更改。

终于对不好的解释感到抱歉。

我让jsfiddle解释方法

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

答案 3 :(得分:0)

我只会部分解决你的问题,因为我没有完整的解决方案。

  

现代HTML5兼容文件不支持框架和框架集标记,即使浏览器仍然支持它们

已弃用框架以支持iframe。这应该表现得非常相似。

为了保证两个窗格之间的同步与您已经设置的约束,您将不得不编写自定义JS,特别是因为您是框架/包反对。