How to autoscroll when PDF content select

WebViewer Version:

Do you have an issue with a specific file(s)?
Can you reproduce using one of our samples or online demos?
Are you using the WebViewer server?
Does the issue only happen on certain browsers?
Is your issue related to a front-end framework?
Is your issue related to annotations?

Please give a brief summary of your issue:
(Think of this as an email subject)

Please describe your issue and provide steps to reproduce it:
(The more descriptive your answer, the faster we are able to help you)

Please provide a link to a minimal sample where the issue is reproducible:

We want to add one enhance is called when you select the content from PDF using mouse and its not automatically moving to the next page,

Hello, I’m Ron, an automated tech support bot :robot:

While you wait for one of our customer support representatives to get back to you, please check out some of these documentation pages:

Guides:APIs:Forums:

Any update?.
This is big blocker for us.

Hello,

Thank you for contacting us about WebViewer. Can I clarify exactly what you are trying to do? You said you wanted to

add one enhance is called when you select the content from PDF using mouse and its not automatically moving to the next page,

​It sounds like you want WebViewer to automatically scroll the document pages when the cursor is near the top or bottom of the page when selecting text (I’m assuming you mean text when you said “content”). Is that correct or did you want another behaviour?

Best Regards,

Andrew Yip
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

Hello,

Yes. You right. When i say content means text in the PDF page.

When i am selecting the text in the PDF using mouse and when it will come to bottom of the page it is not moving to the next page.

Any updates?.

We struck here.

Pdftron we are using in ReactJs code.

Hello,

We don’t currently have this feature built in ( it’s something that is in our backlog, but we don’t have a timeline for when it’ll be added). However you can add it by doing the following

Webviewer({}, document.getElementById('viewer')).then(async (instance) => {
  const { docViewer, Tools } = instance;
 
  const origSelect = Tools.TextTool.prototype.mouseMove;
  
  Tools.TextTool._moveDeltaCoor = {x: 0, y: 0}; // setting default values
  Tools.TextTool.prototype.mouseMove = function () {
    //run the original function
    origSelect.apply(this, arguments);

    if (!this['pageCoordinates'][1]) {
      return
    } 

    //this['pageCoordinates'][0] is the starting moust location 
    //this['pageCoordinates'][1] is the current mouse location
    const pageCoordinates = this['pageCoordinates'][1];

    //need to get a "delta" to track the direction the mouse is moving
    const moveDeltaX = pageCoordinates['x'] - this._moveDeltaCoor.x;
    const moveDeltaY = pageCoordinates['y'] - this._moveDeltaCoor.y;
    this._moveDeltaCoor.x = pageCoordinates['x'];
    this._moveDeltaCoor.y = pageCoordinates['y'];

    //get the mouse location on the window
    const currentMouseLocation = docViewer.getDisplayModeManager().pageToWindow({ x: pageCoordinates['x'], y: pageCoordinates['y'] }, pageCoordinates['pageNumber']);
    const currentX = currentMouseLocation.x;
    const currentY = currentMouseLocation.y;

    const zoomLevel = docViewer.getZoomLevel();
    //how close to the edge of the page before it start scrolling, can adjust this with zoom leve as needed
    const edgeBuffer = 100;
    //want to move faster when zoomed in, you can adjust this as needed
    const speed = 15 * zoomLevel;

    const headerOffset = docViewer.getScrollViewElement().offsetTop;
    const viewTopOffset = docViewer.getScrollViewElement().scrollTop + headerOffset + edgeBuffer;
    const viewBottomOffset = viewTopOffset + docViewer.getScrollViewElement().parentElement.scrollHeight - edgeBuffer * 2;
    const viewLeftOffset = docViewer.getScrollViewElement().scrollLeft + edgeBuffer;
    const viewRightOffset = docViewer.getScrollViewElement().scrollLeft + docViewer.getScrollViewElement().parentElement.scrollWidth - edgeBuffer;

    //update scroll position if mouse is within the "buffer"
    if (moveDeltaY < 0 && currentY < viewTopOffset) {
      docViewer.getScrollViewElement().scrollTop -= speed;
    }
    if (moveDeltaY > 0 && currentY > viewBottomOffset) {
      docViewer.getScrollViewElement().scrollTop += speed;
    }
    if (moveDeltaX < 0 && currenX < viewLeftOffset) {
      docViewer.getScrollViewElement().scrollLeft -= speed;
    }
    if (moveDeltaX > 0 && currenX > viewRightOffset) {
      docViewer.getScrollViewElement().scrollLeft += speed;
    }
  }
});

Feel free to let us know if you want me to clarify something about the code above.

Best Regards,

Andrew Yip
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

Thank a lot for your reply.

Pdftron:8.1.0

We are not find _moveDeltaCoor inside Core/ documentViewer.

What values we need to pass for arguments

OrigSelect.apply(this, arguments).

const currentMouseLocation = docViewer.getDisplayModeManager().pageToWindow({ x: pageCoordinates['x'], y: pageCoordinates['y'] }, pageCoordinates['pageNumber']); --> pageToWindow method also not there inside docViewer.getDisplayModeManager()

Is this problem with versions ?.

This is s bigger blocker for us.

@Andrew_Yip : Waiting for your reply.

Hi,

Sorry for the confusion, I wrote the previous code using a development setup and didn’t test it using our production build. Try the following sample instead (I’ll add comments for the changes made, comments describing how it works can be found be in the previous sample above)

  const { docViewer } = instance;
   // instead of using "Tools.TextTool.prototype", use the "getToolModeMap().TextSelect" instead 
  const textSelectTool = instance.docViewer.getToolModeMap().TextSelect;
  const origSelect = textSelectTool.mouseMove;
  
  // "_moveDeltaCoor" should now work, you can also do something like
  // let moveDeltaCoorX = 0; let moveDeltaCoorY = 0; 
  // and store the values in variables instead of on the "textSelectTool" object
  textSelectTool._moveDeltaCoor = {x: 0, y: 0};
  textSelectTool.mouseMove = function () {
    origSelect.apply(this, arguments);
  
    if (!this['pageCoordinates'][1]) {
      return
    } 
  
    const pageCoordinates = this['pageCoordinates'][1];
  
    const moveDeltaX = pageCoordinates['x'] - this._moveDeltaCoor.x;
    const moveDeltaY = pageCoordinates['y'] - this._moveDeltaCoor.y;
    this._moveDeltaCoor.x = pageCoordinates['x'];
    this._moveDeltaCoor.y = pageCoordinates['y'];
  
    // need to call "getDisplayMode()" before "pageToWindow"
    const currentMouseLocation =  docViewer.getDisplayModeManager().getDisplayMode().pageToWindow({ x: pageCoordinates['x'], y: pageCoordinates['y'] }, pageCoordinates['pageNumber']);
    
    const currentX = currentMouseLocation.x;
    const currentY = currentMouseLocation.y;
  
    // use "getZoom" instead of "getZoomLevel", "getZoomLevel" was added  in version 8.3
    const zoomLevel = docViewer.getZoom();
    const edgeBuffer = 100;
    const speed = 15 * zoomLevel;
  
    const headerOffset = docViewer.getScrollViewElement().offsetTop;
    const viewTopOffset = docViewer.getScrollViewElement().scrollTop + headerOffset + edgeBuffer;
    const viewBottomOffset = viewTopOffset + docViewer.getScrollViewElement().parentElement.scrollHeight - edgeBuffer * 2;
    const viewLeftOffset = docViewer.getScrollViewElement().scrollLeft + edgeBuffer;
    const viewRightOffset = docViewer.getScrollViewElement().scrollLeft + docViewer.getScrollViewElement().parentElement.scrollWidth - edgeBuffer;
  
    if (moveDeltaY < 0 && currentY < viewTopOffset) {
      docViewer.getScrollViewElement().scrollTop -= speed;
    }
    if (moveDeltaY > 0 && currentY > viewBottomOffset) {
      docViewer.getScrollViewElement().scrollTop += speed;
    }
    // should be "currentX" instead of "currenX", I had a typo when cleaning up the code before
    if (moveDeltaX < 0 && currentX < viewLeftOffset) {
      docViewer.getScrollViewElement().scrollLeft -= speed;
    }
    if (moveDeltaX > 0 && currentX > viewRightOffset) {
      docViewer.getScrollViewElement().scrollLeft += speed;
    }
  }

The following code should work now. Feel free to let me know if you want me to clarify something. Also we are based in the Pacific Time Zone (UTC 07:00), so we might be able to see your messages till the next day

Best Regards,

Andrew Yip
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

const headerOffset = docViewer.getScrollViewElement().offsetTop. —> offsetTop is not there inside const headerOffset = docViewer.getScrollViewElement()

It’s available in const headerOffset = docViewer.getScrollViewElement().parentElwmwnt.offsetTop

Can you please confirm

Hello,

That is a bit odd, I’m seeing
Screen Shot 2022-08-17 at 11.43.34 AM

Actually depending on the “edgeBuffer” you are using, that code might not be needed. It’s mainly for having scrolling up start before the mouse cursor reaches the header. You can try getting the header some other ways (or even remove that depending on your “edgeBuffer”).

Best Regards,

Andrew Yip
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

Thanks a lot for your help and appreciated for your prompt reply. @Andrew_Yip

Hi,

I’m glad you were able to get this to work. Feel free to let us know if you have other related questions

Best Regards,

Andrew Yip
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

There is small issue we have been notified that if any annotations already enabled then without selecting content paging is little moving.

Can you please help us to handle that scenario.

Hi,

Thank you for pointing this issue out. I think near the start of the mouseMove function, it’s using “this[‘pageCoordinates[1]’]” to check if users are selecting text or not.

  textSelectTool.mouseMove = function () {
    origSelect.apply(this, arguments);
    if (!this['pageCoordinates'][1]) {
      return;
    } 

This doesn’t seem to work in some cases. You should change the above to be

  textSelectTool.mouseMove = function (e) {
    origSelect.apply(this, arguments);
    if (!this['pageCoordinates'][1] || !e.buttons !== 1) {
      return;
    } 

Use the e.buttons to check if the left mouse button is being pressed before trying to scroll. Before I was thinking this['pageCoordinates'][1] would be enough but that doesn’t work when annotations are selected.

Best Regards,

Andrew Yip
Software Developer
PDFTron Systems, Inc.
www.pdftron.com

Thank you for your reply.

Point 1:
!e.buttons !== 1 -->looks like condition is wrong

e.buttons !== 1 or !e.buttons === 1
we can keep any one has a above.

Point 2:
origSelect.apply(this, arguments); -->its throwing sonar warning [ ESLint: Use the rest parameters instead of ‘arguments’.(prefer-rest-params). How handle e and arguments in the functions.]