/* score-reader.js — Page navigation, zoom and pan for the full score reader. Configuration is read from #score-reader-stage data attributes: data-page-count — total number of score pages data-pages — comma-separated list of absolute page SVG URLs Pages are fetched and inlined as live SVG rather than pointed at with an . Three things follow from that, and they are the reason for it: the notation inherits the theme's `color` (an -loaded SVG resolves `currentColor` against its own root, so it can only ever draw black); zooming is a width change on a vector, not a rescaled bitmap; and the elements are in the DOM, which is what any later staff- or measure-level feature will need. */ (function () { 'use strict'; var stage = document.getElementById('score-reader-stage'); var viewport = document.getElementById('score-reader-viewport'); var pageEl = document.getElementById('score-page'); var folio = document.getElementById('score-folio'); var prevBtn = document.getElementById('score-prev'); var nextBtn = document.getElementById('score-next'); var bar = document.getElementById('score-reader-bar'); if (!stage || !viewport || !pageEl || !folio || !prevBtn || !nextBtn) return; var pages = (stage.dataset.pages || '').split(',').filter(function (p) { return p.length > 0; }); var pageCount = pages.length; if (pageCount === 0) return; /* nothing to display */ var currentPage = 1; var ratio = null; /* page width / height, learned from page 1 */ var naturalW = null; /* page width in CSS px at 100 % */ var cache = new Map(); /* ------------------------------------------------------------------ Fetching and inlining ------------------------------------------------------------------ */ /* An ordinary web link, a fragment, or a relative path. Mirrors the convention Catalog.safeHref applies on the Haskell side. */ var SAFE_HREF = /^(https?:|\/|#|\.)/i; /* innerHTML and adoptNode never execute a