polymer-paper-rails 0.1.0

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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +69 -0
  3. data/Rakefile +1 -0
  4. data/app/assets/components/core/animation/web-animations.html.erb +1 -0
  5. data/app/assets/components/core/animation/web-animations.js +5666 -0
  6. data/app/assets/components/core/icon/core-icon.css +25 -0
  7. data/app/assets/components/core/icon/core-icon.html.erb +126 -0
  8. data/app/assets/components/core/iconset/core-iconset.html.erb +236 -0
  9. data/app/assets/components/core/input/core-input.css +35 -0
  10. data/app/assets/components/core/input/core-input.html.erb +385 -0
  11. data/app/assets/components/core/list/core-list.css +20 -0
  12. data/app/assets/components/core/list/core-list.html.erb +403 -0
  13. data/app/assets/components/core/media-query/core-media-query.html +86 -0
  14. data/app/assets/components/core/menu/core-menu.css +18 -0
  15. data/app/assets/components/core/menu/core-menu.html.erb +62 -0
  16. data/app/assets/components/core/menu/core-submenu.css +29 -0
  17. data/app/assets/components/core/menu/core-submenu.html.erb +106 -0
  18. data/app/assets/components/core/meta/core-meta.html +143 -0
  19. data/app/assets/components/core/overlay/core-key-helper.html +17 -0
  20. data/app/assets/components/core/overlay/core-overlay-layer.html +112 -0
  21. data/app/assets/components/core/overlay/core-overlay.html.erb +661 -0
  22. data/app/assets/components/core/range/core-range.html +106 -0
  23. data/app/assets/components/core/selection/core-selection.html +148 -0
  24. data/app/assets/components/core/selector/core-selector.html.erb +423 -0
  25. data/app/assets/components/core/style/core-style.html +386 -0
  26. data/app/assets/components/core/transition/core-transition-css.html.erb +76 -0
  27. data/app/assets/components/core/transition/core-transition-overlay.css +46 -0
  28. data/app/assets/components/core/transition/core-transition.html.erb +44 -0
  29. data/app/assets/components/paper-button/paper-button.css +115 -0
  30. data/app/assets/components/paper-button/paper-button.html.erb +210 -0
  31. data/app/assets/components/paper-checkbox/paper-checkbox.css +262 -0
  32. data/app/assets/components/paper-checkbox/paper-checkbox.html.erb +104 -0
  33. data/app/assets/components/paper-dialog/paper-dialog-transition.css +59 -0
  34. data/app/assets/components/paper-dialog/paper-dialog-transition.html.erb +27 -0
  35. data/app/assets/components/paper-dialog/paper-dialog.css +0 -0
  36. data/app/assets/components/paper-dialog/paper-dialog.html.erb +176 -0
  37. data/app/assets/components/paper-fab/paper-fab.css +27 -0
  38. data/app/assets/components/paper-fab/paper-fab.html.erb +55 -0
  39. data/app/assets/components/paper-focusable/paper-focusable.html +144 -0
  40. data/app/assets/components/paper-icon-button/paper-icon-button.css +17 -0
  41. data/app/assets/components/paper-icon-button/paper-icon-button.html.erb +87 -0
  42. data/app/assets/components/paper-input/error-100.png +0 -0
  43. data/app/assets/components/paper-input/error-200.png +0 -0
  44. data/app/assets/components/paper-input/paper-input.html.erb +398 -0
  45. data/app/assets/components/paper-input/paper-input.scss +203 -0
  46. data/app/assets/components/paper-item/paper-item.css +30 -0
  47. data/app/assets/components/paper-item/paper-item.html.erb +103 -0
  48. data/app/assets/components/paper-menu-button/paper-menu-button-overlay.html.erb +86 -0
  49. data/app/assets/components/paper-menu-button/paper-menu-button-transition.css +19 -0
  50. data/app/assets/components/paper-menu-button/paper-menu-button-transition.html.erb +118 -0
  51. data/app/assets/components/paper-menu-button/paper-menu-button.css +86 -0
  52. data/app/assets/components/paper-menu-button/paper-menu-button.html.erb +128 -0
  53. data/app/assets/components/paper-progress/paper-progress.css +35 -0
  54. data/app/assets/components/paper-progress/paper-progress.html.erb +98 -0
  55. data/app/assets/components/paper-radio-button/paper-radio-button.css +98 -0
  56. data/app/assets/components/paper-radio-button/paper-radio-button.html.erb +148 -0
  57. data/app/assets/components/paper-radio-group/paper-radio-group.html.erb +68 -0
  58. data/app/assets/components/paper-ripple/paper-ripple.html +426 -0
  59. data/app/assets/components/paper-shadow/paper-shadow.css +81 -0
  60. data/app/assets/components/paper-shadow/paper-shadow.html.erb +212 -0
  61. data/app/assets/components/paper-slider/paper-slider.css +193 -0
  62. data/app/assets/components/paper-slider/paper-slider.html.erb +310 -0
  63. data/app/assets/components/paper-tabs/paper-tab.css +49 -0
  64. data/app/assets/components/paper-tabs/paper-tab.html.erb +66 -0
  65. data/app/assets/components/paper-tabs/paper-tabs.css +57 -0
  66. data/app/assets/components/paper-tabs/paper-tabs.html.erb +127 -0
  67. data/app/assets/components/paper-toast/paper-toast.css +0 -0
  68. data/app/assets/components/paper-toast/paper-toast.html.erb +258 -0
  69. data/app/assets/components/paper-toggle-button/paper-toggle-button.css +61 -0
  70. data/app/assets/components/paper-toggle-button/paper-toggle-button.html.erb +125 -0
  71. data/lib/polymer-paper-rails/engine.rb +4 -0
  72. data/lib/polymer-paper-rails/version.rb +3 -0
  73. data/lib/polymer-paper-rails.rb +2 -0
  74. metadata +158 -0
