diff options
Diffstat (limited to 'p/scripts')
| -rw-r--r-- | p/scripts/main.js | 88 |
1 files changed, 75 insertions, 13 deletions
diff --git a/p/scripts/main.js b/p/scripts/main.js index d1752624e..1e35c84fa 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -37,6 +37,7 @@ function xmlHttpRequestJson(req) { // <Global context> /* eslint-disable no-var */ var context; +var prevTitle; /* eslint-enable no-var */ (function parseJsonVars() { @@ -155,9 +156,10 @@ function incUnreadsFeed(article, feed_id, nb) { } } - let isCurrentView = false; // Update unread: title - document.title = document.title.replace(/^((?:\([\s0-9]+\) )?)/, function (m, p1) { + let isCurrentView = false; + const currentTitle = prevTitle || document.title; + const newTitle = currentTitle.replace(/^((?:\([\s0-9]+\) )?)/, function (m, p1) { const feed = document.getElementById(feed_id); if (article || (feed && feed.closest('.active'))) { isCurrentView = true; @@ -169,6 +171,11 @@ function incUnreadsFeed(article, feed_id, nb) { return p1; } }); + if (prevTitle) { + prevTitle = newTitle; + } else { + document.title = newTitle; + } return isCurrentView; } @@ -1235,24 +1242,79 @@ function init_stream(stream) { el = ev.target.closest('.item.share > button[data-type="print"]'); if (el) { // Print - const tmp_window = window.open(); - for (let i = 0; i < document.styleSheets.length; i++) { - tmp_window.document.writeln('<link href="' + document.styleSheets[i].href + '" rel="stylesheet" type="text/css" />'); - } + const html = document.documentElement; + const head = document.head.cloneNode(true); + head.querySelectorAll('script').forEach(js => js.remove()); + const flux_content = el.closest('.flux_content'); let content_el = null; if (flux_content) { - content_el = el.closest('.flux_content').querySelector('.content'); + content_el = el.closest('.flux_content').querySelector('.content').cloneNode(true); } if (content_el === null) { - content_el = el.closest('.flux').querySelector('.flux_content .content'); + content_el = el.closest('.flux').querySelector('.flux_content .content').cloneNode(true); } + + content_el.querySelectorAll('a').forEach(link => { + // Avoid leaking the instance URL in PDFs + if (link.href.startsWith(location.origin)) { + link.removeAttribute('href'); + } + }); + + content_el.querySelectorAll('details').forEach(el => el.setAttribute('open', 'open')); + + const articleTitle = content_el.querySelector('.title a').innerText; + prevTitle = document.title; + + // Chrome uses the parent's title to get the PDF save filename + document.title = articleTitle; + + // Firefox uses the iframe's title to get the PDF save filename + // Note: Firefox Mobile saves PDFs with a filename that looks like: `temp[19 random digits].PDF` regardless of title + head.querySelector('title').innerText = articleTitle; + loadLazyImages(content_el); - tmp_window.document.writeln(content_el.innerHTML); - tmp_window.document.close(); - tmp_window.focus(); - tmp_window.print(); - tmp_window.close(); + + const print_frame = document.createElement('iframe'); + print_frame.style.display = 'none'; + print_frame.srcdoc = ` + <!DOCTYPE html> + <html class="${html.getAttribute('class')}"> + <head> + ${head.innerHTML} + </head> + <body> + ${content_el.outerHTML} + </body> + </html> + `; + document.body.prepend(print_frame); + + function afterPrint() { + print_frame.remove(); + document.title = prevTitle; + prevTitle = ''; + + window.removeEventListener('focus', afterPrint); + } + + print_frame.onload = () => { + const tmp_window = print_frame.contentWindow; + + // Needed for Chrome + tmp_window.matchMedia('print').onchange = (e) => { + // UA check is needed to not trigger on Chrome Mobile + if (!e.matches && !navigator.userAgent.includes('Mobi')) { + afterPrint(); + } + }; + tmp_window.print(); + }; + + // Needed for Firefox and Chrome Mobile + window.addEventListener('focus', afterPrint); + return false; } |
