153 lines
4.6 KiB
JavaScript
153 lines
4.6 KiB
JavaScript
|
|
/**
|
|||
|
|
* @name Float Page v1.0
|
|||
|
|
* @author Julie Blanc <contact@julie-blanc.fr>
|
|||
|
|
* @see { @link https://gitlab.com/csspageweaver/plugins/floatPage }
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
|||
|
|
|
|||
|
|
export class floatPage extends Handler {
|
|||
|
|
constructor(chunker, polisher, caller) {
|
|||
|
|
super(chunker, polisher, caller);
|
|||
|
|
this.selectorBottom = new Set();
|
|||
|
|
this.selectorTop = new Set();
|
|||
|
|
this.selectorNextPage = new Set();
|
|||
|
|
this.nextPageElem = new Set();
|
|||
|
|
this.nextPageElemTemp = new Set();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
onDeclaration(declaration, dItem, dList, rule) {
|
|||
|
|
// Read customs properties
|
|||
|
|
if (declaration.property == "--pagedjs-float-page") {
|
|||
|
|
// get selector of the declaration (NOTE: need csstree.js)
|
|||
|
|
let selector = csstree.generate(rule.ruleNode.prelude);
|
|||
|
|
// Push selector in correct set
|
|||
|
|
if(declaration.value.value.includes("bottom")) {
|
|||
|
|
this.selectorBottom.add(selector);
|
|||
|
|
}else if(declaration.value.value.includes("top")) {
|
|||
|
|
this.selectorTop.add(selector);
|
|||
|
|
}else if(declaration.value.value.includes("next-page")) {
|
|||
|
|
this.selectorNextPage.add(selector);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
afterParsed(parsed){
|
|||
|
|
// bottom
|
|||
|
|
for (let item of this.selectorBottom) {
|
|||
|
|
let elems = parsed.querySelectorAll(item);
|
|||
|
|
for (let elem of elems) {
|
|||
|
|
elem.classList.add("float-page_bottom");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// top
|
|||
|
|
for (let item of this.selectorTop) {
|
|||
|
|
let elems = parsed.querySelectorAll(item);
|
|||
|
|
for (let elem of elems) {
|
|||
|
|
elem.classList.add("float-page_top");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// next-page
|
|||
|
|
for (let item of this.selectorNextPage) {
|
|||
|
|
let elems = parsed.querySelectorAll(item);
|
|||
|
|
for (let elem of elems) {
|
|||
|
|
elem.classList.add("float-page_next-page");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
afterPageLayout(pageElement, page, breakToken){
|
|||
|
|
|
|||
|
|
// TOP (positionning)
|
|||
|
|
let floatTopPage = pageElement.querySelector(".float-page_top");
|
|||
|
|
if(floatTopPage){
|
|||
|
|
let selector = buildCssSelector(floatTopPage.parentNode);
|
|||
|
|
parent = pageElement.querySelector(selector)
|
|||
|
|
parent.insertBefore(floatTopPage, parent.firstChild);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BOTTOM (positionning)
|
|||
|
|
let floatBottomPage = pageElement.querySelector(".float-page_bottom");
|
|||
|
|
if(floatBottomPage){
|
|||
|
|
let selector = buildCssSelector(floatBottomPage.parentNode);
|
|||
|
|
parent = pageElement.querySelector(selector);
|
|||
|
|
parent.insertBefore(floatBottomPage, parent.firstChild);
|
|||
|
|
floatBottomPage.style.position = "absolute";
|
|||
|
|
floatBottomPage.style.bottom = "0px";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NEXT PAGE (positionning into parent section)
|
|||
|
|
for (let elem of this.nextPageElemTemp) {
|
|||
|
|
let cleanedSelector = elem.parentSelector.replace(/^#document-fragment\s*>\s*/, '');
|
|||
|
|
let parent = pageElement.querySelector(cleanedSelector);
|
|||
|
|
|
|||
|
|
let node = elem.elem;
|
|||
|
|
if(parent){
|
|||
|
|
parent.insertBefore(node, parent.firstChild);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
this.nextPageElemTemp.clear();
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NEXT PAGE (pass to next page) -------------------
|
|||
|
|
|
|||
|
|
renderNode(clone, node) {
|
|||
|
|
if (node.nodeType == 1 && node.classList.contains("float-page_next-page")) {
|
|||
|
|
clone.remove();
|
|||
|
|
this.nextPageElem.add({ elem: node, parentSelector: buildCssSelector(node.parentNode) });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onPageLayout(page, Token, layout) {
|
|||
|
|
for (let elem of this.nextPageElem) {
|
|||
|
|
page.insertBefore(elem.elem, page.firstChild);
|
|||
|
|
this.nextPageElemTemp.add(elem);
|
|||
|
|
}
|
|||
|
|
this.nextPageElem.clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// FONCTIONS --------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
// Function to build the CSS selector from the element and its parents
|
|||
|
|
function buildCssSelector(element) {
|
|||
|
|
let selector = [];
|
|||
|
|
let current = element;
|
|||
|
|
|
|||
|
|
while (current) {
|
|||
|
|
if (current.classList && current.classList.contains('pagedjs_page_content')) {
|
|||
|
|
break; // Stop if the parent with class 'pagedjs_page_content' is found
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let currentSelector = current.nodeName.toLowerCase();
|
|||
|
|
|
|||
|
|
if (current.id) {
|
|||
|
|
currentSelector += `[data-id="${current.id}"]`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (current.className) {
|
|||
|
|
currentSelector += `.${current.className.split(' ').join('.')}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
selector.unshift(currentSelector);
|
|||
|
|
current = current.parentNode;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
selector = selector.join(' > ');
|
|||
|
|
// selector = selector.replace(/#document-fragment( > )?/g, ''); // Clean the CSS selector by removing '#document-fragment'
|
|||
|
|
|
|||
|
|
return selector;
|
|||
|
|
}
|