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
107
108
109
110
111
112
113
114
115
116
117
118
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
<!--
A plumber component which joins a number of input bindings. It outputs a list
consisting of all of the inputs that are not null or undefined.
It can take explicit arguments [in0...in98] or it can pull its arguments from
a dom-repeat template, provided that it is given the property name it is looking
for on the repeated children, and that property has {notify: true}. The repeat
binding involves some magic and may not be totally reliable; ping danmane@ if
something goes wrong.
Example:
<hydrogen-join
in1="[[foo1]]"
in2="[[foo2]]"
in3="[[foo3]]"
out="{{foos}}" // equivalent to [foo1].push(foo2).push(foo3)
></hydrogen-join>
<hydrogen-join out="{{foo}}" in-join-property="out">
<template is="dom-repeat" items="[[foos]]">
<foo item="[[item]]"></foo> //foo has a property out: {type: Array, notify: true}
</template>
</hydrogen-join>
Swapping the inJoinProperty is not currently supported, it will warn if you try.
There's a possible bug in repeat mode if an element is removed from the dom-repeat,
but continues to exist somewhere else, and continues to fire property-changed events.
Then the hydrogen-join will inappropriately record its value, even though it is not
still connected in hydrogen-join's DOM.
@demo
-->
<dom-module id="hydrogen-join">
<script>
var declaration = {
is: 'hydrogen-join',
properties: {
out: {type: Array, readOnly: true, notify: true},
_items: {type: Array, value: function() {return [];}},
/* Property to pull from dom-repeated child nodes and then pull and join */
inJoinProperty: {type: String, observer: "_modifyJoinProperty"},
},
listeners: {
"dom-change": "_syncListenersAndState",
},
/* If we are in repeat-mode, ensure all event listeners are setup, and pull
* items out of whatever children currently exist
*/
_syncListenersAndState: function() {
if (this.inJoinProperty == null) {
// this codepath is for pulling properties out of children in a repeat
return;
}
function repeatUpdateFunction(i) {
return function(e) {
this._items[i] = e.detail.value;
// Debounce just in case something else thrashes
this.debounce("updateOut", this._updateOutput)
}
}
// create a new items array to replace the old one, otherwise old items
// might never get removed when their corresponding element leaves
this._items = [];
// Sadly, we need to bind an update function onto every child node,
// because the property-changed event does not bubble.
for (var i=0; i<this.childNodes.length; i++) {
var child = this.childNodes[i];
if (child.properties != null && child.properties[this.inJoinProperty] != null) {
child.addEventListener(this.inJoinProperty + "-changed", repeatUpdateFunction(i).bind(this));
this._items[i] = child[this.inJoinProperty];
}
}
this._updateOutput();
},
_modifyJoinProperty: function(newJoinProperty, oldJoinProperty) {
if (oldJoinProperty != null) {
console.warning("Changing the join property may be unsafe. Have fun!");
}
this._syncListenersAndState();
},
_updateOutput: function() {
var out = [];
for (var i=0; i<99; i++) {
if (this._items[i] != null) {
out.push(this._items[i]);
}
}
this._setOut(out);
}
};
/* Programatically add properties in0-in98, with associated observers */
function argsUpdateFunction(i) {
return function(newval) {
this._items[i] = newval;
if (i === 98) {
console.warn("You're updating the last arg (98). Possibly some values are being lost");
}
if (this.inJoinProperty != null) {
console.warn("It looks like you're providing a join property and also arguments. This is not supported.")
}
this.debounce("updateOut", this._updateOutput)
}
}
// I got 99 arguments and ain't off by 1!
for (var i = 0; i < 99; i++) {
var propName = "in" + i;
var updateName = "_update" + i;
var property = {type: Object, observer: updateName};
declaration.properties[propName] = property;
declaration[updateName] = argsUpdateFunction(i);
}
Polymer(declaration);
</script>
</dom-module>
|