-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslotted-element.js
106 lines (89 loc) · 2.78 KB
/
slotted-element.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import FE from './fetch-element.js';
import { CssChain as $ } from 'css-chain';
export * from './fetch-element.js';
export const FetchElement = FE;
function createNode( tag, prop, val ){ const el = document.createElement(tag); el[prop]=val; return el; }
export class
SlottedElement extends FE
{
static get observedAttributes(){ return [ 'template', ...FE.observedAttributes ]; }
connectedCallback()
{ this._$ = $(this);
this.slotsInit();
super.connectedCallback();
}
attributeChangedCallback( name, oldValue, newValue )
{
if( name !== 'template')
return super.attributeChangedCallback( name, oldValue, newValue );
this.template = newValue;
this.initialized && this.slotsInit();
}
$( css ){ return css? this._$.$(css): this._$; }
fetch( url, options )
{
this.slotOnly('loading')
return super.fetch( url, options ).finally( ()=>this.slotOnly(this.state) );
}
setContent( html )
{
if( this.slots.loaded )
{ const slot = this.slotClone('loaded')
slot.innerHTML = html;
this.slotAdd(slot);
}else
this.innerHTML = html;
}
// slot API
slotsInit()
{
if( !this.slots )
{ this.slots = {};
this.$( '[slot]' ).map( node =>this.slots[ node.slot ] = node )
}
const $i = this._$
, a = $i.attr('template');
if( a ) $i.template( $('#'+a ) )
else if( this.template )
$i.template( createNode( 'template', 'innerHTML', this.template ) )
else
$i.template();
this.src || this.slotOnly('loaded');
}
slotOnly( name )
{ this.$( '[slot-cloned]' )
.filter( el => el.slot !== name )
.remove();
const $s = this.$().slots(name);
$s.length && this.$().slots().attr('hidden','hidden');
if( !this.$( `[slot="${name}"][slot-cloned]` ).length )
this.slotAdd(name);
this.$().slots(name).removeAttribute('hidden');
}
slotsClear()
{ this.$( '[slot-cloned]' )
.remove();
}
slotClone( name )
{
const slot = this.slots[ name ]
if( !slot )
return;
const ret = slot.cloneNode( true );
ret.setAttribute( 'slot-cloned', true );
ret.hidden = false;
return ret;
}
slotAdd( node )
{
const slot = node.slot ? node: this.slotClone( node )
, ref = this.$(`slot[name="${node.slot || node}"]`);
let added;
for( let r of ref)
added = r.parentElement.insertBefore( slot, r );
return added;
}
}
export default SlottedElement;
window.customElements.define('slotted-element', SlottedElement);
export { $ as CssChain };