|
1 |
| -class PdfHistory { |
2 |
| - constructor() { |
3 |
| - this.locations = []; |
4 |
| - this.current_idx = -1; |
5 |
| - } |
6 |
| - |
7 |
| - add(pre, post) { |
8 |
| - if (this.locations.length == 0) { |
9 |
| - this.locations = [pre, post]; |
10 |
| - this.current_idx = 1; |
11 |
| - return; |
12 |
| - } |
13 |
| - this.locations[this.current_idx] = pre; |
14 |
| - if (this.locations.length === ++this.current_idx) { // there are no forwards |
15 |
| - this.locations.push(post); |
16 |
| - } else { |
17 |
| - this.locations[this.current_idx] = post; |
18 |
| - this.locations.splice(this.current_idx + 1) |
19 |
| - } |
20 |
| - } |
21 |
| - |
22 |
| - back() { |
23 |
| - console.log("Back"); |
24 |
| - if (this.canGoBack()) this.locations[--this.current_idx].scrollIntoView(); |
25 |
| - // console.log(this.locations, this.current_idx); |
26 |
| - } |
27 |
| - |
28 |
| - forward() { |
29 |
| - console.log("Forward", this.locations); |
30 |
| - if (this.canGoForward()) this.locations[++this.current_idx].scrollIntoView(); |
31 |
| - // console.log(this.locations, this.current_idx); |
32 |
| - } |
33 |
| - |
34 |
| - canGoBack() { |
35 |
| - return this.current_idx > 0; |
36 |
| - } |
37 |
| - |
38 |
| - canGoForward() { |
39 |
| - return this.current_idx < this.locations.length - 1; |
40 |
| - } |
41 |
| -} |
42 |
| - |
43 |
| -class pdfLocation { |
44 |
| - constructor(pageNumber, left, top) { |
45 |
| - this.page = pageNumber; |
46 |
| - this.left = left; |
47 |
| - this.top = top; |
48 |
| - } |
49 |
| - |
50 |
| - scrollIntoView() { |
51 |
| - top?.window.lsPdfViewer.scrollPageIntoView({ |
52 |
| - pageNumber: this.page, |
53 |
| - destArray: [null, { name: "XYZ" }, |
54 |
| - this.left, this.top] |
55 |
| - }); |
56 |
| - } |
57 |
| -} |
58 |
| - |
59 |
| -function waitForElement(selector) { |
60 |
| - return new Promise(resolve => { |
61 |
| - if (top?.document.querySelector(selector)) { |
62 |
| - return resolve(top?.document.querySelector(selector)); |
63 |
| - } |
64 |
| - |
65 |
| - const observer = new MutationObserver(mutations => { |
66 |
| - if (top?.document.querySelector(selector)) { |
67 |
| - resolve(top?.document.querySelector(selector)); |
68 |
| - observer.disconnect(); |
69 |
| - } |
70 |
| - }); |
71 |
| - |
72 |
| - observer.observe(top?.document.querySelector("div#app-single-container"), { |
73 |
| - childList: true, |
74 |
| - subtree: true |
75 |
| - }); |
76 |
| - }); |
77 |
| -} |
78 |
| - |
79 |
| -function initialize(ele) { |
80 |
| - let pdfHistory = new PdfHistory(); |
81 |
| - |
82 |
| - function callback(e) { |
83 |
| - const ele = e.srcElement; |
84 |
| - if (ele.tagName !== 'A' || ele.className !== "internalLink") |
85 |
| - return; |
86 |
| - const viewer = top?.lsPdfViewer; |
87 |
| - |
88 |
| - /* An example of viewer._location |
89 |
| - { |
90 |
| - "pageNumber": 235, |
91 |
| - "scale": "auto", |
92 |
| - "top": 784, |
93 |
| - "left": 0, |
94 |
| - "rotation": 0, |
95 |
| - "pdfOpenParams": "#page=235&zoom=auto,0,784" |
96 |
| - } */ |
97 |
| - const pre = new pdfLocation(viewer._location.pageNumber, viewer._location.left, viewer._location.top); |
98 |
| - setTimeout(() => { |
99 |
| - // console.log(viewer.scroll) |
100 |
| - const post = new pdfLocation(viewer._location.pageNumber, viewer._location.left, viewer._location.top); |
101 |
| - pdfHistory.add(pre, post); |
102 |
| - }, 100); |
103 |
| - // console.log({ pdfHistory }); |
104 |
| - } |
105 |
| - |
106 |
| - setTimeout(() => { |
107 |
| - const toolbar = top?.document.querySelector(".extensions__pdf-toolbar > div > div.buttons"); |
108 |
| - let bck_btn = top?.document.createElement("a"); |
109 |
| - bck_btn.innerHTML = left_arr; |
110 |
| - let fwd_btn = top?.document.createElement("a"); |
111 |
| - fwd_btn.innerHTML = right_arr; |
112 |
| - bck_btn.onclick = pdfHistory.back.bind(pdfHistory); // fix `this` issue |
113 |
| - fwd_btn.onclick = pdfHistory.forward.bind(pdfHistory); |
114 |
| - fwd_btn.style.margin = "auto"; // center the svg vertically |
115 |
| - bck_btn.style.margin = "auto"; |
116 |
| - bck_btn.style.marginLeft = "4px"; |
117 |
| - fwd_btn.style.padding = "4px"; |
118 |
| - bck_btn.style.padding = "4px"; |
119 |
| - toolbar.insertBefore(fwd_btn, toolbar.children[0]); |
120 |
| - toolbar.insertBefore(bck_btn, toolbar.children[0]); |
121 |
| - top?.document.addEventListener('click', callback, false); |
122 |
| - toolbar.lastElementChild?.addEventListener('click', () => { |
123 |
| - pdfHistory = null; |
124 |
| - top?.document.removeEventListener('click', callback); |
125 |
| - }); |
126 |
| - }, 1500); |
127 |
| -} |
128 |
| - |
129 |
| -async function main() { |
130 |
| - while (true) { |
131 |
| - if (top?.document.querySelector("div.extensions__pdf-viewer") == null) { |
132 |
| - const ele = await waitForElement("div.extensions__pdf-viewer"); |
133 |
| - initialize(ele); |
134 |
| - } |
135 |
| - await new Promise(r => setTimeout(r, 800)); |
136 |
| - } |
137 |
| -} |
138 |
| - |
139 |
| -const left_arr = ` |
140 |
| -<svg stroke="currentColor" fill="none" width="16" class="icon" stroke-width="2" stroke-linejoin="round" viewBox="0 0 24 24" stroke-linecap="round" height="16"> |
141 |
| - <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> |
142 |
| - <line y1="12" x1="5" y2="12" x2="19"></line> |
143 |
| - <line y1="16" x1="9" y2="12" x2="5"></line> |
144 |
| - <line y1="8" x1="9" y2="12" x2="5"></line> |
145 |
| - </svg>`; |
146 |
| - |
147 |
| -const right_arr = ` |
148 |
| - <svg stroke="currentColor" fill="none" width="16" class="icon" stroke-width="2" stroke-linejoin="round" viewBox="0 0 24 24" stroke-linecap="round" height="16"> |
149 |
| - <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> |
150 |
| - <line y1="12" x1="5" y2="12" x2="19"></line> |
151 |
| - <line y1="16" x1="15" y2="12" x2="19"></line> |
152 |
| - <line y1="8" x1="15" y2="12" x2="19"></line> |
153 |
| - </svg>`; |
154 |
| - |
155 |
| -const isDebug = false; |
156 |
| - |
157 |
| -logseq.ready(() => { |
158 |
| - isDebug && logseq.App.showMsg("❤️ logseq-pdf-nav has bean loaded!"); |
159 |
| - main(); |
160 |
| -}).catch(console.error); |
| 1 | +class PdfHistory { |
| 2 | + constructor() { |
| 3 | + this.locations = []; |
| 4 | + this.current_idx = -1; |
| 5 | + } |
| 6 | + |
| 7 | + add(pre, post) { |
| 8 | + if (this.locations.length == 0) { |
| 9 | + this.locations = [pre, post]; |
| 10 | + this.current_idx = 1; |
| 11 | + return; |
| 12 | + } |
| 13 | + this.locations[this.current_idx] = pre; |
| 14 | + if (this.locations.length === ++this.current_idx) { // there are no forwards |
| 15 | + this.locations.push(post); |
| 16 | + } else { |
| 17 | + this.locations[this.current_idx] = post; |
| 18 | + this.locations.splice(this.current_idx + 1) |
| 19 | + } |
| 20 | + } |
| 21 | + |
| 22 | + back() { |
| 23 | + console.log("Back"); |
| 24 | + if (this.canGoBack()) this.locations[--this.current_idx].scrollIntoView(); |
| 25 | + // console.log(this.locations, this.current_idx); |
| 26 | + } |
| 27 | + |
| 28 | + forward() { |
| 29 | + console.log("Forward", this.locations); |
| 30 | + if (this.canGoForward()) this.locations[++this.current_idx].scrollIntoView(); |
| 31 | + // console.log(this.locations, this.current_idx); |
| 32 | + } |
| 33 | + |
| 34 | + canGoBack() { |
| 35 | + return this.current_idx > 0; |
| 36 | + } |
| 37 | + |
| 38 | + canGoForward() { |
| 39 | + return this.current_idx < this.locations.length - 1; |
| 40 | + } |
| 41 | +} |
| 42 | + |
| 43 | +class pdfLocation { |
| 44 | + constructor(pageNumber, left, top) { |
| 45 | + this.page = pageNumber; |
| 46 | + this.left = left; |
| 47 | + this.top = top; |
| 48 | + } |
| 49 | + |
| 50 | + scrollIntoView() { |
| 51 | + const viewer = top?.window.lsActivePdfViewer || top?.window.lsPdfViewer; |
| 52 | + viewer.scrollPageIntoView({ |
| 53 | + pageNumber: this.page, |
| 54 | + destArray: [null, { name: "XYZ" }, |
| 55 | + this.left, this.top] |
| 56 | + }); |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +function waitForElement(selector) { |
| 61 | + return new Promise(resolve => { |
| 62 | + if (top?.document.querySelector(selector)) { |
| 63 | + return resolve(top?.document.querySelector(selector)); |
| 64 | + } |
| 65 | + |
| 66 | + const observer = new MutationObserver(mutations => { |
| 67 | + if (top?.document.querySelector(selector)) { |
| 68 | + resolve(top?.document.querySelector(selector)); |
| 69 | + observer.disconnect(); |
| 70 | + } |
| 71 | + }); |
| 72 | + |
| 73 | + observer.observe(top?.document.querySelector("div#app-single-container"), { |
| 74 | + childList: true, |
| 75 | + subtree: true |
| 76 | + }); |
| 77 | + }); |
| 78 | +} |
| 79 | + |
| 80 | +function initialize(ele) { |
| 81 | + let pdfHistory = new PdfHistory(); |
| 82 | + |
| 83 | + function callback(e) { |
| 84 | + const ele = e.srcElement; |
| 85 | + if (ele.tagName !== 'A' || ele.className !== "internalLink") |
| 86 | + return; |
| 87 | + const viewer = top?.lsActivePdfViewer || top?.lsPdfViewer; |
| 88 | + |
| 89 | + /* An example of viewer._location |
| 90 | + { |
| 91 | + "pageNumber": 235, |
| 92 | + "scale": "auto", |
| 93 | + "top": 784, |
| 94 | + "left": 0, |
| 95 | + "rotation": 0, |
| 96 | + "pdfOpenParams": "#page=235&zoom=auto,0,784" |
| 97 | + } */ |
| 98 | + const pre = new pdfLocation(viewer._location.pageNumber, viewer._location.left, viewer._location.top); |
| 99 | + setTimeout(() => { |
| 100 | + // console.log(viewer.scroll) |
| 101 | + const post = new pdfLocation(viewer._location.pageNumber, viewer._location.left, viewer._location.top); |
| 102 | + pdfHistory.add(pre, post); |
| 103 | + }, 100); |
| 104 | + // console.log({ pdfHistory }); |
| 105 | + } |
| 106 | + |
| 107 | + setTimeout(() => { |
| 108 | + const toolbar = top?.document.querySelector(".extensions__pdf-toolbar > div > div.buttons"); |
| 109 | + let bck_btn = top?.document.createElement("a"); |
| 110 | + bck_btn.innerHTML = left_arr; |
| 111 | + let fwd_btn = top?.document.createElement("a"); |
| 112 | + fwd_btn.innerHTML = right_arr; |
| 113 | + bck_btn.onclick = pdfHistory.back.bind(pdfHistory); // fix `this` issue |
| 114 | + fwd_btn.onclick = pdfHistory.forward.bind(pdfHistory); |
| 115 | + fwd_btn.style.margin = "auto"; // center the svg vertically |
| 116 | + bck_btn.style.margin = "auto"; |
| 117 | + bck_btn.style.marginLeft = "4px"; |
| 118 | + fwd_btn.style.padding = "4px"; |
| 119 | + bck_btn.style.padding = "4px"; |
| 120 | + toolbar.insertBefore(fwd_btn, toolbar.children[0]); |
| 121 | + toolbar.insertBefore(bck_btn, toolbar.children[0]); |
| 122 | + top?.document.addEventListener('click', callback, false); |
| 123 | + toolbar.lastElementChild?.addEventListener('click', () => { |
| 124 | + pdfHistory = null; |
| 125 | + top?.document.removeEventListener('click', callback); |
| 126 | + }); |
| 127 | + }, 1500); |
| 128 | +} |
| 129 | + |
| 130 | +async function main() { |
| 131 | + while (true) { |
| 132 | + if (top?.document.querySelector("div.extensions__pdf-viewer") == null) { |
| 133 | + const ele = await waitForElement("div.extensions__pdf-viewer"); |
| 134 | + initialize(ele); |
| 135 | + } |
| 136 | + await new Promise(r => setTimeout(r, 800)); |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +const left_arr = ` |
| 141 | +<svg stroke="currentColor" fill="none" width="16" class="icon" stroke-width="2" stroke-linejoin="round" viewBox="0 0 24 24" stroke-linecap="round" height="16"> |
| 142 | + <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> |
| 143 | + <line y1="12" x1="5" y2="12" x2="19"></line> |
| 144 | + <line y1="16" x1="9" y2="12" x2="5"></line> |
| 145 | + <line y1="8" x1="9" y2="12" x2="5"></line> |
| 146 | + </svg>`; |
| 147 | + |
| 148 | +const right_arr = ` |
| 149 | + <svg stroke="currentColor" fill="none" width="16" class="icon" stroke-width="2" stroke-linejoin="round" viewBox="0 0 24 24" stroke-linecap="round" height="16"> |
| 150 | + <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> |
| 151 | + <line y1="12" x1="5" y2="12" x2="19"></line> |
| 152 | + <line y1="16" x1="15" y2="12" x2="19"></line> |
| 153 | + <line y1="8" x1="15" y2="12" x2="19"></line> |
| 154 | + </svg>`; |
| 155 | + |
| 156 | +const isDebug = false; |
| 157 | + |
| 158 | +logseq.ready(() => { |
| 159 | + isDebug && logseq.App.showMsg("❤️ logseq-pdf-nav has bean loaded!"); |
| 160 | + main(); |
| 161 | +}).catch(console.error); |
0 commit comments