-
Notifications
You must be signed in to change notification settings - Fork 0
/
AttributeLink.html
96 lines (91 loc) · 3.5 KB
/
AttributeLink.html
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
<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="attribute-link">
<script>
Polymer({
is: 'attribute-link',
properties: {
source: {
type: String,
reflectToAttribute: true,
observer: 'setupAttributeObservers'
},
target: {
type: String,
reflectToAttribute: true
},
transformation: {
type: String,
reflectToAttribute: true,
observer: 'transformationChanged'
},
noLocalLink: {
type: Boolean,
value: false,
reflectToAttribute: true
}
},
created: function() {
this.mutationObservers = [];
},
attached: function() {
this.setupAttributeObservers();
},
detached: function() {
this.removeAttributeObservers();
},
transformationChanged: function() {
// TODO: check tranformation for harmful code
this.transformationFunction = function(source) { return eval(this.transformation); };
},
setupAttributeObservers: function() {
if (!this.isAttached) return;
this.removeAttributeObservers();
this.bodyChanged = false;
this.bodyMutationObserver = new MutationObserver((function() {
this.async(function() {
if (this.bodyChanged) this.setupAttributeObservers();
}, 1000);
this.bodyChanged = true;
}).bind(this));
this.bodyMutationObserver.observe(document.body, { childList: true, subtree: true });
var source = this.parseConnectionString(this.source);
if (!source) return;
var elements = document.querySelectorAll(source.selector);
for (var i = 0, c = elements.length; i < c; i++) {
var mutationObserver = new MutationObserver(this.handleAttributeChange.bind(this));
mutationObserver.observe(elements[i], { attributes: true, attributeFilter: [source.attribute] });
this.mutationObservers.push(mutationObserver);
}
},
removeAttributeObservers: function() {
if (this.bodyMutationObserver) {
this.bodyMutationObserver.disconnect();
this.bodyMutationObserver = null;
}
for (var i in this.mutationObservers) {
this.mutationObservers[i].disconnect();
this.mutationObservers[i] = null;
}
this.mutationObservers = [];
},
handleAttributeChange: function(records) {
var value = records[0].target.getAttribute(records[0].attributeName),
target = this.parseConnectionString(this.target);
if (!target) return;
if (this.transformation) value = this.transformationFunction.call(this, value);
if (typeof value === 'undefined') return;
this.fire('linkedAttributeChanged', { selector: target.selector, attribute: target.attribute, value: value }, { node: this.parentNode });
if (this.noLocalLink) return;
var elements = document.querySelectorAll(target.selector);
for (var i = 0, c = elements.length; i < c; i++) {
if (value !== elements[i].getAttribute(target.attribute)) elements[i].setAttribute(target.attribute, value);
if (target.attribute == 'value') elements[i][target.attribute] = value;
}
},
parseConnectionString: function(str) {
var p = str.lastIndexOf('@');
return (p < 0) ? null : { selector: str.substr(0, p), attribute: str.substr(p+1) };
}
});
</script>
</dom-module>