Before this fix clicking an external link in the viewer iframe had no
effect (other than an error being reported in the browser dev tools
console) because the attempt to navigate the top browser context was
suppressed due to sandboxing.
A workaround is to let the external link blocker page to be loaded in the
viewer iframe and then detect that situation and handle it in the viewer JS
code.
This commit makes external links clickable but (temporarily)
handles them by unconditionally displaying the confirmation page (as if
kiwix-serve has been started with the --blockexternal option). This will
be fixed shortly.
A small defect is that the browsing history entry preceding the external
resource access confirmation page is duplicated.
The previous "fix" (merged PR #924) was buggy. It not only didn't work
in Chromium v90, but in more recent versions too.
I verified that this fix works in Firefox (v111) and Chromium (v90):
- Attempts by the ZIM content to break out of the viewer iframe are
blocked.
- PDFs are displayed in the viewer.
Added a <noscript> elements which hides everything on the welcome page if javascript is not enabled.
It displays a text to tell the user to navigate to /nojs endpoint
Added cursor type and hints to the UI language selection button. The
hints are always in English since seeing a hint in an unfamiliar language
doesn't help and English is the current lingua franca.
This prevents scripts running inside an iframe from inadvertently
manipulating the top browsing context. However a malicious script could
still remove the sandboxing imposed on it (because the combination of
"allow-same-origin" and "allow-scripts" is vulnerable).
Since kiwixNav is sticky for larger screens now, the tiles area on mobile devices is incredibly low.
This change hides kiwixNav if the screen is scrolled.
If a translation JSON file doesn't contain the 'name' (self-name)
attribute of the translation language then that language is not included
in the list of languages available in the UI language selector.
The language selector on the welcome page has been replaced with
a smaller button that opens a modal language selector. Though the
code for introducing such a modal language selector has been added
in i18n.js, its appearance relies on styles defined in index.css.
Once this new UI for changing the UI language is approved, it must be
used in the ZIM viewer too.
Known issues:
- selecting the language with arrow keys (using the keyboard only,
without pressing space first, so that the full list of languages is
shown) doesn't work because as soon as the current language is changed
the modal language selector disappears.
If the userlang query param is present in the URL it is used to set the
UI language and then is removed from the URL.
Unlike the ZIM viewer, changing the UI language on the welcome page
isn't recorded in the navigation history (and probably it should work
the same way in the ZIM viewer where the appearance of the web page is
affected by the UI language changes to a significantly smaller extent).
This translation has to deal with handling of plural forms which is a
tricky part of internationalization, but we are not going to complicate
things in our code and will offload the headache to translators (they
will have to invent a single message for all numbers).
This change adds a <link> element in the head node of welcome page.
Browsers with extensions for RSS will show a sign to navigate to the feed.
The link changes based on current set filters.
The recently introduced ZIM viewer UI language selector looked
adequately nice under Firefox without any explicit styling applied.
Under SeaMonkey, however, its default look and feel was intolerable, so
I used this opportunity to make the UI language selector comply with the
current fashion of the ZIM viewer toolbar.
SeaMonkey doesn't yet support [Window.visualViewport][1]. As a result the
height of the content iframe element was initialized to the default 150
pixels and never changed. Fortunately there is [Window.innerHeight][2]
which is supported from the very first days of the Gecko layout engine.
The difference between `Window.visualViewport.height` and
`Window.innerHeight` is that the latter also includes
- the height of the horizontal scroll bar, if present (but in a correctly
implemented ZIM viewer there shouldn't be a horizontal scroll bar for the
full web-page, so it's OK)
- the height of the on-screen keyboard (which is mostly used on mobile
devices where SeaMonkey doesn't run). And it is also arguable if the
appearing on-screen keyboard should squeeze the iframe or slide over
it (in which latter case it may make more sense to always use `innerHeight`
instead of `visualViewport.height`).
[1]: https://developer.mozilla.org/en-US/docs/Web/API/Window/visualViewport
[2]: https://developer.mozilla.org/en-US/docs/Web/API/Window/innerHeight