mirror of
https://github.com/kiwix/kiwix-js.git
synced 2025-09-09 15:21:46 -04:00
Closes #439.
This commit is contained in:
parent
d1d5d24e7c
commit
dd0d55b6fd
@ -283,6 +283,8 @@
|
||||
<iframe id="articleContent" class="articleIFrame" src="article.html"></iframe>
|
||||
</article>
|
||||
<footer>
|
||||
<!-- Bootstrap alert box -->
|
||||
<div id="alertBoxFooter"></div>
|
||||
<div id="navigationButtons" class="btn-toolbar">
|
||||
<div class="btn-group btn-group-justified">
|
||||
<a class="btn btn-lg" id="btnHomeBottom" title="Home"><span class="glyphicon glyphicon-home"></span></a>
|
||||
|
@ -78,6 +78,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
// Define behavior of HTML elements
|
||||
$('#searchArticles').on('click', function(e) {
|
||||
$("#welcomeText").hide();
|
||||
$('.alert').hide();
|
||||
$("#searchingArticles").show();
|
||||
pushBrowserHistoryState(null, $('#prefix').val());
|
||||
searchDirEntriesFromPrefix($('#prefix').val());
|
||||
@ -857,6 +858,11 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
// common in unsupported packaged UIs, e.g. PhET ZIMs.
|
||||
var regexpActiveContent = /<script\b(?:(?![^>]+src\b)|(?=[^>]+src\b=["'][^"']+?app\.js))(?!>[^<]+(?:importScript\(\)|toggleOpenSection))(?![^>]+type\s*=\s*["'](?:math\/|[^"']*?math))/i;
|
||||
|
||||
// DEV: The regex below matches ZIM links (anchor hrefs) that should have the html5 "donwnload" attribute added to
|
||||
// the link. This is currently the case for epub and pdf files in Project Gutenberg ZIMs -- add any further types you need
|
||||
// to support to this regex. The "zip" has been added here as an example of how to support further filetypes
|
||||
var regexpDownloadLinks = /^.*?\.epub($|\?)|^.*?\.pdf($|\?)|^.*?\.zip($|\?)/i;
|
||||
|
||||
// Cache for CSS styles contained in ZIM.
|
||||
// It significantly speeds up subsequent page display. See kiwix-js issue #335
|
||||
var cssCache = new Map();
|
||||
@ -890,6 +896,9 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
|
||||
// Tell jQuery we're removing the iframe document: clears jQuery cache and prevents memory leaks [kiwix-js #361]
|
||||
$('#articleContent').contents().remove();
|
||||
|
||||
// Remove from DOM any download alert box that was activated in uiUtil.displayFileDownloadAlert function
|
||||
$('#downloadAlert').alert('close');
|
||||
|
||||
var iframeArticleContent = document.getElementById('articleContent');
|
||||
|
||||
@ -961,12 +970,26 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
// It's an external URL : we should open it in a new tab
|
||||
this.target = "_blank";
|
||||
} else {
|
||||
// It's a link to another article
|
||||
// Add an onclick event to go to this article
|
||||
// It's a link to an article or file in the ZIM
|
||||
var decodedURL = decodeURIComponent(zimUrl);
|
||||
var contentType;
|
||||
var downloadAttrValue;
|
||||
// Some file types need to be downloaded rather than displayed (e.g. *.epub)
|
||||
// The HTML download attribute can be Boolean or a string representing the specified filename for saving the file
|
||||
// For Boolean values, getAttribute can return any of the following: download="" download="download" download="true"
|
||||
// So we need to test hasAttribute first: see https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute
|
||||
// However, we cannot rely on the download attribute having been set, so we also need to test for known download file types
|
||||
var isDownloadableLink = this.hasAttribute('download') || regexpDownloadLinks.test(href);
|
||||
if (isDownloadableLink) {
|
||||
downloadAttrValue = this.getAttribute('download');
|
||||
// Normalize the value to a true Boolean or a filename string or true if there is no download attribute
|
||||
downloadAttrValue = /^(download|true|\s*)$/i.test(downloadAttrValue) || downloadAttrValue || true;
|
||||
contentType = this.getAttribute('type');
|
||||
}
|
||||
// Add an onclick event to extract this article or file from the ZIM
|
||||
// instead of following the link
|
||||
$(this).on('click', function (e) {
|
||||
var decodedURL = decodeURIComponent(zimUrl);
|
||||
goToArticle(decodedURL);
|
||||
goToArticle(decodedURL, downloadAttrValue, contentType);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
@ -1159,16 +1182,24 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
|
||||
|
||||
/**
|
||||
* Replace article content with the one of the given title
|
||||
* @param {String} title
|
||||
* Extracts the content of the given article title, or a downloadable file, from the ZIM
|
||||
*
|
||||
* @param {String} title The path and filename to the article or file to be extracted
|
||||
* @param {Boolean|String} download A Bolean value that will trigger download of title, or the filename that should
|
||||
* be used to save the file in local FS (in HTML5 spec, a string value for the download attribute is optional)
|
||||
* @param {String} contentType The mimetype of the downloadable file, if known
|
||||
*/
|
||||
function goToArticle(title) {
|
||||
function goToArticle(title, download, contentType) {
|
||||
$("#searchingArticles").show();
|
||||
title = uiUtil.removeUrlParameters(title);
|
||||
selectedArchive.getDirEntryByTitle(title).then(function(dirEntry) {
|
||||
if (dirEntry === null || dirEntry === undefined) {
|
||||
$("#searchingArticles").hide();
|
||||
alert("Article with title " + title + " not found in the archive");
|
||||
} else if (download) {
|
||||
selectedArchive.readBinaryFile(dirEntry, function (fileDirEntry, content) {
|
||||
uiUtil.displayFileDownloadAlert(title, download, contentType, content);
|
||||
});
|
||||
} else {
|
||||
params.isLandingPage = false;
|
||||
$('#activeContent').alert('close');
|
||||
|
@ -119,6 +119,62 @@ define([], function() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a Bootstrap alert box at the foot of the page to enable saving the content of the given title to the device's filesystem
|
||||
* and initiates download/save process if this is supported by the OS or Browser
|
||||
*
|
||||
* @param {String} title The path and filename to the file to be extracted
|
||||
* @param {Boolean|String} download A Bolean value that will trigger download of title, or the filename that should
|
||||
* be used to save the file in local FS
|
||||
* @param {String} contentType The mimetype of the downloadable file, if known
|
||||
* @param {Uint8Array} content The binary-format content of the downloadable file
|
||||
*/
|
||||
function displayFileDownloadAlert(title, download, contentType, content) {
|
||||
// We have to create the alert box in code, because Bootstrap removes it completely from the DOM when the user dismisses it
|
||||
document.getElementById('alertBoxFooter').innerHTML =
|
||||
'<div id="downloadAlert" class="alert alert-info alert-dismissible">' +
|
||||
' <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>' +
|
||||
' <span id="alertMessage"></span>' +
|
||||
'</div>';
|
||||
// Download code adapted from https://stackoverflow.com/a/19230668/9727685
|
||||
if (!contentType) {
|
||||
// DEV: Add more contentTypes here for downloadable files
|
||||
if (/\.epub$/.test(title)) contentType = 'application/epub+zip';
|
||||
if (/\.pdf$/.test(title)) contentType = 'application/pdf';
|
||||
if (/\.zip$/.test(title)) contentType = 'application/zip';
|
||||
}
|
||||
// Set default contentType if there has been no match
|
||||
if (!contentType) contentType = 'application/octet-stream';
|
||||
var a = document.createElement('a');
|
||||
var blob = new Blob([content], { 'type': contentType });
|
||||
// If the filename to use for saving has not been specified, construct it from title
|
||||
var filename = download === true ? title.replace(/^.*\/([^\/]+)$/, '$1') : download;
|
||||
// Make filename safe
|
||||
filename = filename.replace(/[\/\\:*?"<>|]/g, '_');
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.target = '_blank';
|
||||
a.type = contentType;
|
||||
a.download = filename;
|
||||
a.classList.add('alert-link');
|
||||
a.innerHTML = filename;
|
||||
var alertMessage = document.getElementById('alertMessage');
|
||||
alertMessage.innerHTML = '<strong>Download</strong> If the download does not start, please tap the following link: ';
|
||||
// We have to add the anchor to a UI element for Firefox to be able to click it programmatically: see https://stackoverflow.com/a/27280611/9727685
|
||||
alertMessage.appendChild(a);
|
||||
try { a.click(); }
|
||||
catch (err) {
|
||||
// If the click fails, user may be able to download by manually clicking the link
|
||||
// But for IE11 we need to force use of the saveBlob method with the onclick event
|
||||
if (window.navigator && window.navigator.msSaveBlob) {
|
||||
a.addEventListener('click', function(e) {
|
||||
window.navigator.msSaveBlob(blob, filename);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
}
|
||||
$("#searchingArticles").hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
@ -126,6 +182,7 @@ define([], function() {
|
||||
feedNodeWithBlob: feedNodeWithBlob,
|
||||
replaceCSSLinkWithInlineCSS: replaceCSSLinkWithInlineCSS,
|
||||
removeUrlParameters: removeUrlParameters,
|
||||
displayActiveContentWarning: displayActiveContentWarning
|
||||
displayActiveContentWarning: displayActiveContentWarning,
|
||||
displayFileDownloadAlert: displayFileDownloadAlert
|
||||
};
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user