Guest User

Untitled

a guest
Sep 17th, 2025
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.26 KB | None | 0 0
  1. <div class="pdf-container">
  2. <div class="pdf-controls" id="pdfControls2">
  3. <div class="control-group">
  4. <button id="prevBtn2">Previous</button>
  5. <span class="page-info">
  6. Page <span id="currentPage2">-</span> of <span id="totalPages2">-</span>
  7. </span>
  8. <button id="nextBtn2">Next</button>
  9. </div>
  10. <div class="zoom-controls">
  11. <label for="zoomSelect2" style="font-size: 14px">Zoom:</label>
  12. <select id="zoomSelect2" class="zoom-select">
  13. <option value="0.5">50%</option>
  14. <option value="0.75">75%</option>
  15. <option value="1" selected>100%</option>
  16. <option value="1.25">125%</option>
  17. <option value="1.5">150%</option>
  18. <option value="2">200%</option>
  19. <option value="fit">Fit Width</option>
  20. </select>
  21. </div>
  22. </div>
  23. <div class="pdf-viewer" id="pdfViewer2">
  24. <div class="loading" id="loading2">Loading PDF...</div>
  25. </div>
  26. </div>
  27. <script>
  28. // PDF.js worker setup
  29. pdfjsLib.GlobalWorkerOptions.workerSrc =
  30. "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js";
  31.  
  32. class PDFViewer2 {
  33. constructor(url) {
  34. this.url = url;
  35. this.pdfDoc = null;
  36. this.currentPage = 1;
  37. this.totalPages = 0;
  38. this.scale = 1;
  39. this.container = document.getElementById("pdfViewer2");
  40. this.loading = document.getElementById("loading2");
  41. this.prevBtn = document.getElementById("prevBtn2");
  42. this.nextBtn = document.getElementById("nextBtn2");
  43. this.zoomSelect = document.getElementById("zoomSelect2");
  44. this.pdfControls = document.getElementById("pdfControls2");
  45. this.initializeControls();
  46. this.loadPDF();
  47. }
  48.  
  49. initializeControls() {
  50. this.prevBtn.addEventListener("click", () => this.previousPage());
  51. this.nextBtn.addEventListener("click", () => this.nextPage());
  52. this.zoomSelect.addEventListener("change", (e) =>
  53. this.changeZoom(e.target.value)
  54. );
  55. // Keyboard navigation scoped only when controls are focused
  56. this.pdfControls.addEventListener("keydown", (e) => {
  57. if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
  58. this.previousPage();
  59. e.preventDefault();
  60. } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
  61. this.nextPage();
  62. e.preventDefault();
  63. }
  64. });
  65. // Make pdfControls focusable for keyboard events
  66. this.pdfControls.tabIndex = 0;
  67. }
  68.  
  69. async loadPDF() {
  70. try {
  71. await this.tryDirectLoad();
  72. } catch (error) {
  73. console.error("Direct load failed:", error);
  74. await this.tryWithMultipleProxies();
  75. }
  76. }
  77.  
  78. async tryDirectLoad() {
  79. const loadingTask = pdfjsLib.getDocument({
  80. url: this.url,
  81. withCredentials: false,
  82. disableRange: true,
  83. disableStream: true,
  84. });
  85. this.pdfDoc = await loadingTask.promise;
  86. this.totalPages = this.pdfDoc.numPages;
  87. this.updatePageInfo();
  88. this.updateControls();
  89. await this.renderAllPages();
  90. this.loading.style.display = "none";
  91. }
  92.  
  93. async tryWithMultipleProxies() {
  94. const proxies = [
  95. `https://api.codetabs.com/v1/proxy?quest=${encodeURIComponent(this.url)}`,
  96. `https://cors-proxy.htmldriven.com/?url=${encodeURIComponent(this.url)}`,
  97. ];
  98. for (let i = 0; i < proxies.length; i++) {
  99. try {
  100. console.log(
  101. `Trying proxy ${i + 1}/${proxies.length}: ${proxies[i].split("?")[0]}...`
  102. );
  103. const controller = new AbortController();
  104. const timeoutId = setTimeout(() => controller.abort(), 10000);
  105. const response = await fetch(proxies[i], {
  106. signal: controller.signal,
  107. method: "GET",
  108. headers: { Accept: "application/pdf,*/*" },
  109. });
  110. clearTimeout(timeoutId);
  111. if (!response.ok) {
  112. throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  113. }
  114. const pdfBlob = await response.blob();
  115. if (pdfBlob.type && !pdfBlob.type.includes("pdf")) {
  116. throw new Error(`Received ${pdfBlob.type} instead of PDF`);
  117. }
  118. const pdfArrayBuffer = await pdfBlob.arrayBuffer();
  119. const loadingTask = pdfjsLib.getDocument({
  120. data: pdfArrayBuffer,
  121. disableRange: true,
  122. disableStream: true,
  123. });
  124. this.pdfDoc = await loadingTask.promise;
  125. this.totalPages = this.pdfDoc.numPages;
  126. this.updatePageInfo();
  127. this.updateControls();
  128. await this.renderAllPages();
  129. this.loading.style.display = "none";
  130. console.log(`Successfully loaded PDF using proxy ${i + 1}`);
  131. return;
  132. } catch (proxyError) {
  133. console.error(`Proxy ${i + 1} failed:`, proxyError.message);
  134. if (i === proxies.length - 1) {
  135. this.tryIframeEmbedding();
  136. }
  137. }
  138. }
  139. }
  140.  
  141. tryIframeEmbedding() {
  142. console.log("Attempting iframe embedding as final fallback...");
  143. this.container.innerHTML = `
  144. <div style="text-align: center; padding: 20px; background: #f9f9f9; margin: 20px; border-radius: 4px;">
  145. <p style="margin-bottom: 15px; color: #666;">
  146. <iframe
  147. src="${this.url}"
  148. width="100%"
  149. height="1000px"
  150. style="border: 1px solid #ccc; border-radius: 4px;"
  151. onload="console.log('PDF iframe loaded successfully')"
  152. onerror="console.error('PDF iframe failed to load')">
  153. <p>Your browser does not support iframes.
  154. <a href="${this.url}" target="_blank" style="color: #007bff;">Click here to view the PDF in a new tab</a>
  155. </p>
  156. </iframe>
  157. <p style="margin-top: 15px; font-size: 14px; color: #666;">
  158. <a href="${this.url}" target="_blank" style="color: #007bff; text-decoration: none;">
  159. Open PDF in new tab
  160. </a>
  161. </p>
  162. </div>
  163. `;
  164. this.loading.style.display = "none";
  165. this.pdfControls.style.display = "none";
  166. setTimeout(() => {
  167. const iframe = this.container.querySelector("iframe");
  168. try {
  169. if (iframe.contentWindow) {
  170. console.log("Iframe embedding appears to be working");
  171. }
  172. } catch (e) {
  173. console.warn("PDF server may be blocking iframe embedding");
  174. this.showFinalError();
  175. }
  176. }, 3000);
  177. }
  178.  
  179. showFinalError() {
  180. this.container.innerHTML = `
  181. <div style="text-align: center; padding: 30px; background: #fff3cd; margin: 20px; border-radius: 4px; border: 1px solid #ffeaa7;">
  182. <h3 style="color: #856404; margin-bottom: 20px;">🚫 Unable to Load External PDF</h3>
  183. <p style="color: #856404; margin-bottom: 15px; line-height: 1.6;">
  184. The PDF cannot be loaded due to CORS restrictions and server policies.<br>
  185. This is a security limitation imposed by the PDF hosting server.
  186. </p>
  187. <div style="background: white; padding: 20px; border-radius: 4px; margin: 20px 0; text-align: left;">
  188. <h4 style="color: #495057; margin-bottom: 15px;">✅ Working Solutions:</h4>
  189. <ol style="color: #495057; line-height: 1.8; padding-left: 20px;">
  190. <li><strong>Download and host locally:</strong> Save the PDF to your server</li>
  191. <li><strong>Server-side proxy:</strong> Create a backend endpoint to fetch the PDF</li>
  192. <li><strong>Use PDF.js Express:</strong> Commercial solution with better CORS handling</li>
  193. <li><strong>Google Docs Viewer:</strong> Use iframe with Google's viewer</li>
  194. </ol>
  195. </div>
  196. <div style="margin-top: 20px;">
  197. <a href="${this.url}" target="_blank"
  198. style="display: inline-block; padding: 12px 24px; background: #007bff; color: white;
  199. text-decoration: none; border-radius: 4px; font-weight: 500;">
  200. Open PDF in new tab
  201. </a>
  202. </div>
  203. <p style="margin-top: 20px; font-size: 12px; color: #6c757d;">
  204. PDF URL: ${this.url}
  205. </p>
  206. </div>
  207. `;
  208. }
  209.  
  210. async renderAllPages() {
  211. this.container.innerHTML = "";
  212. for (let pageNum = 1; pageNum <= this.totalPages; pageNum++) {
  213. const pageContainer = document.createElement("div");
  214. pageContainer.className = "page-container";
  215. pageContainer.id = `page2-${pageNum}`;
  216. const canvas = document.createElement("canvas");
  217. canvas.className = "pdf-page";
  218. pageContainer.appendChild(canvas);
  219. this.container.appendChild(pageContainer);
  220. await this.renderPage(pageNum, canvas);
  221. }
  222. }
  223.  
  224. async renderPage(pageNum, canvas) {
  225. try {
  226. const page = await this.pdfDoc.getPage(pageNum);
  227. const viewport = page.getViewport({ scale: this.scale });
  228. canvas.height = viewport.height;
  229. canvas.width = viewport.width;
  230. const renderContext = {
  231. canvasContext: canvas.getContext("2d"),
  232. viewport: viewport,
  233. };
  234. await page.render(renderContext).promise;
  235. } catch (error) {
  236. console.error(`Error rendering page ${pageNum}:`, error);
  237. }
  238. }
  239.  
  240. changeZoom(zoomValue) {
  241. if (zoomValue === "fit") {
  242. const containerWidth = this.container.clientWidth - 40;
  243. this.scale = containerWidth / 612;
  244. } else {
  245. this.scale = parseFloat(zoomValue);
  246. }
  247. this.renderAllPages();
  248. }
  249.  
  250. previousPage() {
  251. if (this.currentPage > 1) {
  252. this.currentPage--;
  253. this.scrollToPage(this.currentPage);
  254. this.updatePageInfo();
  255. this.updateControls();
  256. }
  257. }
  258.  
  259. nextPage() {
  260. if (this.currentPage < this.totalPages) {
  261. this.currentPage++;
  262. this.scrollToPage(this.currentPage);
  263. this.updatePageInfo();
  264. this.updateControls();
  265. }
  266. }
  267.  
  268. scrollToPage(pageNum) {
  269. const pageElement = document.getElementById(`page2-${pageNum}`);
  270. if (pageElement) {
  271. pageElement.scrollIntoView({ behavior: "smooth", block: "start" });
  272. }
  273. }
  274.  
  275. updatePageInfo() {
  276. document.getElementById("currentPage2").textContent = this.currentPage;
  277. document.getElementById("totalPages2").textContent = this.totalPages;
  278. }
  279.  
  280. updateControls() {
  281. this.prevBtn.disabled = this.currentPage <= 1;
  282. this.nextBtn.disabled = this.currentPage >= this.totalPages;
  283. }
  284.  
  285. showError(message) {
  286. this.container.innerHTML = `<div class="error">${message}</div>`;
  287. this.loading.style.display = "none";
  288. }
  289. }
  290.  
  291. // Example instantiation for second PDF viewer - change the URL to your second PDF
  292. const pdfUrl2 = "https://example.com/your-second-pdf.pdf";
  293. const pdfViewer2Instance = new PDFViewer2(pdfUrl2);
  294.  
  295. // Update current page based on scroll position for second viewer
  296. document.getElementById("pdfViewer2").addEventListener("scroll", () => {
  297. const viewer = document.getElementById("pdfViewer2");
  298. const pages = document.querySelectorAll(".page-container");
  299. pages.forEach((page, index) => {
  300. const rect = page.getBoundingClientRect();
  301. const viewerRect = viewer.getBoundingClientRect();
  302. if (rect.top <= viewerRect.top + 100 && rect.bottom >= viewerRect.top + 100) {
  303. const newPage = index + 1;
  304. if (newPage !== pdfViewer2Instance.currentPage) {
  305. document.getElementById("currentPage2").textContent = newPage;
  306. document.getElementById("prevBtn2").disabled = newPage <= 1;
  307. document.getElementById("nextBtn2").disabled = newPage >= pdfViewer2Instance.totalPages;
  308. pdfViewer2Instance.currentPage = newPage; // sync internal state
  309. }
  310. }
  311. });
  312. });
  313. </script>
  314.  
Advertisement
Add Comment
Please, Sign In to add comment