You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
8.7 KiB
JavaScript

let classNotes = "margin-note"; // ← Change the CLASS of the notes here
let notesFloat = "outside"; // ← Change the POSITION of the notes here
class marginNotes extends Paged.Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
}
beforeParsed(content) {
let notes = content.querySelectorAll("." + classNotes);
for (let i = 0; i < notes.length; ++i) {
// Add call notes
var spanCall = document.createElement("span");
spanCall.classList.add("note-call");
spanCall.classList.add("note-call_" + classNotes);
spanCall.dataset.noteCall = classNotes + '-' + i + 1;
notes[i].parentNode.insertBefore(spanCall, notes[i]);
// Add marker notes
var spanMarker = document.createElement("span");
spanMarker.classList.add("note-marker");
spanMarker.classList.add("note-marker_" + classNotes);
spanMarker.dataset.noteMarker = classNotes + '-' + i + 1;
notes[i].prepend(spanMarker);
// Hide notes to avoid rendering problems
notes[i].style.display = "none";
}
/* NOTE FLOAT ---------------------------------------------------------------------------------- */
let positionRight = 'left: calc(var(--pagedjs-pagebox-width) - var(--pagedjs-margin-left) - var(--pagedjs-margin-right) - 1px); width: var(--pagedjs-margin-right);';
let positionLeft = 'left: calc(var(--pagedjs-margin-left)*-1 - 1px); width: var(--pagedjs-margin-left);'
let notePosition;
switch (notesFloat) {
case 'inside':
notePosition = '.pagedjs_left_page .' + classNotes + '{' + positionRight + '} \
.pagedjs_right_page .' + classNotes + '{' + positionLeft + '}';
break;
case 'left':
notePosition = '.pagedjs_left_page .' + classNotes + '{' + positionLeft + '} \
.pagedjs_right_page .' + classNotes + '{' + positionLeft + '}';
break;
case 'right':
notePosition = '.pagedjs_left_page .' + classNotes + '{' + positionRight + '} \
.pagedjs_right_page .' + classNotes + '{' + positionRight + '}';
break;
default:
notePosition = '.pagedjs_left_page .' + classNotes + '{' + positionLeft + '} \
.pagedjs_right_page .' + classNotes + '{' + positionRight + '}';
}
/* SPECIFIC CSS ---------------------------------------------------------------------------------- */
addcss('\
body {\
counter-reset: callNote_' + toCamelClassNote(classNotes) + ' markerNote_' + toCamelClassNote(classNotes) + ';\
}\
\
.' + classNotes + '{\
position: absolute;\
text-align-last: initial;\
box-sizing: border-box;\
}\
\
.note-call_' + classNotes + ' {\
counter-increment: callNote_' + toCamelClassNote(classNotes) + ';\
}\
\
.note-call_' + classNotes + '::after {\
content: counter(callNote_' + toCamelClassNote(classNotes) + ');\
}\
\
.note-marker_' + classNotes + ' {\
counter-increment: markerNote_' + toCamelClassNote(classNotes) + ';\
}\
.note-marker_' + classNotes + '::before {\
content: counter(markerNote_' + toCamelClassNote(classNotes) + ') ". ";\
}\
' + notePosition);
} /* end beforeParsed*/
afterPageLayout(pageElement, page, breakToken) {
let notes = pageElement.querySelectorAll("." + classNotes);
let noteOverflow = false;
let notesHeightAll = [];
if (typeof (notes) != 'undefined' && notes != null && notes.length != 0) {
for (let n = 0; n < notes.length; ++n) {
// Display notes of the page
notes[n].style.display = "inline-block";
// Add height of the notes to array notesHeightAll
let noteHeight = notes[n].offsetHeight;
notesHeightAll.push(noteHeight);
// Add margins of the notes to array notesHeightAll
if (n >= 1) {
let margins = biggestMargin(notes[n - 1], notes[n]);
notesHeightAll.push(margins);
}
}
/* FIT PAGE ------------------------------------------------------------------------------------- */
// Calculate if all notes fit on the page;
let reducer = (accumulator, currentValue) => accumulator + currentValue;
let allHeight = notesHeightAll.reduce(reducer);
let maxHeight = pageElement.querySelectorAll(".pagedjs_page_content")[0].offsetHeight;
if (allHeight > maxHeight) {
/* IF DOESN'T FIT ----------------------------------------------------------------------------- */
// positions all the notes one after the other starting from the top
notes[0].style.top = parseInt(window.getComputedStyle(notes[0]).marginBottom, 10) * -1 + "px";
for (let a = 1; a < notes.length; ++a) {
let notePrev = notes[a - 1];
let newMargin = biggestMargin(notePrev, notes[a]);
let newTop = notePrev.offsetTop + notePrev.offsetHeight - marginNoteTop(notes[a]) + newMargin;
notes[a].style.top = newTop + "px";
}
// alert
let pageNumber = pageElement.dataset.pageNumber;
alert("Rendering issue \n ☞ A marginal note overflow on page " + pageNumber + " (this is because there is too many on this page and paged.js can't breaks notes between pages for now.)");
noteOverflow = true;
} else {
/* PUSH DOWN ---------------------------------------------------- */
for (let i = 0; i < notes.length; ++i) {
if (i >= 1) {
let noteTop = notes[i].offsetTop;
let notePrev = notes[i - 1];
let newMargin = biggestMargin(notes[i], notePrev);
let notePrevBottom = notePrev.offsetTop - marginNoteTop(notePrev) + notePrev.offsetHeight + newMargin;
// Push down the note to bottom if it's over the previous one
if (notePrevBottom > noteTop) {
notes[i].style.top = notePrevBottom + "px";
}
}
}
/* PUSH UP ---------------------------------------------- */
// Height of the page content
let contentHeight = pageElement.querySelectorAll(".pagedjs_page_content")[0].querySelectorAll("div")[0].offsetHeight;
// Check if last note overflow
let nbrLength = notes.length - 1;
let lastNote = notes[nbrLength];
let lastNoteHeight = lastNote.offsetHeight + marginNoteTop(lastNote);
let noteBottom = lastNote.offsetTop + lastNoteHeight;
if (noteBottom > contentHeight) {
// Push up the last note
lastNote.style.top = contentHeight - lastNoteHeight + "px";
// Push up previous note(s) if if it's over the note
for (let i = nbrLength; i >= 1; --i) {
let noteLastTop = notes[i].offsetTop;
let notePrev = notes[i - 1];
let notePrevHeight = notePrev.offsetHeight;
let newMargin = biggestMargin(notePrev, notes[i]);
let notePrevBottom = notePrev.offsetTop + notePrev.offsetHeight + newMargin;
if (notePrevBottom > noteLastTop) {
notePrev.style.top = notes[i].offsetTop - marginNoteTop(notePrev) - notePrevHeight - newMargin + "px";
}
}
} /* end push up */
}
}
}/* end afterPageLayout*/
}
Paged.registerHandlers(marginNotes);
/* FUNCTIONS --------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------- */
// MARGINS
function marginNoteTop(elem) {
let marginTop = parseInt(window.getComputedStyle(elem).marginTop, 10)
return marginTop;
}
function marginNoteBottom(elem) {
let marginBottom = parseInt(window.getComputedStyle(elem).marginBottom, 10)
return marginBottom;
}
function biggestMargin(a, b) {
let margin;
let marginBottom = marginNoteBottom(a);
let marginTop = marginNoteTop(b);
if (marginBottom > marginTop) {
margin = marginBottom;
} else {
margin = marginTop;
}
return margin;
}
// ADD CSS
function addcss(css) {
var head = document.getElementsByTagName('head')[0];
var s = document.createElement('style');
s.setAttribute('type', 'text/css');
if (s.styleSheet) { // IE
s.styleSheet.cssText = css;
} else {// the world
s.appendChild(document.createTextNode(css));
}
head.appendChild(s);
}
// CAMEL CLASS NOTE
function toCamelClassNote(elem) {
let splitClass = elem.split("-");
if (splitClass.length > 1) {
for (let s = 1; s < splitClass.length; ++s) {
let strCapilize = splitClass[s].charAt(0).toUpperCase() + splitClass[s].slice(1)
splitClass[s] = strCapilize;
}
}
let reducer = (accumulator, currentValue) => accumulator + currentValue;
let classCamel = splitClass.reduce(reducer);
return classCamel;
}