Skip to content
This repository was archived by the owner on Sep 22, 2022. It is now read-only.

Commit 817bb26

Browse files
authored
Merge pull request #4 from github/muan/private-methods
Move private functions out of public API
2 parents d8d1953 + 1ef2422 commit 817bb26

File tree

2 files changed

+140
-139
lines changed

2 files changed

+140
-139
lines changed

dist/index-umd.js

+69-72
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,70 @@
6868
;
6969
Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype);
7070
Object.setPrototypeOf(_CustomElement, HTMLElement);
71+
function createCloseButton(el) {
72+
var closeButton = document.createElement('button');
73+
closeButton.innerHTML = closeIcon();
74+
closeButton.classList.add('dd-close-button');
75+
closeButton.setAttribute('type', 'button');
76+
closeButton.setAttribute('aria-label', 'Close dialog');
77+
closeButton.setAttribute('data-close-dialog', true);
78+
el.appendChild(closeButton);
79+
return closeButton;
80+
}
81+
82+
function autofocus(el) {
83+
var autofocus = el.querySelector('[autofocus]');
84+
if (!autofocus) {
85+
autofocus = el;
86+
el.setAttribute('tabindex', '-1');
87+
}
88+
autofocus.focus();
89+
}
90+
91+
function captureDismissal(event) {
92+
if (event.target.hasAttribute('data-close-dialog') || event.target.closest('[data-close-dialog]')) {
93+
event.target.closest('details').open = false;
94+
}
95+
}
96+
97+
function keyDownHelpers(event) {
98+
if (event.key === 'Escape') {
99+
event.currentTarget.open = false;
100+
} else if (event.key === 'Tab') {
101+
restrictTabBehavior(event);
102+
}
103+
}
104+
105+
function restrictTabBehavior(event) {
106+
event.preventDefault();
107+
108+
var dialog = event.currentTarget;
109+
var elements = Array.from(dialog.querySelectorAll('a, input, button, textarea')).filter(function (element) {
110+
return !element.disabled && element.offsetWidth > 0 && element.offsetHeight > 0;
111+
});
112+
113+
var movement = event.shiftKey ? -1 : 1;
114+
var currentFocus = elements.filter(function (el) {
115+
return el.matches(':focus');
116+
})[0];
117+
var targetIndex = elements.length - 1;
118+
119+
if (currentFocus) {
120+
var currentIndex = elements.indexOf(currentFocus);
121+
if (currentIndex !== -1) {
122+
var newIndex = currentIndex + movement;
123+
if (newIndex >= 0) targetIndex = newIndex % elements.length;
124+
}
125+
}
126+
127+
elements[targetIndex].focus();
128+
}
129+
130+
// Pulled from https://github.com/primer/octicons
131+
// We're only using one octicon so it doesn't make sense to include the whole module
132+
function closeIcon() {
133+
return '<svg version="1.1" width="12" height="16" viewBox="0 0 12 16" aria-hidden="true"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>';
134+
}
71135

