Skip to content

Image component integration - #219

Open
hizclick wants to merge 93 commits into
developfrom
image-component-integration
Open

hizclick wants to merge 93 commits into
developfrom
image-component-integration

Conversation

@hizclick

@hizclick hizclick commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

Integration of the edirom-image-viewer web component

Description, Context and related Issue

This PR integrates the new OpenSeadragon-based edirom-image-viewer web component into the Edirom Online Frontend and rewires the existing ExtJS image window to drive it. It replaces the previous tightly-coupled OpenSeadragon usage with a reusable, attribute-driven custom element (rendered in its own Shadow DOM), so the facsimile viewer can be developed and reused independently of the ExtJS application.

The result is a clean split of responsibilities: the component owns all viewer rendering (tiles, pagination, and every overlay — measures, measure labels, movements, annotation badges, and their tooltips), while ExtJS only provides data and the surrounding window UI. The host communicates with the component purely through attributes and custom events — no direct OpenSeadragon API calls remain in the ExtJS layer.

What this PR delivers:

  • New web component (resources/js/edirom-image-viewer/): a self-contained edirom-image-viewer.js custom element built on OpenSeadragon, with IIIF manifest / tile-source loading, sequence & collection modes, zoom/pan/rotation, configurable native controls, and a fully attribute-driven API plus custom events. Includes component metadata (README.md, LICENSE, CITATION.cff, CODE_OF_CONDUCT.md). The component is included as a git submodule.
  • ExtJS integration (OpenSeaDragonViewer.js): the ExtJS image viewer now instantiates the custom element and communicates with it purely through attributes/events instead of direct OpenSeadragon API calls — keeping all viewer state (page, zoom, rotation, controls) in sync with the surrounding Edirom UI (page spinner, top bar, source views).
  • Unified zones-data overlay model: every overlay type — annotations, measures, measure labels, and movements (mdivs) — is now pushed through one zones-data map keyed by a namespaced zone key (measure:<key>, mdiv:<key>, annotation:<…>). Each zone entry carries its type, optional page, rectangle (ulx/uly/lrx/lry), CSS classes (containerClass/innerClass), an optional label, a group (so badges on the same region stack), a preloaded tooltip HTML, a click fn, and generic filters tokens. Each sub-map (measures / mdivs / annotations) is merged on its own push, so re-pushing one type never drops the others. This replaces the former separate measures-data / mdivs-data / annotations-data / measure-numbers-data attributes.
  • Universal zone navigation attribute: navigation to any zone (a bar, a movement, or a generic region) goes through the single semantic zone attribute, set to the namespaced key with an optional |<nonce> token so repeated jumps to the same key re-fire. Same-page jumps fit the region directly; cross-page jumps switch page, wait for tiles, then fit — enabling the source / concordance views to jump the facsimile to a specific bar or movement, including across pages. Wired through PageBasedView / MeasureBasedView / SourceView.
  • Annotation overlays (push model): annotations are pushed as annotation-typed entries in zones-data; the component renders the clickable badges in its Shadow DOM and fires a zone-click event back to the host for the click action. The annotation tooltip is rendered by the component itself from a per-zone tooltip HTML field — the host preloads each annotation's server-rendered tooltip HTML up front (fetched in parallel, with a safety-net timeout) and pushes it into zones-data, and the relevant edition / overlay CSS is injected into the Shadow DOM so the tooltip is styled correctly.
  • Type visibility via visible-types: whole overlay types are shown/hidden through the visible-types attribute (a JSON array of the zone types to render, e.g. ["annotation","measure"]), without discarding the pushed zones-data. This is a pure visibility switch (no re-fetch / re-push) and replaces the former per-feature show-annotations / show-measure-numbers booleans.
  • Generic filtering via hidden-filters (two-way sync): category & priority filtering now uses a single generic hidden-filters set — the union of the taxonomy tokens the user has unchecked; the component hides any annotation carrying one of them. "No filter" is the empty set and "hide all" is every token, so the old ["undefined"] / [] sentinels and the separate visible-categories / visible-priorities attributes are gone. The component emits a filter-changed event (carrying detail.hiddenFilters) whenever the filter changes — including when hidden-filters is set externally (e.g. via DevTools) — so the host keeps its filter-menu checkboxes in sync with no feedback loop.
  • Measure labels folded into zones: measure-number boxes are no longer a separate attribute; each measure zone carries its label and label CSS class (measureInner / measureInnerEmpty), and they show/hide with the measure type via visible-types, re-applied on every page render.
  • Total-pages sync: the component fires a total-pages-changed event when its tile-source set shrinks (e.g. a page is removed), so the host trims its page list / spinner bounds and notifies the owning view.
  • Zoom & jump fixes: because OpenSeadragon's animation spring does not advance in this embedding, all viewport operations are forced to immediate mode, and setZoom now clamps to [minzoomlevel, maxzoomlevel] — fixing zoom-bar overshoot beyond the configured maximum and jump/zoom spring-back.
  • Fullscreen fix: the component overrides OpenSeadragon's default setFullScreen to use the standard Fullscreen API on the component host element.
  • Declarative view-mode: the active source view mode is pushed to the component via the view-mode attribute so host code can react.
  • Documentation: the component README.md documents all attributes (incl. preserveviewport, minzoomlevel, maxzoomlevel, zones-data, zone, visible-types, hidden-filters, fitrect, triggerhome, sequencemode, view-mode), public methods, events (page-changed, total-pages-changed, zone-click, filter-changed, zoom, image-ready), and the "Zones", "Region Navigation" and "Annotation Overlays" guides.