@@ -0,0 +1,106 @@
1
+ <!--
2
+ Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3
+ This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
4
+ The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5
+ The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
6
+ Code distributed by Google as part of the polymer project is also
7
+ subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
8
+ -->
9
+
10
+ <!--
11
+ The `core-range` element is used for managing a numeric value within a given
12
+ range. It has no visual appearance and is typically used in conjunction with
13
+ another element.
14
+
15
+ One can build a progress bar using `core-range` like this:
16
+
17
+ <core-range min="0" max="200" value="100" ratio="{{ratio}}"></core-range>
18
+ <div class="progress-bar" style="width: {{ratio}}%;"></div>
19
+
20
+ @group Polymer Core Elements
21
+ @element core-range
22
+ @homepage github.io
23
+
24
+ -->
25
+
26
+ <polymer-element name="core-range" attributes="value min max step ratio">
27
+ <script>
28
+
29
+ Polymer('core-range', {
30
+
31
+ /**
32
+ * The number that represents the current value.
33
+ *
34
+ * @attribute value
35
+ * @type number
36
+ * @default 0
37
+ */
38
+ value: 0,
39
+
40
+ /**
41
+ * The number that indicates the minimum value of the range.
42
+ *
43
+ * @attribute min
44
+ * @type number
45
+ * @default 0
46
+ */
47
+ min: 0,
48
+
49
+ /**
50
+ * The number that indicates the maximum value of the range.
51
+ *
52
+ * @attribute max
53
+ * @type number
54
+ * @default 100
55
+ */
56
+ max: 100,
57
+
58
+ /**
59
+ * Specifies the value granularity of the range's value.
60
+ *
61
+ * @attribute step
62
+ * @type number
63
+ * @default 1
64
+ */
65
+ step: 1,
66
+
67
+ /**
68
+ * Returns the ratio of the value.
69
+ *
70
+ * @attribute ratio
71
+ * @type number
72
+ * @default 0
73
+ */
74
+ ratio: 0,
75
+
76
+ observe: {
77
+ 'value min max step': 'update'
78
+ },
79
+
80
+ calcRatio: function(value) {
81
+ return (this.clampValue(value) - this.min) / (this.max - this.min);
82
+ },
83
+
84
+ clampValue: function(value) {
85
+ return Math.min(this.max, Math.max(this.min, this.calcStep(value)));
86
+ },
87
+
88
+ calcStep: function(value) {
89
+ return this.step ? (Math.round(value / this.step) / (1 / this.step)) : value;
90
+ },
91
+
92
+ validateValue: function() {
93
+ var v = this.clampValue(this.value);
94
+ this.value = this.oldValue = isNaN(v) ? this.oldValue : v;
95
+ return this.value !== v;
96
+ },
97
+
98
+ update: function() {
99
+ this.validateValue();
100
+ this.ratio = this.calcRatio(this.value) * 100;
101
+ }
102
+
103
+ });
104
+
105
+ </script>
106
+ </polymer-element>
@@ -0,0 +1,148 @@
1
+ <!--
2
+ Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3
+ This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
4
+ The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5
+ The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
6
+ Code distributed by Google as part of the polymer project is also
7
+ subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
8
+ -->
9
+ <!--
10
+ @group Polymer Core Elements
11
+
12
+ The `<core-selection>` element is used to manage selection state. It has no
13
+ visual appearance and is typically used in conjunction with another element.
14
+ For example, [core-selector](#core-selector)
15
+ use a `<core-selection>` to manage selection.
16
+
17
+ To mark an item as selected, call the `select(item)` method on
18
+ `<core-selection>`. The item itself is an argument to this method.
19
+
20
+ The `<core-selection>`element manages selection state for any given set of
21
+ items. When an item is selected, the `core-select` event is fired.
22
+
23
+ The attribute `multi` indicates if multiple items can be selected at once.
24
+
25
+ Example:
26
+
27
+ <polymer-element name="selection-example">
28
+ <template>
29
+ <style>
30
+ polyfill-next-selector { content: ':host > .selected'; }
31
+ ::content > .selected {
32
+ font-weight: bold;
33
+ font-style: italic;
34
+ }
35
+ </style>
36
+ <ul on-tap="{{itemTapAction}}">
37
+ <content></content>
38
+ </ul>
39
+ <core-selection id="selection" multi
40
+ on-core-select="{{selectAction}}"></core-selection>
41
+ </template>
42
+ <script>
43
+ Polymer('selection-example', {
44
+ itemTapAction: function(e, detail, sender) {
45
+ this.$.selection.select(e.target);
46
+ },
47
+ selectAction: function(e, detail, sender) {
48
+ detail.item.classList.toggle('selected', detail.isSelected);
49
+ }
50
+ });
51
+ </script>
52
+ </polymer-element>
53
+
54
+ <selection-example>
55
+ <li>Red</li>
56
+ <li>Green</li>
57
+ <li>Blue</li>
58
+ </selection-example>
59
+
60
+ @element core-selection
61
+ -->
62
+
63
+ <!--
64
+ Fired when an item's selection state is changed. This event is fired both
65
+ when an item is selected or deselected. The `isSelected` detail property
66
+ contains the selection state.
67
+
68
+ @event core-select
69
+ @param {Object} detail
70
+ @param {boolean} detail.isSelected true for selection and false for de-selection
71
+ @param {Object} detail.item the item element
72
+ -->
73
+
74
+ <polymer-element name="core-selection" attributes="multi" hidden>
75
+ <script>
76
+ Polymer('core-selection', {
77
+ /**
78
+ * If true, multiple selections are allowed.
79
+ *
80
+ * @attribute multi
81
+ * @type boolean
82
+ * @default false
83
+ */
84
+ multi: false,
85
+ ready: function() {
86
+ this.clear();
87
+ },
88
+ clear: function() {
89
+ this.selection = [];
90
+ },
91
+ /**
92
+ * Retrieves the selected item(s).
93
+ * @method getSelection
94
+ * @returns Returns the selected item(s). If the multi property is true,
95
+ * getSelection will return an array, otherwise it will return
96
+ * the selected item or undefined if there is no selection.
97
+ */
98
+ getSelection: function() {
99
+ return this.multi ? this.selection : this.selection[0];
100
+ },
101
+ /**
102
+ * Indicates if a given item is selected.
103
+ * @method isSelected
104
+ * @param {any} item The item whose selection state should be checked.
105
+ * @returns Returns true if `item` is selected.
106
+ */
107
+ isSelected: function(item) {
108
+ return this.selection.indexOf(item) >= 0;
109
+ },
110
+ setItemSelected: function(item, isSelected) {
111
+ if (item !== undefined && item !== null) {
112
+ if (isSelected) {
113
+ this.selection.push(item);
114
+ } else {
115
+ var i = this.selection.indexOf(item);
116
+ if (i >= 0) {
117
+ this.selection.splice(i, 1);
118
+ }
119
+ }
120
+ this.fire("core-select", {isSelected: isSelected, item: item});
121
+ }
122
+ },
123
+ /**
124
+ * Set the selection state for a given `item`. If the multi property
125
+ * is true, then the selected state of `item` will be toggled; otherwise
126
+ * the `item` will be selected.
127
+ * @method select
128
+ * @param {any} item: The item to select.
129
+ */
130
+ select: function(item) {
131
+ if (this.multi) {
132
+ this.toggle(item);
133
+ } else if (this.getSelection() !== item) {
134
+ this.setItemSelected(this.getSelection(), false);
135
+ this.setItemSelected(item, true);
136
+ }
137
+ },
138
+ /**
139
+ * Toggles the selection state for `item`.
140
+ * @method toggle
141
+ * @param {any} item: The item to toggle.
142
+ */
143
+ toggle: function(item) {
144
+ this.setItemSelected(item, !this.isSelected(item));
145
+ }
146
+ });
147
+ </script>
148
+ </polymer-element>
@@ -0,0 +1,423 @@
1
+ <!--
2
+ Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3
+ This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
4
+ The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
5
+ The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
6
+ Code distributed by Google as part of the polymer project is also
7
+ subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
8
+ -->
9
+
10
+ <!--
11
+ @group Polymer Core Elements
12
+
13
+ `<core-selector>` is used to manage a list of elements that can be selected.
14
+
15
+ The attribute `selected` indicates which item element is being selected.
16
+ The attribute `multi` indicates if multiple items can be selected at once.
17
+ Tapping on the item element would fire `core-activate` event. Use
18
+ `core-select` event to listen for selection changes.
19
+
20
+ Example:
21
+
22
+ <core-selector selected="0">
23
+ <div>Item 1</div>
24
+ <div>Item 2</div>
25
+ <div>Item 3</div>
26
+ </core-selector>
27
+
28
+ `<core-selector>` is not styled. Use the `core-selected` CSS class to style the selected element.
29
+
30
+ <style>
31
+ .item.core-selected {
32
+ background: #eee;
33
+ }
34
+ </style>
35
+ ...
36
+ <core-selector>
37
+ <div class="item">Item 1</div>
38
+ <div class="item">Item 2</div>
39
+ <div class="item">Item 3</div>
40
+ </core-selector>
41
+
42
+ @element core-selector
43
+ @status stable
44
+ @homepage github.io
45
+ -->
46
+
47
+ <!--
48
+ Fired when an item's selection state is changed. This event is fired both
49
+ when an item is selected or deselected. The `isSelected` detail property
50
+ contains the selection state.
51
+
52
+ @event core-select
53
+ @param {Object} detail
54
+ @param {boolean} detail.isSelected true for selection and false for deselection
55
+ @param {Object} detail.item the item element
56
+ -->
57
+ <!--
58
+ Fired when an item element is tapped.
59
+
60
+ @event core-activate
61
+ @param {Object} detail
62
+ @param {Object} detail.item the item element
63
+ -->
64
+
65
+ <%= html_import_tag 'core/selection/core-selection'%>
66
+
67
+ <polymer-element name="core-selector"
68
+ attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap target itemsSelector activateEvent">
69
+
70
+ <template>
71
+ <core-selection id="selection" multi="{{multi}}" on-core-select="{{selectionSelect}}"></core-selection>
72
+ <content id="items" select="*"></content>
73
+ </template>
74
+
75
+ <script>
76
+
77
+ Polymer('core-selector', {
78
+
79
+ /**
80
+ * Gets or sets the selected element. Default to use the index
81
+ * of the item element.
82
+ *
83
+ * If you want a specific attribute value of the element to be
84
+ * used instead of index, set "valueattr" to that attribute name.
85
+ *
86
+ * Example:
87
+ *
88
+ * <core-selector valueattr="label" selected="foo">
89
+ * <div label="foo"></div>
90
+ * <div label="bar"></div>
91
+ * <div label="zot"></div>
92
+ * </core-selector>
93
+ *
94
+ * In multi-selection this should be an array of values.
95
+ *
96
+ * Example:
97
+ *
98
+ * <core-selector id="selector" valueattr="label" multi>
99
+ * <div label="foo"></div>
100
+ * <div label="bar"></div>
101
+ * <div label="zot"></div>
102
+ * </core-selector>
103
+ *
104
+ * this.$.selector.selected = ['foo', 'zot'];
105
+ *
106
+ * @attribute selected
107
+ * @type Object
108
+ * @default null
109
+ */
110
+ selected: null,
111
+
112
+ /**
113
+ * If true, multiple selections are allowed.
114
+ *
115
+ * @attribute multi
116
+ * @type boolean
117
+ * @default false
118
+ */
119
+ multi: false,
120
+
121
+ /**
122
+ * Specifies the attribute to be used for "selected" attribute.
123
+ *
124
+ * @attribute valueattr
125
+ * @type string
126
+ * @default 'name'
127
+ */
128
+ valueattr: 'name',
129
+
130
+ /**
131
+ * Specifies the CSS class to be used to add to the selected element.
132
+ *
133
+ * @attribute selectedClass
134
+ * @type string
135
+ * @default 'core-selected'
136
+ */
137
+ selectedClass: 'core-selected',
138
+
139
+ /**
140
+ * Specifies the property to be used to set on the selected element
141
+ * to indicate its active state.
142
+ *
143
+ * @attribute selectedProperty
144
+ * @type string
145
+ * @default ''
146
+ */
147
+ selectedProperty: '',
148
+
149
+ /**
150
+ * Specifies the attribute to set on the selected element to indicate
151
+ * its active state.
152
+ *
153
+ * @attribute selectedAttribute
154
+ * @type string
155
+ * @default 'active'
156
+ */
157
+ selectedAttribute: 'active',
158
+
159
+ /**
160
+ * Returns the currently selected element. In multi-selection this returns
161
+ * an array of selected elements.
162
+ *
163
+ * @attribute selectedItem
164
+ * @type Object
165
+ * @default null
166
+ */
167
+ selectedItem: null,
168
+
169
+ /**
170
+ * In single selection, this returns the model associated with the
171
+ * selected element.
172
+ *
173
+ * @attribute selectedModel
174
+ * @type Object
175
+ * @default null
176
+ */
177
+ selectedModel: null,
178
+
179
+ /**
180
+ * In single selection, this returns the selected index.
181
+ *
182
+ * @attribute selectedIndex
183
+ * @type number
184
+ * @default -1
185
+ */
186
+ selectedIndex: -1,
187
+
188
+ /**
189
+ * The target element that contains items. If this is not set
190
+ * core-selector is the container.
191
+ *
192
+ * @attribute target
193
+ * @type Object
194
+ * @default null
195
+ */
196
+ target: null,
197
+
198
+ /**
199
+ * This can be used to query nodes from the target node to be used for
200
+ * selection items. Note this only works if the 'target' property is set.
201
+ *
202
+ * Example:
203
+ *
204
+ * <core-selector target="{{$.myForm}}" itemsSelector="input[type=radio]"></core-selector>
205
+ * <form id="myForm">
206
+ * <label><input type="radio" name="color" value="red"> Red</label> <br>
207
+ * <label><input type="radio" name="color" value="green"> Green</label> <br>
208
+ * <label><input type="radio" name="color" value="blue"> Blue</label> <br>
209
+ * <p>color = {{color}}</p>
210
+ * </form>
211
+ *
212
+ * @attribute itemSelector
213
+ * @type string
214
+ * @default ''
215
+ */
216
+ itemsSelector: '',
217
+
218
+ /**
219
+ * The event that would be fired from the item element to indicate
220
+ * it is being selected.
221
+ *
222
+ * @attribute activateEvent
223
+ * @type string
224
+ * @default 'tap'
225
+ */
226
+ activateEvent: 'tap',
227
+
228
+ /**
229
+ * Set this to true to disallow changing the selection via the
230
+ * `activateEvent`.
231
+ *
232
+ * @attribute notap
233
+ * @type boolean
234
+ * @default false
235
+ */
236
+ notap: false,
237
+
238
+ ready: function() {
239
+ this.activateListener = this.activateHandler.bind(this);
240
+ this.observer = new MutationObserver(this.updateSelected.bind(this));
241
+ if (!this.target) {
242
+ this.target = this;
243
+ }
244
+ },
245
+
246
+ get items() {
247
+ if (!this.target) {
248
+ return [];
249
+ }
250
+ var nodes = this.target !== this ? (this.itemsSelector ?
251
+ this.target.querySelectorAll(this.itemsSelector) :
252
+ this.target.children) : this.$.items.getDistributedNodes();
253
+ return Array.prototype.filter.call(nodes || [], function(n) {
254
+ return n && n.localName !== 'template';
255
+ });
256
+ },
257
+
258
+ targetChanged: function(old) {
259
+ if (old) {
260
+ this.removeListener(old);
261
+ this.observer.disconnect();
262
+ this.clearSelection();
263
+ }
264
+ if (this.target) {
265
+ this.addListener(this.target);
266
+ this.observer.observe(this.target, {childList: true});
267
+ this.updateSelected();
268
+ }
269
+ },
270
+
271
+ addListener: function(node) {
272
+ node.addEventListener(this.activateEvent, this.activateListener);
273
+ },
274
+
275
+ removeListener: function(node) {
276
+ node.removeEventListener(this.activateEvent, this.activateListener);
277
+ },
278
+
279
+ get selection() {
280
+ return this.$.selection.getSelection();
281
+ },
282
+
283
+ selectedChanged: function() {
284
+ this.updateSelected();
285
+ },
286
+
287
+ updateSelected: function() {
288
+ this.validateSelected();
289
+ if (this.multi) {
290
+ this.clearSelection();
291
+ this.selected && this.selected.forEach(function(s) {
292
+ this.valueToSelection(s);
293
+ }, this);
294
+ } else {
295
+ this.valueToSelection(this.selected);
296
+ }
297
+ },
298
+
299
+ validateSelected: function() {
300
+ // convert to an array for multi-selection
301
+ if (this.multi && !Array.isArray(this.selected) &&
302
+ this.selected !== null && this.selected !== undefined) {
303
+ this.selected = [this.selected];
304
+ }
305
+ },
306
+
307
+ clearSelection: function() {
308
+ if (this.multi) {
309
+ this.selection.slice().forEach(function(s) {
310
+ this.$.selection.setItemSelected(s, false);
311
+ }, this);
312
+ } else {
313
+ this.$.selection.setItemSelected(this.selection, false);
314
+ }
315
+ this.selectedItem = null;
316
+ this.$.selection.clear();
317
+ },
318
+
319
+ valueToSelection: function(value) {
320
+ var item = (value === null || value === undefined) ?
321
+ null : this.items[this.valueToIndex(value)];
322
+ this.$.selection.select(item);
323
+ },
324
+
325
+ updateSelectedItem: function() {
326
+ this.selectedItem = this.selection;
327
+ },
328
+
329
+ selectedItemChanged: function() {
330
+ if (this.selectedItem) {
331
+ var t = this.selectedItem.templateInstance;
332
+ this.selectedModel = t ? t.model : undefined;
333
+ } else {
334
+ this.selectedModel = null;
335
+ }
336
+ this.selectedIndex = this.selectedItem ?
337
+ parseInt(this.valueToIndex(this.selected)) : -1;
338
+ },
339
+
340
+ valueToIndex: function(value) {
341
+ // find an item with value == value and return it's index
342
+ for (var i=0, items=this.items, c; (c=items[i]); i++) {
343
+ if (this.valueForNode(c) == value) {
344
+ return i;
345
+ }
346
+ }
347
+ // if no item found, the value itself is probably the index
348
+ return value;
349
+ },
350
+
351
+ valueForNode: function(node) {
352
+ return node[this.valueattr] || node.getAttribute(this.valueattr);
353
+ },
354
+
355
+ // events fired from <core-selection> object
356
+ selectionSelect: function(e, detail) {
357
+ this.updateSelectedItem();
358
+ if (detail.item) {
359
+ this.applySelection(detail.item, detail.isSelected);
360
+ }
361
+ },
362
+
363
+ applySelection: function(item, isSelected) {
364
+ if (this.selectedClass) {
365
+ item.classList.toggle(this.selectedClass, isSelected);
366
+ }
367
+ if (this.selectedProperty) {
368
+ item[this.selectedProperty] = isSelected;
369
+ }
370
+ if (this.selectedAttribute && item.setAttribute) {
371
+ if (isSelected) {
372
+ item.setAttribute(this.selectedAttribute, '');
373
+ } else {
374
+ item.removeAttribute(this.selectedAttribute);
375
+ }
376
+ }
377
+ },
378
+
379
+ // event fired from host
380
+ activateHandler: function(e) {
381
+ if (!this.notap) {
382
+ var i = this.findDistributedTarget(e.target, this.items);
383
+ if (i >= 0) {
384
+ var item = this.items[i];
385
+ var s = this.valueForNode(item) || i;
386
+ if (this.multi) {
387
+ if (this.selected) {
388
+ this.addRemoveSelected(s);
389
+ } else {
390
+ this.selected = [s];
391
+ }
392
+ } else {
393
+ this.selected = s;
394
+ }
395
+ this.asyncFire('core-activate', {item: item});
396
+ }
397
+ }
398
+ },
399
+
400
+ addRemoveSelected: function(value) {
401
+ var i = this.selected.indexOf(value);
402
+ if (i >= 0) {
403
+ this.selected.splice(i, 1);
404
+ } else {
405
+ this.selected.push(value);
406
+ }
407
+ this.valueToSelection(value);
408
+ },
409
+
410
+ findDistributedTarget: function(target, nodes) {
411
+ // find first ancestor of target (including itself) that
412
+ // is in nodes, if any
413
+ while (target && target != this) {
414
+ var i = Array.prototype.indexOf.call(nodes, target);
415
+ if (i >= 0) {
416
+ return i;
417
+ }
418
+ target = target.parentNode;
419
+ }
420
+ }
421
+ });
422
+ </script>
423
+ </polymer-element>