First work on d-figure

This commit is contained in:
Ludwig Schubert
2017-08-21 18:43:26 -07:00
parent dea6f27995
commit 5e237be027
3 changed files with 151 additions and 1 deletions
+24
View File
@@ -67,6 +67,30 @@
print(a, end=' ')
a, b = b, a+b
</d-code>
<d-figure id="last-figure"></d-figure>
<script>
const figure = document.querySelector("d-figure#last-figure");
figure.addEventListener("init", function() {
const initTag = document.createElement("span");
initTag.textContent = "initialized!"
figure.appendChild(initTag);
});
figure.addEventListener("almostonscreen", function() {
const initTag = figure.querySelector("span");
initTag.textContent = "almostonscreen"
console.log('almostonscreen')
});
figure.addEventListener("onscreen", function() {
const initTag = figure.querySelector("span");
initTag.textContent = "onscreen"
console.log('onscreen')
});
figure.addEventListener("offscreen", function() {
const initTag = figure.querySelector("span");
initTag.textContent = "offscreen!"
console.log('offscreen')
});
</script>
<p>That's it for the example article!</p>
<aside>Some text.</aside>
</d-article>
+2 -1
View File
@@ -17,11 +17,12 @@ import { DMath } from './components/d-math';
import { References } from './components/d-references';
import { Title } from './components/d-title';
import { TOC } from './components/d-toc';
import { Figure } from './components/d-figure';
const components = [
Abstract, Acknowledgements, Appendix, Article, Bibliography,
Byline, Cite, Code, Footnote, FootnoteList, FrontMatter, DMath,
References, Title, TOC,
References, Title, TOC, Figure,
];
/* Distill website specific components */
+125
View File
@@ -0,0 +1,125 @@
`Figure
d-figure provides a state-machine of visibility events:
scroll out of view
+----------------+
*do work here* | |
+------+ +----------------+ +-+---------+ +-v---------+
| init +----> almostonscreen +----> onscreen | | offscreen |
+------+ +----------------+ +---------^-+ +---------+-+
| |
+----------------+
scroll into view
TODO:
* default styling
* get rid of init state?
* shadow dom?
* resizing/default size?
* offer centerscreen event?
* polyfills
`
const intersectionMargin = 1000;
export class Figure extends HTMLElement {
static get is() { return 'd-figure'; }
constructor() {
super();
// keep track of communicated state
this._init = false;
this._onscreen = false;
this._offscreen = true;
// we use two separate observers:
// one with an extra 1000px margin to warn if the viewpoint gets close,
// and one for the actual on/off screen events
this._marginObserver = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting && !this._almostonscreen) {
this.almostonscreen();
this._marginObserver.disconnect();
}
}
}, {
root: null, // listen on entire viewport
rootMargin: intersectionMargin + 'px 0px ' + intersectionMargin + 'px 0px',
threshold: 1.0,
});
this._directObserver = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
if (!this._almostonscreen) { this.almostonscreen(); }
if (this._offscreen) { this.onscreen(); }
} else {
if (this._onscreen) { this.offscreen(); }
}
}
}, {
root: null, // listen on entire viewport
rootMargin: '0px',
threshold: [0, 1.0],
});
}
connectedCallback() {
this._marginObserver.observe(this);
this._directObserver.observe(this);
this.init();
}
/* Override addEventListener
* We want to notify elements that register late as well.
*/
addEventListener(eventName, callback) {
super.addEventListener(eventName, callback);
// if we had already dispatched something while presumingly no one was listening, we do so again
if (this._init && eventName === 'init') {
this.init();
}
if (this._almostonscreen && eventName === 'almostonscreen') {
this.almostonscreen();
}
if (this._onscreen && eventName === 'onscreen') {
this.onscreen();
}
}
/* Custom Events */
init() {
this._init = true;
const event = new CustomEvent('init');
this.dispatchEvent(event);
}
almostonscreen() {
this._almostonscreen = true;
const event = new CustomEvent('almostonscreen');
this.dispatchEvent(event);
}
onscreen() {
this._onscreen = true;
this._offscreen = false;
const event = new CustomEvent('onscreen');
this.dispatchEvent(event);
}
offscreen() {
this._onscreen = false;
this._offscreen = true;
const event = new CustomEvent('offscreen');
this.dispatchEvent(event);
}
}