From 8ee8cb8150515a50e929f48cf586c629c1cd9275 Mon Sep 17 00:00:00 2001
From: Jaifroid
Date: Tue, 31 Oct 2023 23:00:56 +0000
Subject: [PATCH 1/4] Slide away UI elements with swipe even on non-scrollable
pages #1141 (#1142)
---
i18n/en.jsonp.js | 6 +-
i18n/es.jsonp.js | 6 +-
i18n/fr.jsonp.js | 6 +-
www/index.html | 14 ++++-
www/js/app.js | 100 ++++++++------------------------
www/js/lib/uiUtil.js | 135 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 182 insertions(+), 85 deletions(-)
diff --git a/i18n/en.jsonp.js b/i18n/en.jsonp.js
index 0f50243f5..96bf626c1 100644
--- a/i18n/en.jsonp.js
+++ b/i18n/en.jsonp.js
@@ -31,8 +31,8 @@ document.localeJson = {
"configure-compatibility-images-control": "Use WebP workaround if needed",
"configure-display-settings-title": "Display settings",
"configure-display-panel-header": "Display options",
- "configure-display-slideaway": "Hide header and footer when scrolling down (scroll up slightly to show again)",
- "configure-display-slideaway-tip": "Header and footer will slide away when scrolling down at least 50 pixels, and will slide back when you scroll up. The option is now on by default.",
+ "configure-display-slideaway": "Hide header and footer when scrolling or swiping down (scroll up slightly to show again)",
+ "configure-display-slideaway-tip": "Header and footer will slide away when scrolling or (on fixed pages, swiping) down at least 50 pixels, and will slide back when you scroll up. On fixed pages, you can also use Ctrl/Command + UpArrow or DownArrow. The option is now on by default.",
"configure-display-uianimations": "Animate transition between app pages",
"configure-display-uianimations-tip": "The animation is on by default and can be disabled by unchecking this option.",
"configure-display-homekeyfocus": "Use Home key to focus search bar (may rarely have side effects on ZIM files that handle Home key)",
@@ -208,6 +208,8 @@ document.localeJson = {
"about-search-para2": "Title search matches the start of an article title, so if you search for 'France' you will get 'France (country)', 'France (disambiguation)', 'France (film)', etc. This kind of search tries to be case-insensitive, but the number of case variants tried is necessarily limited. If not enough results are returned, you can increase the maximum number of search results using the slider in Configuration.",
"about-search-para3": "Alphabetical search: If you type a letter of the alphabet in the search box (upper case may be most useful), it will show an alphabetical list of articles starting with that letter. This is useful for ZIM archives that have descriptive rather than semantic titles (e.g. TED Talks). You can also display a list of all titles (up to the limit set in Configuration) simply by clicking the search button without typing anything.",
"about-search-para4": "Full-text search: This type of search is only availalbe in relatively recent desktop browsers, and if the archive contains a full-text index. If it is supported, it will be used automatically, but it is slower than title search, and you may notice a delay before the results are added to the title-search results. Additionally, full-text search cannot be used if your archive is split into various chunks. To see whether it is available, look in the API panel at the bottom of the Configuration page after you have loaded a ZIM. If it says \"Xapian [fulltext]\" then it should be automatically enabled for that ZIM.",
+ "about-remove-navbars": "Removing navigation bars",
+ "about-remove-navbars-para1": "The default setting is for the top and bottom navigation bars to slide away when you scroll down and slide back when you scroll up. However, in some ZIM archives, e.g. PhET, it is not possible to scroll, and the navigation bars can obscure some content. In this case, in most browsers you can swipe up or down on the window (with touch or with the mouse wheel/touchpad) to toggle the display of the navigation bars. In all browsers, you can also use the Ctrl/Cmd + UpArrow/DownArrow keys.",
"about-image-download-para1": "Unfortunately, it is not usually possible to download and save an image from a ZIM article using the context menu (after right-clicking or long-pressing the image). One workaround is to choose \"Copy Image\" in the context menu, then paste it in any suitable software (Paint, Gimp etc, or even a Word processor), and then save it from there.",
"about-privacy-short-title": "Short version:",
"about-privacy-short-para1": "Kiwix JS works offline, and does not collect or record any of your personal data. It only remembers your browsing history for the duration of a session (for the purpose of returning to previously viewed pages). This history is lost on exiting the app and is not recorded in any way.",
diff --git a/i18n/es.jsonp.js b/i18n/es.jsonp.js
index 2b07db35f..999b01a3b 100644
--- a/i18n/es.jsonp.js
+++ b/i18n/es.jsonp.js
@@ -31,8 +31,8 @@ document.localeJson = {
"configure-compatibility-images-control": "Usar solución alternativa WebP si es necesario",
"configure-display-settings-title": "Configurar página",
"configure-display-panel-header": "Opciones de página",
- "configure-display-slideaway": "Ocultar encabezado y pie de página al desplazarse hacia abajo (desplácese hacia arriba para mostrarlos de nuevo)",
- "configure-display-slideaway-tip": "El encabezado y el pie de página se ocultarán al desplazarse hacia abajo al menos 50 píxeles, y volverán a aparecer al desplazarse hacia arriba. La opción está activada por defecto.",
+ "configure-display-slideaway": "Ocultar encabezado y pie de página al desplazarse o deslizar hacia abajo (desplácese hacia arriba para mostrarlos de nuevo)",
+ "configure-display-slideaway-tip": "El encabezado y el pie de página se ocultarán al desplazarse o (en páginas fijas, deslizar) hacia abajo al menos 50 píxeles, y volverán a aparecer al desplazarse hacia arriba. En las páginas fijas, también puede usar Ctrl/Command + FlechaArriba o FlechaAbajo. La opción está activada por defecto.",
"configure-display-uianimations": "Animar transición entre páginas de la aplicación",
"configure-display-uianimations-tip": "La animación está activada por defecto y puede ser desactivada desmarcando esta opción.",
"configure-display-homekeyfocus": "Usar tecla Inicio para enfocar la barra de búsqueda (puede tener efectos secundarios en archivos ZIM que manejen la tecla Inicio)",
@@ -208,6 +208,8 @@ document.localeJson = {
"about-search-para2": "La búsqueda por título coincide con el inicio de un título de artículo, por lo que si busca 'Francia', obtendrá 'Francia (país)', 'Francia (desambiguación)', 'Francia (película)', etc. Este tipo de búsqueda intenta ser insensible a las mayúsculas y minúsculas, pero el número de variantes de mayúsculas y minúsculas que se prueban es necesariamente limitado. Si no se devuelven suficientes resultados, puede aumentar el número máximo de resultados de búsqueda utilizando el control deslizante de Configuración.",
"about-search-para3": "La búsqueda alfabética: Si escribe una letra del alfabeto en el campo de búsqueda (las mayúsculas pueden ser más útiles), se mostrará una lista alfabética de artículos que empiezan por esa letra. Esto es útil para los archivos ZIM que tienen títulos descriptivos en lugar de semánticos (por ejemplo, TED Talks). También se puede mostrar una lista de todos los títulos (hasta el límite establecido en Configuración) simplemente haciendo clic en el botón de búsqueda sin escribir nada.",
"about-search-para4": "La búsqueda de texto completo: Este tipo de búsqueda sólo está disponible en los navegadores de escritorio relativamente recientes, y si el archivo contiene un índice de texto completo. Si es compatible, se utilizará automáticamente, pero es más lenta que la búsqueda por título, y puede notar un retraso antes de que los resultados se añadan a los resultados de la búsqueda por título. Además, la búsqueda de texto completo no se puede utilizar si su archivo está dividido en varios fragmentos. Para ver si está disponible, mire en el panel API en la parte inferior de la página de Configuración después de haber cargado un ZIM. Si dice \"Xapian [fulltext]\", entonces debería estar habilitada automáticamente para ese ZIM.",
+ "about-remove-navbars": "Eliminación de barras de navegación",
+ "about-remove-navbars-para1": "La configuración predeterminada es que las barras de navegación superior e inferior se deslicen cuando se desplaza hacia abajo y vuelvan a aparecer cuando se desplaza hacia arriba. Sin embargo, en algunos archivos ZIM, por ejemplo, PhET, no es posible desplazarse, y las barras de navegación pueden ocultar parte del contenido. En este caso, en la mayoría de los navegadores puede deslizar hacia arriba o hacia abajo en la ventana (con el tacto o con la rueda del ratón/touchpad) para alternar la visualización de las barras de navegación. En todos los navegadores, también puede utilizar las teclas Ctrl/Cmd + FlechaArriba/FlechaAbajo.",
"about-image-download-para1": "Desafortunadamente, no suele ser posible descargar y guardar una imagen de un artículo ZIM utilizando el menú contextual (después de hacer clic con el botón derecho o mantener pulsada la imagen). Una solución alternativa es elegir \"Copiar imagen\" en el menú contextual, luego pegarla en cualquier software adecuado (Paint, Gimp, etc, o incluso un procesador de textos), y luego guardarla desde allí.",
"about-privacy-short-title": "Versión corta:",
"about-privacy-short-para1": "Kiwix JS funciona sin conexión a Internet y no recopila ni registra ninguno de los datos personales del usuario. Sólo recuerda su historial de navegación durante la duración de una sesión (con el fin de volver a las páginas vistadas anteriormente). Este historial se pierde al salir de la aplicación y no se registra de ninguna manera.",
diff --git a/i18n/fr.jsonp.js b/i18n/fr.jsonp.js
index cd6a9ce8c..11e9b6865 100644
--- a/i18n/fr.jsonp.js
+++ b/i18n/fr.jsonp.js
@@ -31,8 +31,8 @@ document.localeJson = {
"configure-compatibility-images-control": "Utiliser workaround pour les images WebP si nécessaire",
"configure-display-settings-title": "Configurer l'affichage",
"configure-display-panel-header": "Options de l'affichage",
- "configure-display-slideaway": "Masquer l'en-tête et le pied de page lors du défilement (défilez vers le haut pour les afficher à nouveau)",
- "configure-display-slideaway-tip": "L'en-tête et le pied de page disparaîtront lorsque vous ferez défiler vers le bas d'au moins 50 pixels, et réapparaîtront lorsque vous ferez défiler vers le haut. L'option est maintenant activée par défaut.",
+ "configure-display-slideaway": "Masquer l'en-tête et le pied de page lors du défilement ou du balayage vers le bas (défilez légèrement vers le haut pour les afficher à nouveau)",
+ "configure-display-slideaway-tip": "L'en-tête et le pied de page disparaîtront lors du défilement ou du balayage vers le bas d'au moins 50 pixels, et réapparaîtront lorsque vous remonterez. Sur les pages fixes, vous pouvez également utiliser Ctrl/Command + Flèche haut ou bas. L'option est maintenant activée par défaut.",
"configure-display-uianimations": "Animer la transition entre les pages de l'application",
"configure-display-uianimations-tip": "L'animation est activée par défaut et peut être désactivée en décochant cette option.",
"configure-display-homekeyfocus": "Utiliser la touche Accueil pour mettre le focus sur la barre de recherche (peut avoir des effets secondaires sur les fichiers ZIM qui gèrent la touche Accueil)",
@@ -208,6 +208,8 @@ document.localeJson = {
"about-search-para2": "La recherche par titre correspond au début d'un titre d'article, de sorte que si vous cherchez « France », vous obtiendrez « France (pays) », « France (désambiguïsation) », « France (film) », etc. Ce type de recherche tente d'être insensible à la casse, mais le nombre de variantes de casse testées est nécessairement limité. Si vous ne trouvez pas assez de résultats, vous pouvez augmenter le nombre maximal de résultats de recherche à l'aide du curseur de la page de Configuration.",
"about-search-para3": "Recherche alphabétique: Si vous tapez une lettre de l'alphabet dans le champ de recherche (les majuscules peuvent être plus utiles), une liste alphabétique des articles commençant par cette lettre s'affichera. Cette fonction est utile pour les archives du ZIM dont les titres sont plus descriptifs que sémantiques (par exemple, TED Talks). Vous pouvez également afficher une liste de tous les titres (jusqu'à la limite fixée dans la Configuration) en cliquant simplement sur le bouton de recherche sans rien taper.",
"about-search-para4": "La recherche de texte intégral n'est disponible que dans les navigateurs de bureau relativement récents, et si l'archive contient un index de texte intégral. Si elle est prise en charge, elle sera utilisée automatiquement, mais elle est plus lente que la recherche par titre, et vous pouvez remarquer un délai avant que les résultats ne soient ajoutés aux résultats de la recherche par titre. De plus, la recherche de texte intégral ne peut pas être utilisée si votre fichier est découpé en pluseurs parties. Pour voir si elle est disponible, regardez dans le panneau API en bas de la page de Configuration après avoir chargé un ZIM. S'il indique « Xapian [fulltext] », alors elle devrait être activée automatiquement pour ce ZIM.",
+ "about-remove-navbars": "Suppression des barres de navigation",
+ "about-remove-navbars-para1": "Le paramètre par défaut est que les barres de navigation supérieure et inférieure disparaissent lorsque vous faites défiler vers le bas et réapparaissent lorsque vous faites défiler vers le haut. Cependant, dans certaines archives ZIM, par exemple PhET, il n'est pas possible de faire défiler, et les barres de navigation peuvent masquer une partie du contenu. Dans ce cas, dans la plupart des navigateurs, vous pouvez faire glisser vers le haut ou vers le bas sur la fenêtre (avec le toucher ou avec la molette de la souris/touchpad) pour basculer l'affichage des barres de navigation. Dans tous les navigateurs, vous pouvez également utiliser les touches Ctrl/Cmd + FlècheHaut/FlècheBas.",
"about-image-download-para1": "Malheureusement, il n'est généralement pas possible de télécharger et d'enregistrer une image à partir d'un article ZIM en utilisant le menu contextuel (après un clic droit ou un appui long sur l'image). Une solution de contournement consiste à choisir « Copier l'image » dans le menu contextuel, puis à la coller dans un logiciel approprié (Paint, Gimp, etc., ou même un traitement de texte), puis à l'enregistrer à partir de là.",
"about-privacy-short-title": "Version courte :",
"about-privacy-short-para1": "Kiwix JS fonctionne hors ligne et ne collecte ni ne stocke aucune donnée personnelle de l'utilisateur. Il se souvient uniquement de l'historique de navigation pendant la durée d'une session (afin de pouvoir revenir aux pages précédemment visitées). Cet historique est perdu lorsque vous quittez l'application et n'est enregistré d'aucune manière.",
diff --git a/www/index.html b/www/index.html
index aa21affbd..dd960ca3f 100644
--- a/www/index.html
+++ b/www/index.html
@@ -128,6 +128,7 @@
+ The default setting is for the top and bottom navigation bars to slide away when you scroll down and slide back when you scroll up. However,
+ in some ZIM archives, e.g. PhET, it is not possible to scroll, and the navigation bars can obscure some content. In this case, in most browsers
+ you can swipe up or down on the window (with touch or with the mouse wheel/touchpad) to toggle the display of the navigation bars. In all browsers,
+ you can also use the Ctrl/Cmd + UpArrow/DownArrow keys.
+
Unfortunately it is not usually possible to download and save an image from a ZIM article using the context menu (after right-clicking
@@ -500,9 +510,9 @@
Display settings
Display options:
-
diff --git a/www/js/app.js b/www/js/app.js
index 0146e54b8..22de96e7b 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -87,73 +87,10 @@ appstate['search'] = {
// A Boolean to store the update status of the PWA version (currently only used with Firefox Extension)
appstate['pwaUpdateNeeded'] = false; // This will be set to true if the Service Worker has an update waiting
-// Placeholders for the article container and the article window
+// Placeholders for the article container, the article window, and the search-article area
const articleContainer = document.getElementById('articleContent');
const articleWindow = articleContainer.contentWindow;
const region = document.getElementById('search-article');
-const header = document.getElementById('top');
-const footer = document.getElementById('footer');
-// Edge Legacy requires setting the z-index of the header to prevent it disappearing beneath the iframe
-if ('MSBlobBuilder' in window) {
- header.style.position = 'relative';
- header.style.zIndex = 1;
-}
-
-let oldScrollY = 0;
-
-// Slides away or restores the header and footer
-function slideAway () {
- const newScrollY = articleWindow.pageYOffset;
- if (newScrollY === oldScrollY || document.activeElement === document.getElementById('prefix')) return;
- if (newScrollY < oldScrollY) {
- restoreUIElements();
- } else if (newScrollY - oldScrollY > 50 && /\(0p?x?\)/.test(header.style.transform)) {
- // Hide the toolbars if user has scrolled and not already hidden
- hideUIElements();
- }
- oldScrollY = newScrollY;
-};
-
-// Hides slide-away UI elements
-function hideUIElements () {
- // Hide the toolbars if user has scrolled and not already hidden
- const headerStyles = getComputedStyle(header);
- const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom) - 2;
- const footerStyles = getComputedStyle(footer);
- const footerHeight = parseFloat(footerStyles.height) + parseFloat(footerStyles.marginTop) - 2;
- header.style.transform = 'translateY(-' + headerHeight + 'px)';
- articleContainer.style.transform = 'translateY(-' + headerHeight + 'px)';
- const iframeHeight = parseFloat(articleContainer.style.height.replace('px', ''));
- articleContainer.style.height = iframeHeight + headerHeight + 'px';
- footer.style.transform = 'translateY(' + footerHeight + 'px)';
- region.style.height = window.innerHeight + headerHeight + 10 + 'px';
-}
-
-// Restores slide-away UI elements
-function restoreUIElements () {
- header.style.transform = 'translateY(0)';
- // Needed for Windows Mobile to prevent header disappearing beneath iframe
- articleContainer.style.transform = 'translateY(-1px)';
- footer.style.transform = 'translateY(0)';
- setTimeout(function () {
- const headerStyles = getComputedStyle(document.getElementById('top'));
- const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
- articleContainer.style.height = window.innerHeight - headerHeight + 'px';
- region.style.height = window.innerHeight + 10 + 'px';
- }, 200);
-}
-
-let scrollThrottle = false;
-
-// Throttles the slide-away function
-function scroller () {
- if (scrollThrottle) return;
- scrollThrottle = true;
- slideAway();
- setTimeout(function () {
- scrollThrottle = false;
- }, 250);
-};
switchHomeKeyToFocusSearchBar();
@@ -208,7 +145,7 @@ function resizeIFrame () {
const libraryContent = document.getElementById('libraryContent');
const frames = [articleContainer, libraryContent];
const nestedFrame = libraryContent.contentWindow.document.getElementById('libraryIframe');
- restoreUIElements();
+ uiUtil.showSlidingUIElements();
for (let i = 0; i < frames.length; i++) {
const iframe = frames[i];
if (iframe.style.display === 'none') {
@@ -228,8 +165,20 @@ function resizeIFrame () {
}
}
- // Add the scroll event listener to the article window
- if (params.slideAway) articleWindow.onscroll = scroller;
+ // Remove and add the scroll event listener to the new article window
+ // Note that IE11 doesn't support wheel or touch events on the iframe, but it does support keydown and scroll
+ articleWindow.removeEventListener('scroll', uiUtil.scroller);
+ articleWindow.removeEventListener('touchstart', uiUtil.scroller);
+ articleWindow.removeEventListener('touchend', uiUtil.scroller);
+ articleWindow.removeEventListener('wheel', uiUtil.scroller);
+ articleWindow.removeEventListener('keydown', uiUtil.scroller);
+ if (params.slideAway) {
+ articleWindow.addEventListener('scroll', uiUtil.scroller);
+ articleWindow.addEventListener('touchstart', uiUtil.scroller);
+ articleWindow.addEventListener('touchend', uiUtil.scroller);
+ articleWindow.addEventListener('wheel', uiUtil.scroller);
+ articleWindow.addEventListener('keydown', uiUtil.scroller);
+ }
}
document.addEventListener('DOMContentLoaded', function () {
@@ -538,17 +487,14 @@ document.querySelectorAll('input[type="checkbox"][name=hideActiveContentWarning]
});
document.getElementById('slideAwayCheck').addEventListener('change', function (e) {
params.slideAway = e.target.checked;
- if (!params.slideAway) {
- articleWindow.onscroll = null;
- } else {
- if (typeof navigator.getDeviceStorages === 'function') {
- // We are in Firefox OS, which may have a bug with this setting turned on - see [kiwix-js #1140]
- uiUtil.systemAlert(translateUI.t('dialog-slideawaycheck-message') || ('This setting may not work correctly on Firefox OS. ' +
- 'If you find that some ZIM links become unresponsive, try turning this setting off.'), translateUI.t('dialog-slideawaycheck-title') || 'Warning');
- }
- articleWindow.onscroll = scroller;
+ if (typeof navigator.getDeviceStorages === 'function') {
+ // We are in Firefox OS, which may have a bug with this setting turned on - see [kiwix-js #1140]
+ uiUtil.systemAlert(translateUI.t('dialog-slideawaycheck-message') || ('This setting may not work correctly on Firefox OS. ' +
+ 'If you find that some ZIM links become unresponsive, try turning this setting off.'), translateUI.t('dialog-slideawaycheck-title') || 'Warning');
}
settingsStore.setItem('slideAway', params.slideAway, Infinity);
+ // This has methods to add or remove the event listeners needed
+ resizeIFrame();
});
document.querySelectorAll('input[type="checkbox"][name=showUIAnimations]').forEach(function (element) {
element.addEventListener('change', function () {
@@ -1716,7 +1662,7 @@ function readArticle (dirEntry) {
setTimeout(function () {
uiUtil.spinnerDisplay(false);
}, 4000);
- restoreUIElements();
+ uiUtil.showSlidingUIElements();
}
}
}
diff --git a/www/js/lib/uiUtil.js b/www/js/lib/uiUtil.js
index c70d165f8..8aa756e2f 100644
--- a/www/js/lib/uiUtil.js
+++ b/www/js/lib/uiUtil.js
@@ -29,6 +29,138 @@ import util from './util.js';
import settingsStore from './settingsStore.js';
import translateUI from './translateUI.js';
+// Placeholders for the article container and the article window
+const region = document.getElementById('search-article');
+const header = document.getElementById('top');
+const footer = document.getElementById('footer');
+
+/**
+ * Hides slide-away UI elements
+ */
+function hideSlidingUIElements () {
+ const articleContainer = document.getElementById('articleContent');
+ const headerStyles = getComputedStyle(header);
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom) - 2;
+ const footerStyles = getComputedStyle(footer);
+ const footerHeight = parseFloat(footerStyles.height) + parseFloat(footerStyles.marginTop) - 2;
+ header.style.transform = 'translateY(-' + headerHeight + 'px)';
+ articleContainer.style.transform = 'translateY(-' + headerHeight + 'px)';
+ const iframeHeight = parseFloat(articleContainer.style.height.replace('px', ''));
+ articleContainer.style.height = iframeHeight + headerHeight + 'px';
+ footer.style.transform = 'translateY(' + footerHeight + 'px)';
+ region.style.height = window.innerHeight + headerHeight + 10 + 'px';
+}
+
+/**
+ * Restores slide-away UI elements
+ */
+function showSlidingUIElements () {
+ const articleContainer = document.getElementById('articleContent');
+ header.style.transform = 'translateY(0)';
+ // Needed for Windows Mobile to prevent header disappearing beneath iframe
+ articleContainer.style.transform = 'translateY(-1px)';
+ footer.style.transform = 'translateY(0)';
+ setTimeout(function () {
+ const headerStyles = getComputedStyle(document.getElementById('top'));
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
+ articleContainer.style.height = window.innerHeight - headerHeight + 'px';
+ region.style.height = window.innerHeight + 10 + 'px';
+ }, 200);
+}
+
+let scrollThrottle = false;
+
+/**
+ * Luuncher for the slide-away function, including a throttle to prevent it being called too often
+ */
+function scroller (e) {
+ const articleContainer = document.getElementById('articleContent');
+ if (scrollThrottle) return;
+ // windowIsScrollable gets set and reset in slideAway()
+ if (windowIsScrollable && e.type === 'wheel') return;
+ const newScrollY = articleContainer.contentWindow.pageYOffset;
+ // If it's a wheel event and we're actually scrolling, get out of the way and let the scroll event handle it
+ if ((/^touch|^wheel|^keydown/.test(e.type)) && newScrollY !== oldScrollY) {
+ oldScrollY = newScrollY;
+ return;
+ }
+ scrollThrottle = true;
+ // Call the main function
+ slideAway(e);
+ let timeout = 250;
+ if (/^touch|^keydown/.test(e.type)) {
+ scrollThrottle = false;
+ return;
+ } else if (e.type === 'wheel' && Math.abs(e.deltaY) > 6) {
+ timeout = 1200;
+ }
+ setTimeout(function () {
+ scrollThrottle = false;
+ }, timeout);
+};
+
+// Edge Legacy requires setting the z-index of the header to prevent it disappearing beneath the iframe
+if ('MSBlobBuilder' in window) {
+ header.style.position = 'relative';
+ header.style.zIndex = 1;
+}
+
+let oldScrollY = 0;
+let timeoutResetScrollable;
+let windowIsScrollable = false;
+
+// Slides away or restores the header and footer
+function slideAway (e) {
+ const articleContainer = document.getElementById('articleContent');
+ const newScrollY = articleContainer.contentWindow.pageYOffset;
+ let delta;
+ const visibleState = /\(0p?x?\)/.test(header.style.transform);
+ // If the search field is focused and elements are not showing, do not slide away
+ if (document.activeElement === document.getElementById('prefix')) {
+ if (!visibleState) showSlidingUIElements();
+ } else if (e.type === 'scroll') {
+ windowIsScrollable = true;
+ if (newScrollY === oldScrollY) return;
+ if (newScrollY < oldScrollY) {
+ showSlidingUIElements();
+ } else if (newScrollY - oldScrollY > 50 && /\(0p?x?\)/.test(header.style.transform)) {
+ // Hide the toolbars if user has scrolled and not already hidden
+ hideSlidingUIElements();
+ }
+ oldScrollY = newScrollY;
+ // Debounces the scroll at end of page
+ const resetScrollable = function () {
+ windowIsScrollable = false;
+ };
+ clearTimeout(timeoutResetScrollable);
+ timeoutResetScrollable = setTimeout(resetScrollable, 3000);
+ } else {
+ let hideOrShow = visibleState ? hideSlidingUIElements : showSlidingUIElements;
+ if (newScrollY === 0 && windowIsScrollable) {
+ // If we are at the top of a scrollable page, always restore the UI elements
+ hideOrShow = showSlidingUIElements;
+ }
+ if (e.type === 'touchend') {
+ delta = Math.abs(e.changedTouches[0].screenY);
+ if (delta > 50) {
+ hideOrShow();
+ }
+ } else if (e.type === 'wheel') {
+ delta = Math.abs(e.deltaY);
+ if (delta > 6) {
+ hideOrShow();
+ }
+ } else if (e.type === 'keydown') {
+ // IE11 produces Up and Down instead of ArrowUp and ArrowDown
+ if ((e.ctrlKey || e.metaKey) && /^(Arrow)?(Up|Down)$/.test(e.key)) {
+ hideOrShow();
+ }
+ }
+ // DEBUG for non-scrolling events events
+ // console.debug('eventType: ' + e.type + ' oldScrollY: ' + oldScrollY + ' newScrollY: ' + newScrollY + ' windowIsScrollable: ' + windowIsScrollable);
+ }
+}
+
/**
* Displays a Bootstrap alert or confirm dialog box depending on the options provided
*
@@ -843,6 +975,9 @@ function getBrowserLanguage () {
* Functions and classes exposed by this module
*/
export default {
+ hideSlidingUIElements: hideSlidingUIElements,
+ showSlidingUIElements: showSlidingUIElements,
+ scroller: scroller,
systemAlert: systemAlert,
feedNodeWithDataURI: feedNodeWithDataURI,
determineCanvasElementsWorkaround: determineCanvasElementsWorkaround,
From ef29fdc07bb551256c900c4b57a37accc23d8d89 Mon Sep 17 00:00:00 2001
From: Jaifroid
Date: Wed, 1 Nov 2023 21:55:32 +0000
Subject: [PATCH 2/4] Fix region resizing and make swipe > 2/3 screen
---
i18n/en.jsonp.js | 2 +-
i18n/es.jsonp.js | 2 +-
i18n/fr.jsonp.js | 2 +-
www/index.html | 4 ++--
www/js/lib/uiUtil.js | 15 +++++++++------
5 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/i18n/en.jsonp.js b/i18n/en.jsonp.js
index 96bf626c1..4fbd95ca6 100644
--- a/i18n/en.jsonp.js
+++ b/i18n/en.jsonp.js
@@ -209,7 +209,7 @@ document.localeJson = {
"about-search-para3": "Alphabetical search: If you type a letter of the alphabet in the search box (upper case may be most useful), it will show an alphabetical list of articles starting with that letter. This is useful for ZIM archives that have descriptive rather than semantic titles (e.g. TED Talks). You can also display a list of all titles (up to the limit set in Configuration) simply by clicking the search button without typing anything.",
"about-search-para4": "Full-text search: This type of search is only availalbe in relatively recent desktop browsers, and if the archive contains a full-text index. If it is supported, it will be used automatically, but it is slower than title search, and you may notice a delay before the results are added to the title-search results. Additionally, full-text search cannot be used if your archive is split into various chunks. To see whether it is available, look in the API panel at the bottom of the Configuration page after you have loaded a ZIM. If it says \"Xapian [fulltext]\" then it should be automatically enabled for that ZIM.",
"about-remove-navbars": "Removing navigation bars",
- "about-remove-navbars-para1": "The default setting is for the top and bottom navigation bars to slide away when you scroll down and slide back when you scroll up. However, in some ZIM archives, e.g. PhET, it is not possible to scroll, and the navigation bars can obscure some content. In this case, in most browsers you can swipe up or down on the window (with touch or with the mouse wheel/touchpad) to toggle the display of the navigation bars. In all browsers, you can also use the Ctrl/Cmd + UpArrow/DownArrow keys.",
+ "about-remove-navbars-para1": "The default setting is for the top and bottom navigation bars to slide away when you scroll down and slide back when you scroll up. However, in some ZIM archives, e.g. PhET, it is not possible to scroll, and the navigation bars can obscure some content. In this case, in most browsers you can swipe decisively up or down on the window (with touch or with the mouse wheel/touchpad) to toggle the display of the navigation bars. In all browsers, you can also use the Ctrl/Cmd + UpArrow/DownArrow keys.",
"about-image-download-para1": "Unfortunately, it is not usually possible to download and save an image from a ZIM article using the context menu (after right-clicking or long-pressing the image). One workaround is to choose \"Copy Image\" in the context menu, then paste it in any suitable software (Paint, Gimp etc, or even a Word processor), and then save it from there.",
"about-privacy-short-title": "Short version:",
"about-privacy-short-para1": "Kiwix JS works offline, and does not collect or record any of your personal data. It only remembers your browsing history for the duration of a session (for the purpose of returning to previously viewed pages). This history is lost on exiting the app and is not recorded in any way.",
diff --git a/i18n/es.jsonp.js b/i18n/es.jsonp.js
index 999b01a3b..c28d89504 100644
--- a/i18n/es.jsonp.js
+++ b/i18n/es.jsonp.js
@@ -209,7 +209,7 @@ document.localeJson = {
"about-search-para3": "La búsqueda alfabética: Si escribe una letra del alfabeto en el campo de búsqueda (las mayúsculas pueden ser más útiles), se mostrará una lista alfabética de artículos que empiezan por esa letra. Esto es útil para los archivos ZIM que tienen títulos descriptivos en lugar de semánticos (por ejemplo, TED Talks). También se puede mostrar una lista de todos los títulos (hasta el límite establecido en Configuración) simplemente haciendo clic en el botón de búsqueda sin escribir nada.",
"about-search-para4": "La búsqueda de texto completo: Este tipo de búsqueda sólo está disponible en los navegadores de escritorio relativamente recientes, y si el archivo contiene un índice de texto completo. Si es compatible, se utilizará automáticamente, pero es más lenta que la búsqueda por título, y puede notar un retraso antes de que los resultados se añadan a los resultados de la búsqueda por título. Además, la búsqueda de texto completo no se puede utilizar si su archivo está dividido en varios fragmentos. Para ver si está disponible, mire en el panel API en la parte inferior de la página de Configuración después de haber cargado un ZIM. Si dice \"Xapian [fulltext]\", entonces debería estar habilitada automáticamente para ese ZIM.",
"about-remove-navbars": "Eliminación de barras de navegación",
- "about-remove-navbars-para1": "La configuración predeterminada es que las barras de navegación superior e inferior se deslicen cuando se desplaza hacia abajo y vuelvan a aparecer cuando se desplaza hacia arriba. Sin embargo, en algunos archivos ZIM, por ejemplo, PhET, no es posible desplazarse, y las barras de navegación pueden ocultar parte del contenido. En este caso, en la mayoría de los navegadores puede deslizar hacia arriba o hacia abajo en la ventana (con el tacto o con la rueda del ratón/touchpad) para alternar la visualización de las barras de navegación. En todos los navegadores, también puede utilizar las teclas Ctrl/Cmd + FlechaArriba/FlechaAbajo.",
+ "about-remove-navbars-para1": "La configuración predeterminada es que las barras de navegación superior e inferior se deslicen cuando se desplaza hacia abajo y vuelvan a aparecer cuando se desplaza hacia arriba. Sin embargo, en algunos archivos ZIM, por ejemplo, PhET, no es posible desplazarse, y las barras de navegación pueden ocultar parte del contenido. En este caso, en la mayoría de los navegadores puede deslizar decididamente hacia arriba o hacia abajo en la ventana (con el tacto o con la rueda del ratón/touchpad) para alternar la visualización de las barras de navegación. En todos los navegadores, también puede utilizar las teclas Ctrl/Cmd + FlechaArriba/FlechaAbajo.",
"about-image-download-para1": "Desafortunadamente, no suele ser posible descargar y guardar una imagen de un artículo ZIM utilizando el menú contextual (después de hacer clic con el botón derecho o mantener pulsada la imagen). Una solución alternativa es elegir \"Copiar imagen\" en el menú contextual, luego pegarla en cualquier software adecuado (Paint, Gimp, etc, o incluso un procesador de textos), y luego guardarla desde allí.",
"about-privacy-short-title": "Versión corta:",
"about-privacy-short-para1": "Kiwix JS funciona sin conexión a Internet y no recopila ni registra ninguno de los datos personales del usuario. Sólo recuerda su historial de navegación durante la duración de una sesión (con el fin de volver a las páginas vistadas anteriormente). Este historial se pierde al salir de la aplicación y no se registra de ninguna manera.",
diff --git a/i18n/fr.jsonp.js b/i18n/fr.jsonp.js
index 11e9b6865..0a8475423 100644
--- a/i18n/fr.jsonp.js
+++ b/i18n/fr.jsonp.js
@@ -209,7 +209,7 @@ document.localeJson = {
"about-search-para3": "Recherche alphabétique: Si vous tapez une lettre de l'alphabet dans le champ de recherche (les majuscules peuvent être plus utiles), une liste alphabétique des articles commençant par cette lettre s'affichera. Cette fonction est utile pour les archives du ZIM dont les titres sont plus descriptifs que sémantiques (par exemple, TED Talks). Vous pouvez également afficher une liste de tous les titres (jusqu'à la limite fixée dans la Configuration) en cliquant simplement sur le bouton de recherche sans rien taper.",
"about-search-para4": "La recherche de texte intégral n'est disponible que dans les navigateurs de bureau relativement récents, et si l'archive contient un index de texte intégral. Si elle est prise en charge, elle sera utilisée automatiquement, mais elle est plus lente que la recherche par titre, et vous pouvez remarquer un délai avant que les résultats ne soient ajoutés aux résultats de la recherche par titre. De plus, la recherche de texte intégral ne peut pas être utilisée si votre fichier est découpé en pluseurs parties. Pour voir si elle est disponible, regardez dans le panneau API en bas de la page de Configuration après avoir chargé un ZIM. S'il indique « Xapian [fulltext] », alors elle devrait être activée automatiquement pour ce ZIM.",
"about-remove-navbars": "Suppression des barres de navigation",
- "about-remove-navbars-para1": "Le paramètre par défaut est que les barres de navigation supérieure et inférieure disparaissent lorsque vous faites défiler vers le bas et réapparaissent lorsque vous faites défiler vers le haut. Cependant, dans certaines archives ZIM, par exemple PhET, il n'est pas possible de faire défiler, et les barres de navigation peuvent masquer une partie du contenu. Dans ce cas, dans la plupart des navigateurs, vous pouvez faire glisser vers le haut ou vers le bas sur la fenêtre (avec le toucher ou avec la molette de la souris/touchpad) pour basculer l'affichage des barres de navigation. Dans tous les navigateurs, vous pouvez également utiliser les touches Ctrl/Cmd + FlècheHaut/FlècheBas.",
+ "about-remove-navbars-para1": "Le paramètre par défaut est que les barres de navigation supérieure et inférieure disparaissent lorsque vous faites défiler vers le bas et réapparaissent lorsque vous faites défiler vers le haut. Cependant, dans certaines archives ZIM, par exemple PhET, il n'est pas possible de faire défiler, et les barres de navigation peuvent masquer une partie du contenu. Dans ce cas, dans la plupart des navigateurs, vous pouvez faire glisser de manière décisive vers le haut ou vers le bas sur la fenêtre (avec le toucher ou avec la molette de la souris/touchpad) pour basculer l'affichage des barres de navigation. Dans tous les navigateurs, vous pouvez également utiliser les touches Ctrl/Cmd + FlècheHaut/FlècheBas.",
"about-image-download-para1": "Malheureusement, il n'est généralement pas possible de télécharger et d'enregistrer une image à partir d'un article ZIM en utilisant le menu contextuel (après un clic droit ou un appui long sur l'image). Une solution de contournement consiste à choisir « Copier l'image » dans le menu contextuel, puis à la coller dans un logiciel approprié (Paint, Gimp, etc., ou même un traitement de texte), puis à l'enregistrer à partir de là.",
"about-privacy-short-title": "Version courte :",
"about-privacy-short-para1": "Kiwix JS fonctionne hors ligne et ne collecte ni ne stocke aucune donnée personnelle de l'utilisateur. Il se souvient uniquement de l'historique de navigation pendant la durée d'une session (afin de pouvoir revenir aux pages précédemment visitées). Cet historique est perdu lorsque vous quittez l'application et n'est enregistré d'aucune manière.",
diff --git a/www/index.html b/www/index.html
index dd960ca3f..e758c1a36 100644
--- a/www/index.html
+++ b/www/index.html
@@ -237,8 +237,8 @@
Removing navigation bars
The default setting is for the top and bottom navigation bars to slide away when you scroll down and slide back when you scroll up. However,
in some ZIM archives, e.g. PhET, it is not possible to scroll, and the navigation bars can obscure some content. In this case, in most browsers
- you can swipe up or down on the window (with touch or with the mouse wheel/touchpad) to toggle the display of the navigation bars. In all browsers,
- you can also use the Ctrl/Cmd + UpArrow/DownArrow keys.
+ you can swipe decisively up or down on the window (with touch or with the mouse wheel/touchpad) to toggle the display of the navigation bars.
+ In all browsers, you can also use the Ctrl/Cmd + UpArrow/DownArrow keys.
diff --git a/www/js/lib/uiUtil.js b/www/js/lib/uiUtil.js
index 8aa756e2f..0e5ca68bd 100644
--- a/www/js/lib/uiUtil.js
+++ b/www/js/lib/uiUtil.js
@@ -30,7 +30,6 @@ import settingsStore from './settingsStore.js';
import translateUI from './translateUI.js';
// Placeholders for the article container and the article window
-const region = document.getElementById('search-article');
const header = document.getElementById('top');
const footer = document.getElementById('footer');
@@ -48,7 +47,6 @@ function hideSlidingUIElements () {
const iframeHeight = parseFloat(articleContainer.style.height.replace('px', ''));
articleContainer.style.height = iframeHeight + headerHeight + 'px';
footer.style.transform = 'translateY(' + footerHeight + 'px)';
- region.style.height = window.innerHeight + headerHeight + 10 + 'px';
}
/**
@@ -64,7 +62,6 @@ function showSlidingUIElements () {
const headerStyles = getComputedStyle(document.getElementById('top'));
const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
articleContainer.style.height = window.innerHeight - headerHeight + 'px';
- region.style.height = window.innerHeight + 10 + 'px';
}, 200);
}
@@ -79,14 +76,19 @@ function scroller (e) {
// windowIsScrollable gets set and reset in slideAway()
if (windowIsScrollable && e.type === 'wheel') return;
const newScrollY = articleContainer.contentWindow.pageYOffset;
- // If it's a wheel event and we're actually scrolling, get out of the way and let the scroll event handle it
+ // If it's a non-scroll event and we're actually scrolling, get out of the way and let the scroll event handle it
if ((/^touch|^wheel|^keydown/.test(e.type)) && newScrollY !== oldScrollY) {
oldScrollY = newScrollY;
return;
}
+ if (e.type === 'touchstart') {
+ oldTouchY = e.touches[0].screenY;
+ return;
+ }
scrollThrottle = true;
// Call the main function
slideAway(e);
+ // Set timeouts for the throttle
let timeout = 250;
if (/^touch|^keydown/.test(e.type)) {
scrollThrottle = false;
@@ -106,6 +108,7 @@ if ('MSBlobBuilder' in window) {
}
let oldScrollY = 0;
+let oldTouchY = 0;
let timeoutResetScrollable;
let windowIsScrollable = false;
@@ -141,8 +144,8 @@ function slideAway (e) {
hideOrShow = showSlidingUIElements;
}
if (e.type === 'touchend') {
- delta = Math.abs(e.changedTouches[0].screenY);
- if (delta > 50) {
+ delta = Math.abs(oldTouchY - e.changedTouches[0].screenY);
+ if (delta > articleContainer.contentWindow.innerHeight / 1.5) {
hideOrShow();
}
} else if (e.type === 'wheel') {
From 279133be283ee039c19959621d49b2d6d2852570 Mon Sep 17 00:00:00 2001
From: Jaifroid
Date: Thu, 2 Nov 2023 08:02:39 +0000
Subject: [PATCH 3/4] Fix resizeIframe compatibility with overflow hiding
---
www/js/app.js | 44 ++++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/www/js/app.js b/www/js/app.js
index 22de96e7b..179b7c8d7 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -142,27 +142,30 @@ darkPreference.onchange = function () {
*/
function resizeIFrame () {
const headerStyles = getComputedStyle(document.getElementById('top'));
+ const library = document.getElementById('library');
const libraryContent = document.getElementById('libraryContent');
- const frames = [articleContainer, libraryContent];
+ const liHomeNav = document.getElementById('liHomeNav');
const nestedFrame = libraryContent.contentWindow.document.getElementById('libraryIframe');
uiUtil.showSlidingUIElements();
- for (let i = 0; i < frames.length; i++) {
- const iframe = frames[i];
- if (iframe.style.display === 'none') {
- // We are in About or Configuration, so we only set the region height
- region.style.height = window.innerHeight + 'px';
- nestedFrame.style.height = window.innerHeight - 110 + 'px';
- } else {
- // IE cannot retrieve computed headerStyles till the next paint, so we wait a few ticks
- setTimeout(function () {
- // Get header height *including* its bottom margin
- const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
- iframe.style.height = window.innerHeight - headerHeight + 'px';
- // We have to allow a minimum safety margin of 10px for 'iframe' and 'header' to fit within 'region'
- region.style.height = window.innerHeight + 10 + 'px';
- nestedFrame.style.height = window.innerHeight - 110 + 'px';
- }, 100);
- }
+ if (library.style.display !== 'none') {
+ // We are in Library, so we set the height of the library iframes to the window height minus the header height
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
+ libraryContent.style.height = window.innerHeight + 'px';
+ nestedFrame.style.height = window.innerHeight - headerHeight + 'px';
+ region.style.overflowY = 'hidden';
+ } else if (!liHomeNav.classList.contains('active')) {
+ // We are not in Home, so we reset the region height
+ region.style.height = window.innerHeight + 'px';
+ region.style.overflowY = 'auto';
+ } else {
+ // IE cannot retrieve computed headerStyles till the next paint, so we wait a few ticks
+ setTimeout(function () {
+ // Get header height *including* its bottom margin
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
+ articleContainer.style.height = window.innerHeight - headerHeight + 'px';
+ // Hide the scrollbar of Configure / About
+ region.style.overflowY = 'hidden';
+ }, 100);
}
// Remove and add the scroll event listener to the new article window
@@ -409,9 +412,7 @@ document.getElementById('btnConfigure').addEventListener('click', function (even
document.getElementById('liAboutNav').setAttribute('class', '');
$('.navbar-collapse').collapse('hide');
// Show the selected content in the page
-
uiUtil.tabTransitionToSection('config', params.showUIAnimations);
-
refreshAPIStatus();
refreshCacheStatus();
uiUtil.checkUpdateStatus(appstate);
@@ -425,10 +426,8 @@ document.getElementById('btnAbout').addEventListener('click', function (event) {
document.getElementById('liConfigureNav').setAttribute('class', '');
document.getElementById('liAboutNav').setAttribute('class', 'active');
$('.navbar-collapse').collapse('hide');
-
// Show the selected content in the page
uiUtil.tabTransitionToSection('about', params.showUIAnimations);
-
// Use a timeout of 400ms because uiUtil.applyAnimationToSection uses a timeout of 300ms
setTimeout(resizeIFrame, 400);
});
@@ -1342,6 +1341,7 @@ document.getElementById('libraryBtn').addEventListener('click', function (e) {
Function('try{}catch{}')();
iframe.setAttribute('src', params.libraryUrl);
uiUtil.tabTransitionToSection('library', params.showUIAnimations);
+ resizeIFrame();
} catch (error) {
window.open(params.altLibraryUrl, '_blank')
}
From bd19ae71f0719f20600d8e438f34e529613e19da Mon Sep 17 00:00:00 2001
From: Jaifroid
Date: Thu, 2 Nov 2023 11:34:37 +0000
Subject: [PATCH 4/4] Make auto focus search bar depend on home key option
(#1144)
---
i18n/en.jsonp.js | 7 +++---
i18n/es.jsonp.js | 7 +++---
i18n/fr.jsonp.js | 7 +++---
www/css/app.css | 2 +-
www/index.html | 4 ++--
www/js/app.js | 53 +++++++++++++++++++++++---------------------
www/js/lib/uiUtil.js | 25 +++++++++++----------
7 files changed, 56 insertions(+), 49 deletions(-)
diff --git a/i18n/en.jsonp.js b/i18n/en.jsonp.js
index 4fbd95ca6..2f4b691c6 100644
--- a/i18n/en.jsonp.js
+++ b/i18n/en.jsonp.js
@@ -35,8 +35,8 @@ document.localeJson = {
"configure-display-slideaway-tip": "Header and footer will slide away when scrolling or (on fixed pages, swiping) down at least 50 pixels, and will slide back when you scroll up. On fixed pages, you can also use Ctrl/Command + UpArrow or DownArrow. The option is now on by default.",
"configure-display-uianimations": "Animate transition between app pages",
"configure-display-uianimations-tip": "The animation is on by default and can be disabled by unchecking this option.",
- "configure-display-homekeyfocus": "Use Home key to focus search bar (may rarely have side effects on ZIM files that handle Home key)",
- "configure-display-homekeyfocus-tip": "Enables quick access to search, no matter where you are in an article.",
+ "configure-display-homekeyfocus": "Home key and Home tab focus search bar (may have side effects on ZIMs that handle Home key)",
+ "configure-display-homekeyfocus-tip": "Auto-focuses the search bar when you press the Home key, and also when you click or tap on the Home tab. Enables quick access to search, no matter where you are in an article.",
"configure-display-openexternallinks": "Open external links in new tabs. Disabling this might break kiwix-js UI in some specific cases",
"configure-display-openexternallinks-tip": "Opens the external links outside kiwix-js (avoids some side-effects affecting kiwix-js UI).",
"configure-display-selectapptheme": "Select app theme (content inversion is experimental):",
@@ -132,6 +132,7 @@ document.localeJson = {
"dialog-error-title": "Error!",
"dialog-file-notset-message": "Data files not set",
"dialog-file-notset-title": "Archive not ready",
+ "dialog-focussearchbarcheck-message": "Please note that this setting focuses the search bar when you go to a ZIM landing page, disabling sliding away of header and footer on that page (only).",
"dialog-invalid-archivelocation-title": "Error: invalid archive files location",
"dialog-invalid-archivelocation-message": "It looks like you have put some archive files at the root of your sdcard (or internal storage). Please move them to a subdirectory",
"dialog-invalid-zim-title": "Invalid file format",
@@ -162,10 +163,10 @@ document.localeJson = {
"dialog-serviceworker-unsupported-fallback": "Use JQuery mode",
"dialog-serviceworker-defaultmodechange-title": "Change of default content injection mode",
"dialog-serviceworker-defaultmodechange-message": "
We have switched you to ServiceWorker mode (this is now the default). It supports more types of ZIM archives and is much more robust.
If you experience problems with this mode, you can switch back to the (now deprecated) JQuery mode. In that case, please report the problems you experienced to us (see About section).
",
- "dialog-slideawaycheck-title": "Warning",
"dialog-slideawaycheck-message": "This setting may not work correctly on Firefox OS. If you find that some ZIM links become unresponsive, try turning this setting off.",
"dialog-unsupported-archivetype-message": "
You are attempting to open a Zimit-style archive, which is currently unsupported in this app.
There is experimental support for this kind of archive in the Kiwix JS PWA. Go to: https://pwa.kiwix.org.
Alternatively, you can use Kiwix Serve to serve this archive to your browser from localhost. Kiwix Serve is included with Kiwix Desktop.
",
"dialog-unsupported-archivetype-title": "Unsupported archive type!",
+ "dialog-warning": "Warning",
"dialog-welcome-title": "Welcome",
"dialog-welcome-message": "Welcome to Kiwix! This application needs at least a ZIM file in your SD-card (or internal storage). Please download one and put it on the device (see About section). Also check that your device is not connected to a computer through USB device storage (which often locks the SD-card content)",
"about": "About",
diff --git a/i18n/es.jsonp.js b/i18n/es.jsonp.js
index c28d89504..ba3a173bf 100644
--- a/i18n/es.jsonp.js
+++ b/i18n/es.jsonp.js
@@ -35,8 +35,8 @@ document.localeJson = {
"configure-display-slideaway-tip": "El encabezado y el pie de página se ocultarán al desplazarse o (en páginas fijas, deslizar) hacia abajo al menos 50 píxeles, y volverán a aparecer al desplazarse hacia arriba. En las páginas fijas, también puede usar Ctrl/Command + FlechaArriba o FlechaAbajo. La opción está activada por defecto.",
"configure-display-uianimations": "Animar transición entre páginas de la aplicación",
"configure-display-uianimations-tip": "La animación está activada por defecto y puede ser desactivada desmarcando esta opción.",
- "configure-display-homekeyfocus": "Usar tecla Inicio para enfocar la barra de búsqueda (puede tener efectos secundarios en archivos ZIM que manejen la tecla Inicio)",
- "configure-display-homekeyfocus-tip": "Habilita acceso rápido a la búsqueda con el teclado, sin importar en qué parte del artículo esté.",
+ "configure-display-homekeyfocus": "La tecla y la pestaña Inicio enfocan la barra de búsqueda (puede tener efectos secundarios en archivos que manejen la tecla Inicio)",
+ "configure-display-homekeyfocus-tip": "Enfoca automáticamente la barra de búsqueda al pulsar la tecla Inicio, y también al hacer clic o tocar en la pestaña Inicio. Habilita acceso rápido a la búsqueda con el teclado, sin importar en qué parte del artículo esté.",
"configure-display-openexternallinks": "Abrir enlaces externos en nuevas pestañas. Si desactiva esto, se puede romper la interfaz de kiwix-js en algunos casos específicos",
"configure-display-openexternallinks-tip": "Abre los enlaces externos fuera de kiwix-js (evita algunos efectos secundarios que afectan la interfaz de kiwix-js).",
"configure-display-selectapptheme": "Seleccionar tema de la aplicación (la inversión de contenido es experimental):",
@@ -132,6 +132,7 @@ document.localeJson = {
"dialog-error-title": "¡Error!",
"dialog-file-notset-message": "El archivo no está cargado correctamente",
"dialog-file-notset-title": "Archivo no listo",
+ "dialog-focussearchbarcheck-message": "Tenga en cuenta que esta configuración enfoca la barra de búsqueda cuando abre la página de inicio de un archivo, y por eso desactiva el deslizamiento del encabezado y pie en esta página (únicamente).",
"dialog-invalid-archivelocation-title": "Error: ubicación de archivos no válida",
"dialog-invalid-archivelocation-message": "Parece que ha puesto algunos archivos de archivo en la raíz de su tarjeta SD (o almacenamiento interno). Por favor, muévalos a un subdirectorio",
"dialog-invalid-zim-title": "Formato de archivo inválido",
@@ -162,10 +163,10 @@ document.localeJson = {
"dialog-serviceworker-unsupported-fallback": "Use modo JQuery",
"dialog-serviceworker-defaultmodechange-title": "Cambio del modo de inyección de contenido predeterminado",
"dialog-serviceworker-defaultmodechange-message": "
Le hemos cambiado al modo ServiceWorker (ahora es el modo predeterminado). Soporta más tipos de archivo ZIM y es mucho más robusto.
Si tiene problemas con este modo, puede volver al modo JQuery (ahora obsoleto). En tal caso, por favor, informe de los problemas que ha experimentado (véase la página Información).
",
- "dialog-slideawaycheck-title": "¡Aviso!",
"dialog-slideawaycheck-message": "Esta configuración puede no funcionar correctamente en Firefox OS. Si encuentra que algunos enlaces ZIM no responden, se recomienda desactivar esta configuración.",
"dialog-unsupported-archivetype-message": "
Está intentando abrir un archivo de estilo Zimit, que actualmente no es compatible con esta aplicación.
Hay soporte experimental para este tipo de archivo en la PWA de Kiwix JS. Vaya a: https://pwa.kiwix.org.
Alternativamente, puede usar Kiwix Serve para servir este archivo a su navegador desde localhost. Kiwix Serve está incluido con Kiwix Desktop.
",
"dialog-unsupported-archivetype-title": "¡Tipo de archivo no compatible!",
+ "dialog-warning": "¡Aviso!",
"dialog-welcome-title": "Bienvenide",
"dialog-welcome-message": "¡Bienvenide a Kiwix! Esta aplicación necesita al menos un archivo ZIM en su tarjeta SD (o almacenamiento interno). Por favor, descargue uno y póngalo en el dispositivo (véase la sección Información). También compruebe que su dispositivo no está conectado a un ordenador a través del almacenamiento de dispositivos USB (que a menudo bloquea el contenido de la tarjeta SD).",
"about": "Información",
diff --git a/i18n/fr.jsonp.js b/i18n/fr.jsonp.js
index 0a8475423..abec3ef36 100644
--- a/i18n/fr.jsonp.js
+++ b/i18n/fr.jsonp.js
@@ -35,8 +35,8 @@ document.localeJson = {
"configure-display-slideaway-tip": "L'en-tête et le pied de page disparaîtront lors du défilement ou du balayage vers le bas d'au moins 50 pixels, et réapparaîtront lorsque vous remonterez. Sur les pages fixes, vous pouvez également utiliser Ctrl/Command + Flèche haut ou bas. L'option est maintenant activée par défaut.",
"configure-display-uianimations": "Animer la transition entre les pages de l'application",
"configure-display-uianimations-tip": "L'animation est activée par défaut et peut être désactivée en décochant cette option.",
- "configure-display-homekeyfocus": "Utiliser la touche Accueil pour mettre le focus sur la barre de recherche (peut avoir des effets secondaires sur les fichiers ZIM qui gèrent la touche Accueil)",
- "configure-display-homekeyfocus-tip": "Active l'accès rapide à la recherche par clavier, quel que soit l'endroit où vous vous trouvez dans l'article.",
+ "configure-display-homekeyfocus": "La touche et l'onglet Accueil mettent le focus sur la barre de recherche (peut avoir des effets secondaires chez les fichiers qui gèrent la touche Accueil)",
+ "configure-display-homekeyfocus-tip": "La barre de recherche se focalise automatiquement lorsque vous appuyez sur la touche Accueil, ainsi que lorsque vous cliquez ou tapez sur l'onglet Accueil. Active l'accès rapide à la recherche par clavier, quel que soit l'endroit où vous vous trouvez dans l'article.",
"configure-display-openexternallinks": "Ouvrir les liens externes dans de nouveaux onglets. Si vous désactivez cette option, l'interface de kiwix-js peut être cassée dans certains cas spécifiques",
"configure-display-openexternallinks-tip": "Ouvre les liens externes en dehors de kiwix-js (évite certains effets secondaires affectant l'interface de kiwix-js).",
"configure-display-selectapptheme": "Sélectionner le thème de l'application (le mode inversé est expérimentale) :",
@@ -132,6 +132,7 @@ document.localeJson = {
"dialog-error-title": "Erreur !",
"dialog-file-notset-message": "Le fichier n'est pas chargé correctement",
"dialog-file-notset-title": "Fichier non chargé",
+ "dialog-focussearchbarcheck-message": "Veuillez noter que ce paramètre met le focus sur la barre de recherche lorsque vous allez sur la page d'accueil d'un ZIM, désactivant le glissement de l'en-tête et du pied sur cette page (uniquement).",
"dialog-invalid-archivelocation-title": "Erreur : emplacement d'archive non valide",
"dialog-invalid-archivelocation-message": "Il semble que vous ayez placé des fichiers d'archive à la racine de votre carte SD (ou de votre stockage interne). Veuillez les déplacer dans un sous-répertoire",
"dialog-invalid-zim-title": "Format de fichier non valide",
@@ -162,10 +163,10 @@ document.localeJson = {
"dialog-serviceworker-unsupported-fallback": "Utiliser le mode JQuery",
"dialog-serviceworker-defaultmodechange-title": "Changement du mode d'injection de contenu par défaut",
"dialog-serviceworker-defaultmodechange-message": "
Nous vous avons basculé en mode ServiceWorker (c'est maintenant le mode par défaut). Il prend en charge plus de types de fichiers ZIM et est beaucoup plus robuste.
Si vous rencontrez des problèmes avec ce mode, vous pouvez revenir au mode JQuery (maintenant obsolète). Dans ce cas, veuillez signaler les problèmes que vous avez rencontrés (voir la page Informations).
",
- "dialog-slideawaycheck-title": "Avertissement",
"dialog-slideawaycheck-message": "Ce paramètre peut ne pas fonctionner correctement chez Firefox OS. Si vous constatez que certains liens ZIM deviennent inactifs, veuillez désactiver ce paramètre.",
"dialog-unsupported-archivetype-message": "
Vous essayez d'ouvrir un fichier de style Zimit, qui n'est actuellement pas pris en charge par cette application.
Il existe une prise en charge expérimentale de ce type de fichier dans la PWA de Kiwix JS. Allez sur : https://pwa.kiwix.org.
Alternativement, vous pouvez utiliser Kiwix Serve pour servir ce fichier à votre navigateur à partir de localhost. Kiwix Serve est inclus dans Kiwix Desktop.
",
"dialog-unsupported-archivetype-title": "Type de fichier non pris en charge !",
+ "dialog-warning": "Avertissement",
"dialog-welcome-title": "Bienvenue",
"dialog-welcome-message": "Bienvenue dans Kiwix ! Cette application a besoin d'au moins un fichier ZIM sur votre carte SD (ou stockage interne). Veuillez en télécharger un et le placer sur l'appareil (voir la section Informations). Veuillez également vérifier que votre appareil n'est pas connecté à un ordinateur via le stockage USB (ce qui bloque souvent le contenu de la carte SD).",
"about": "Informations",
diff --git a/www/css/app.css b/www/css/app.css
index 1f1d0fa0d..620093e7e 100644
--- a/www/css/app.css
+++ b/www/css/app.css
@@ -72,7 +72,7 @@
margin-bottom: 12px !important;
}
-#top, #articleContent, #footer {
+#top, #articleContent, #footer, article {
transition: transform 0.3s ease;
}
diff --git a/www/index.html b/www/index.html
index e758c1a36..0944c1328 100644
--- a/www/index.html
+++ b/www/index.html
@@ -522,10 +522,10 @@
Display settings
-
+
- Use Home key to focus search bar (may rarely have side effects on ZIM files that handle Home key)
+ Home key and Home tab focus search bar (may have side effects on ZIMs that handle Home key)
diff --git a/www/js/app.js b/www/js/app.js
index 179b7c8d7..2b6e5242d 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -146,27 +146,28 @@ function resizeIFrame () {
const libraryContent = document.getElementById('libraryContent');
const liHomeNav = document.getElementById('liHomeNav');
const nestedFrame = libraryContent.contentWindow.document.getElementById('libraryIframe');
- uiUtil.showSlidingUIElements();
- if (library.style.display !== 'none') {
- // We are in Library, so we set the height of the library iframes to the window height minus the header height
- const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
- libraryContent.style.height = window.innerHeight + 'px';
- nestedFrame.style.height = window.innerHeight - headerHeight + 'px';
- region.style.overflowY = 'hidden';
- } else if (!liHomeNav.classList.contains('active')) {
- // We are not in Home, so we reset the region height
- region.style.height = window.innerHeight + 'px';
- region.style.overflowY = 'auto';
- } else {
- // IE cannot retrieve computed headerStyles till the next paint, so we wait a few ticks
- setTimeout(function () {
+ // There is a race condition with the slide animations, so we have to wait more than 300ms
+ setTimeout(function () {
+ uiUtil.showSlidingUIElements();
+ if (library.style.display !== 'none') {
+ // We are in Library, so we set the height of the library iframes to the window height minus the header height
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
+ libraryContent.style.height = window.innerHeight + 'px';
+ nestedFrame.style.height = window.innerHeight - headerHeight + 'px';
+ region.style.overflowY = 'hidden';
+ } else if (!liHomeNav.classList.contains('active')) {
+ // We are not in Home, so we reset the region height
+ region.style.height = window.innerHeight + 'px';
+ region.style.overflowY = 'auto';
+ } else {
// Get header height *including* its bottom margin
const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
articleContainer.style.height = window.innerHeight - headerHeight + 'px';
// Hide the scrollbar of Configure / About
region.style.overflowY = 'hidden';
- }, 100);
- }
+ }
+ // IE cannot retrieve computed headerStyles till the next paint, so we wait a few ticks even if UI animations are disabled
+ }, params.showUIAnimations ? 400 : 100);
// Remove and add the scroll event listener to the new article window
// Note that IE11 doesn't support wheel or touch events on the iframe, but it does support keydown and scroll
@@ -386,7 +387,7 @@ document.getElementById('btnHome').addEventListener('click', function (event) {
// Give the focus to the search field, and clean up the page contents
document.getElementById('prefix').value = '';
- document.getElementById('prefix').focus();
+ if (params.useHomeKeyToFocusSearchBar) document.getElementById('prefix').focus();
var articleList = document.getElementById('articleList');
var articleListHeaderMessage = document.getElementById('articleListHeaderMessage');
while (articleList.firstChild) articleList.removeChild(articleList.firstChild);
@@ -489,7 +490,7 @@ document.getElementById('slideAwayCheck').addEventListener('change', function (e
if (typeof navigator.getDeviceStorages === 'function') {
// We are in Firefox OS, which may have a bug with this setting turned on - see [kiwix-js #1140]
uiUtil.systemAlert(translateUI.t('dialog-slideawaycheck-message') || ('This setting may not work correctly on Firefox OS. ' +
- 'If you find that some ZIM links become unresponsive, try turning this setting off.'), translateUI.t('dialog-slideawaycheck-title') || 'Warning');
+ 'If you find that some ZIM links become unresponsive, try turning this setting off.'), translateUI.t('dialog-warning') || 'Warning');
}
settingsStore.setItem('slideAway', params.slideAway, Infinity);
// This has methods to add or remove the event listeners needed
@@ -501,13 +502,15 @@ document.querySelectorAll('input[type="checkbox"][name=showUIAnimations]').forEa
settingsStore.setItem('showUIAnimations', params.showUIAnimations, Infinity);
})
});
-document.querySelectorAll('input[type="checkbox"][name=useHomeKeyToFocusSearchBar]').forEach(function (element) {
- element.addEventListener('change', function () {
- params.useHomeKeyToFocusSearchBar = !!this.checked;
- settingsStore.setItem('useHomeKeyToFocusSearchBar', params.useHomeKeyToFocusSearchBar, Infinity);
- switchHomeKeyToFocusSearchBar();
- })
-})
+document.getElementById('useHomeKeyToFocusSearchBarCheck').addEventListener('change', function (e) {
+ params.useHomeKeyToFocusSearchBar = e.target.checked;
+ settingsStore.setItem('useHomeKeyToFocusSearchBar', params.useHomeKeyToFocusSearchBar, Infinity);
+ switchHomeKeyToFocusSearchBar();
+ if (params.useHomeKeyToFocusSearchBar && params.slideAway) {
+ uiUtil.systemAlert(translateUI.t('dialog-focussearchbarcheck-message') || 'Please note that this setting focuses the search bar when you go to a ZIM landing page, disabling sliding away of header and footer on that page (only).',
+ translateUI.t('dialog-warning') || 'Warning');
+ }
+});
document.querySelectorAll('input[type="checkbox"][name=openExternalLinksInNewTabs]').forEach(function (element) {
element.addEventListener('change', function () {
params.openExternalLinksInNewTabs = !!this.checked;
diff --git a/www/js/lib/uiUtil.js b/www/js/lib/uiUtil.js
index 0e5ca68bd..0bb61665d 100644
--- a/www/js/lib/uiUtil.js
+++ b/www/js/lib/uiUtil.js
@@ -38,15 +38,16 @@ const footer = document.getElementById('footer');
*/
function hideSlidingUIElements () {
const articleContainer = document.getElementById('articleContent');
- const headerStyles = getComputedStyle(header);
- const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom) - 2;
+ const articleElement = document.querySelector('article');
const footerStyles = getComputedStyle(footer);
const footerHeight = parseFloat(footerStyles.height) + parseFloat(footerStyles.marginTop) - 2;
- header.style.transform = 'translateY(-' + headerHeight + 'px)';
- articleContainer.style.transform = 'translateY(-' + headerHeight + 'px)';
- const iframeHeight = parseFloat(articleContainer.style.height.replace('px', ''));
- articleContainer.style.height = iframeHeight + headerHeight + 'px';
+ const headerStyles = getComputedStyle(header);
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom) - 2;
+ const iframeHeight = parseFloat(articleElement.style.height.replace('px', ''));
footer.style.transform = 'translateY(' + footerHeight + 'px)';
+ articleContainer.style.height = iframeHeight + headerHeight + 'px';
+ header.style.transform = 'translateY(-' + headerHeight + 'px)';
+ articleElement.style.transform = 'translateY(-' + headerHeight + 'px)';
}
/**
@@ -54,15 +55,15 @@ function hideSlidingUIElements () {
*/
function showSlidingUIElements () {
const articleContainer = document.getElementById('articleContent');
+ const articleElement = document.querySelector('article');
+ const headerStyles = getComputedStyle(document.getElementById('top'));
+ const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
header.style.transform = 'translateY(0)';
// Needed for Windows Mobile to prevent header disappearing beneath iframe
- articleContainer.style.transform = 'translateY(-1px)';
+ articleElement.style.transform = 'translateY(-1px)';
footer.style.transform = 'translateY(0)';
- setTimeout(function () {
- const headerStyles = getComputedStyle(document.getElementById('top'));
- const headerHeight = parseFloat(headerStyles.height) + parseFloat(headerStyles.marginBottom);
- articleContainer.style.height = window.innerHeight - headerHeight + 'px';
- }, 200);
+ articleElement.style.height = window.innerHeight - headerHeight + 'px';
+ articleContainer.style.height = window.innerHeight - headerHeight + 'px';
}
let scrollThrottle = false;