Compare commits

...

5 Commits

Author SHA1 Message Date
caribaud b12cf2c4f1 new eslint fixes run 2023-06-05 00:40:25 +02:00
caribaud 5a1987f77b single quote -> double quote 2023-06-05 00:20:32 +02:00
caribaud f1cfb326d5 Fix declaration order 2023-06-05 00:19:28 +02:00
caribaud 7299157521 new round of fixing eslint findings 2023-06-05 00:16:02 +02:00
caribaud c6f88e8d85 fix trailling whitespace 2023-06-04 21:38:56 +02:00
2 changed files with 229 additions and 208 deletions

View File

@ -31,6 +31,9 @@
"function-paren-newline": ["warn", "consistent"], "function-paren-newline": ["warn", "consistent"],
"no-magic-numbers": ["error", {"ignore": [0,1,2,100]}], "no-magic-numbers": ["error", {"ignore": [0,1,2,100]}],
"quote-props": ["warn", "as-needed"], "quote-props": ["warn", "as-needed"],
"no-unused-vars": ["error", {"argsIgnorePattern": "^_"}] "no-unused-vars": ["error", {"argsIgnorePattern": "^_"}],
"max-len" : ["warn", {"code": 88}],
"capitalized-comments": "off",
"operator-linebreak": ["warn", "before"]
} }
} }

View File