Refs #12

How Has This Been Tested?

Tested locally with the full Edirom Online stack via Docker Compose, building the frontend from this branch against the develop backend:

export FE_BRANCH=image-component-integration && \
export BE_BRANCH=develop && \
docker compose down --volumes --remove-orphans && \
docker compose build --no-cache && \
docker compose up

Manual verification in the running app (eXist-db at localhost:8080, app at /exist/apps/Edirom-Online-Frontend/):

  • Image loading & paging: sources load via the component; page spinner, next/previous, and direct page jumps stay in sync; sequence mode (true) loads a single page item and collection mode (false) loads all images. Removing a page fires total-pages-changed and trims the host page list / spinner.
  • Measure switching: push measures into zones-data, then trigger zone="measure:<key>|<nonce>". Verified both same-page and cross-page jumps fire page-changed and fit the region aspect-correctly and centered (e.g. a measure on page 2 with rect 1170,240 → 1360,1180).
  • Movement (mdiv) switching: push movements into zones-data and trigger zone="mdiv:<key>|<nonce>" to jump to a movement's first page; verified correct page/movement navigation from the source views.
  • Zoom clamping: with maxzoomlevel=5, setZoom(10) clamps to 5; with minzoomlevel=0.5, setZoom(0.01) clamps to 0.5; no jump/zoom spring-back.
  • Annotations: push annotation zones into zones-data (each carrying its type:'annotation', rect, innerClass, preloaded tooltip HTML, click fn, and filters tokens) and make them visible via viewer.setAttribute('visible-types', '["annotation"]'); the badge renders, hovering shows the component-rendered tooltip (styled via the injected CSS), and clicking fires zone-click so the host runs the action.
  • Type visibility: toggling visible-types between ["annotation","measure"] and [] shows/hides whole overlay types without re-pushing zones-data, and the chosen state persists across page changes.
  • Filtering (hidden-filters): viewer.setAttribute('hidden-filters', '["ediromAnnotPrio1"]') hides annotations carrying that token; '[]' shows all. Setting the attribute externally re-checks/unchecks the matching host menu items via the filter-changed event, with no feedback loop.
  • Measure labels: measure zones with a label render the numbered box and empty ones use measureInnerEmpty; visibility follows the measure type in visible-types and persists across page changes.
  • No-warning defaults: a freshly created viewer with zone="", visible-types="[]", hidden-filters="[]", view-mode="" produces no console warnings.

Types of changes

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Documentation Update
  • Improvement

Overview

  • I have updated the inline documentation accordingly.
  • I have performed a self-review of my code, according to the style guide
  • I have read the CONTRIBUTING document.

@hizclick

Copy link
Copy Markdown
Contributor Author

Opened PR #276 to extract the duplicated ImageViewer host-side setup into a shared ImageViewerHost.js helper.

