mirror of
https://github.com/wassname/template.git
synced 2026-07-26 13:37:31 +08:00
WIP switch to webcomponents loader async polyfills; multiple small fixes for Firefox and generally more defensive coding
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Template } from '../mixins/template';
|
||||
// import { Template } from '../mixins/template';
|
||||
import { Controller } from '../controller';
|
||||
|
||||
const isOnlyWhitespace = /^\s*$/;
|
||||
@@ -31,7 +31,7 @@ export class Article extends HTMLElement {
|
||||
|
||||
connectedCallback() {
|
||||
document.onreadystatechange = function () {
|
||||
console.log("onreadystatechange:");
|
||||
console.log('onreadystatechange:');
|
||||
console.log(document.readyState);
|
||||
};
|
||||
console.info('Article tag connected, we can now listen to controller events.');
|
||||
|
||||
@@ -35,6 +35,12 @@ export class Bibliography extends HTMLElement {
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
requestAnimationFrame(() => {
|
||||
this.parseIfPossible();
|
||||
});
|
||||
}
|
||||
|
||||
parseIfPossible() {
|
||||
const scriptTag = this.querySelector('script');
|
||||
if (!scriptTag) return;
|
||||
|
||||
@@ -49,12 +49,6 @@ export class Cite extends T(HTMLElement) {
|
||||
|
||||
/* Lifecycle */
|
||||
|
||||
// constructor() {
|
||||
// super();
|
||||
// // Cite.currentId += 1;
|
||||
// // this.citeId = Cite.currentId;
|
||||
// }
|
||||
|
||||
connectedCallback() {
|
||||
this.outerSpan = this.root.querySelector('#citation-');
|
||||
this.innerSpan = this.root.querySelector('.citation-number');
|
||||
@@ -105,11 +99,15 @@ export class Cite extends T(HTMLElement) {
|
||||
return index == -1 ? '?' : index + 1 + '';
|
||||
});
|
||||
const textContent = '[' + numberStrings.join(', ') + ']';
|
||||
this.innerSpan.textContent = textContent;
|
||||
if (this.innerSpan) {
|
||||
this.innerSpan.textContent = textContent;
|
||||
}
|
||||
}
|
||||
|
||||
set entries(entries) {
|
||||
this.hoverBox.innerHTML = entries.map(hover_cite).join('<br><br>');
|
||||
if (this.hoverBox) {
|
||||
this.hoverBox.innerHTML = entries.map(hover_cite).join('<br><br>');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ export const Controller = {
|
||||
citeTag.entries = entries;
|
||||
},
|
||||
|
||||
onCiteKeyChanged(event) {
|
||||
onCiteKeyChanged() {
|
||||
// const [citeTag, keys] = event.detail;
|
||||
|
||||
// update citations
|
||||
@@ -145,7 +145,7 @@ export const Controller = {
|
||||
return;
|
||||
} else {
|
||||
Controller.loaded = true;
|
||||
console.log('Controller running DOMContentLoaded')
|
||||
console.log('Controller running DOMContentLoaded');
|
||||
}
|
||||
|
||||
const frontMatterTag = document.querySelector('d-front-matter');
|
||||
|
||||
@@ -37,6 +37,11 @@ export default function(dom, data) {
|
||||
<meta property="description" itemprop="description" content="${escape(data.description)}" />
|
||||
<meta property="article:published" itemprop="datePublished" content="${data.publishedISODateOnly}" />
|
||||
<meta property="article:created" itemprop="dateCreated" content="${data.publishedISODateOnly}" />
|
||||
`);
|
||||
}
|
||||
|
||||
if (data.updatedDate) {
|
||||
appendHead(`
|
||||
<meta property="article:modified" itemprop="dateModified" content="${data.updatedDate.toISOString()}" />
|
||||
`);
|
||||
}
|
||||
|
||||
+63
-36
@@ -1,47 +1,74 @@
|
||||
const webcomponentPath = 'https://distill.pub/third-party/polyfills/webcomponents-lite.js';
|
||||
const intersectionObserverPath = 'https://distill.pub/third-party/polyfills/intersection-observer.js';
|
||||
|
||||
const template = `
|
||||
if ('IntersectionObserver' in window &&
|
||||
'IntersectionObserverEntry' in window &&
|
||||
'intersectionRatio' in IntersectionObserverEntry.prototype) {
|
||||
// Platform supports IntersectionObserver natively! :-)
|
||||
if (!('isIntersecting' in IntersectionObserverEntry.prototype)) {
|
||||
Object.defineProperty(IntersectionObserverEntry.prototype,
|
||||
'isIntersecting', {
|
||||
get: function () {
|
||||
return this.intersectionRatio > 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Platform does not support webcomponents--loading polyfills synchronously.
|
||||
const scriptTag = document.createElement('script');
|
||||
scriptTag.src = '${intersectionObserverPath}';
|
||||
scriptTag.async = false;
|
||||
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
|
||||
}
|
||||
// const template = `
|
||||
// if ('IntersectionObserver' in window &&
|
||||
// 'IntersectionObserverEntry' in window &&
|
||||
// 'intersectionRatio' in IntersectionObserverEntry.prototype) {
|
||||
// // Platform supports IntersectionObserver natively! :-)
|
||||
// if (!('isIntersecting' in IntersectionObserverEntry.prototype)) {
|
||||
// Object.defineProperty(IntersectionObserverEntry.prototype,
|
||||
// 'isIntersecting', {
|
||||
// get: function () {
|
||||
// return this.intersectionRatio > 0;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// // Platform does not support webcomponents--loading polyfills synchronously.
|
||||
// const scriptTag = document.createElement('script');
|
||||
// scriptTag.src = '${intersectionObserverPath}';
|
||||
// scriptTag.async = false;
|
||||
// document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
|
||||
// }
|
||||
//
|
||||
// if ('registerElement' in document &&
|
||||
// 'import' in document.createElement('link') &&
|
||||
// 'content' in document.createElement('template')) {
|
||||
// // Platform supports webcomponents natively! :-)
|
||||
// } else {
|
||||
// // Platform does not support webcomponents--loading polyfills synchronously.
|
||||
// const scriptTag = document.createElement('script');
|
||||
// scriptTag.src = '${webcomponentPath}';
|
||||
// scriptTag.async = false;
|
||||
// document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// `;
|
||||
|
||||
if ('registerElement' in document &&
|
||||
'import' in document.createElement('link') &&
|
||||
'content' in document.createElement('template')) {
|
||||
// Platform supports webcomponents natively! :-)
|
||||
} else {
|
||||
// Platform does not support webcomponents--loading polyfills synchronously.
|
||||
const scriptTag = document.createElement('script');
|
||||
scriptTag.src = '${webcomponentPath}';
|
||||
scriptTag.async = false;
|
||||
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
|
||||
}
|
||||
|
||||
const addBackIn = `
|
||||
window.addEventListener('WebComponentsReady', function() {
|
||||
console.warn('WebComponentsReady');
|
||||
const loaderTag = document.createElement('script');
|
||||
loaderTag.src = 'http://localhost:8888/dist/template.v2.js';
|
||||
document.head.insertBefore(loaderTag, document.head.firstChild);
|
||||
});
|
||||
`;
|
||||
|
||||
export default function render(dom) {
|
||||
// pull out template script tag
|
||||
const templateTag = dom.querySelector('script[src*="template.v2.js"]');
|
||||
templateTag.parentNode.removeChild(templateTag);
|
||||
|
||||
// add loader
|
||||
const loaderTag = dom.createElement('script');
|
||||
loaderTag.src = 'https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.17/webcomponents-loader.js';
|
||||
dom.head.insertBefore(loaderTag, dom.head.firstChild);
|
||||
|
||||
// add loader event listener to add tempalrte back in
|
||||
const addTag = dom.createElement('script');
|
||||
addTag.innerHTML = addBackIn;
|
||||
dom.head.insertBefore(addTag, dom.head.firstChild);
|
||||
|
||||
|
||||
// create polyfill script tag
|
||||
const polyfillScriptTag = dom.createElement('script');
|
||||
polyfillScriptTag.innerHTML = template;
|
||||
polyfillScriptTag.id = 'polyfills';
|
||||
// const polyfillScriptTag = dom.createElement('script');
|
||||
// polyfillScriptTag.innerHTML = template;
|
||||
// polyfillScriptTag.id = 'polyfills';
|
||||
|
||||
// insert at appropriate position--before any other script tag
|
||||
const firstScriptTag = dom.head.querySelector('script');
|
||||
dom.head.insertBefore(polyfillScriptTag, firstScriptTag);
|
||||
// const firstScriptTag = dom.head.querySelector('script');
|
||||
// dom.head.insertBefore(polyfillScriptTag, firstScriptTag);
|
||||
}
|
||||
|
||||
+81
-81
@@ -90,14 +90,14 @@ const T = Template('d-slider', `
|
||||
|
||||
</style>
|
||||
|
||||
<div class="background">
|
||||
<div class="track"></div>
|
||||
<div class="track-fill"></div>
|
||||
<div class="knob-container">
|
||||
<div class="knob-highlight"></div>
|
||||
<div class="knob"></div>
|
||||
<div class='background'>
|
||||
<div class='track'></div>
|
||||
<div class='track-fill'></div>
|
||||
<div class='knob-container'>
|
||||
<div class='knob-highlight'></div>
|
||||
<div class='knob'></div>
|
||||
</div>
|
||||
<div class="ticks"></div>
|
||||
<div class='ticks'></div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
@@ -121,18 +121,18 @@ export class Slider extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
this.connected = true;
|
||||
this.setAttribute("role", "slider");
|
||||
this.setAttribute('role', 'slider');
|
||||
// Makes the element tab-able.
|
||||
if (!this.hasAttribute("tabindex")) { this.setAttribute("tabindex", 0); }
|
||||
if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', 0); }
|
||||
|
||||
// Keeps track of keyboard vs. mouse interactions for focus rings
|
||||
this.mouseEvent = false;
|
||||
|
||||
// Handles to shadow DOM elements
|
||||
this.knob = this.root.querySelector(".knob-container");
|
||||
this.background = this.root.querySelector(".background");
|
||||
this.trackFill = this.root.querySelector(".track-fill");
|
||||
this.track = this.root.querySelector(".track");
|
||||
this.knob = this.root.querySelector('.knob-container');
|
||||
this.background = this.root.querySelector('.background');
|
||||
this.trackFill = this.root.querySelector('.track-fill');
|
||||
this.track = this.root.querySelector('.track');
|
||||
|
||||
// Default values for attributes
|
||||
this.min = this.min ? this.min : 0;
|
||||
@@ -148,108 +148,108 @@ export class Slider extends T(HTMLElement) {
|
||||
|
||||
this.drag = drag()
|
||||
.container(this.background)
|
||||
.on("start", () => {
|
||||
.on('start', () => {
|
||||
this.mouseEvent = true;
|
||||
this.background.classList.add("mousedown");
|
||||
this.background.classList.add('mousedown');
|
||||
this.changeValue = this.value;
|
||||
this.dragUpdate();
|
||||
})
|
||||
.on("drag", () => {
|
||||
.on('drag', () => {
|
||||
this.dragUpdate();
|
||||
})
|
||||
.on("end", () => {
|
||||
.on('end', () => {
|
||||
this.mouseEvent = false;
|
||||
this.background.classList.remove("mousedown");
|
||||
this.background.classList.remove('mousedown');
|
||||
this.dragUpdate();
|
||||
if (this.changeValue !== this.value) this.dispatchChange();
|
||||
this.changeValue = this.value;
|
||||
});
|
||||
this.drag(select(this.background));
|
||||
|
||||
this.addEventListener("focusin", (e) => {
|
||||
this.addEventListener('focusin', () => {
|
||||
if(!this.mouseEvent) {
|
||||
this.background.classList.add("focus");
|
||||
this.background.classList.add('focus');
|
||||
}
|
||||
});
|
||||
this.addEventListener("focusout", (e) => {
|
||||
this.background.classList.remove("focus");
|
||||
this.addEventListener('focusout', () => {
|
||||
this.background.classList.remove('focus');
|
||||
});
|
||||
this.addEventListener("keydown", this.onKeyDown);
|
||||
this.addEventListener('keydown', this.onKeyDown);
|
||||
|
||||
}
|
||||
|
||||
static get observedAttributes() {return ["min", "max", "value", "step", "ticks", "origin", "tickValues", "tickLabels"]; }
|
||||
static get observedAttributes() {return ['min', 'max', 'value', 'step', 'ticks', 'origin', 'tickValues', 'tickLabels']; }
|
||||
|
||||
attributeChangedCallback(attr, oldValue, newValue) {
|
||||
if (attr == "min") {
|
||||
if (attr == 'min') {
|
||||
this.min = +newValue;
|
||||
this.setAttribute("aria-valuemin", this.min);
|
||||
this.setAttribute('aria-valuemin', this.min);
|
||||
}
|
||||
if (attr == "max") {
|
||||
if (attr == 'max') {
|
||||
this.max = +newValue;
|
||||
this.setAttribute("aria-valuemax", this.max);
|
||||
this.setAttribute('aria-valuemax', this.max);
|
||||
}
|
||||
if (attr == "value") {
|
||||
if (attr == 'value') {
|
||||
this.update(+newValue);
|
||||
}
|
||||
if (attr == "origin") {
|
||||
if (attr == 'origin') {
|
||||
this.origin = +newValue;
|
||||
this.update(this.value);
|
||||
}
|
||||
if (attr == "step") {
|
||||
if (attr == 'step') {
|
||||
if (newValue > 0) {
|
||||
this.step = +newValue;
|
||||
}
|
||||
}
|
||||
if (attr == "ticks") {
|
||||
this.ticks = (newValue === "" ? true : newValue);
|
||||
if (attr == 'ticks') {
|
||||
this.ticks = (newValue === '' ? true : newValue);
|
||||
}
|
||||
}
|
||||
|
||||
onKeyDown(e) {
|
||||
onKeyDown(event) {
|
||||
this.changeValue = this.value;
|
||||
let stopPropagation = false;
|
||||
switch (event.keyCode) {
|
||||
case keyCodes.left:
|
||||
case keyCodes.down:
|
||||
this.update(this.value - this.step)
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.right:
|
||||
case keyCodes.up:
|
||||
this.update(this.value + this.step)
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.pageUp:
|
||||
this.update(this.value + this.step * 10)
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.left:
|
||||
case keyCodes.down:
|
||||
this.update(this.value - this.step);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.right:
|
||||
case keyCodes.up:
|
||||
this.update(this.value + this.step);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.pageUp:
|
||||
this.update(this.value + this.step * 10);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
|
||||
case keyCodes.pageDown:
|
||||
this.update(this.value + this.step * 10)
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.home:
|
||||
this.update(this.min);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.end:
|
||||
this.update(this.max);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case keyCodes.pageDown:
|
||||
this.update(this.value + this.step * 10);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.home:
|
||||
this.update(this.min);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case keyCodes.end:
|
||||
this.update(this.max);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (stopPropagation) {
|
||||
this.background.classList.add("focus");
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.background.classList.add('focus');
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (this.changeValue !== this.value) this.dispatchChange();
|
||||
}
|
||||
}
|
||||
|
||||
validateValueRange(min, max, value) {
|
||||
return Math.max(Math.min(max, value), min)
|
||||
return Math.max(Math.min(max, value), min);
|
||||
}
|
||||
|
||||
quantizeValue(value, step) {
|
||||
@@ -265,53 +265,53 @@ export class Slider extends T(HTMLElement) {
|
||||
|
||||
update(value) {
|
||||
let v = value;
|
||||
if (this.step !== "any") {
|
||||
if (this.step !== 'any') {
|
||||
v = this.quantizeValue(value, this.step);
|
||||
}
|
||||
v = this.validateValueRange(this.min, this.max, v);
|
||||
if (this.connected) {
|
||||
this.knob.style.left = this.scale(v) * 100 + "%";
|
||||
this.trackFill.style.width = this.scale(this.min + Math.abs(v - this.origin)) * 100 + "%";
|
||||
this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + "%";
|
||||
this.knob.style.left = this.scale(v) * 100 + '%';
|
||||
this.trackFill.style.width = this.scale(this.min + Math.abs(v - this.origin)) * 100 + '%';
|
||||
this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + '%';
|
||||
}
|
||||
if (this.value !== v) {
|
||||
this.value = v;
|
||||
this.setAttribute("aria-valuenow", this.value);
|
||||
this.setAttribute('aria-valuenow', this.value);
|
||||
this.dispatchInput();
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatches only on a committed change (basically only on mouseup).
|
||||
dispatchChange() {
|
||||
const e = new Event("change");
|
||||
const e = new Event('change');
|
||||
this.dispatchEvent(e, {});
|
||||
}
|
||||
|
||||
// Dispatches on each value change.
|
||||
dispatchInput() {
|
||||
const e = new Event("input");
|
||||
const e = new Event('input');
|
||||
this.dispatchEvent(e, {});
|
||||
}
|
||||
|
||||
renderTicks() {
|
||||
const ticksContainer = this.root.querySelector(".ticks");
|
||||
const ticksContainer = this.root.querySelector('.ticks');
|
||||
if (this.ticks !== false) {
|
||||
let tickData = [];
|
||||
if (this.ticks > 0) {
|
||||
tickData = this.scale.ticks(this.ticks);
|
||||
} else if (this.step === "any") {
|
||||
} else if (this.step === 'any') {
|
||||
tickData = this.scale.ticks();
|
||||
} else {
|
||||
tickData = range(this.min, this.max + 1e-6, this.step);
|
||||
}
|
||||
tickData.forEach(d => {
|
||||
const tick = document.createElement("div");
|
||||
tick.classList.add("tick");
|
||||
tick.style.left = this.scale(d) * 100 + "%";
|
||||
ticksContainer.appendChild(tick)
|
||||
const tick = document.createElement('div');
|
||||
tick.classList.add('tick');
|
||||
tick.style.left = this.scale(d) * 100 + '%';
|
||||
ticksContainer.appendChild(tick);
|
||||
});
|
||||
} else {
|
||||
ticksContainer.style.display = "none";
|
||||
ticksContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user