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

Side by Side Diff: pkg/mdv/lib/src/bindings.dart

Issue 18117012: [package:mdv] Support binding to HTMLSelectElement.selectedIndex (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix merge issue Created 7 years, 5 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
« no previous file with comments | « pkg/mdv/lib/mdv.dart ('k') | pkg/mdv/lib/src/input_element.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of mdv; 5 part of mdv;
6 6
7 // This code is a port of Model-Driven-Views: 7 // This code is a port of Model-Driven-Views:
8 // https://github.com/polymer-project/mdv 8 // https://github.com/polymer-project/mdv
9 // The code mostly comes from src/template_element.js 9 // The code mostly comes from src/template_element.js
10 10
11 typedef void _ChangeHandler(value); 11 typedef void _ChangeHandler(value);
12 12
13 abstract class _InputBinding { 13 abstract class _InputBinding {
14 final InputElement element; 14 // InputElement or SelectElement
15 final element;
15 PathObserver binding; 16 PathObserver binding;
16 StreamSubscription _pathSub; 17 StreamSubscription _pathSub;
17 StreamSubscription _eventSub; 18 StreamSubscription _eventSub;
18 19
19 _InputBinding(this.element, model, String path) { 20 _InputBinding(this.element, model, String path) {
20 binding = new PathObserver(model, path); 21 binding = new PathObserver(model, path);
21 _pathSub = binding.bindSync(valueChanged); 22 _pathSub = binding.bindSync(valueChanged);
22 _eventSub = _getStreamForInputType(element).listen(updateBinding); 23 _eventSub = _getStreamForInputType(element).listen(updateBinding);
23 } 24 }
24 25
(...skipping 19 matching lines...) Expand all
44 }); 45 });
45 checkbox.onChange.listen((e) { 46 checkbox.onChange.listen((e) {
46 fired.add(Element.changeEvent); 47 fired.add(Element.changeEvent);
47 }); 48 });
48 checkbox.dispatchEvent(new MouseEvent('click', view: window)); 49 checkbox.dispatchEvent(new MouseEvent('click', view: window));
49 // WebKit/Blink don't fire the change event if the element is outside the 50 // WebKit/Blink don't fire the change event if the element is outside the
50 // document, so assume 'change' for that case. 51 // document, so assume 'change' for that case.
51 return fired.length == 1 ? Element.changeEvent : fired.first; 52 return fired.length == 1 ? Element.changeEvent : fired.first;
52 }(); 53 }();
53 54
54 static Stream<Event> _getStreamForInputType(InputElement element) { 55 static Stream<Event> _getStreamForInputType(element) {
55 switch (element.type) { 56 switch (element.type) {
56 case 'checkbox': 57 case 'checkbox':
57 return _checkboxEventType.forTarget(element); 58 return _checkboxEventType.forTarget(element);
58 case 'radio': 59 case 'radio':
59 case 'select-multiple': 60 case 'select-multiple':
60 case 'select-one': 61 case 'select-one':
61 return element.onChange; 62 return element.onChange;
62 default: 63 default:
63 return element.onInput; 64 return element.onInput;
64 } 65 }
65 } 66 }
66 } 67 }
67 68
68 class _ValueBinding extends _InputBinding {
69 _ValueBinding(element, model, path) : super(element, model, path);
70
71 void valueChanged(value) {
72 element.value = value == null ? '' : '$value';
73 }
74
75 void updateBinding(e) {
76 binding.value = element.value;
77 }
78 }
79
80 class _CheckedBinding extends _InputBinding {
81 _CheckedBinding(element, model, path) : super(element, model, path);
82
83 void valueChanged(value) {
84 element.checked = _toBoolean(value);
85 }
86
87 void updateBinding(e) {
88 binding.value = element.checked;
89
90 // Only the radio button that is getting checked gets an event. We
91 // therefore find all the associated radio buttons and update their
92 // CheckedBinding manually.
93 if (element is InputElement && element.type == 'radio') {
94 for (var r in _getAssociatedRadioButtons(element)) {
95 var checkedBinding = _mdv(r)._checkedBinding;
96 if (checkedBinding != null) {
97 // Set the value directly to avoid an infinite call stack.
98 checkedBinding.binding.value = false;
99 }
100 }
101 }
102 }
103
104 // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
105 // Returns an array containing all radio buttons other than |element| that
106 // have the same |name|, either in the form that |element| belongs to or,
107 // if no form, in the document tree to which |element| belongs.
108 //
109 // This implementation is based upon the HTML spec definition of a
110 // "radio button group":
111 // http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state. html#radio-button-group
112 //
113 static Iterable _getAssociatedRadioButtons(element) {
114 if (!_isNodeInDocument(element)) return [];
115 if (element.form != null) {
116 return element.form.nodes.where((el) {
117 return el != element &&
118 el is InputElement &&
119 el.type == 'radio' &&
120 el.name == element.name;
121 });
122 } else {
123 var radios = element.document.queryAll(
124 'input[type="radio"][name="${element.name}"]');
125 return radios.where((el) => el != element && el.form == null);
126 }
127 }
128
129 // TODO(jmesserly): polyfill document.contains API instead of doing it here
130 static bool _isNodeInDocument(Node node) {
131 // On non-IE this works:
132 // return node.document.contains(node);
133 var document = node.document;
134 if (node == document || node.parentNode == document) return true;
135 return document.documentElement.contains(node);
136 }
137 }
138 69
139 // TODO(jmesserly): not sure what kind of boolean conversion rules to 70 // TODO(jmesserly): not sure what kind of boolean conversion rules to
140 // apply for template data-binding. HTML attributes are true if they're 71 // apply for template data-binding. HTML attributes are true if they're
141 // present. However Dart only treats "true" as true. Since this is HTML we'll 72 // present. However Dart only treats "true" as true. Since this is HTML we'll
142 // use something closer to the HTML rules: null (missing) and false are false, 73 // use something closer to the HTML rules: null (missing) and false are false,
143 // everything else is true. See: https://github.com/polymer-project/mdv/issues/5 9 74 // everything else is true. See: https://github.com/polymer-project/mdv/issues/5 9
144 bool _toBoolean(value) => null != value && false != value; 75 bool _toBoolean(value) => null != value && false != value;
145 76
146 Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) { 77 Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
147 var clone = node.clone(false); // Shallow clone. 78 var clone = node.clone(false); // Shallow clone.
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 nodeExt._templateIterator = null; 421 nodeExt._templateIterator = null;
491 } 422 }
492 } 423 }
493 424
494 _nodeOrCustom(node).unbindAll(); 425 _nodeOrCustom(node).unbindAll();
495 for (var c = node.firstChild; c != null; c = c.nextNode) { 426 for (var c = node.firstChild; c != null; c = c.nextNode) {
496 _unbindAllRecursively(c); 427 _unbindAllRecursively(c);
497 } 428 }
498 } 429 }
499 } 430 }
OLDNEW
« no previous file with comments | « pkg/mdv/lib/mdv.dart ('k') | pkg/mdv/lib/src/input_element.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698