72136
var DetailsDialogElement = function (_CustomElement2) {
73137
_inherits(DetailsDialogElement, _CustomElement2);
@@ -81,16 +145,13 @@
81145
_createClass(DetailsDialogElement, [{
82146
key: 'connectedCallback',
83147
value: function connectedCallback() {
84-
this.createCloseButton();
148+
this.closeButton = createCloseButton(this);
85149
this.details = this.parentElement;
86150
this.setAttribute('role', 'dialog');
87151

88-
var keyDownHelpers = this.keyDownHelpers.bind(this);
89-
var captureDismissal = this.captureDismissal.bind(this);
90-
91152
this.details.addEventListener('toggle', function () {
92153
if (this.details.open) {
93-
this.autofocus();
154+
autofocus(this);
94155
this.details.addEventListener('keydown', keyDownHelpers);
95156
this.addEventListener('click', captureDismissal);
96157
} else {
@@ -128,73 +189,9 @@
128189
}.bind(this), { capture: true });
129190
}
130191
}, {
131-
key: 'createCloseButton',
132-
value: function createCloseButton() {
133-
this.closeButton = document.createElement('button');
134-
this.closeButton.innerHTML = this.closeIcon();
135-
this.closeButton.classList.add('dd-close-button');
136-
this.closeButton.setAttribute('type', 'button');
137-
this.closeButton.setAttribute('aria-label', 'Close dialog');
138-
this.closeButton.setAttribute('data-close-dialog', true);
139-
this.appendChild(this.closeButton);
140-
}
141-
}, {
142-
key: 'autofocus',
143-
value: function autofocus() {
144-
var autofocus = this.querySelector('[autofocus]');
145-
if (!autofocus) {
146-
autofocus = this;
147-
this.setAttribute('tabindex', '-1');
148-
}
149-
autofocus.focus();
150-
}
151-
}, {
152-
key: 'captureDismissal',
153-
value: function captureDismissal(event) {
154-
if (event.target.hasAttribute('data-close-dialog')) {
155-
this.details.open = false;
156-
}
157-
}
158-
}, {
159-
key: 'keyDownHelpers',
160-
value: function keyDownHelpers(event) {
161-
if (event.key === 'Escape') {
162-
event.currentTarget.open = false;
163-
} else if (event.key === 'Tab') {
164-
this.restrictTabBehavior(event);
165-
}
166-
}
167-
}, {
168-
key: 'restrictTabBehavior',
169-
value: function restrictTabBehavior(event) {
170-
event.preventDefault();
171-
172-
var modal = event.currentTarget;
173-
var elements = Array.from(modal.querySelectorAll('a, input, button, textarea')).filter(function (element) {
174-
return !element.disabled && element.offsetWidth > 0 && element.offsetHeight > 0;
175-
});
176-
177-
elements.unshift(this.closeButton);
178-
var movement = event.shiftKey ? -1 : 1;
179-
var currentFocus = elements.filter(function (el) {
180-
return el.matches(':focus');
181-
})[0];
182-
var targetIndex = elements.length - 1;
183-
184-
if (currentFocus) {
185-
var currentIndex = elements.indexOf(currentFocus);
186-
if (currentIndex !== -1) {
187-
var newIndex = currentIndex + movement;
188-
if (newIndex >= 0) targetIndex = newIndex % elements.length;
189-
}
190-
}
191-
192-
elements[targetIndex].focus();
193-
}
194-
}, {
195-
key: 'closeIcon',
196-
value: function closeIcon() {
197-
return '<svg version="1.1" width="12" height="16" viewBox="0 0 12 16" aria-hidden="true"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>';
192+
key: 'toggle',
193+
value: function toggle(boolean) {
194+
boolean ? this.details.setAttribute('open', true) : this.details.removeAttribute('open');
198195
}
199196
}]);
200197

index.js

+71-67
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,77 @@
1+
function createCloseButton(el) {
2+
const closeButton = document.createElement('button')
3+
closeButton.innerHTML = closeIcon()
4+
closeButton.classList.add('dd-close-button')
5+
closeButton.setAttribute('type', 'button')
6+
closeButton.setAttribute('aria-label', 'Close dialog')
7+
closeButton.setAttribute('data-close-dialog', true)
8+
el.appendChild(closeButton)
9+
return closeButton
10+
}
11+
12+
function autofocus(el) {
13+
let autofocus = el.querySelector('[autofocus]')
14+
if (!autofocus) {
15+
autofocus = el
16+
el.setAttribute('tabindex', '-1')
17+
}
18+
autofocus.focus()
19+
}
20+
21+
function captureDismissal(event) {
22+
if (event.target.hasAttribute('data-close-dialog') || event.target.closest('[data-close-dialog]')) {
23+
event.target.closest('details').open = false
24+
}
25+
}
26+
27+
function keyDownHelpers(event) {
28+
if (event.key === 'Escape') {
29+
event.currentTarget.open = false
30+
} else if (event.key === 'Tab') {
31+
restrictTabBehavior(event)
32+
}
33+
}
34+
35+
function restrictTabBehavior(event) {
36+
event.preventDefault()
37+
38+
const dialog = event.currentTarget
39+
const elements = Array.from(dialog.querySelectorAll('a, input, button, textarea')).filter(function(element) {
40+
return !element.disabled && element.offsetWidth > 0 && element.offsetHeight > 0
41+
})
42+
43+
const movement = event.shiftKey ? -1 : 1
44+
const currentFocus = elements.filter(el => el.matches(':focus'))[0]
45+
let targetIndex = elements.length - 1
46+
47+
if (currentFocus) {
48+
const currentIndex = elements.indexOf(currentFocus)
49+
if (currentIndex !== -1) {
50+
const newIndex = currentIndex + movement
51+
if (newIndex >= 0) targetIndex = newIndex % elements.length
52+
}
53+
}
54+
55+
elements[targetIndex].focus()
56+
}
57+
58+
// Pulled from https://github.com/primer/octicons
59+
// We're only using one octicon so it doesn't make sense to include the whole module
60+
function closeIcon() {
61+
return '<svg version="1.1" width="12" height="16" viewBox="0 0 12 16" aria-hidden="true"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>'
62+
}
63+
164
class DetailsDialogElement extends HTMLElement {
265
connectedCallback() {
3-
this.createCloseButton()
66+
this.closeButton = createCloseButton(this)
467
this.details = this.parentElement
568
this.setAttribute('role', 'dialog')
669

7-
const keyDownHelpers = this.keyDownHelpers.bind(this)
8-
const captureDismissal = this.captureDismissal.bind(this)
9-
1070
this.details.addEventListener(
1171
'toggle',
1272
function() {
1373
if (this.details.open) {
14-
this.autofocus()
74+
autofocus(this)
1575
this.details.addEventListener('keydown', keyDownHelpers)
1676
this.addEventListener('click', captureDismissal)
1777
} else {
@@ -30,68 +90,12 @@ class DetailsDialogElement extends HTMLElement {
3090
)
3191
}
3292

33-
createCloseButton() {
34-
this.closeButton = document.createElement('button')
35-
this.closeButton.innerHTML = this.closeIcon()
36-
this.closeButton.classList.add('dd-close-button')
37-
this.closeButton.setAttribute('type', 'button')
38-
this.closeButton.setAttribute('aria-label', 'Close dialog')
39-
this.closeButton.setAttribute('data-close-dialog', true)
40-
this.appendChild(this.closeButton)
41-
}
42-
43-
autofocus() {
44-
let autofocus = this.querySelector('[autofocus]')
45-
if (!autofocus) {
46-
autofocus = this
47-
this.setAttribute('tabindex', '-1')
48-
}
49-
autofocus.focus()
50-
}
51-
52-
captureDismissal(event) {
53-
if (event.target.hasAttribute('data-close-dialog')) {
54-
this.details.open = false
55-
}
56-
}
57-
58-
keyDownHelpers(event) {
59-
if (event.key === 'Escape') {
60-
event.currentTarget.open = false
61-
} else if (event.key === 'Tab') {
62-
this.restrictTabBehavior(event)
63-
}
64-
}
65-
66-
restrictTabBehavior(event) {
67-
event.preventDefault()
68-
69-
const modal = event.currentTarget
70-
const elements = Array.from(modal.querySelectorAll('a, input, button, textarea')).filter(function(element) {
71-
return !element.disabled && element.offsetWidth > 0 && element.offsetHeight > 0
72-
})
73-
74-
elements.unshift(this.closeButton)
75-
const movement = event.shiftKey ? -1 : 1
76-
const currentFocus = elements.filter(el => el.matches(':focus'))[0]
77-
let targetIndex = elements.length - 1
78-
79-
if (currentFocus) {
80-
const currentIndex = elements.indexOf(currentFocus)
81-
if (currentIndex !== -1) {
82-
const newIndex = currentIndex + movement
83-
if (newIndex >= 0) targetIndex = newIndex % elements.length
84-
}
85-
}
86-
87-
elements[targetIndex].focus()
88-
}
89-
90-
// Pulled from https://github.com/primer/octicons
91-
// We're only using one octicon so it doesn't make sense to include the whole module
92-
closeIcon() {
93-
return '<svg version="1.1" width="12" height="16" viewBox="0 0 12 16" aria-hidden="true"><path d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>'
93+
toggle(boolean) {
94+
boolean ? this.details.setAttribute('open', true) : this.details.removeAttribute('open')
9495
}
9596
}
9697

97-
window.customElements.define('details-dialog', DetailsDialogElement)
98+
if (!window.customElements.get('details-dialog')) {
99+
window.HTMLDetailsDialogElement = DetailsDialogElement
100+
window.customElements.define('details-dialog', DetailsDialogElement)
101+
}

0 commit comments

Comments
 (0)