-
Notifications
You must be signed in to change notification settings - Fork 62
/
ember-wormhole.js
76 lines (66 loc) · 2.4 KB
/
ember-wormhole.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
import Ember from 'ember';
var computed = Ember.computed;
var observer = Ember.observer;
var run = Ember.run;
export default Ember.Component.extend({
to: computed.alias('destinationElementId'),
destinationElementId: null,
destinationElement: computed('destinationElementId', 'renderInPlace', function() {
return this.get('renderInPlace') ? this.element : document.getElementById(this.get('destinationElementId'));
}),
renderInPlace: false,
didInsertElement: function() {
this._super(...arguments);
this._firstNode = this.element.firstChild;
this._lastNode = this.element.lastChild;
this.appendToDestination();
},
willDestroyElement: function() {
this._super(...arguments);
var firstNode = this._firstNode;
var lastNode = this._lastNode;
run.schedule('render', () => {
this.removeRange(firstNode, lastNode);
});
},
destinationDidChange: observer('destinationElement', function() {
var destinationElement = this.get('destinationElement');
if (destinationElement !== this._firstNode.parentNode) {
run.schedule('render', this, 'appendToDestination');
}
}),
appendToDestination: function() {
var destinationElement = this.get('destinationElement');
var currentActiveElement = document.activeElement;
if (!destinationElement) {
var destinationElementId = this.get('destinationElementId');
if (destinationElementId) {
throw new Error(`ember-wormhole failed to render into '#${this.get('destinationElementId')}' because the element is not in the DOM`);
}
throw new Error('ember-wormhole failed to render content because the destinationElementId was set to an undefined or falsy value.');
}
this.appendRange(destinationElement, this._firstNode, this._lastNode);
if (document.activeElement !== currentActiveElement) {
currentActiveElement.focus();
}
},
appendRange: function(destinationElement, firstNode, lastNode) {
while(firstNode) {
destinationElement.insertBefore(firstNode, null);
firstNode = firstNode !== lastNode ? lastNode.parentNode.firstChild : null;
}
},
removeRange: function(firstNode, lastNode) {
var node = lastNode;
do {
var next = node.previousSibling;
if (node.parentNode) {
node.parentNode.removeChild(node);
if (node === firstNode) {
break;
}
}
node = next;
} while (node);
}
});