mirror of
https://github.com/kiwix/kiwix-js.git
synced 2025-09-17 19:26:04 -04:00
parent
c353468a0d
commit
e595a49d70
@ -124,6 +124,18 @@
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.alert-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#alertBoxHeader {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
|
@ -202,7 +202,8 @@
|
||||
<div id="openLocalFiles" style="display: none;">
|
||||
Please select the .zim file (or all the .zimaa, .zimab etc in case of a split ZIM file)<br />
|
||||
<input type="file" id="archiveFiles" multiple class="btn" accept=".zim,.dat,.idx,.txt,.zimaa,.zimab,.zimac,.zimad,.zimae,.zimaf,.zimag,.zimah,.zimai,.zimaj,.zimak,.zimal,.zimam,.ziman,.zimao,.zimap,.zimaq,.zimar,.zimas,.zimat,.zimau,.zimav,.zimaw,.zimax,.zimay,.zimaz,.zimba,.zimbb,.zimbc,.zimbd,.zimbe,.zimbf,.zimbg,.zimbh,.zimbi,.zimbj,.zimbk,.zimbl,.zimbm,.zimbn,.zimbo,.zimbp,.zimbq,.zimbr,.zimbs,.zimbt,.zimbu,.zimbv,.zimbw,.zimbx,.zimby,.zimbz" /><br />
|
||||
<strong>Only Mediawiki-based (wiki*.zim* files, like wikipedia) and StackExchange contents have been tested</strong> for now. Audio/video/dynamic contents are not supported for now.<br />
|
||||
<strong>Only Mediawiki-based (wiki*.zim* files, like wikipedia), StackExchange and some video-based ZIMs (e.g. TEDx) have been tested</strong>.
|
||||
Dynamic content is not currently supported in jQuery mode.<br />
|
||||
</div>
|
||||
<div id="scanningForArchives" style="display: none;">
|
||||
<br /> Scanning for archives... Please wait <img src="img/spinner.gif" alt="Please wait..." />
|
||||
@ -216,6 +217,22 @@
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<h3>Display settings</h3>
|
||||
<div class="column">
|
||||
<div class="panel panel-info" id="displaySettingsDiv">
|
||||
<div class="panel-heading">Display options:</div>
|
||||
<div class="panel-body">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="hideActiveContentWarning" id="hideActiveContentWarningCheck">
|
||||
<strong>Permanently hide active content warning</strong> (for experienced users)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Expert settings</h3>
|
||||
<div class="column">
|
||||
@ -236,7 +253,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-info" id="apiStatusDiv">
|
||||
<div class="panel panel-warning" id="apiStatusDiv">
|
||||
<div class="panel-heading">API Status</div>
|
||||
<div class="panel-body">
|
||||
<div id="serviceWorkerStatus"></div>
|
||||
@ -261,6 +278,8 @@
|
||||
<div id="articleList" class="list-group">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Bootstrap alert box -->
|
||||
<div id="alertBoxHeader"></div>
|
||||
<iframe id="articleContent" class="articleIFrame" src="article.html"></iframe>
|
||||
</article>
|
||||
<footer>
|
||||
|
@ -49,6 +49,18 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
*/
|
||||
var selectedArchive = null;
|
||||
|
||||
/**
|
||||
* A global parameter object for storing variables that need to be remembered between page loads
|
||||
* or across different functions
|
||||
*
|
||||
* @type Object
|
||||
*/
|
||||
var params = {};
|
||||
|
||||
// Set parameters and associated UI elements from cookie
|
||||
params['hideActiveContentWarning'] = cookies.getItem('hideActiveContentWarning') === 'true';
|
||||
document.getElementById('hideActiveContentWarningCheck').checked = params.hideActiveContentWarning;
|
||||
|
||||
/**
|
||||
* Resize the IFrame height, so that it fills the whole available height in the window
|
||||
*/
|
||||
@ -159,6 +171,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
$('#articleListWithHeader').hide();
|
||||
$("#searchingArticles").hide();
|
||||
$('#articleContent').hide();
|
||||
$('.alert').hide();
|
||||
refreshAPIStatus();
|
||||
return false;
|
||||
});
|
||||
@ -178,22 +191,31 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
$('#articleListWithHeader').hide();
|
||||
$("#searchingArticles").hide();
|
||||
$('#articleContent').hide();
|
||||
$('.alert').hide();
|
||||
return false;
|
||||
});
|
||||
$('input:radio[name=contentInjectionMode]').on('change', function(e) {
|
||||
// Do the necessary to enable or disable the Service Worker
|
||||
setContentInjectionMode(this.value);
|
||||
});
|
||||
|
||||
$('input:checkbox[name=hideActiveContentWarning]').on('change', function (e) {
|
||||
params.hideActiveContentWarning = this.checked ? true : false;
|
||||
cookies.setItem('hideActiveContentWarning', params.hideActiveContentWarning, Infinity);
|
||||
});
|
||||
|
||||
/**
|
||||
* Displays of refreshes the API status shown to the user
|
||||
*/
|
||||
function refreshAPIStatus() {
|
||||
var apiStatusPanel = document.getElementById('apiStatusDiv');
|
||||
apiStatusPanel.classList.remove('panel-success', 'panel-warning');
|
||||
var apiPanelClass = 'panel-success';
|
||||
if (isMessageChannelAvailable()) {
|
||||
$('#messageChannelStatus').html("MessageChannel API available");
|
||||
$('#messageChannelStatus').removeClass("apiAvailable apiUnavailable")
|
||||
.addClass("apiAvailable");
|
||||
} else {
|
||||
apiPanelClass = 'panel-warning';
|
||||
$('#messageChannelStatus').html("MessageChannel API unavailable");
|
||||
$('#messageChannelStatus').removeClass("apiAvailable apiUnavailable")
|
||||
.addClass("apiUnavailable");
|
||||
@ -204,15 +226,19 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
$('#serviceWorkerStatus').removeClass("apiAvailable apiUnavailable")
|
||||
.addClass("apiAvailable");
|
||||
} else {
|
||||
apiPanelClass = 'panel-warning';
|
||||
$('#serviceWorkerStatus').html("ServiceWorker API available, but not registered");
|
||||
$('#serviceWorkerStatus').removeClass("apiAvailable apiUnavailable")
|
||||
.addClass("apiUnavailable");
|
||||
}
|
||||
} else {
|
||||
apiPanelClass = 'panel-warning';
|
||||
$('#serviceWorkerStatus').html("ServiceWorker API unavailable");
|
||||
$('#serviceWorkerStatus').removeClass("apiAvailable apiUnavailable")
|
||||
.addClass("apiUnavailable");
|
||||
}
|
||||
apiStatusPanel.classList.add(apiPanelClass);
|
||||
|
||||
}
|
||||
|
||||
var contentInjectionMode;
|
||||
@ -640,6 +666,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
*/
|
||||
function searchDirEntriesFromPrefix(prefix) {
|
||||
if (selectedArchive !== null && selectedArchive.isReady()) {
|
||||
$('#activeContent').alert('close');
|
||||
selectedArchive.findDirEntriesWithPrefix(prefix.trim(), MAX_SEARCH_RESULT_SIZE, populateListOfArticles);
|
||||
} else {
|
||||
$('#searchingArticles').hide();
|
||||
@ -713,12 +740,11 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
$("#searchingArticles").show();
|
||||
if (dirEntry.isRedirect()) {
|
||||
selectedArchive.resolveRedirect(dirEntry, readArticle);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
params.isLandingPage = false;
|
||||
readArticle(dirEntry);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
alert("Data files not set");
|
||||
}
|
||||
}
|
||||
@ -823,6 +849,13 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
// remove any relative or absolute path from ZIM-style URLs.
|
||||
// DEV: If you want to support more namespaces, add them to the END of the character set [-IJ] (not to the beginning)
|
||||
var regexpTagsWithZimUrl = /(<(?:img|script|link|video|audio|source|track)\b[^>]*?\s)(?:src|href)(\s*=\s*["'])(?:\.\.\/|\/)+(?=[-IJ]\/)/ig;
|
||||
// Regex below tests the html of an article for active content [kiwix-js #466]
|
||||
// It inspects every <script> block in the html and matches in the following cases: 1) the script loads a UI application called app.js;
|
||||
// 2) the script block has inline content that does not contain "importScript()" or "toggleOpenSection" (these strings are used widely
|
||||
// in our fully supported wikimedia ZIMs, so they are excluded); 3) the script block is not of type "math" (these are MathJax markup
|
||||
// scripts used extensively in Stackexchange ZIMs). Note that the regex will match ReactJS <script type="text/html"> markup, which is
|
||||
// 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;
|
||||
|
||||
// Cache for CSS styles contained in ZIM.
|
||||
// It significantly speeds up subsequent page display. See kiwix-js issue #335
|
||||
@ -836,6 +869,11 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
* @param {String} htmlArticle
|
||||
*/
|
||||
function displayArticleContentInIframe(dirEntry, htmlArticle) {
|
||||
// Display Bootstrap warning alert if the landing page contains active content
|
||||
if (!params.hideActiveContentWarning && params.isLandingPage) {
|
||||
if (regexpActiveContent.test(htmlArticle)) uiUtil.displayActiveContentWarning();
|
||||
}
|
||||
|
||||
// Replaces ZIM-style URLs of img, script, link and media tags with a data-kiwixurl to prevent 404 errors [kiwix-js #272 #376]
|
||||
// This replacement also processes the URL to remove the path so that the URL is ready for subsequent jQuery functions
|
||||
htmlArticle = htmlArticle.replace(regexpTagsWithZimUrl, '$1data-kiwixurl$2');
|
||||
@ -1132,6 +1170,8 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
$("#searchingArticles").hide();
|
||||
alert("Article with title " + title + " not found in the archive");
|
||||
} else {
|
||||
params.isLandingPage = false;
|
||||
$('#activeContent').alert('close');
|
||||
readArticle(dirEntry);
|
||||
}
|
||||
}).fail(function(e) { alert("Error reading article with title " + title + " : " + e); });
|
||||
@ -1145,6 +1185,8 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
alert("Error finding random article.");
|
||||
} else {
|
||||
if (dirEntry.namespace === 'A') {
|
||||
params.isLandingPage = false;
|
||||
$('#activeContent').alert('close');
|
||||
readArticle(dirEntry);
|
||||
} else {
|
||||
// If the random title search did not end up on an article,
|
||||
@ -1164,6 +1206,7 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies','abstractFiles
|
||||
$("#welcomeText").show();
|
||||
} else {
|
||||
if (dirEntry.namespace === 'A') {
|
||||
params.isLandingPage = true;
|
||||
readArticle(dirEntry);
|
||||
} else {
|
||||
console.error("The main page of this archive does not seem to be an article");
|
||||
|
@ -84,12 +84,48 @@ define([], function() {
|
||||
return url.replace(regexpRemoveUrlParameters, "$1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a Bootstrap warning alert with information about how to access content in a ZIM with unsupported active UI
|
||||
*/
|
||||
function displayActiveContentWarning() {
|
||||
// We have to add the alert box in code, because Bootstrap removes it completely from the DOM when the user dismisses it
|
||||
var alertHTML =
|
||||
'<div id="activeContent" class="alert alert-warning alert-dismissible fade in">' +
|
||||
'<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>' +
|
||||
'<strong>Unable to display active content:</strong> This ZIM is not fully supported in jQuery mode.<br />' +
|
||||
'Content may be available by searching above (type a space or a letter of the alphabet), or else ' +
|
||||
'<a id="swModeLink" href="#contentInjectionModeDiv" class="alert-link">switch to Service Worker mode</a> ' +
|
||||
'if your platform supports it. [<a id="stop" href="#displaySettingsDiv" class="alert-link">Permanently hide</a>]' +
|
||||
'</div>';
|
||||
document.getElementById('alertBoxHeader').innerHTML = alertHTML;
|
||||
['swModeLink', 'stop'].forEach(function(id) {
|
||||
// Define event listeners for both hyperlinks in alert box: these take the user to the Config tab and highlight
|
||||
// the options that the user needs to select
|
||||
document.getElementById(id).addEventListener('click', function () {
|
||||
var elementID = id === 'stop' ? 'hideActiveContentWarningCheck' : 'serviceworkerModeRadio';
|
||||
var thisLabel = document.getElementById(elementID).parentNode;
|
||||
thisLabel.style.borderColor = 'red';
|
||||
thisLabel.style.borderStyle = 'solid';
|
||||
var btnHome = document.getElementById('btnHome');
|
||||
[thisLabel, btnHome].forEach(function (ele) {
|
||||
// Define event listeners to cancel the highlighting both on the highlighted element and on the Home tab
|
||||
ele.addEventListener('mousedown', function () {
|
||||
thisLabel.style.borderColor = '';
|
||||
thisLabel.style.borderStyle = '';
|
||||
});
|
||||
});
|
||||
document.getElementById('btnConfigure').click();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
return {
|
||||
feedNodeWithBlob: feedNodeWithBlob,
|
||||
replaceCSSLinkWithInlineCSS: replaceCSSLinkWithInlineCSS,
|
||||
removeUrlParameters: removeUrlParameters
|
||||
removeUrlParameters: removeUrlParameters,
|
||||
displayActiveContentWarning: displayActiveContentWarning
|
||||
};
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user