OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Polymer Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style | |
3 // license that can be found in the LICENSE file. | |
4 | |
5 library todomvc.web.lib_elements.polymer_selector; | |
6 | |
7 import 'dart:html'; | |
8 import 'package:polymer/polymer.dart'; | |
9 import 'package:template_binding/template_binding.dart' show | |
10 nodeBind, isSemanticTemplate; | |
11 import 'polymer_selection.dart'; | |
12 | |
13 // TODO(jmesserly): get this from polymer_ui_elements package. | |
14 @CustomTag('polymer-selector') | |
15 class PolymerSelector extends PolymerElement { | |
16 /** | |
17 * Gets or sets the selected element. Default is to use the index | |
18 * of the currently selected element. | |
19 * | |
20 * If you want a specific attribute value of the selected element to be | |
21 * used instead of index, set "valueattr" to that attribute name. | |
22 * | |
23 * Example: | |
24 * | |
25 * <polymer-selector valueattr="label" selected="foo"> | |
26 * <div label="foo"></div> | |
27 * <div label="bar"></div> | |
28 * <div label="zot"></div> | |
29 * </polymer-selector> | |
30 */ | |
31 @published String selected; | |
32 | |
33 /** If true, multiple selections are allowed. */ | |
34 @published bool multi = false; | |
35 | |
36 /** Specifies the attribute to be used for "selected" attribute. */ | |
37 @published String valueattr = 'name'; | |
38 | |
39 /** Specifies the CSS class to be used to add to the selected element. */ | |
40 @published String selectedClass = 'polymer-selected'; | |
41 | |
42 /** | |
43 * Specifies the property to be used to set on the selected element | |
44 * to indicate its active state. | |
45 */ | |
46 @published String selectedProperty = 'active'; | |
47 | |
48 /** Returns the model associated with the selected element. */ | |
49 @published var selectedModel; | |
50 | |
51 @published bool notap = false; | |
52 | |
53 @observable var selectedItem; | |
54 | |
55 factory PolymerSelector() => new Element.tag('polymer-selector'); | |
56 PolymerSelector.created() : super.created(); | |
57 | |
58 List<Node> get items => ($['items'] as ContentElement).getDistributedNodes() | |
59 .where((n) => !isSemanticTemplate(n)).toList(); | |
60 | |
61 get selection => ($['selection'] as PolymerSelection).getSelection(); | |
62 | |
63 void selectedChanged() { | |
64 valueToSelection(selected); | |
65 } | |
66 | |
67 void valueToSelection(value) { | |
68 var item = items.firstWhere((i) => valueForNode(i) == value, | |
69 orElse: () => null); | |
70 | |
71 selectedItem = item; | |
72 ($['selection'] as PolymerSelection).select(item); | |
73 updateSelectedModel(); | |
74 } | |
75 | |
76 void updateSelectedModel() { | |
77 if (selectedItem != null) { | |
78 var t = nodeBind(selectedItem).templateInstance; | |
79 selectedModel = t != null ? t.model : null; | |
80 } else { | |
81 selectedModel = null; | |
82 } | |
83 } | |
84 | |
85 String valueForNode(node) { | |
86 // TODO(jmesserly): faster way to do this | |
87 var value = new PathObserver(node, valueattr).value; | |
88 return value != null ? value : node.attributes[valueattr]; | |
89 } | |
90 | |
91 // events fired from <polymer-selection> object | |
92 void selectionSelect(e, PolymerSelectEventDetail detail) { | |
93 if (detail.item != null) { | |
94 if (selectedClass != null) { | |
95 detail.item.classes.toggle(selectedClass, detail.isSelected); | |
96 } | |
97 if (selectedProperty != null) { | |
98 new PathObserver(detail.item, selectedProperty).value = | |
99 detail.isSelected; | |
100 } | |
101 } | |
102 } | |
103 | |
104 // event fired from host | |
105 void activateHandler(e) { | |
106 if (!notap) { | |
107 var i = findDistributedTarget(e.target, items); | |
108 if (i >= 0) { | |
109 var selected = valueForNode(items[i]); | |
110 if (selected == null) selected = i; | |
111 if (multi) { | |
112 valueToSelection(selected); | |
113 } else { | |
114 this.selected = selected; | |
115 } | |
116 asyncFire('polymer-activate', detail: | |
117 new PolymerActivateEventDetail(items[i])); | |
118 } | |
119 } | |
120 } | |
121 | |
122 int findDistributedTarget(Node target, List<Node> nodes) { | |
123 // find first ancestor of target (including itself) that | |
124 // is in inNodes, if any | |
125 while (target != null && target != this) { | |
126 var i = nodes.indexOf(target); | |
127 if (i >= 0) return i; | |
128 target = target.parentNode; | |
129 } | |
130 return -1; | |
131 } | |
132 } | |
133 | |
134 class PolymerActivateEventDetail { | |
135 final item; | |
136 | |
137 PolymerActivateEventDetail(this.item); | |
138 } | |
OLD | NEW |