@daniel-jettka daniel-jettka moved this from Done to Ready for Review in Edirom Development Sep 16, 2026
@hizclick

Copy link
Copy Markdown
Contributor Author

hizclick and others added 3 commits September 22, 2026 09:30
#275)

* Remove FontAwesome dependency from edirom-image-viewer by making annotation stylesheet injection and category icons fully host-driven; closes #271.

* populate iconHtml for the beschreibung/rasurTektur annotation zones when building zones-data

* remove OpednSeadragon from resources and update the styling of annotations
hizclick and others added 3 commits September 22, 2026 14:27
…m-Online-Frontend into image-component-integration
[ftr]: ImageViewer host wiring into a shared helper
@DennisFriedl

DennisFriedl commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

this PR points to an old submodule version of the image-viewer (commit 7613617. Could you update it to point to the newest commit d8b80d564e9cfb08833a87aa82dc7aa73e9bf07d?

Could you also please update this PR to be up to date with develop?

…tegration

# Conflicts:
#	app/controller/window/source/SourceView.js
#	app/view/window/image/ImageViewer.js
#	app/view/window/image/OpenSeaDragonViewer.js
#	app/view/window/source/MeasureBasedView.js
#	app/view/window/source/PageBasedView.js
#	app/view/window/source/SourceView.js
#	app/view/window/text/TextFacsimileSplitView.js
@hizclick

Copy link
Copy Markdown
Contributor Author

@DennisFriedl, now the merge conflict is resolved, and the submodule is up to date

@DennisFriedl

DennisFriedl commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

I noticed the following issues:

  1. The jumping between zones is abrupt again and not smooth as it should be.
  2. The viewer does not zoom to the zone initally when switching to the measure based view but stays in the "zoomed out" view.
  3. Measure numbers get duplicated when navigating to the next page. Then the measure numbers of the current and the previous page are rendered at the same time.

@hizclick

Copy link
Copy Markdown
Contributor Author

I noticed the following issues:

  1. The jumping between zones is abrupt again and not smooth as it should be.
  2. The viewer does not zoom to the zone initally when switching to the measure based view but stays in the "zoomed out" view.
  3. Measure numbers get duplicated when navigating to the next page. Then the measure numbers of the current and the previous page are rendered at the same time.

Thank you @DennisFriedl, fixed with commit c3f6ee2

@DennisFriedl

Copy link
Copy Markdown
Member

Thank you, @hizclick. These issues seem to be resolved now!

While testing this PR I had the following thoughts about old behaviour of the Image Viewer that your PR did not introduce but that we could maybe think about solving with it?

1. Are the annotation icons centered correctly?

Bildschirmfoto 2026-10-26 um 13 32 55

Here the icons seem to be centered horizontally but the first icon is cut off at the bottom, isn't it?

Bildschirmfoto 2026-10-26 um 13 32 59

But here the same icons seem to be aligned more to the right.

Bildschirmfoto 2026-10-26 um 13 33 06

And here the icons seem to move even further to the right and get cut off at the right side.

2. The annotations are covering the measure numbers

Currently the annotations are fully overlaying the measure numbers, making the measure numbers unreadable. Would it be a complicated to e.g. place the measure number below the annotations column?

3. Switching between the Page Based View and Measure Based View

At the moment, the Page Based View and Measure Based View have two distinct counters of the "current page". When I start the Image Viewer on the Page Based View on page 1, then switch to the Measure Based View and move to another page (let's say page 2), a switch back to the Page Based View leads me back to page 1 even though the "current page" is page 2, isn't it? In my optinion a switch between the views should not disturb the currently opened page. Navigating to page 2 in the Measure Paged View a switch to the Page Based View should also show me the second page but fully zoomed out. The same happens the other way around. Navigating to page 3 in the Page Based View and then switching to the Measure Based View shows me the last selected measure OR the first measure of the document which can be on completely different pages. Instead, I would expect a measure view of the first measure of the currently selected page (if this page contains a measure), wouldn't I?

@DennisFriedl

Copy link
Copy Markdown
Member

I created a PR to fix the centering issue: #325

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready for Review

Development

Successfully merging this pull request may close these issues.

[ftr] Integration of edirom-image-viewer web component

6 participants