Skip to content

Commit 4e098ed

Browse files
committed
feat: Use private # fields etc in MyBookmarkletElement; blog (#63)(#59)
1 parent 0c915ff commit 4e098ed

6 files changed

Lines changed: 86 additions & 74 deletions

File tree

src/blog.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
export { MyAnalyticsElement } from './components/MyAnalyticsElement.js';
55
export { MyCodepenEmbedElement } from './components/MyCodepenEmbedElement.js';
6+
export { MyFeedElement } from './components/MyFeedElement.js';
67
export { MyGaadWidgetElement } from './components/MyGaadWidgetElement.js';
78
export { MyGtagElement } from './components/MyGtagElement.js';
89
export { MyLoomEmbedElement } from './components/MyLoomEmbedElement.js';
@@ -11,4 +12,4 @@ export { MySearchElement } from './components/MySearchElement.js';
1112
export { MySiteCounterElement } from './components/MySiteCounterElement.js';
1213
export { MySkipLinkElement } from './components/MySkipLinkElement.js';
1314
export { MyTranscriptElement } from './components/MyTranscriptElement.js';
14-
export { defineMyElements } from './defineMyElements.js';
15+
export { defineMyElements } from './util/defineMyElements.js';

src/components/MyBookmarkletElement.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ export class MyBookmarkletElement extends HTMLElement {
1616
*/
1717
get name () { return this.getAttribute('name') || this.textContent || 'Bookmarklet'; }
1818

19-
get originPlaceholder () { return '{__ORIGIN__}'; }
19+
get #originPlaceholder () { return '{__ORIGIN__}'; }
2020

2121
/** Load the bookmarklet source code into the link from a function.
2222
* @param {function} theFunction
2323
*/
2424
fromFunction (theFunction) {
2525
console.assert(typeof theFunction === 'function', 'Expecting function as parameter.');
2626
const EL = document.createElement('a');
27-
const BODY = this._extractFunctionBody(theFunction);
28-
const SCRIPT = this._fixScriptUrl(BODY);
27+
const BODY = this.#extractFunctionBody(theFunction);
28+
const SCRIPT = this.#fixScriptUrl(BODY);
2929

3030
EL.href = `javascript:${SCRIPT}`;
3131
EL.textContent = this.name;
@@ -38,13 +38,13 @@ export class MyBookmarkletElement extends HTMLElement {
3838
* @param {function} theFunction
3939
* @return {string}
4040
*/
41-
_extractFunctionBody (theFunction) {
41+
#extractFunctionBody (theFunction) {
4242
const fnString = theFunction.toString();
4343
return fnString.slice(fnString.indexOf('{') + 1, fnString.lastIndexOf('}'));
4444
}
4545

46-
_fixScriptUrl (script) {
47-
return script.replace(this.originPlaceholder, location.origin);
46+
#fixScriptUrl (script) {
47+
return script.replace(this.#originPlaceholder, location.origin);
4848
}
4949

5050
connectedCallback () {

src/components/MyFoobarElement.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import attachTemplate from '../util/attachTemplate.js';
2+
13
/**
24
* Boilerplate template.
35
*
@@ -9,22 +11,26 @@
911
* @status beta
1012
* @since 1.0.0
1113
*/
12-
13-
import { MyElement } from '../MyElement.js';
14-
15-
export class MyFoobarElement extends MyElement {
14+
export class MyFoobarElement extends HTMLElement {
1615
static getTag () {
1716
return 'my-foobar';
1817
}
1918

19+
get #htmlTemplate () {
20+
return `
21+
<template>Hello world!</template>
22+
`;
23+
}
24+
2025
/* constructor () { // "Useless constructor"!
2126
super();
2227
} */
2328

2429
async connectedCallback () {
2530
// const name = this.getAttribute('name') || 'A name attribute';
2631

27-
await this.getTemplate('my-foobar');
32+
attachTemplate(this.#htmlTemplate).to.shadowDOM(this);
33+
// Was: await this.getTemplate('my-foobar');
2834

2935
console.debug('my-foobar:', this);
3036
}

src/components/MyGaadWidgetElement.js

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import MyMinElement from '../MyMinElement.js';
1+
import attachTemplate from '../util/attachTemplate.js';
22

3-
const { location } = window;
3+
const { HTMLElement, location } = window;
44

55
/**
66
* A Global Accessibility Awareness Day banner.
@@ -12,41 +12,42 @@ const { location } = window;
1212
* @TODO ~ Monitor hard-coded date-text in template!
1313
* @see https://github.com/nfreear/gaad-widget/blob/3.x/data/gaad.json
1414
*/
15-
export class MyGaadWidgetElement extends MyMinElement {
15+
export class MyGaadWidgetElement extends HTMLElement {
1616
static getTag () { return 'my-gaad-widget'; }
1717

1818
// Simple test for the month of May!
19-
get _isMay () { return new Date().getMonth() === 4; }
19+
get #isMay () { return new Date().getMonth() === 4; }
2020

21-
get _force () { return /gaad=force/.test(location.search); }
21+
get #forceUrl () { return /gaad=force/.test(location.search); }
2222

23-
get _year () { return new Date().getFullYear(); }
23+
get #year () { return new Date().getFullYear(); }
2424

25-
get _styleUrl () { return 'https://nfreear.github.io/elements/src/style/my-gaad-widget.css'; }
26-
get _gaadUrl () { return 'https://accessibility.day/?utm_source=github&utm_campaign=gaad-widget'; }
27-
get _icalUrl () { return 'https://unpkg.com/gaad-widget@^3/data/gaad.en.ics'; }
25+
get #styleUrl () { return 'https://nfreear.github.io/elements/src/style/my-gaad-widget.css'; }
26+
get #gaadUrl () { return 'https://accessibility.day/?utm_source=github&utm_campaign=gaad-widget'; }
27+
get #icalUrl () { return 'https://unpkg.com/gaad-widget@^3/data/gaad.en.ics'; }
2828

2929
connectedCallback () {
30-
if (this._shouldShow) {
31-
this._attachLocalTemplate(this._template);
32-
this._setDataYear();
30+
if (this.#shouldShow) {
31+
attachTemplate(this.#htmlTemplate).to.shadowDOM(this);
32+
// this._attachLocalTemplate(this._template);
33+
this.#setDataYear();
3334
}
3435

35-
console.debug('my-gaad-widget:', this._shouldShow, this);
36+
console.debug('my-gaad-widget:', this.#shouldShow, this);
3637
}
3738

38-
get _shouldShow () { return this._isMay || this._force; }
39+
get #shouldShow () { return this.#isMay || this.#forceUrl; }
3940

40-
_setDataYear () {
41+
#setDataYear () {
4142
const ELEM = this.shadowRoot.querySelector('.gaad-widget-js');
42-
ELEM.dataset.year = this._year;
43+
ELEM.dataset.year = this.#year;
4344
}
4445

45-
get _template () {
46+
get #htmlTemplate () {
4647
// <style>${this._stylesheet}</style>
4748
return `
4849
<template>
49-
<link rel="stylesheet" href="${this._styleUrl}">
50+
<link rel="stylesheet" href="${this.#styleUrl}">
5051
<div
5152
part="div"
5253
lang="en" dir="ltr"
@@ -61,10 +62,10 @@ export class MyGaadWidgetElement extends MyMinElement {
6162
<i class="tx y2029" hidden>17th, 2029 and mark the 18th</i>
6263
<i class="tx y2030" hidden>16th, 2030 and mark the 19th</i>
6364
64-
<a part="a" href="${this._gaadUrl}" target="_top">Global Accessibility Awareness Day (GAAD)</a>.
65+
<a part="a" href="${this.#gaadUrl}" target="_top">Global Accessibility Awareness Day (GAAD)</a>.
6566
<div class="w">
6667
<a class="p" href="https://github.com/nfreear/gaad-widget#usage" aria-label="Put gaad-widget on your web site (v3.4.0)" target="_top">↓</a>
67-
<a class="c" part="ical" href="${this._icalUrl}" aria-label="Download an iCal calendar file" title="Download an iCal calendar file"
68+
<a class="c" part="ical" href="${this.#icalUrl}" aria-label="Download an iCal calendar file" title="Download an iCal calendar file"
6869
>📆</a>
6970
</div>
7071
</div>

src/components/MyTranscriptElement.js

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import MyMinElement from '../MyMinElement.js';
1+
import attachTemplate from '../util/attachTemplate.js';
2+
// import MyMinElement from '../MyMinElement.js';
23

3-
const { fetch } = window;
4+
const { fetch, HTMLElement } = window;
45

56
/**
67
* Display transcript for an iframe-based embed (E.g. <my-loom-embed>)
@@ -11,12 +12,15 @@ const { fetch } = window;
1112
* @status experimental
1213
* @since 1.8.0
1314
*/
14-
export class MyTranscriptElement extends MyMinElement {
15+
export class MyTranscriptElement extends HTMLElement {
16+
#captions;
17+
#listItems;
18+
1519
static getTag () { return 'my-transcript'; }
1620

1721
get open () { return this.hasAttribute('open') ? 'open' : ''; }
1822

19-
get _template () {
23+
get #htmlTemplate () {
2024
return `
2125
<template>
2226
<style> [ part *= ' active' ] { border: 1px solid #b00; } </style>
@@ -40,88 +44,88 @@ export class MyTranscriptElement extends MyMinElement {
4044
// console.assert(url, '"embed-origin" (iframe) - Attribute required.');
4145
}
4246

43-
get _vttParserJs () { return 'https://unpkg.com/@plussub/srt-vtt-parser@^2/dist/index.js'; }
47+
get #vttParserJs () { return 'https://unpkg.com/@plussub/srt-vtt-parser@^2/dist/index.js'; }
4448

4549
async connectedCallback () {
4650
console.assert(this.embedOrigin, '"embed-origin" (iframe) - Attribute required for dynamic transcript.');
4751

48-
await this._fetchAndParseCaptionFile();
52+
await this.#fetchAndParseCaptionFile();
4953

50-
this._attachLocalTemplate(this._template);
54+
attachTemplate(this.#htmlTemplate).to.shadowDOM(this);
5155

52-
this._listItems = this._createCaptionElements();
56+
this.#listItems = this.#createCaptionElements();
5357

5458
if (this.embedOrigin) {
55-
window.addEventListener('message', (ev) => this._onMessageEvent(ev));
59+
window.addEventListener('message', (ev) => this.#onMessageEvent(ev));
5660
}
5761
}
5862

59-
async _parseCaptions (data) {
60-
const { parse } = await import(this._vttParserJs);
63+
async #parseCaptions (data) {
64+
const { parse } = await import(this.#vttParserJs);
6165
console.assert(parse, 'Expecting "parse" function.');
6266

6367
const CAP = parse(data);
6468
console.assert(CAP && CAP.entries.length, 'Expecting VTT/SRT captions.');
6569
return CAP;
6670
}
6771

68-
async _fetchAndParseCaptionFile () {
72+
async #fetchAndParseCaptionFile () {
6973
const RESP = await fetch(this.href);
7074
if (!RESP.ok) {
7175
throw new Error(`Caption fetch error: ${RESP.status} ~ ${this.href}`);
7276
}
7377
const TEXT = await RESP.text();
74-
const CAP = await this._parseCaptions(TEXT);
78+
const CAP = await this.#parseCaptions(TEXT);
7579

7680
console.debug('my-transcript, Captions:', CAP.entries.length, CAP, this);
77-
this._captions = CAP.entries;
78-
return this._captions;
81+
this.#captions = CAP.entries;
82+
return this.#captions;
7983
}
8084

81-
_createCaptionElements () {
82-
return this._captions.map(({ id, from, to, text }) => {
85+
#createCaptionElements () {
86+
return this.#captions.map(({ id, from, to, text }) => {
8387
const listItem = document.createElement('li');
8488
listItem.textContent = text;
8589
listItem.dataset.cid = id;
8690
listItem.dataset.from = from;
8791
listItem.dataset.to = to;
88-
this._listElement.appendChild(listItem);
92+
this.#listElement.appendChild(listItem);
8993
return listItem;
9094
});
9195
}
9296

93-
_resetCaptionElements () {
97+
#resetCaptionElements () {
9498
this._listItems.forEach((el) => { el.setAttribute('part', 'li inactive'); });
9599
}
96100

97-
_queryCaptionElement (cid) {
98-
return this._listElement.querySelector(`[data-cid = "${cid}"]`);
101+
#queryCaptionElement (cid) {
102+
return this.#listElement.querySelector(`[data-cid = "${cid}"]`);
99103
}
100104

101-
get _listElement () {
105+
get #listElement () {
102106
return this.shadowRoot.querySelector('ol');
103107
}
104108

105-
_findCaption (seconds) {
109+
#findCaption (seconds) {
106110
const millis = parseInt(1000 * seconds);
107-
return this._captions.find(({ from, to }) => millis >= from && millis <= to);
111+
return this.#captions.find(({ from, to }) => millis >= from && millis <= to);
108112
}
109113

110114
/** Relies on player.js on <iframe>
111115
* @see https://github.com/embedly/player.js
112116
*/
113-
_onMessageEvent (ev) {
117+
#onMessageEvent (ev) {
114118
if (ev.origin !== this.embedOrigin) { return; }
115119

116120
const DATA = JSON.parse(ev.data);
117121
const { event, value } = DATA;
118122

119123
if (event === 'timeupdate') {
120124
const { seconds } = value;
121-
const caption = this._findCaption(seconds);
125+
const caption = this.#findCaption(seconds);
122126
if (caption) {
123-
this._resetCaptionElements();
124-
const itemElem = this._queryCaptionElement(caption.id);
127+
this.#resetCaptionElements();
128+
const itemElem = this.#queryCaptionElement(caption.id);
125129
itemElem.setAttribute('part', 'li active');
126130
// itemElem.dataset.active = true;
127131

src/components/MyYoutubeEmbedElement.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ export class MyYoutubeEmbedElement extends HTMLElement {
2020
return EL;
2121
}
2222

23-
get _ytJavaScript () { return 'https://www.youtube.com/iframe_api'; }
23+
get #ytJavaScript () { return 'https://www.youtube.com/iframe_api'; }
2424

25-
get _urlRegex () { return /(youtu.be\/|youtube.com\/watch\?v=)(.+)/; }
25+
get #urlRegex () { return /(youtu.be\/|youtube.com\/watch\?v=)(.+)/; }
2626

2727
get video () {
2828
const ytUrl = this.childAnchorElem.href;
2929
const text = this.childAnchorElem.textContent;
30-
const M = ytUrl.match(this._urlRegex);
30+
const M = ytUrl.match(this.#urlRegex);
3131
console.assert(M, `YouTube URL doesn't match: ${ytUrl}`);
3232
return M ? { id: M[2], text } : null;
3333
}
@@ -43,12 +43,12 @@ export class MyYoutubeEmbedElement extends HTMLElement {
4343
shadow.appendChild(slotElem);
4444
shadow.appendChild(divElem);
4545

46-
this._onYouTubeIframeAPIReady(divElem);
46+
this.#onYouTubeIframeAPIReady(divElem);
4747

48-
await this._loadJavascript(shadow);
48+
await this.#loadJavascript(shadow);
4949
}
5050

51-
_onYouTubeIframeAPIReady (playerElem) {
51+
#onYouTubeIframeAPIReady (playerElem) {
5252
window.onYouTubeIframeAPIReady = () => {
5353
const { YT } = window;
5454
this._player = new YT.Player(playerElem, {
@@ -59,16 +59,16 @@ export class MyYoutubeEmbedElement extends HTMLElement {
5959
playsinline: 1
6060
},
6161
events: {
62-
onReady: (ev) => this._onPlayerReady(ev),
63-
onStateChange: (ev) => this._onPlayerStateChange(ev)
62+
onReady: (ev) => this.#onPlayerReady(ev),
63+
onStateChange: (ev) => this.#onPlayerStateChange(ev)
6464
}
6565
});
6666
console.debug('onYouTubeIframeAPIReady:', this._player, YT.PlayerState, YT);
6767
this.dataset.ready = true;
6868
};
6969
}
7070

71-
_onPlayerReady (ev) {
71+
#onPlayerReady (ev) {
7272
const { target } = ev;
7373
const { videoId } = target.options;
7474
this.dataset.videoId = videoId;
@@ -84,12 +84,12 @@ export class MyYoutubeEmbedElement extends HTMLElement {
8484
this.dataset.ready = true;
8585
}
8686

87-
_onPlayerStateChange (ev) {
88-
const STATE = this._state(ev.data);
87+
#onPlayerStateChange (ev) {
88+
const STATE = this.#state(ev.data);
8989
console.debug('onPlayerStateChange:', STATE.text, ev);
9090
}
9191

92-
_state (id) {
92+
#state (id) {
9393
const STATES = [
9494
{ id: 3, text: 'buffering' },
9595
{ id: 5, text: 'cued' },
@@ -103,10 +103,10 @@ export class MyYoutubeEmbedElement extends HTMLElement {
103103
return state;
104104
}
105105

106-
async _loadJavascript (parent) {
106+
async #loadJavascript (parent) {
107107
// return await import('https://www.youtube.com/iframe_api');
108108
const SCRIPT = document.createElement('script');
109-
SCRIPT.src = this._ytJavaScript;
109+
SCRIPT.src = this.#ytJavaScript;
110110
parent.appendChild(SCRIPT);
111111
}
112112
}

0 commit comments

Comments
 (0)