Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(876)

Side by Side Diff: third_party/pkg/angular/lib/directive/input_select.dart

Issue 124053002: Adding Angular and dependent packages for testing (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 part of angular.directive;
2
3 typedef dynamic ItemEval(dynamic item, num index);
4
5 /**
6 * HTML [SELECT] element with angular data-binding if used with [NgModelDirectiv e].
7 *
8 * The [NgModelDirective] will receive the currently selected item. The binding is
9 * performed on the [OPTION].[value] property.
10 * An empty [OPTION].[value] is treated as null.
11 *
12 * If you the model contains value which does not map to any [OPTION] then a new
13 * unknown [OPTION] is inserted into the list. Once the model points to an exist ing
14 * [OPTION] the unknown [OPTION] is removed.
15 *
16 * Becouse [OPTION].[value] attribute is a string, the model is bound to a strin g.
17 * If there is need to bind to an object then [OptionValueDirective] should be u sed.
18 *
19 */
20 @NgDirective(
21 selector: 'select[ng-model]',
22 visibility: NgDirective.CHILDREN_VISIBILITY
23 )
24 class InputSelectDirective implements NgAttachAware {
25 final Expando<OptionValueDirective> expando = new Expando<OptionValueDirective >();
26 final dom.SelectElement _selectElement;
27 final NodeAttrs _attrs;
28 final NgModel _model;
29 final Scope _scope;
30
31 final dom.OptionElement _unknownOption = new dom.OptionElement();
32 dom.OptionElement _nullOption;
33
34 _SelectMode _mode = new _SelectMode(null, null, null);
35 bool _dirty = false;
36
37 InputSelectDirective(dom.Element this._selectElement, this._attrs, this._model , this._scope) {
38 _unknownOption.value = '?';
39 _unknownOption.text = ''; // Explicit due to dartbug.com/14407
40 _selectElement.querySelectorAll('option').forEach((o) {
41 if (_nullOption == null && o.value == '') {
42 _nullOption = o;
43 }
44 });
45 }
46
47 attach() {
48 _attrs.observe('multiple', (value) {
49 _mode.destroy();
50 if (value == null) {
51 _model.watchCollection = false;
52 _mode = new _SingleSelectMode(expando, _selectElement, _model, _nullOpti on, _unknownOption);
53 } else {
54 _model.watchCollection = true;
55 _mode = new _MultipleSelectionMode(expando, _selectElement, _model);
56 }
57 _mode.onModelChange(_model.viewValue);
58 });
59
60 _selectElement.onChange.listen((event) => _mode.onViewChange(event));
61 _model.render = (value) => _mode.onModelChange(value);
62 }
63
64 /**
65 * This method invalidates the current state of the selector and forces a rere ndering of the
66 * options using the [Scope.$evalAsync].
67 */
68 dirty() {
69 if (!_dirty) {
70 _dirty = true;
71 _scope.$evalAsync(() {
72 _dirty = false;
73 _mode.onModelChange(_model.viewValue);
74 });
75 }
76 }
77 }
78
79 /**
80 * Since the [value] attirbute of the [OPTION] can only be a string, Angular pro vides
81 * [ng-value] which allows binding to any expression.
82 *
83 */
84 @NgDirective(
85 selector: 'option',
86 publishTypes: const [TextChangeListener],
87 map: const {'ng-value': '&ngValue'}
88 )
89 class OptionValueDirective implements TextChangeListener, NgAttachAware, NgDetac hAware {
90 final InputSelectDirective _inputSelectDirective;
91 final NodeAttrs _attrs;
92
93 Getter _ngValue;
94
95 OptionValueDirective(this._attrs, this._inputSelectDirective) {
96 if (_inputSelectDirective != null) {
97 _inputSelectDirective.expando[_attrs.element] = this;
98 }
99 }
100
101 attach() {
102 if (_inputSelectDirective != null) {
103 this._attrs.observe('value', (_) => _inputSelectDirective.dirty());
104 }
105 }
106
107 call(String text) {
108 if (_inputSelectDirective != null) {
109 _inputSelectDirective.dirty();
110 }
111 }
112
113 detach() {
114 if (_inputSelectDirective != null) {
115 _inputSelectDirective.dirty();
116 _inputSelectDirective.expando[_attrs.element] = null;
117 }
118 }
119
120 set ngValue(Getter value) => _ngValue = value;
121 get ngValue =>
122 _attrs['ng-value'] is String ? _ngValue() : (_attrs.element as dom.OptionEle ment).value;
123 }
124
125 class _SelectMode {
126 final Expando<OptionValueDirective> expando;
127 final dom.SelectElement select;
128 final NgModel model;
129
130 _SelectMode(this.expando, this.select, this.model);
131
132 onViewChange(event) {}
133 onModelChange(value) {}
134 destroy() {}
135
136 get _options => select.querySelectorAll('option');
137 _forEachOption(fn, [quiteOnReturn = false]) {
138 for(var os = _options, i = 0, ii = os.length; i < ii; i++) {
139 var retValue = fn(os[i], i);
140 if (quiteOnReturn && retValue != null) {
141 return retValue;
142 }
143 }
144 return null;
145 }
146 }
147
148 class _SingleSelectMode extends _SelectMode {
149 final dom.OptionElement _unknownOption;
150 final dom.OptionElement _nullOption;
151
152 bool _unknownOptionActive = false;
153
154 _SingleSelectMode(Expando<OptionValueDirective> expando,
155 dom.SelectElement select,
156 NgModel model,
157 this._nullOption,
158 this._unknownOption
159 ): super(expando, select, model) {
160 }
161
162 onViewChange(event) {
163 var i = 0;
164 model.viewValue = _forEachOption((option, _) {
165 if (option.selected) {
166 return option == _nullOption ? null : expando[option].ngValue;
167 }
168 if (option != _unknownOption && option != _nullOption) {
169 i++;
170 }
171 }, true);
172 }
173
174 onModelChange(value) {
175 var found = false;
176 _forEachOption((option, i) {
177 if (option == _unknownOption) return;
178 var selected = value == null ? option == _nullOption : expando[option].ngV alue == value;
179 found = found || selected;
180 option.selected = selected;
181 });
182
183 if (!found) {
184 if (!_unknownOptionActive) {
185 select.insertBefore(_unknownOption, select.firstChild);
186 _unknownOption.selected = true;
187 _unknownOptionActive = true;
188 }
189 } else {
190 if (_unknownOptionActive) {
191 _unknownOption.remove();
192 _unknownOptionActive = false;
193 }
194 }
195 }
196 }
197
198 class _MultipleSelectionMode extends _SelectMode {
199 _MultipleSelectionMode(Expando<OptionValueDirective> expando,
200 dom.SelectElement select,
201 NgModel model
202 ): super(expando, select, model);
203
204 onViewChange(event) {
205 var selected = [];
206 var fn = (o, i) => o.value;
207
208 _forEachOption((o, i) {
209 if (o.selected) {
210 selected.add(expando[o].ngValue);
211 }
212 });
213 model.viewValue = selected;
214 }
215
216 onModelChange(List selectedValues) {
217 num index = 0;
218 Function fn = (o, i) => o.selected = null;
219
220 if (selectedValues is List) {
221 fn = (o, i) => o.selected = selectedValues.contains(expando[o].ngValue);
222 }
223
224 _forEachOption(fn);
225 }
226 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698