Skip to content
Snippets Groups Projects
Verified Commit f67212aa authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

feat: new toc control finished #189

parent 11fca424
No related branches found
No related tags found
No related merge requests found
......@@ -18,8 +18,8 @@
<div>
<monster-table-of-content style="border:1px solid red;display:flex">
<monster-table-of-content style="display:flex;padding:15px">
<div style="padding:45px">
<h1>Headline 1</h1>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore
et
......@@ -155,7 +155,7 @@
<hr>
<p><strong>ENDE</strong></p>
</div>
</monster-table-of-content>
......
......@@ -230,16 +230,16 @@ document.body.appendChild(element);</code></pre>
<div class="option-headline">Type</div>
<div class="option-headline">Default</div>
<div class="option-headline">Description</div>
<div>templates</div><div>object</div><div></div><div>templates - The templates for the control.</div>
<div>templates.main</div><div>string</div><div></div><div>templates.main - The main template.</div>
<div>mode</div><div>string</div><div></div><div>mode - The mode of the popper. Possible values are `click`, `enter`, `manual`, `focus`, "auto" or a combination of them.</div>
<div>content</div><div>string</div><div></div><div>content - The content of the popper.</div>
<div>popper</div><div>object</div><div></div><div>popper - The popper options.</div>
<div>popper.placement</div><div>string</div><div></div><div>popper.placement - The placement of the popper. Possible values are `top`, `bottom`, `left` and `right`.</div>
<div>popper.middleware</div><div>array<function></div><div></div><div>popper.middleware - The middleware functions of the popper.</div>
<div>popper.middlewareInit</div><div>array<function></div><div></div><div>popper.middlewareInit - The middleware init functions of the popper.</div>
<div>features</div><div>object</div><div></div><div>features - The features of the popper.</div>
<div>features.preventPropagateOpenEvents</div><div>boolean</div><div></div><div>features.preventPropagateOpenEvents - Prevents the open event from being sent.</div>
<div>templates</div><div>object</div><div></div><div>templates The templates for the control.</div>
<div>templates.main</div><div>string</div><div></div><div>templates.main The main template.</div>
<div>mode</div><div>string</div><div></div><div>mode The mode of the popper. Possible values are `click`, `enter`, `manual`, `focus`, "auto" or a combination of them.</div>
<div>content</div><div>string</div><div></div><div>content The content of the popper.</div>
<div>popper</div><div>object</div><div></div><div>popper The popper options.</div>
<div>popper.placement</div><div>string</div><div></div><div>popper.placement The placement of the popper. Possible values are `top`, `bottom`, `left` and `right`.</div>
<div>popper.middleware</div><div>function[]</div><div></div><div>popper.middleware The middleware functions of the popper.</div>
<div>popper.middlewareInit</div><div>function[]</div><div></div><div>popper.middlewareInit The middleware init functions of the popper.</div>
<div>features</div><div>object</div><div></div><div>features The features of the popper.</div>
<div>features.preventPropagateOpenEvents</div><div>boolean</div><div></div><div>features.preventPropagateOpenEvents Prevents the open event from being sent.</div>
</div><br>
<h2>Properties and Attributes</h2>
<ul>
......
......@@ -118,17 +118,16 @@ class Popper extends CustomControl {
*
* The individual configuration values can be found in the table.
*
* @property {Object} templates - The templates for the control.
* @property {string} templates.main - The main template.
* @property {string} mode - The mode of the popper. Possible values are `click`, `enter`, `manual`, `focus`, "auto" or a combination of them.
* @property {string} content - The content of the popper.
* @property {object} popper - The popper options.
* @property {string} popper.placement - The placement of the popper. Possible values are `top`, `bottom`, `left` and `right`.
* @property {Array<function>} popper.middleware - The middleware functions of the popper.
* @property {Array<function>} popper.middlewareInit - The middleware init functions of the popper.
* @property {Object} features - The features of the popper.
* @property {boolean} features.preventPropagateOpenEvents - Prevents the open event from being sent.
* @extends {Button}
* @property {Object} templates The templates for the control.
* @property {string} templates.main The main template.
* @property {string} mode The mode of the popper. Possible values are `click`, `enter`, `manual`, `focus`, "auto" or a combination of them.
* @property {string} content The content of the popper.
* @property {object} popper The popper options.
* @property {string} popper.placement The placement of the popper. Possible values are `top`, `bottom`, `left` and `right`.
* @property {function[]} popper.middleware The middleware functions of the popper.
* @property {function[]} popper.middlewareInit The middleware init functions of the popper.
* @property {Object} features The features of the popper.
* @property {boolean} features.preventPropagateOpenEvents Prevents the open event from being sent.
*/
get defaults() {
return Object.assign({}, super.defaults, {
......
......@@ -17,7 +17,36 @@
cursor: pointer;
width: 20px;
transition: top 0.3s ease, visibility 0.1s ease;
transition: top 0.2s ease, visibility 0.1s ease;
& [data-monster-role="navigation-list"] {
& ul {
margin: 0;
padding: 0 0 0 10px;
list-style-type: none;
}
& ul li {
position: relative;
padding-left: 10px;
}
& ul li:before {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 10px;
border-left: 1px dotted var(--monster-color-primary-2);
margin-top: 0;
}
}
& [data-monster-role=navigation-control] {
width: 20px;
}
& .heading-strip {
display: flex;
......@@ -52,7 +81,4 @@
}
}
......@@ -26,6 +26,7 @@ import {isFunction} from "../../types/is.mjs";
import {TableOfContentStyleSheet} from "./stylesheet/table-of-content.mjs";
import {fireCustomEvent} from "../../dom/events.mjs";
import {getWindow} from "../../dom/util.mjs";
import "../layout/popper.mjs";
export {TableOfContent};
......@@ -33,15 +34,27 @@ export {TableOfContent};
* @private
* @type {symbol}
*/
export const tableOfContentElementSymbol = Symbol("tableOfContentElement");
const tableOfContentElementSymbol = Symbol("tableOfContentElement");
/**
* @private
* @type {symbol}
*/
export const navigationElementSymbol = Symbol("navigation");
const navigationElementSymbol = Symbol("navigation");
/**
* @private
* @type {symbol}
*/
const navigationControlElementSymbol = Symbol("navigationControlElement");
/**
* @private
* @type {symbol}
*/
const navigationListElementSymbol = Symbol("navigationListElement");
/**
* @private
* @type {symbol}
......@@ -181,6 +194,7 @@ class TableOfContent extends CustomElement {
* @private
*/
function calcAndSetNavigationTopWindowContext() {
const thisTop = this.getBoundingClientRect().top;
const topViewport = window.scrollY;
let top = Math.max(topViewport, thisTop);
......@@ -196,11 +210,13 @@ function calcAndSetNavigationTopWindowContext() {
* @private
*/
function calcAndSetNavigationTopScrollableParentContext() {
const windowTop = getWindow().scrollY;
const thisRect = this.getBoundingClientRect();
const thisTop = thisRect.top;
const thisBottom = thisRect.bottom;
const scrollTop = this[scrollableParentSymbol].scrollTop;
let top = thisTop + scrollTop;
let top = windowTop + thisTop + scrollTop;
if (thisBottom < top) {
top = thisBottom;
......@@ -227,10 +243,10 @@ function initNavigation() {
const div = document.createElement('div');
div.classList.add('heading-strip');
div.classList.add('level-' + heading.tagName.toLowerCase());
this[navigationElementSymbol].appendChild(div);
this[navigationControlElementSymbol].appendChild(div);
}
this[navigationListElementSymbol].appendChild(createListFromHeadings.call(this, headings).sublist);
}
/**
......@@ -240,6 +256,7 @@ function initNavigation() {
* @returns {{sublist: HTMLUListElement, lastIndex: number}} An object containing the sublist and the index of the last processed element.
*/
function createListFromHeadings(nodeList, currentLevel = 1) {
const self = this;
let ul = document.createElement('ul');
let i = 0;
......@@ -250,11 +267,22 @@ function createListFromHeadings(nodeList, currentLevel = 1) {
if (level === currentLevel) {
const li = document.createElement('li');
li.textContent = node.textContent;
li.addEventListener('click', (e) => {
e.stopPropagation();
getWindow().requestAnimationFrame(() => {
window.scrollTo(0, 0);
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
// mostly supported
node?.scrollIntoView({behavior: "smooth"});
});
});
ul.appendChild(li);
i++;
} else if (level > currentLevel) {
if (ul.lastChild) {
const {sublist, lastIndex} = createListFromHeadings(nodeList.slice(i), level);
const {sublist, lastIndex} = createListFromHeadings.call(self, nodeList.slice(i), level);
ul.lastChild.appendChild(sublist);
i += lastIndex;
} else {
......@@ -305,7 +333,7 @@ function initEventHandler() {
this[windowEventHandlerSymbol] = function () {
if (!ticking) {
window.requestAnimationFrame(() => {
getWindow().requestAnimationFrame(() => {
calcAndSetNavigationTopWindowContext.call(self);
ticking = false;
});
......@@ -315,7 +343,7 @@ function initEventHandler() {
this[scrollableEventHandlerSymbol] = function () {
if (!ticking) {
window.requestAnimationFrame(() => {
getWindow().requestAnimationFrame(() => {
calcAndSetNavigationTopScrollableParentContext.call(self);
ticking = false;
});
......@@ -335,7 +363,7 @@ function findScrollableParent(element) {
let parent = element.parentElement;
while (parent) {
const overflowY = window.getComputedStyle(parent).overflowY;
const overflowY = getWindow().getComputedStyle(parent).overflowY;
if (overflowY === 'scroll' || overflowY === 'auto') {
return parent;
}
......@@ -356,6 +384,14 @@ function initControlReferences() {
this[navigationElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}="navigation"]`,
);
this[navigationControlElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}="navigation-control"]`,
);
this[navigationListElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}="navigation-list"]`,
);
}
/**
......@@ -366,8 +402,14 @@ function getTemplate() {
// language=HTML
return `
<div data-monster-role="control" part="control">
<div class="navigation" data-monster-role="navigation"></div>
<monster-popper>sdfsdfsdf</monster-popper>
<div class="navigation" data-monster-role="navigation">
<monster-popper data-monster-option-mode="enter">
<div slot="button" data-monster-role="navigation-control">
</div>
<div data-monster-role="navigation-list">
</div>
</monster-popper>
</div>
<slot></slot>
</div>`;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment