Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aa6d392

Browse files
authoredOct 4, 2023
Fix 22887: set up custom component in connectedCallback (mdn#62)
* Prettier * Fix issue 22887: set up custom component in connectedCallback * Prettier * Update web component examples to match guide
1 parent 10a3944 commit aa6d392

File tree

9 files changed

+179
-159
lines changed

9 files changed

+179
-159
lines changed
 
Lines changed: 69 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,89 @@
11
<!DOCTYPE html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8">
3+
<head>
4+
<meta charset="UTF-8" />
55
<title>Expanding list web component</title>
66
<style>
7-
ul {
8-
list-style-type: none;
9-
}
7+
ul {
8+
list-style-type: none;
9+
}
1010

11-
li::before {
12-
display:inline-block;
13-
width: 1rem;
14-
height: 1rem;
15-
margin-right: 0.25rem;
16-
content:"";
17-
}
11+
li::before {
12+
display: inline-block;
13+
width: 1rem;
14+
height: 1rem;
15+
margin-right: 0.25rem;
16+
content: "";
17+
}
1818

19-
.open::before, .closed::before {
20-
background-size: 1rem 1rem;
21-
position: relative;
22-
top: 0.25rem;
23-
opacity: 0.3;
24-
}
19+
.open::before,
20+
.closed::before {
21+
background-size: 1rem 1rem;
22+
position: relative;
23+
top: 0.25rem;
24+
opacity: 0.3;
25+
}
2526

26-
.open::before {
27-
background-image: url(img/down.png);
28-
}
27+
.open::before {
28+
background-image: url(img/down.png);
29+
}
2930

30-
.closed::before {
31-
background-image: url(img/right.png);
32-
}
31+
.closed::before {
32+
background-image: url(img/right.png);
33+
}
3334

34-
.closed .closed::before, .closed .open::before {
35-
display: none;
36-
}
35+
.closed .closed::before,
36+
.closed .open::before {
37+
display: none;
38+
}
3739
</style>
38-
</head>
39-
<body>
40+
<script src="main.js" defer></script>
41+
</head>
42+
<body>
4043
<h1>Expanding list web component</h1>
4144
<ul is="expanding-list">
42-
<li>UK
45+
<li>
46+
UK
47+
<ul>
48+
<li>
49+
Yorkshire
4350
<ul>
44-
<li>Yorkshire
45-
<ul>
46-
<li>Leeds
47-
<ul>
48-
<li>Train station</li>
49-
<li>Town hall</li>
50-
<li>Headrow</li>
51-
</ul>
52-
</li>
53-
<li>Bradford</li>
54-
<li>Hull</li>
55-
</ul>
56-
</li>
51+
<li>
52+
Leeds
53+
<ul>
54+
<li>Train station</li>
55+
<li>Town hall</li>
56+
<li>Headrow</li>
57+
</ul>
58+
</li>
59+
<li>Bradford</li>
60+
<li>Hull</li>
5761
</ul>
58-
</li>
59-
<li>USA
62+
</li>
63+
</ul>
64+
</li>
65+
<li>
66+
USA
67+
<ul>
68+
<li>
69+
California
6070
<ul>
61-
<li>California
62-
<ul>
63-
<li>Los Angeles</li>
64-
<li>San Francisco</li>
65-
<li>Berkeley</li>
66-
</ul>
67-
</li>
68-
<li>Nevada</li>
69-
<li>Oregon</li>
71+
<li>Los Angeles</li>
72+
<li>San Francisco</li>
73+
<li>Berkeley</li>
7074
</ul>
71-
</li>
75+
</li>
76+
<li>Nevada</li>
77+
<li>Oregon</li>
78+
</ul>
79+
</li>
7280
</ul>
73-
81+
7482
<ul>
75-
<li>Not</li>
76-
<li>an</li>
77-
<li>expanding</li>
78-
<li>list</li>
83+
<li>Not</li>
84+
<li>an</li>
85+
<li>expanding</li>
86+
<li>list</li>
7987
</ul>
80-
81-
<script src="main.js"></script>
82-
</body>
88+
</body>
8389
</html>

‎expanding-list-web-component/main.js

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,57 @@ class ExpandingList extends HTMLUListElement {
44
// Always call super first in constructor
55
// Return value from super() is a reference to this element
66
self = super();
7+
}
78

9+
connectedCallback() {
810
// Get ul and li elements that are a child of this custom ul element
911
// li elements can be containers if they have uls within them
10-
const uls = Array.from(self.querySelectorAll('ul'));
11-
const lis = Array.from(self.querySelectorAll('li'));
12-
12+
const uls = Array.from(self.querySelectorAll("ul"));
13+
const lis = Array.from(self.querySelectorAll("li"));
1314
// Hide all child uls
1415
// These lists will be shown when the user clicks a higher level container
15-
uls.forEach(ul => {
16-
ul.style.display = 'none';
16+
uls.forEach((ul) => {
17+
ul.style.display = "none";
1718
});
1819

1920
// Look through each li element in the ul
20-
lis.forEach(li => {
21+
lis.forEach((li) => {
2122
// If this li has a ul as a child, decorate it and add a click handler
22-
if (li.querySelectorAll('ul').length > 0) {
23+
if (li.querySelectorAll("ul").length > 0) {
2324
// Add an attribute which can be used by the style
2425
// to show an open or closed icon
25-
li.setAttribute('class', 'closed');
26+
li.setAttribute("class", "closed");
2627

2728
// Wrap the li element's text in a new span element
2829
// so we can assign style and event handlers to the span
2930
const childText = li.childNodes[0];
30-
const newSpan = document.createElement('span');
31+
const newSpan = document.createElement("span");
3132

3233
// Copy text from li to span, set cursor style
3334
newSpan.textContent = childText.textContent;
34-
newSpan.style.cursor = 'pointer';
35-
35+
newSpan.style.cursor = "pointer";
36+
3637
// Add click handler to this span
37-
newSpan.onclick = self.showul;
38-
38+
newSpan.addEventListener("click", (e) => {
39+
// next sibling to the span should be the ul
40+
const nextul = e.target.nextElementSibling;
41+
42+
// Toggle visible state and update class attribute on ul
43+
if (nextul.style.display == "block") {
44+
nextul.style.display = "none";
45+
nextul.parentNode.setAttribute("class", "closed");
46+
} else {
47+
nextul.style.display = "block";
48+
nextul.parentNode.setAttribute("class", "open");
49+
}
50+
});
3951
// Add the span and remove the bare text node from the li
4052
childText.parentNode.insertBefore(newSpan, childText);
4153
childText.parentNode.removeChild(childText);
4254
}
4355
});
4456
}
45-
46-
// li click handler
47-
showul = function (e) {
48-
// next sibling to the span should be the ul
49-
const nextul = e.target.nextElementSibling;
50-
51-
// Toggle visible state and update class attribute on ul
52-
if (nextul.style.display == 'block') {
53-
nextul.style.display = 'none';
54-
nextul.parentNode.setAttribute('class', 'closed');
55-
} else {
56-
nextul.style.display = 'block';
57-
nextul.parentNode.setAttribute('class', 'open');
58-
}
59-
};
6057
}
6158

6259
// Define the new element
63-
customElements.define('expanding-list', ExpandingList, { extends: 'ul' });
60+
customElements.define("expanding-list", ExpandingList, { extends: "ul" });

‎life-cycle-callbacks/index.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta charset="utf-8">
4+
<meta charset="utf-8" />
55
<title>Life cycle callbacks test</title>
66
<style>
77
custom-square {
@@ -18,6 +18,5 @@ <h1>Life cycle callbacks test</h1>
1818
<button class="update">Update attributes</button>
1919
<button class="remove">Remove custom-square from DOM</button>
2020
</div>
21-
2221
</body>
2322
</html>

‎life-cycle-callbacks/main.js

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,56 @@ class Square extends HTMLElement {
33
// Specify observed attributes so that
44
// attributeChangedCallback will work
55
static get observedAttributes() {
6-
return ['c', 'l'];
6+
return ["color", "size"];
77
}
88

99
constructor() {
1010
// Always call super first in constructor
1111
super();
1212

13-
const shadow = this.attachShadow({mode: 'open'});
13+
const shadow = this.attachShadow({ mode: "open" });
1414

15-
const div = document.createElement('div');
16-
const style = document.createElement('style');
15+
const div = document.createElement("div");
16+
const style = document.createElement("style");
1717
shadow.appendChild(style);
1818
shadow.appendChild(div);
1919
}
2020

2121
connectedCallback() {
22-
console.log('Custom square element added to page.');
22+
console.log("Custom square element added to page.");
2323
updateStyle(this);
2424
}
2525

2626
disconnectedCallback() {
27-
console.log('Custom square element removed from page.');
27+
console.log("Custom square element removed from page.");
2828
}
2929

3030
adoptedCallback() {
31-
console.log('Custom square element moved to new page.');
31+
console.log("Custom square element moved to new page.");
3232
}
3333

3434
attributeChangedCallback(name, oldValue, newValue) {
35-
console.log('Custom square element attributes changed.');
35+
console.log("Custom square element attributes changed.");
3636
updateStyle(this);
3737
}
3838
}
3939

40-
customElements.define('custom-square', Square);
40+
customElements.define("custom-square", Square);
4141

4242
function updateStyle(elem) {
4343
const shadow = elem.shadowRoot;
44-
shadow.querySelector('style').textContent = `
44+
shadow.querySelector("style").textContent = `
4545
div {
46-
width: ${elem.getAttribute('l')}px;
47-
height: ${elem.getAttribute('l')}px;
48-
background-color: ${elem.getAttribute('c')};
46+
width: ${elem.getAttribute("size")}px;
47+
height: ${elem.getAttribute("size")}px;
48+
background-color: ${elem.getAttribute("color")};
4949
}
5050
`;
5151
}
5252

53-
const add = document.querySelector('.add');
54-
const update = document.querySelector('.update');
55-
const remove = document.querySelector('.remove');
53+
const add = document.querySelector(".add");
54+
const update = document.querySelector(".update");
55+
const remove = document.querySelector(".remove");
5656
let square;
5757

5858
update.disabled = true;
@@ -62,25 +62,28 @@ function random(min, max) {
6262
return Math.floor(Math.random() * (max - min + 1) + min);
6363
}
6464

65-
add.onclick = function() {
65+
add.onclick = function () {
6666
// Create a custom square element
67-
square = document.createElement('custom-square');
68-
square.setAttribute('l', '100');
69-
square.setAttribute('c', 'red');
67+
square = document.createElement("custom-square");
68+
square.setAttribute("size", "100");
69+
square.setAttribute("color", "red");
7070
document.body.appendChild(square);
7171

7272
update.disabled = false;
7373
remove.disabled = false;
7474
add.disabled = true;
7575
};
7676

77-
update.onclick = function() {
77+
update.onclick = function () {
7878
// Randomly update square's attributes
79-
square.setAttribute('l', random(50, 200));
80-
square.setAttribute('c', `rgb(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)})`);
79+
square.setAttribute("size", random(50, 200));
80+
square.setAttribute(
81+
"color",
82+
`rgb(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)})`
83+
);
8184
};
8285

83-
remove.onclick = function() {
86+
remove.onclick = function () {
8487
// Remove the square
8588
document.body.removeChild(square);
8689

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta charset="utf-8">
4+
<meta charset="utf-8" />
55
<title>Pop-up info box — web components</title>
66
<script src="main.js" defer></script>
77
</head>
@@ -10,10 +10,15 @@ <h1>Pop-up info widget - web components</h1>
1010

1111
<form>
1212
<div>
13-
<label for="cvc">Enter your CVC <popup-info img="img/alt.png" data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."></popup-info></label>
14-
<input type="text" id="cvc">
13+
<label for="cvc"
14+
>Enter your CVC
15+
<popup-info
16+
img="img/alt.png"
17+
data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."
18+
></popup-info
19+
></label>
20+
<input type="text" id="cvc" />
1521
</div>
1622
</form>
17-
1823
</body>
1924
</html>

‎popup-info-box-external-stylesheet/main.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,43 @@ class PopUpInfo extends HTMLElement {
33
constructor() {
44
// Always call super first in constructor
55
super();
6+
}
67

8+
connectedCallback() {
79
// Create a shadow root
8-
const shadow = this.attachShadow({mode: 'open'});
10+
const shadow = this.attachShadow({ mode: "open" });
911

1012
// Create spans
11-
const wrapper = document.createElement('span');
12-
wrapper.setAttribute('class', 'wrapper');
13+
const wrapper = document.createElement("span");
14+
wrapper.setAttribute("class", "wrapper");
1315

14-
const icon = document.createElement('span');
15-
icon.setAttribute('class', 'icon');
16-
icon.setAttribute('tabindex', 0);
16+
const icon = document.createElement("span");
17+
icon.setAttribute("class", "icon");
18+
icon.setAttribute("tabindex", 0);
1719

18-
const info = document.createElement('span');
19-
info.setAttribute('class', 'info');
20+
const info = document.createElement("span");
21+
info.setAttribute("class", "info");
2022

2123
// Take attribute content and put it inside the info span
22-
const text = this.getAttribute('data-text');
24+
const text = this.getAttribute("data-text");
2325
info.textContent = text;
2426

2527
// Insert icon
2628
let imgUrl;
27-
if(this.hasAttribute('img')) {
28-
imgUrl = this.getAttribute('img');
29+
if (this.hasAttribute("img")) {
30+
imgUrl = this.getAttribute("img");
2931
} else {
30-
imgUrl = 'img/default.png';
32+
imgUrl = "img/default.png";
3133
}
3234

33-
const img = document.createElement('img');
35+
const img = document.createElement("img");
3436
img.src = imgUrl;
3537
icon.appendChild(img);
3638

3739
// Apply external styles to the shadow dom
38-
const linkElem = document.createElement('link');
39-
linkElem.setAttribute('rel', 'stylesheet');
40-
linkElem.setAttribute('href', 'style.css');
40+
const linkElem = document.createElement("link");
41+
linkElem.setAttribute("rel", "stylesheet");
42+
linkElem.setAttribute("href", "style.css");
4143

4244
// Attach the created elements to the shadow dom
4345
shadow.appendChild(linkElem);
@@ -48,4 +50,4 @@ class PopUpInfo extends HTMLElement {
4850
}
4951

5052
// Define the new element
51-
customElements.define('popup-info', PopUpInfo);
53+
customElements.define("popup-info", PopUpInfo);

‎popup-info-box-external-stylesheet/style.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ img {
2222
width: 1.2rem;
2323
}
2424

25-
.icon:hover + .info, .icon:focus + .info {
25+
.icon:hover + .info,
26+
.icon:focus + .info {
2627
opacity: 1;
2728
}
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<meta charset="utf-8">
4+
<meta charset="utf-8" />
55
<title>Pop-up info box — web components</title>
66
<script src="main.js" defer></script>
77
</head>
@@ -10,10 +10,15 @@ <h1>Pop-up info widget - web components</h1>
1010

1111
<form>
1212
<div>
13-
<label for="cvc">Enter your CVC <popup-info img="img/alt.png" data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."></popup-info></label>
14-
<input type="text" id="cvc">
13+
<label for="cvc"
14+
>Enter your CVC
15+
<popup-info
16+
img="img/alt.png"
17+
data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."
18+
></popup-info
19+
></label>
20+
<input type="text" id="cvc" />
1521
</div>
1622
</form>
17-
1823
</body>
1924
</html>

‎popup-info-box-web-component/main.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,41 @@ class PopUpInfo extends HTMLElement {
33
constructor() {
44
// Always call super first in constructor
55
super();
6+
}
67

8+
connectedCallback() {
79
// Create a shadow root
8-
const shadow = this.attachShadow({mode: 'open'});
10+
const shadow = this.attachShadow({ mode: "open" });
911

1012
// Create spans
11-
const wrapper = document.createElement('span');
12-
wrapper.setAttribute('class', 'wrapper');
13+
const wrapper = document.createElement("span");
14+
wrapper.setAttribute("class", "wrapper");
1315

14-
const icon = document.createElement('span');
15-
icon.setAttribute('class', 'icon');
16-
icon.setAttribute('tabindex', 0);
16+
const icon = document.createElement("span");
17+
icon.setAttribute("class", "icon");
18+
icon.setAttribute("tabindex", 0);
1719

18-
const info = document.createElement('span');
19-
info.setAttribute('class', 'info');
20+
const info = document.createElement("span");
21+
info.setAttribute("class", "info");
2022

2123
// Take attribute content and put it inside the info span
22-
const text = this.getAttribute('data-text');
24+
const text = this.getAttribute("data-text");
2325
info.textContent = text;
2426

2527
// Insert icon
2628
let imgUrl;
27-
if(this.hasAttribute('img')) {
28-
imgUrl = this.getAttribute('img');
29+
if (this.hasAttribute("img")) {
30+
imgUrl = this.getAttribute("img");
2931
} else {
30-
imgUrl = 'img/default.png';
32+
imgUrl = "img/default.png";
3133
}
3234

33-
const img = document.createElement('img');
35+
const img = document.createElement("img");
3436
img.src = imgUrl;
3537
icon.appendChild(img);
3638

3739
// Create some CSS to apply to the shadow dom
38-
const style = document.createElement('style');
40+
const style = document.createElement("style");
3941
console.log(style.isConnected);
4042

4143
style.textContent = `
@@ -78,4 +80,4 @@ class PopUpInfo extends HTMLElement {
7880
}
7981

8082
// Define the new element
81-
customElements.define('popup-info', PopUpInfo);
83+
customElements.define("popup-info", PopUpInfo);

0 commit comments

Comments
 (0)
Please sign in to comment.