Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui_utils getVisibleElement not calculating 'left' correctly. #10348

Closed
ColinT opened this issue Dec 11, 2018 · 4 comments
Closed

ui_utils getVisibleElement not calculating 'left' correctly. #10348

ColinT opened this issue Dec 11, 2018 · 4 comments
Labels

Comments

@ColinT
Copy link

ColinT commented Dec 11, 2018

Occuring on [email protected].

Pages are not rendering due to a posible error in ui_utils.getVisibleElement().

Repro by @jgrant95 https://stackblitz.com/edit/ng2-pdf-viewer-qdfyem


To determine whether a page is visible, ui_utils.js looks for the left border of a page on screen:

currentWidth = element.offsetLeft + element.clientLeft;

and compares it to the right border of the containing scroll element:

let left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;

viewRight <= left || currentWidth >= right) {

However, the calculation of left does not take into account scrollEl.offsetLeft, while currentWidth does include element.offsetLeft. Subsequently, right takes on a value less than what it should be.

So, if element.offsetLeft is higher than scrollEl.clientWidth, the page will not render, even if scrollEl.offsetLeft compensates the position of the container to make the page visible.

I believe the correct formula for left is:
let left = scrollEl.scrollLeft + scrollEl.offsetLeft

@Snuffleupagus
Copy link
Collaborator

Snuffleupagus commented Dec 11, 2018

That line of code hasn't changed, in any meaningful way, for many years and any changes to it however minute could risk regressing the PDF viewer in Firefox. Hence a couple of quick questions:

@Snuffleupagus
Copy link
Collaborator

Snuffleupagus commented Dec 11, 2018

I believe the correct formula for left is:
let left = scrollEl.scrollLeft + scrollEl.offsetLeft

Having tested this very quickly, the above change unfortunately seem to break the getVisibleElements function in the default viewer (i.e. the PDF viewer used in Firefox) in at least some cases:

For example, with the sidebar open and using the "Odd Spread"-mode, try running PDFViewerApplication.pdfViewer._getVisiblePages().views in the console for a few different zoom levels and compare with the current master (using the same settings).
With the suggested change, you'll observe that getVisibleElements is no longer able to correctly compute the visible percentage of pages, leading to the wrong page being considered "most visible" (which will break rendering in subtle ways).

@ColinT
Copy link
Author

ColinT commented Dec 12, 2018

Thanks for the guidance. I was able to reproduce the problem by changing simpleviewer.html to have a similar styling as the one in the previous repro. See css class col-6:

<!-- simpleviewer-edited.html -->
<!DOCTYPE html>
<!--
Copyright 2014 Mozilla Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html dir="ltr" mozdisallowselectionprint>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="google" content="notranslate">
  <title>PDF.js viewer using built components</title>

  <style>
    body {
      background-color: #808080;
      margin: 0;
      padding: 0;
    }
    #viewerContainer {
      overflow: auto;
      position: absolute;
      width: 100%;
      height: 100%;
    }
    .col-6 {
      width: 50% !important;
      float: left;
      position: initial !important;
    }
  </style>

  <link rel="stylesheet" href="../../node_modules/pdfjs-dist/web/pdf_viewer.css">

  <script src="../../node_modules/pdfjs-dist/build/pdf.js"></script>
  <script src="../../node_modules/pdfjs-dist/web/pdf_viewer.js"></script>
</head>

<body tabindex="1">
  <div class="col-6">
    Hello World!
  </div>
  <div id="viewerContainer" class="col-6">
    <div id="viewer" class="pdfViewer"></div>
  </div>

  <script src="simpleviewer.js"></script>
</body>
</html>

The pdf I used was: https://cors-anywhere.herokuapp.com/https://www.ets.org/Media/Tests/GRE/pdf/gre_research_validity_data.pdf

Does this mean this kind of styling is not supported?

@ColinT
Copy link
Author

ColinT commented Dec 18, 2018

I solved this by using a relatively positioned parent to correct for the offsetLeft value:

  <!-- ... -->
  <div class="col-6">
    Hello World!
  </div>
  <div class="col-6" style="position:relative;">
    <div id="viewerContainer">
      <div id="viewer" class="pdfViewer"></div>
    </div>
  </div>
  <!-- ... -->

This makes the getVisibleElement calculation valid since offsetLeft is computed using the closest relatively position parent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants