Synchronized Scrolling With Two Different Files?

Forum for the PDF-XChange Editor - Free and Licensed Versions

Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan

Post Reply
shade-cabin-hammock
User
Posts: 328
Joined: Wed Dec 22, 2021 6:33 am

Synchronized Scrolling With Two Different Files?

Post by shade-cabin-hammock »

Hi,

Can I open two different files and have them scroll together?

I know I can set them side by side. Step 1 above, and step 2 below.

But is there any way, once they are set like this, to scroll them together? So that scrolling one scrolls the other?

I got this far in searching online: https://www.pdf-xchange.com/knowle ... nge-Viewer

But, it seemed to apply only to the SAME document? Is there any way to apply this to two DIFERENT documents. So that scrolling the one scrolls the other, too?

sync-scroll.jpg
Sincerely,

SCH
Sincerely,

SCH
User avatar
rakunavi
User
Posts: 871
Joined: Sat Sep 11, 2021 5:04 am

Re: Synchronized Scrolling With Two Different Files?

Post by rakunavi »

Hello SCH,

How about using the JavaScript that benep posted the other day?
At the moment, it doesn't seem to exist as a feature of PDF-XChange Editor itself.

Best regards,
rakunavi
TOP desires for PDFXCE
forum.pdf-xchange.com/viewtopic.php?t=39665 LassoTool
forum.pdf-xchange.com/viewtopic.php?t=38554 CmtGarbled
forum.pdf-xchange.com/viewtopic.php?t=37353 FulScrMultiMon
forum.pdf-xchange.com/viewtopic.php?t=41002 DisableTouchSelect
shade-cabin-hammock
User
Posts: 328
Joined: Wed Dec 22, 2021 6:33 am

Re: Synchronized Scrolling With Two Different Files?

Post by shade-cabin-hammock »

Hi rakunavi,

Wow! Sort of just what the doctor ordered, eh? THANK YOU for pointing this out.

Have you tried it yourself?

Thanks again! : ))))))))))))))))))

SCH
Sincerely,

SCH
User avatar
rakunavi
User
Posts: 871
Joined: Sat Sep 11, 2021 5:04 am

Re: Synchronized Scrolling With Two Different Files?

Post by rakunavi »

Hi SCH,
shade-cabin-hammock wrote: Sun Mar 26, 2023 3:03 am Have you tried it yourself?
Of course.
shade-cabin-hammock wrote: Sun Mar 26, 2023 3:05 am How do we install it?
There are generally two methods of executing JavaScript introduced in this forum, not limited to this script.

Method 1

  • If you want to use the script posted by benep as is, copy it to the clipboard, open the JavaScript Console from the Form tab, paste it and press the Run button.
Method 2

  • Open the following folder with Explorer, etc., and create a new folder with the name "JavaScripts".

    • C:\Users\{user name}\AppData\Roaming\Tracker Software\PDFXEditor\3.0

      (*) You can open the folder "C:\Users\{user name}\AppData\Roaming" by specifying %appdata% in Explorer or in the Start menu.
    Attached below is a script originally created by benep, modified only at the beginning for tool button registration. Save it in the JavaScripts folder created in the above procedure. Once saved, you will be able to run the script from the tool button without having to open the JavaScript console each time.

    Code: Select all

    app.addToolButton({
        cName: "Sync Two Documents",
        cLabel: "Sync Two Documents",
        cExec: "synctwodoc()",
        cTooltext: "Sync Two Documents",
        cEnable: true,
        nPos: -1
    });
    
    function synctwodoc()
    {
      if (!Object.hasOwnProperty.call(global, 'scrollSync')) {
        global.scrollSync = {
    
        activeDocs: {},
        isActive: false,
        doc1: null,
        doc2: null,
        doc1ID: '',
        doc2ID: '',
        state1: '',
        timer: null,
    
        getSelectedEntry: function(lst) {
          for (const key in lst) {
            if (Object.hasOwnProperty.call(lst, key)) {
              const val = +lst[key];
              if ( val >= 0) return {key, val};
            }
          }
        },
    
        checkSync: function() {
          let cnt = 0;
          for (let i = 0; i < app.activeDocs.length; i++) {
            const docIDs = app.activeDocs[i].docID.join('');
            if (docIDs == this.doc1ID || docIDs == this.doc2ID) {
              cnt++;
            }
          }
          if (cnt < 2) {
            global.scrollSync.isActive = false;
            app.clearInterval(global.scrollSync.timer);
            app.alert('Synchronisation of views canceled because of missing document.',1);
          }
        },
    
        doSync: function() {
          global.scrollSync.checkSync();
          try {
            if (global.scrollSync.isActive) {
              const curState = JSON.stringify(global.scrollSync.doc1.viewState);
              if (curState != global.scrollSync.state1) {
                global.scrollSync.state1 = curState;
                global.scrollSync.doc2.viewState = JSON.parse(curState);
              }
            }
          } catch (err) {
            app.clearInterval(global.scrollSync.timer);
            global.scrollSync.isActive = false;
            console.println(JSON.stringify(err));
            app.alert('There was an unexpexted error! See JS-console for more information.');
          }
        },
    
        toggleSyncState: function() {
          const me = global.scrollSync;
          if (me.isActive) {
            me.isActive = false;
            app.clearInterval(me.timer);
            app.alert('Synchronisation canceled.',3);
            return;
          }
          if (app.activeDocs.length < 2) {
            app.alert('There need to be at least two opened documents.',1);
          } else {
            const dialog = {
              initialize: function(dlg) {
                const lst1 = {}, lst2 = {};
                me.activeDocs = {};
                for (let i = 0; i < app.activeDocs.length; i++) {
                  const doc = app.activeDocs[i];
                  const key = (i+1) + ' - ' + (doc.documentFileName.length ? doc.documentFileName : 'New Document*');
                  lst1[key] = (i == 0 ? 1 : -1) * (i+1);
                  lst2[key] = (i == 1 ? 1 : -1) * (i+1);
                  me.activeDocs[key] = doc;
                }
                dlg.load({ lst1, lst2 });
              },
              commit: function(dlg) {
                const data = dlg.store();
                const s1 = me.getSelectedEntry(data.lst1);
                const s2 = me.getSelectedEntry(data.lst2);
                me.doc1 = me.activeDocs[s1.key];
                me.doc2 = me.activeDocs[s2.key];
                me.doc1ID = me.activeDocs[s1.key].docID.join('');
                me.doc2ID = me.activeDocs[s2.key].docID.join('');
                me.isActive = true;
                me.timer = app.setInterval('global.scrollSync.doSync()', 30);
              },
              validate: function(dlg) {
                const data = dlg.store();
                const s1 = me.getSelectedEntry(data.lst1);
                const s2 = me.getSelectedEntry(data.lst2);
                const id1 = me.activeDocs[s1.key].docID.join('');
                const id2 = me.activeDocs[s2.key].docID.join('');
                if (s1.val == s2.val || id1 == id2 ) {
                  app.alert('Choose different files.',1);
                  return false;
                }
                return true;
              },
              description: { name: 'Sync views', align_children: 'align_left', elements: [
                { type: 'static_text', name: 'Choose which documents shall be synced:' },
                { type: 'cluster', name: 'Doc 1 (parent)', align_children: 'align_left', elements: [
                  { type: 'popup', item_id: 'lst1', width: 200 }
                ]},
                { type: 'cluster', name: 'Doc 2 (child)', align_children: 'align_left', elements: [
                  { type: 'popup', item_id: 'lst2', width: 200 }
                ]},
                { type: 'ok_cancel', ok_name: 'sync', cancel_name: 'cancel' }
              ]}
            }
    
            if (app.execDialog(dialog) != 'ok' && me.isActive) {
              me.isActive = false;
              app.clearInterval(me.timer);
              app.alert('Synchronisation canceled.',3);
            }
    
          }
        }
    
        };
      } else {
        if (typeof global.scrollSync.toggleSyncState == 'function') {
          global.scrollSync.toggleSyncState();
        } else {
          app.alert('There already is another scrollSync object without the toggle function!');
        }
      }
    }
    
The first and second halves of the attached verification video test each of these methods. As Stefan commented, the first time you run the script, you need to press the Run button or the Tool button twice.

Tracker Supp-Stefan wrote: Mon Mar 06, 2023 9:26 am I had to run it two times initially to get the dialogue to appear
Please also refer to the following knowledgebase for information on how to use JavaScript with PDF-XChange Editor.

Best regards,
rakunavi
TOP desires for PDFXCE
forum.pdf-xchange.com/viewtopic.php?t=39665 LassoTool
forum.pdf-xchange.com/viewtopic.php?t=38554 CmtGarbled
forum.pdf-xchange.com/viewtopic.php?t=37353 FulScrMultiMon
forum.pdf-xchange.com/viewtopic.php?t=41002 DisableTouchSelect
User avatar
TrackerSupp-Daniel
Site Admin
Posts: 8436
Joined: Wed Jan 03, 2018 6:52 pm

Re: Synchronized Scrolling With Two Different Files?

Post by TrackerSupp-Daniel »

Hello, rakunavi

Thank you for sharing this here, While we do indeed not offer a feature to accomplish this, seeing users like yourself getting creative with the Javascripting capabilities to achieve the desired goal is very nice to see!

Kind regards,
Dan McIntyre - Support Technician
Tracker Software Products (Canada) LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Post Reply