@ -45,7 +45,7 @@ const VERSION_DISPLAY = document.getElementById("melpomene-version");
var PAGES_ZOOMS; var PAGES_ZOOMS;
// The variable ZOOMS can either be defined by another JS file or contructed at init // The variable ZOOMS can either be defined by another JS file or contructed at init
if (typeof PAGES_ZOOMS === 'undefined') if (typeof PAGES_ZOOMS === "undefined")
{ {
PAGES_ZOOMS = null; PAGES_ZOOMS = null;
} }
@ -64,109 +64,6 @@ var MOUSEWHELL_WAIT = false;
// UTILITIES // UTILITIES
// ============= // =============
// Zooms utilites
// --------------
function globalZoomScale()
{
if (READER_PAGES.dataset.globalZoomScale !== undefined)
{
return parseFloat(READER_PAGES.dataset.globalZoomScale);
}
return 1.0;
}
function globalZoomOffsetX()
{
if (READER_PAGES.dataset.globalZoomOffset !== undefined)
{
return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[0]);
}
return 0.0;
}
function globalZoomOffsetY()
{
if (READER_PAGES.dataset.globalZoomOffset !== undefined)
{
return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(',')[1]);
}
return 0.0;
}
function loadZoomsFromImgTagsIfRequired()
{
// Zooms may be defined by another JS file
if (PAGES_ZOOMS === null)
{
PAGES_ZOOMS = [];
// parse the data-zooms of each img and and the page number info
for (let idx = 0; idx < READER_PAGES.children.length; idx += 1)
{
const zoomsRawData = READER_PAGES.children[idx].dataset.zooms;
// ';' separates zooms data, ',' separates values
// We add the page number (adding 1 because of indexing)
const zooms = zoomsRawData.split(";").map(
zoom => [idx + 1].concat(
zoom.split(',').map(
value => parseFloat(value)
)
)
);
PAGES_ZOOMS = PAGES_ZOOMS.concat(zooms);
}
}
}
function getFirstZoomOfPage(pageNumber)
{
for (let zoomIdx = 0; zoomIdx < PAGES_ZOOMS.length; zoomIdx += 1)
{
if (PAGES_ZOOMS[zoomIdx][0] === pageNumber)
{
return zoomIdx;
}
}
}
function getZoomCountForPage(pageNumber)
{
return PAGES_ZOOMS.filter(zoom => zoom[0] === pageNumber).length;
}
function getCurrentZoomIndexForPage()
{
const previousZoomsCount = PAGES_ZOOMS.filter(zoom => zoom[0] < CURRENT_PAGE).length;
return CURRENT_ZOOM - previousZoomsCount + 1;
}
function getReadingProgressPercent()
{
const progressPerPage = 1 / getPagesCount();
if (IS_PAGE_MODE)
{
return 100 * progressPerPage * CURRENT_PAGE;
}
const progressPerZoom = progressPerPage / getZoomCountForPage(CURRENT_PAGE);
const readingProgress = (CURRENT_PAGE - 1) * progressPerPage + getCurrentZoomIndexForPage() * progressPerZoom;
return 100 * readingProgress;
}
function updateProgressBar()
{
PROGRESS_BAR.style.width = getReadingProgressPercent() + "%";
}
// Dimensions utilites // Dimensions utilites
// ------------------- // -------------------
@ -194,11 +91,11 @@ function pageMaxHeight()
{ {
let maxHeight = 0; let maxHeight = 0;
for (let i = 0; i < READER_PAGES.children.length; i += 1) for (let pageIdx = 0; pageIdx < READER_PAGES.children.length; pageIdx += 1)
{ {
if(READER_PAGES.children[i].naturalHeight > maxHeight) if (READER_PAGES.children[pageIdx].naturalHeight > maxHeight)
{ {
maxHeight = READER_PAGES.children[i].naturalHeight; maxHeight = READER_PAGES.children[pageIdx].naturalHeight;
} }
} }
@ -207,7 +104,7 @@ function pageMaxHeight()
function pageVerticalOffset(pageNumber) function pageVerticalOffset(pageNumber)
{ {
return ( pageMaxHeight() - pageOriginalHeight(pageNumber) ) / 2; return (pageMaxHeight() - pageOriginalHeight(pageNumber)) / 2;
} }
function previousPagesWidth(pageNumber) function previousPagesWidth(pageNumber)
@ -224,64 +121,128 @@ function previousPagesWidth(pageNumber)
return totalWidth; return totalWidth;
} }
// Zooms utilites
// --------------
function globalZoomScale()
{
if (READER_PAGES.dataset.globalZoomScale !== undefined)
{
return parseFloat(READER_PAGES.dataset.globalZoomScale);
}
return 1.0;
}
function globalZoomOffsetX()
{
if (READER_PAGES.dataset.globalZoomOffset !== undefined)
{
return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(",")[0]);
}
return 0.0;
}
function globalZoomOffsetY()
{
if (READER_PAGES.dataset.globalZoomOffset !== undefined)
{
return parseFloat(READER_PAGES.dataset.globalZoomOffset.split(",")[1]);
}
return 0.0;
}
function loadZoomsFromImgTagsIfRequired()
{
// Zooms may be defined by another JS file
if (PAGES_ZOOMS === null)
{
PAGES_ZOOMS = [];
// parse the data-zooms of each img and and the page number info
for (let idx = 0; idx < READER_PAGES.children.length; idx += 1)
{
const zoomsRawData = READER_PAGES.children[idx].dataset.zooms;
// ";" separates zooms data, "," separates values
// We add the page number (adding 1 because of indexing)
const zooms = zoomsRawData.split(";").map(
(zoom) => [idx + 1].concat(
zoom.split(",").map(
(value) => parseFloat(value)
)
)
);
PAGES_ZOOMS = PAGES_ZOOMS.concat(zooms);
}
}
}
function getFirstZoomOfPage(pageNumber)
{
for (let zoomIdx = 0; zoomIdx < PAGES_ZOOMS.length; zoomIdx += 1)
{
if (PAGES_ZOOMS[zoomIdx][0] === pageNumber)
{
return zoomIdx;
}
}
return undefined;
}
function getZoomCountForPage(pageNumber)
{
return PAGES_ZOOMS.filter((zoom) => zoom[0] === pageNumber).length;
}
function getCurrentZoomIndexForPage()
{
const previousZoomsCount = PAGES_ZOOMS.filter((zoom) => zoom[0] < CURRENT_PAGE).length;
return CURRENT_ZOOM - previousZoomsCount + 1;
}
function getReadingProgressPercent()
{
const progressPerPage = 1 / getPagesCount();
if (IS_PAGE_MODE)
{
return 100 * progressPerPage * CURRENT_PAGE;
}
const progressPerZoom = progressPerPage / getZoomCountForPage(CURRENT_PAGE);
let readingProgress = (CURRENT_PAGE - 1) * progressPerPage;
readingProgress += getCurrentZoomIndexForPage() * progressPerZoom;
return 100 * readingProgress;
}
function updateProgressBar()
{
PROGRESS_BAR.style.width = `${getReadingProgressPercent()}%`;
}
// ========= // =========
// ACTIONS // ACTIONS
// ========= // =========
function initReader() function updateFocusByWidth(width)
{ {
VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION); FOCUS_OVERLAY_WIDTH.style.width = `${width / READER_CONTENT_FRAME.clientWidth * 100}%`;
FOCUS_OVERLAY_HEIGHT.style.height = "100%";
loadZoomsFromImgTagsIfRequired();
moveReaderDisplayToZoom(0);
// Smoothly show pictures when they intersect with the viewport
const visibilityObserver = new IntersectionObserver(
(entries, _observer) =>
{
entries.forEach((entry) =>
{
if (entry.isIntersecting)
{
entry.target.style.opacity = 1;
entry.target.style.visibility = "visible";
}
else
{
entry.target.style.opacity = 0;
entry.target.style.visibility = "hidden";
}
});
},
{ root: READER_CONTENT_FRAME, rootMargin: "-10px" }
);
for (let i = 0; i < READER_PAGES.children.length; i += 1)
{
const img = READER_PAGES.children[i];
visibilityObserver.observe(img);
PROGRESS_BAR_PAGES.appendChild(document.createElement("div"));
}
READER_PAGES.style.display = "flex";
setTimeout(
() => { READER_PAGES.hidden = false },
"300"
);
setTimeout(
() =>
{
HELP_CONTROLS.style.opacity = null;
HELP_CONTROLS.style.transform = null;
},
DELAY_BEFORE_HIDDING_CONTROLS
);
} }
function updateFocusByHeight(height)
{
FOCUS_OVERLAY_WIDTH.style.width = "100%";
FOCUS_OVERLAY_HEIGHT.style.height = `${height / READER_CONTENT_FRAME.clientHeight * 100}%`;
}
function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy) function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy)
{ {
@ -307,8 +268,8 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy)
width = width + posx; width = width + posx;
posx = 0; posx = 0;
} }
if ((posx + width) > pageOriginalWidth(pageNumber)) if (posx + width > pageOriginalWidth(pageNumber))
{ {
width = pageOriginalWidth(pageNumber) - posx; width = pageOriginalWidth(pageNumber) - posx;
} }
@ -319,18 +280,18 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy)
height = height + posy; height = height + posy;
posy = 0; posy = 0;
} }
if ((posy + height) > pageOriginalHeight(pageNumber)) if (posy + height > pageOriginalHeight(pageNumber))
{ {
height = pageOriginalHeight(pageNumber) - posy; height = pageOriginalHeight(pageNumber) - posy;
} }
// Align the top-left corner of the frame with the page // Align the top-left corner of the frame with the page
READER_PAGES.style.transform = "translate(-" + previousPagesWidth(pageNumber) + "px, -" + pageVerticalOffset(pageNumber) + "px )"; READER_PAGES.style.transform = `translate(-${previousPagesWidth(pageNumber)}px, -${pageVerticalOffset(pageNumber)}px)`;
// Then move so the top-left point of the zoom match the frame top-left // Then move so the top-left point of the zoom match the frame top-left
READER_PAGES.style.transform = "translate(" + (- posx) + "px, " + (-posy) + "px )" + READER_PAGES.style.transform; READER_PAGES.style.transform = `translate(${-posx}px, ${-posy}px) ${READER_PAGES.style.transform}`;
// Then, scale so the zoom would fit the frame, and center the zoom // Then, scale so the zoom would fit the frame, and center the zoom
if (width === 0) if (width === 0)
@ -350,27 +311,27 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy)
// Frame wider than zoom => scale so heights are the same, offset on x // Frame wider than zoom => scale so heights are the same, offset on x
const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientHeight / height; const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientHeight / height;
READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform; READER_PAGES.style.transform = `scale(${zoomToFrameScaleFactor}) ${READER_PAGES.style.transform}`;
const scaledWidth = width * zoomToFrameScaleFactor; const scaledWidth = width * zoomToFrameScaleFactor;
const offset = (READER_CONTENT_FRAME.clientWidth - scaledWidth) / 2; const offset = (READER_CONTENT_FRAME.clientWidth - scaledWidth) / 2;
READER_PAGES.style.transform = "translateX(" + offset + "px)" + READER_PAGES.style.transform; READER_PAGES.style.transform = `translateX(${offset}px) ${READER_PAGES.style.transform}`;
updateFocusByWidth(scaledWidth); updateFocusByWidth(scaledWidth);
} }
else else
{ {
// Frame narower than zoom => scale so left/right match, offset on y // Frame narower than zoom => scale so left/right match, offset on y
const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientWidth / width; const zoomToFrameScaleFactor = READER_CONTENT_FRAME.clientWidth / width;
READER_PAGES.style.transform = "scale(" + zoomToFrameScaleFactor + ")" + READER_PAGES.style.transform; READER_PAGES.style.transform = `scale(${zoomToFrameScaleFactor}) ${READER_PAGES.style.transform}`;
const scaledHeight = height * zoomToFrameScaleFactor; const scaledHeight = height * zoomToFrameScaleFactor;
const offset = (READER_CONTENT_FRAME.clientHeight - scaledHeight) / 2; const offset = (READER_CONTENT_FRAME.clientHeight - scaledHeight) / 2;
READER_PAGES.style.transform = "translateY(" + offset + "px)" + READER_PAGES.style.transform; READER_PAGES.style.transform = `translateY(${offset}px) ${READER_PAGES.style.transform}"`;
updateFocusByHeight(scaledHeight); updateFocusByHeight(scaledHeight);
} }
@ -385,7 +346,13 @@ function moveReaderDisplayToArea(pageNumber, oWidth, oHeight, oPosx, oPosy)
function refreshReaderDisplay() function refreshReaderDisplay()
{ {
moveReaderDisplayToArea(CURRENT_PAGE, CURRENT_WIDTH, CURRENT_HEIGHT, CURRENT_X, CURRENT_Y); moveReaderDisplayToArea(
CURRENT_PAGE,
CURRENT_WIDTH,
CURRENT_HEIGHT,
CURRENT_X,
CURRENT_Y
);
} }
function moveReaderDisplayToPage(pageNumber) function moveReaderDisplayToPage(pageNumber)
@ -395,40 +362,34 @@ function moveReaderDisplayToPage(pageNumber)
function moveReaderDisplayToZoom(index) function moveReaderDisplayToZoom(index)
{ {
moveReaderDisplayToArea(PAGES_ZOOMS[index][0], PAGES_ZOOMS[index][1], PAGES_ZOOMS[index][2], PAGES_ZOOMS[index][3], PAGES_ZOOMS[index][4]); moveReaderDisplayToArea(
PAGES_ZOOMS[index][0],
PAGES_ZOOMS[index][1],
PAGES_ZOOMS[index][2],
PAGES_ZOOMS[index][3],
PAGES_ZOOMS[index][4]
);
CURRENT_ZOOM = index; CURRENT_ZOOM = index;
} }
function updateFocusByWidth(width)
{
FOCUS_OVERLAY_WIDTH.style.width = (width / READER_CONTENT_FRAME.clientWidth * 100) + "%";
FOCUS_OVERLAY_HEIGHT.style.height = "100%";
}
function updateFocusByHeight(height)
{
FOCUS_OVERLAY_WIDTH.style.width = "100%";
FOCUS_OVERLAY_HEIGHT.style.height = (height / READER_CONTENT_FRAME.clientHeight * 100) + "%";
}
function toggleViewMode() function toggleViewMode()
{ {
if (IS_PAGE_MODE) if (IS_PAGE_MODE)
{ {
if (CURRENT_ZOOM !== null) if (CURRENT_ZOOM === null)
{
moveReaderDisplayToZoom(CURRENT_ZOOM);
}
else
{ {
moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE)); moveReaderDisplayToZoom(getFirstZoomOfPage(CURRENT_PAGE));
} }
else
{
moveReaderDisplayToZoom(CURRENT_ZOOM);
}
IS_PAGE_MODE = false; IS_PAGE_MODE = false;
} }
else else
{ {
moveReaderDisplayToPage(CURRENT_PAGE); moveReaderDisplayToPage(CURRENT_PAGE);
@ -453,8 +414,11 @@ function moveReader(toNext)
moveReaderDisplayToPage(CURRENT_PAGE - 1); moveReaderDisplayToPage(CURRENT_PAGE - 1);
CURRENT_ZOOM = null; CURRENT_ZOOM = null;
} }
updateProgressBar();
} }
// Zoom mode
else else
{ {
if (toNext && CURRENT_ZOOM < PAGES_ZOOMS.length - 1) if (toNext && CURRENT_ZOOM < PAGES_ZOOMS.length - 1)
@ -466,9 +430,66 @@ function moveReader(toNext)
{ {
moveReaderDisplayToZoom(CURRENT_ZOOM - 1); moveReaderDisplayToZoom(CURRENT_ZOOM - 1);
} }
updateProgressBar();
}
}
function initReader()
{
VERSION_DISPLAY.innerText = VERSION_DISPLAY.innerText.replace("Unknown version", MELPOMENE_VERSION);
loadZoomsFromImgTagsIfRequired();
moveReaderDisplayToZoom(0);
// Smoothly show pictures when they intersect with the viewport
const visibilityObserver = new IntersectionObserver(
(entries, _observer) =>
{
entries.forEach((entry) =>
{
if (entry.isIntersecting)
{
entry.target.style.opacity = 1;
entry.target.style.visibility = "visible";
}
else
{
entry.target.style.opacity = 0;
entry.target.style.visibility = "hidden";
}
});
},
{
root: READER_CONTENT_FRAME,
rootMargin: "-10px"
}
);
for (let pageIndex = 0; pageIndex < READER_PAGES.children.length; pageIndex += 1)
{
const img = READER_PAGES.children[pageIndex];
visibilityObserver.observe(img);
PROGRESS_BAR_PAGES.appendChild(document.createElement("div"));
} }
updateProgressBar(); READER_PAGES.style.display = "flex";
setTimeout(
() => { READER_PAGES.hidden = false; },
"300"
);
setTimeout(
() =>
{
HELP_CONTROLS.style.opacity = null;
HELP_CONTROLS.style.transform = null;
},
DELAY_BEFORE_HIDDING_CONTROLS
);
} }
@ -494,7 +515,7 @@ function handleKeyPress(key)
{ {
READER_FRAME.requestFullscreen(); READER_FRAME.requestFullscreen();
} }
else else
{ {
document.exitFullscreen(); document.exitFullscreen();
@ -507,12 +528,12 @@ function handleKeyPress(key)
{ {
PROGRESS_BAR_CONTAINER.hidden = false; PROGRESS_BAR_CONTAINER.hidden = false;
} }
else else
{ {
PROGRESS_BAR_CONTAINER.hidden = true; PROGRESS_BAR_CONTAINER.hidden = true;
} }
refreshReaderDisplay(); refreshReaderDisplay();
} }
@ -529,7 +550,7 @@ function handleMouseWhell(event)
// Do disable page scrolling when we do prev/next, though // Do disable page scrolling when we do prev/next, though
if (! READER_FRAME.contains(event.target)) if (!READER_FRAME.contains(event.target))
{ {
return; return;
} }
@ -541,15 +562,12 @@ function handleMouseWhell(event)
{ {
return; return;
} }
else MOUSEWHELL_WAIT = true;
{ setTimeout(
MOUSEWHELL_WAIT = true; () => { MOUSEWHELL_WAIT = false; },
setTimeout( MOUSEWHELL_MIN_DELAY
() => { MOUSEWHELL_WAIT = false; }, );
MOUSEWHELL_MIN_DELAY
);
}
if (event.deltaY > 0) if (event.deltaY > 0)
{ {