@ewc-lib/ewc-popovers 2.0.4-beta → 2.1.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ewc-popover/package.json
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
"main": "src/main.js",
|
|
4
4
|
"license": "EUPL v.1.1",
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@ewc-lib/ewc-css-common": "0.1.0"
|
|
7
|
-
|
|
6
|
+
"@ewc-lib/ewc-css-common": "0.1.0"
|
|
7
|
+
},
|
|
8
|
+
"optionalDependencies": {
|
|
9
|
+
"@ewc-lib/ewc-dialogs": "5.0.10"
|
|
8
10
|
}
|
|
9
11
|
}
|
package/ewc-popover/readme.md
CHANGED
|
@@ -27,6 +27,7 @@ ewc-popover must have 2 children:
|
|
|
27
27
|
|
|
28
28
|
- an HTML element to open/close the popover (**slot="toggle"**)
|
|
29
29
|
- the position of the popover is relative to this element
|
|
30
|
+
- Note: eventListeners (click and keyboard) are being attached to the element ("toggleElement" in element.js)
|
|
30
31
|
- the content of the popover (**slot="content"**)
|
|
31
32
|
- this element is expected to have "display:inline" style
|
|
32
33
|
|
|
@@ -61,3 +62,13 @@ An element within the content can be specified to close the popover.
|
|
|
61
62
|
This is done by setting the attribute "**data-ewc-popover-close**" on it.
|
|
62
63
|
Just existence is checked, value doesn't matter.
|
|
63
64
|
Use case: a close button inside the popover.
|
|
65
|
+
|
|
66
|
+
## Suppressing tooltips
|
|
67
|
+
|
|
68
|
+
On a child with slot="toggle" attribute, the attribute "tooltip-suppressed" is set to "true" when popover opens and set to "false" when the popover closes.
|
|
69
|
+
|
|
70
|
+
This can be seen as an optional interface.
|
|
71
|
+
|
|
72
|
+
If the child implements that interface, the popover expects the child to not show any tooltip. If the child does not inplement that interface, nothing happens - ⚠️ as long as the child doesn't expose any other functionality via the attribute "tooltip-suppressed".
|
|
73
|
+
|
|
74
|
+
Note: ewc-icon-button (a WebComponent intended to be used together with this popover) implements this interface.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Popover from "./popover.js"
|
|
2
2
|
import MARKUP from "./markup.js" // keep this file markup free
|
|
3
3
|
import CSS from "./css.js"
|
|
4
4
|
|
|
@@ -6,15 +6,18 @@ import CSS from "./css.js"
|
|
|
6
6
|
export default class Element extends HTMLElement {
|
|
7
7
|
|
|
8
8
|
#isInitialized=false
|
|
9
|
-
#popover
|
|
9
|
+
#popover = null
|
|
10
|
+
#toggleElement = null
|
|
10
11
|
|
|
11
12
|
constructor() {
|
|
12
|
-
super()
|
|
13
|
+
super()
|
|
14
|
+
this.toggleVisibility = this.toggleVisibility.bind(this)
|
|
15
|
+
this.handleClickGlobal = this.handleClickGlobal.bind(this)
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
connectedCallback(ignoreCheck) {
|
|
16
19
|
if(this.#isInitialized) { return } else { this.#isInitialized=true }
|
|
17
|
-
this.setAttribute("ewc-version", "2.0
|
|
20
|
+
this.setAttribute("ewc-version", "2.1.0-alpha") // please always keep in sync with version in package.json
|
|
18
21
|
if(ignoreCheck || this.childElementCount===2) {
|
|
19
22
|
// please see also comment in html.js
|
|
20
23
|
|
|
@@ -24,13 +27,25 @@ export default class Element extends HTMLElement {
|
|
|
24
27
|
this.shadowRoot.appendChild( MARKUP().cloneNode(true) )
|
|
25
28
|
|
|
26
29
|
const rootElement = this.shadowRoot.querySelector(".main_container")
|
|
27
|
-
|
|
30
|
+
this.#toggleElement = this.shadowRoot.querySelector("slot[name=toggle]").assignedElements()[0]
|
|
28
31
|
const p = {
|
|
29
|
-
toggleElement : toggleElement,
|
|
32
|
+
toggleElement : this.#toggleElement,
|
|
30
33
|
positioninghint : this.hasAttribute("positioninghint") ? this.getAttribute("positioninghint").toLowerCase() : false
|
|
31
34
|
}
|
|
32
|
-
this.#popover = new
|
|
33
|
-
|
|
35
|
+
this.#popover = new Popover(rootElement, p).init()
|
|
36
|
+
|
|
37
|
+
if (this.#toggleElement) {
|
|
38
|
+
this.#toggleElement.addEventListener('click', this.toggleVisibility);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (this.#toggleElement) {
|
|
42
|
+
this.#toggleElement.addEventListener('keydown', e=>{
|
|
43
|
+
if(e.key==="Enter" || e.key===" " || e.key==="ArrowDown") {this.toggleVisibility(e)}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
document.addEventListener('click', this.handleClickGlobal);
|
|
48
|
+
|
|
34
49
|
} else {
|
|
35
50
|
console.error("popover: Must have 2 children: the toggle-element and the content.")
|
|
36
51
|
}
|
|
@@ -41,19 +56,61 @@ export default class Element extends HTMLElement {
|
|
|
41
56
|
|
|
42
57
|
set visibility(val) {
|
|
43
58
|
if(val==true) {
|
|
59
|
+
this.#toggleElement.setAttribute("tooltip-suppressed", "true")
|
|
44
60
|
this.#popover.openPopover()
|
|
61
|
+
this.#popover.positionPopover()
|
|
45
62
|
} else {
|
|
63
|
+
this.#toggleElement.setAttribute("tooltip-suppressed", "false")
|
|
46
64
|
this.#popover.closePopover()
|
|
47
65
|
}
|
|
48
66
|
}
|
|
49
67
|
|
|
50
|
-
toggleVisibility() {
|
|
68
|
+
toggleVisibility(e) {
|
|
69
|
+
if(e) {e.preventDefault()}
|
|
70
|
+
|
|
51
71
|
if(this.#popover.isOpen()) {
|
|
52
|
-
this
|
|
72
|
+
this.visibility = false
|
|
53
73
|
} else {
|
|
54
|
-
this
|
|
74
|
+
this.visibility = true
|
|
55
75
|
}
|
|
56
76
|
}
|
|
57
77
|
|
|
58
78
|
setFocusToToggleElement() {this.#popover.setFocusToToggleElement()}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Handles global click events, triggered outside of the popover.
|
|
82
|
+
* It's tediously complicated :-(
|
|
83
|
+
*/
|
|
84
|
+
handleClickGlobal(e) {
|
|
85
|
+
if (this.#popover.isOpen()) {
|
|
86
|
+
|
|
87
|
+
const rootElement = this.shadowRoot.querySelector(".main_container")
|
|
88
|
+
|
|
89
|
+
// this is the whole popover area
|
|
90
|
+
// we're in shadow DOM. test if element containing content is in also in shadow or in light DOM
|
|
91
|
+
const content = rootElement.querySelector("slot[name=content]")
|
|
92
|
+
const cond1 = content ? content.assignedElements()[0].contains(e.target) : rootElement.querySelector(".ewc-popover__content").contains(e.target)
|
|
93
|
+
|
|
94
|
+
// this is the designated element to toggle the popover
|
|
95
|
+
const cond2 = e.target === this.#toggleElement || e.target === this.#toggleElement.firstElementChild
|
|
96
|
+
|
|
97
|
+
// this is the custom property itself
|
|
98
|
+
// also include derived classes
|
|
99
|
+
const cond3 = e.target.nodeName.slice(0, 11)==="EWC-POPOVER"
|
|
100
|
+
|
|
101
|
+
// this is the element inside the content area with which it should be closed
|
|
102
|
+
// close when such an element was clicked
|
|
103
|
+
const cond4 = e.target.hasAttribute("data-ewc-popover-close")
|
|
104
|
+
|
|
105
|
+
//console.log(!cond2,!cond3,!cond1,cond4)
|
|
106
|
+
|
|
107
|
+
// close if anything other than the popover was clicked
|
|
108
|
+
if(!cond2 && !cond3 && (!cond1 || cond4)) {
|
|
109
|
+
e.preventDefault()
|
|
110
|
+
e.stopImmediatePropagation()
|
|
111
|
+
this.visibility=false
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
59
116
|
}
|
|
@@ -16,7 +16,7 @@ See also comment in html.js
|
|
|
16
16
|
* @param {Boolean} options.attachClickListener
|
|
17
17
|
* @param {Boolean} options.attachKeyListener
|
|
18
18
|
*/
|
|
19
|
-
export class Popover {
|
|
19
|
+
export default class Popover {
|
|
20
20
|
|
|
21
21
|
constructor(
|
|
22
22
|
element,
|
|
@@ -53,9 +53,7 @@ export class Popover {
|
|
|
53
53
|
this.openPopover = this.openPopover.bind(this);
|
|
54
54
|
this.closePopover = this.closePopover.bind(this);
|
|
55
55
|
this.positionPopover = this.positionPopover.bind(this);
|
|
56
|
-
this.handleClickOnToggle = this.handleClickOnToggle.bind(this);
|
|
57
56
|
this.handleKeyboardGlobal = this.handleKeyboardGlobal.bind(this);
|
|
58
|
-
this.handleClickGlobal = this.handleClickGlobal.bind(this);
|
|
59
57
|
this.checkPosition = this.checkPosition.bind(this);
|
|
60
58
|
this.resetStyles = this.resetStyles.bind(this);
|
|
61
59
|
|
|
@@ -79,23 +77,10 @@ export class Popover {
|
|
|
79
77
|
if (this.attachKeyListener) {
|
|
80
78
|
document.addEventListener('keyup', this.handleKeyboardGlobal);
|
|
81
79
|
}
|
|
82
|
-
if (this.attachClickListener) {
|
|
83
|
-
document.addEventListener('click', this.handleClickGlobal);
|
|
84
|
-
}
|
|
85
80
|
|
|
86
81
|
window.addEventListener('resize', this.checkPosition);
|
|
87
82
|
document.addEventListener('scroll', this.checkPosition);
|
|
88
83
|
|
|
89
|
-
if (this.attachClickListener && this.toggle) {
|
|
90
|
-
this.toggle.addEventListener('click', this.handleClickOnToggle);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (this.attachKeyListener && this.toggle) {
|
|
94
|
-
this.toggle.addEventListener('keydown', e=>{
|
|
95
|
-
if(e.key==="Enter" || e.key===" " || e.key==="ArrowDown") {this.handleClickOnToggle(e)}
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
|
|
99
84
|
return this
|
|
100
85
|
}
|
|
101
86
|
|
|
@@ -109,35 +94,16 @@ export class Popover {
|
|
|
109
94
|
if (this.attachKeyListener) {
|
|
110
95
|
document.removeEventListener('keyup', this.handleKeyboardGlobal);
|
|
111
96
|
}
|
|
112
|
-
if (this.attachClickListener) {
|
|
113
|
-
document.removeEventListener('click', this.handleClickGlobal);
|
|
114
|
-
}
|
|
115
97
|
|
|
116
98
|
if (this.toggle.getAttribute('aria-expanded') === 'true') {
|
|
117
99
|
this.closePopover();
|
|
118
100
|
}
|
|
119
101
|
}
|
|
120
102
|
|
|
121
|
-
|
|
103
|
+
isOpen() {
|
|
122
104
|
return this.container.style.display!=="none" && this.container.style.display!==""
|
|
123
105
|
}
|
|
124
106
|
|
|
125
|
-
/**
|
|
126
|
-
* Toggles between collapsed/expanded states.
|
|
127
|
-
*
|
|
128
|
-
* @param {Event} e
|
|
129
|
-
*/
|
|
130
|
-
handleClickOnToggle(e) {
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
// Toggle the popover
|
|
133
|
-
if (this.#isOpen()) {
|
|
134
|
-
this.closePopover();
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
this.openPopover();
|
|
138
|
-
this.positionPopover();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
107
|
openPopover() {
|
|
142
108
|
this.toggle.setAttribute('aria-expanded', 'true');
|
|
143
109
|
this.container.style.display="block"
|
|
@@ -348,7 +314,7 @@ export class Popover {
|
|
|
348
314
|
checkPosition() {
|
|
349
315
|
clearTimeout(this.resizeTimer);
|
|
350
316
|
this.resizeTimer = setTimeout(() => {
|
|
351
|
-
if(this
|
|
317
|
+
if(this.isOpen()) {
|
|
352
318
|
this.positionPopover();
|
|
353
319
|
}
|
|
354
320
|
}, 200);
|
|
@@ -363,7 +329,7 @@ export class Popover {
|
|
|
363
329
|
if (!this.container) return;
|
|
364
330
|
|
|
365
331
|
// assume there's maximally only 1 open
|
|
366
|
-
if(this
|
|
332
|
+
if(this.isOpen()) {
|
|
367
333
|
if (e.key === 'Escape' || e.key === 'Esc') {
|
|
368
334
|
this.closePopover();
|
|
369
335
|
this.setFocusToToggleElement()
|
|
@@ -372,42 +338,7 @@ export class Popover {
|
|
|
372
338
|
}
|
|
373
339
|
|
|
374
340
|
setFocusToToggleElement() {
|
|
375
|
-
this.
|
|
341
|
+
this.toggle.focus()
|
|
376
342
|
}
|
|
377
343
|
|
|
378
|
-
/**
|
|
379
|
-
* Handles global click events, triggered outside of the popover.
|
|
380
|
-
* It's tediously complicated :-(
|
|
381
|
-
*/
|
|
382
|
-
handleClickGlobal(e) {
|
|
383
|
-
if (!this.container) return;
|
|
384
|
-
|
|
385
|
-
if (this.#isOpen()) {
|
|
386
|
-
|
|
387
|
-
// this is the whole popover area
|
|
388
|
-
// we're in shadow DOM. test if element containing content is in also in shadow or in light DOM
|
|
389
|
-
const content = this.container.querySelector("slot[name=content]")
|
|
390
|
-
const cond1 = content ? content.assignedElements()[0].contains(e.target) : this.container.querySelector(".ewc-popover__content").contains(e.target)
|
|
391
|
-
|
|
392
|
-
// this is the designated element to toggle the popover
|
|
393
|
-
const cond2 = e.target === this.toggle || e.target === this.toggle.firstElementChild
|
|
394
|
-
|
|
395
|
-
// this is the custom property itself
|
|
396
|
-
// also include derived classes
|
|
397
|
-
const cond3 = e.target.nodeName.slice(0, 11)==="EWC-POPOVER"
|
|
398
|
-
|
|
399
|
-
// this is the element inside the content area with which it should be closed
|
|
400
|
-
// close when such an element was clicked
|
|
401
|
-
const cond4 = e.target.hasAttribute("data-ewc-popover-close")
|
|
402
|
-
|
|
403
|
-
//console.log(!cond2,cond3,cond1,cond4)
|
|
404
|
-
|
|
405
|
-
// close if anything other than the popover was clicked
|
|
406
|
-
if(!cond2 && !cond3 && (!cond1 || cond4)) {
|
|
407
|
-
e.preventDefault()
|
|
408
|
-
e.stopImmediatePropagation()
|
|
409
|
-
this.closePopover();
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
344
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@ewc-lib/ewc-popovers",
|
|
3
3
|
"description": "Monorepo for EWCL popover WebComponents",
|
|
4
4
|
"//": "please always keep version in sync with version info in the sourcecode",
|
|
5
|
-
"version": "2.0
|
|
5
|
+
"version": "2.1.0-alpha",
|
|
6
6
|
"workspaces": [
|
|
7
7
|
"ewc-popover",
|
|
8
8
|
"ewc-popover-sharing"
|
package/readme.md
CHANGED
|
@@ -118,3 +118,12 @@ Before the 2 popover components were grouped together into this monorepo, they e
|
|
|
118
118
|
|
|
119
119
|
- 2.0.4-beta
|
|
120
120
|
- fix opener bug for X
|
|
121
|
+
|
|
122
|
+
- 2.0.4
|
|
123
|
+
- drop beta
|
|
124
|
+
|
|
125
|
+
- 2.0.5-alpha
|
|
126
|
+
- consolidation of development workflow
|
|
127
|
+
|
|
128
|
+
- 2.1.0-alpha
|
|
129
|
+
- use a child's optional "tooltip-suppressed" functionality
|