polymer-core-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +82 -0
  3. data/Rakefile +2 -0
  4. data/app/assets/components/core-ajax/core-ajax.html.erb +320 -0
  5. data/app/assets/components/core-ajax/core-xhr.html.erb +112 -0
  6. data/app/assets/components/core-animated-pages/core-animated-pages.css +18 -0
  7. data/app/assets/components/core-animated-pages/core-animated-pages.html.erb +413 -0
  8. data/app/assets/components/core-animated-pages/transitions/cascade-transition.html +138 -0
  9. data/app/assets/components/core-animated-pages/transitions/core-transition-pages.html.erb +173 -0
  10. data/app/assets/components/core-animated-pages/transitions/cross-fade.html.erb +173 -0
  11. data/app/assets/components/core-animated-pages/transitions/hero-transition.css +12 -0
  12. data/app/assets/components/core-animated-pages/transitions/hero-transition.html.erb +267 -0
  13. data/app/assets/components/core-animated-pages/transitions/list-cascade.html +58 -0
  14. data/app/assets/components/core-animated-pages/transitions/scale-up.html +37 -0
  15. data/app/assets/components/core-animated-pages/transitions/slide-down.html +55 -0
  16. data/app/assets/components/core-animated-pages/transitions/slide-from-bottom.html +31 -0
  17. data/app/assets/components/core-animated-pages/transitions/slide-from-right.html +35 -0
  18. data/app/assets/components/core-animated-pages/transitions/slide-up.html +82 -0
  19. data/app/assets/components/core-animated-pages/transitions/tile-cascade.html +101 -0
  20. data/app/assets/components/core-animation/core-animation-group.html.erb +168 -0
  21. data/app/assets/components/core-animation/core-animation.html.erb +523 -0
  22. data/app/assets/components/core-animation/web-animations.html.erb +1 -0
  23. data/app/assets/components/core-collapse/core-collapse.css +16 -0
  24. data/app/assets/components/core-collapse/core-collapse.html.erb +247 -0
  25. data/app/assets/components/core-drag-drop/core-drag-drop.html +109 -0
  26. data/app/assets/components/core-drawer-panel/core-drawer-panel.css +162 -0
  27. data/app/assets/components/core-drawer-panel/core-drawer-panel.html.erb +150 -0
  28. data/app/assets/components/core-field/core-field.css +38 -0
  29. data/app/assets/components/core-field/core-field.html.erb +32 -0
  30. data/app/assets/components/core-header-panel/core-header-panel.css +75 -0
  31. data/app/assets/components/core-header-panel/core-header-panel.html.erb +196 -0
  32. data/app/assets/components/core-icon/core-icon.css +25 -0
  33. data/app/assets/components/core-icon/core-icon.html.erb +126 -0
  34. data/app/assets/components/core-icon-button/core-icon-button.css +70 -0
  35. data/app/assets/components/core-icon-button/core-icon-button.html.erb +83 -0
  36. data/app/assets/components/core-icons/core-icons.html +14 -0
  37. data/app/assets/components/core-iconset/core-iconset.html.erb +236 -0
  38. data/app/assets/components/core-iconset-svg/core-iconset-svg.html +170 -0
  39. data/app/assets/components/core-input/core-input.css +35 -0
  40. data/app/assets/components/core-input/core-input.html.erb +311 -0
  41. data/app/assets/components/core-item/core-item.css +31 -0
  42. data/app/assets/components/core-item/core-item.html.erb +80 -0
  43. data/app/assets/components/core-list/core-list.css +20 -0
  44. data/app/assets/components/core-list/core-list.html.erb +403 -0
  45. data/app/assets/components/core-localstorage/core-localstorage.html +126 -0
  46. data/app/assets/components/core-media-query/core-media-query.html +86 -0
  47. data/app/assets/components/core-menu/core-menu.css +18 -0
  48. data/app/assets/components/core-menu/core-menu.html.erb +62 -0
  49. data/app/assets/components/core-menu/core-submenu.css +29 -0
  50. data/app/assets/components/core-menu/core-submenu.html.erb +106 -0
  51. data/app/assets/components/core-menu-button/core-menu-button.css +10 -0
  52. data/app/assets/components/core-menu-button/core-menu-button.html.erb +139 -0
  53. data/app/assets/components/core-meta/core-meta.html +143 -0
  54. data/app/assets/components/core-overlay/core-key-helper.html +17 -0
  55. data/app/assets/components/core-overlay/core-overlay-layer.html +112 -0
  56. data/app/assets/components/core-overlay/core-overlay.html.erb +661 -0
  57. data/app/assets/components/core-pages/core-pages.css +30 -0
  58. data/app/assets/components/core-pages/core-pages.html.erb +43 -0
  59. data/app/assets/components/core-range/core-range.html +107 -0
  60. data/app/assets/components/core-scaffold/core-scaffold.html.erb +147 -0
  61. data/app/assets/components/core-scroll-header-panel/core-scroll-header-panel.css +57 -0
  62. data/app/assets/components/core-scroll-header-panel/core-scroll-header-panel.html.erb +257 -0
  63. data/app/assets/components/core-selection/core-selection.html +148 -0
  64. data/app/assets/components/core-selector/core-selector.html.erb +423 -0
  65. data/app/assets/components/core-shared-lib/core-shared-lib.html +150 -0
  66. data/app/assets/components/core-signals/core-signals.html +83 -0
  67. data/app/assets/components/core-splitter/core-splitter.css.erb +27 -0
  68. data/app/assets/components/core-splitter/core-splitter.html.erb +159 -0
  69. data/app/assets/components/core-splitter/handle-h.svg +4 -0
  70. data/app/assets/components/core-splitter/handle.svg +4 -0
  71. data/app/assets/components/core-style/core-style.html +385 -0
  72. data/app/assets/components/core-toolbar/core-toolbar.css +126 -0
  73. data/app/assets/components/core-toolbar/core-toolbar.html.erb +73 -0
  74. data/app/assets/components/core-tooltip/core-tooltip.css +103 -0
  75. data/app/assets/components/core-tooltip/core-tooltip.html.erb +144 -0
  76. data/app/assets/components/core-transition/core-transition-css.html.erb +76 -0
  77. data/app/assets/components/core-transition/core-transition-overlay.css +46 -0
  78. data/app/assets/components/core-transition/core-transition.html.erb +44 -0
  79. data/app/assets/components/web-animations-js/web-animations.js +5666 -0
  80. data/lib/polymer-core-rails/engine.rb +4 -0
  81. data/lib/polymer-core-rails/version.rb +3 -0
  82. data/lib/polymer-core-rails.rb +2 -0
  83. metadata +167 -0
@@ -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>