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

Side by Side Diff: sdk/lib/html/dartium/html_dartium.dart

Issue 14651030: Version 0.5.7.1 . (Closed) Base URL: http://dart.googlecode.com/svn/trunk/dart/
Patch Set: Created 7 years, 7 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 | « sdk/lib/html/dart2js/html_dart2js.dart ('k') | tests/html/binding_syntax_test.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 /// The Dart HTML library. 1 /// The Dart HTML library.
2 library dart.dom.html; 2 library dart.dom.html;
3 3
4 import 'dart:async'; 4 import 'dart:async';
5 import 'dart:collection'; 5 import 'dart:collection';
6 import 'dart:_collection-dev' hide Symbol; 6 import 'dart:_collection-dev' hide Symbol;
7 import 'dart:html_common'; 7 import 'dart:html_common';
8 import 'dart:indexed_db'; 8 import 'dart:indexed_db';
9 import 'dart:isolate'; 9 import 'dart:isolate';
10 import 'dart:json' as json; 10 import 'dart:json' as json;
(...skipping 7981 matching lines...) Expand 10 before | Expand all | Expand 10 after
7992 * 7992 *
7993 * Currently this does not support propagation through Shadow DOMs. 7993 * Currently this does not support propagation through Shadow DOMs.
7994 */ 7994 */
7995 @Experimental 7995 @Experimental
7996 get model => _model; 7996 get model => _model;
7997 7997
7998 @Experimental 7998 @Experimental
7999 void set model(value) { 7999 void set model(value) {
8000 _ensureTemplate(); 8000 _ensureTemplate();
8001 8001
8002 var syntax = TemplateElement.syntax[attributes['syntax']];
8002 _model = value; 8003 _model = value;
8003 _addBindings(this, model); 8004 _addBindings(this, model, syntax);
8004 } 8005 }
8005 8006
8006 // TODO(jmesserly): const set would be better 8007 // TODO(jmesserly): const set would be better
8007 static const _TABLE_TAGS = const { 8008 static const _TABLE_TAGS = const {
8008 'caption': null, 8009 'caption': null,
8009 'col': null, 8010 'col': null,
8010 'colgroup': null, 8011 'colgroup': null,
8011 'tbody': null, 8012 'tbody': null,
8012 'td': null, 8013 'td': null,
8013 'tfoot': null, 8014 'tfoot': null,
(...skipping 7702 matching lines...) Expand 10 before | Expand all | Expand 10 after
15716 /** Unbinds the attribute [name]. */ 15717 /** Unbinds the attribute [name]. */
15717 @Experimental 15718 @Experimental
15718 void unbind(String name) {} 15719 void unbind(String name) {}
15719 15720
15720 /** Unbinds all bound attributes. */ 15721 /** Unbinds all bound attributes. */
15721 @Experimental 15722 @Experimental
15722 void unbindAll() {} 15723 void unbindAll() {}
15723 15724
15724 TemplateInstance _templateInstance; 15725 TemplateInstance _templateInstance;
15725 15726
15726 // TODO(arv): Consider storing all "NodeRareData" on a single object?
15727 int __instanceTerminatorCount;
15728 int get _instanceTerminatorCount {
15729 if (__instanceTerminatorCount == null) return 0;
15730 return __instanceTerminatorCount;
15731 }
15732 set _instanceTerminatorCount(int value) {
15733 if (value == 0) value = null;
15734 __instanceTerminatorCount = value;
15735 }
15736
15737 /** Gets the template instance that instantiated this node, if any. */ 15727 /** Gets the template instance that instantiated this node, if any. */
15738 @Experimental 15728 @Experimental
15739 TemplateInstance get templateInstance => 15729 TemplateInstance get templateInstance =>
15740 _templateInstance != null ? _templateInstance : 15730 _templateInstance != null ? _templateInstance :
15741 (parent != null ? parent.templateInstance : null); 15731 (parent != null ? parent.templateInstance : null);
15742 15732
15743 Node.internal() : super.internal(); 15733 Node.internal() : super.internal();
15744 15734
15745 static const int ATTRIBUTE_NODE = 2; 15735 static const int ATTRIBUTE_NODE = 2;
15746 15736
(...skipping 10923 matching lines...) Expand 10 before | Expand all | Expand 10 after
26670 * 26660 *
26671 * TemplateElement.syntax['MySyntax'] = new MySyntax(); 26661 * TemplateElement.syntax['MySyntax'] = new MySyntax();
26672 * 26662 *
26673 * See <https://github.com/toolkitchen/mdv/blob/master/docs/syntax.md> for more 26663 * See <https://github.com/toolkitchen/mdv/blob/master/docs/syntax.md> for more
26674 * information about Custom Syntax. 26664 * information about Custom Syntax.
26675 */ 26665 */
26676 // TODO(jmesserly): if this is just one method, a function type would make it 26666 // TODO(jmesserly): if this is just one method, a function type would make it
26677 // more Dart-friendly. 26667 // more Dart-friendly.
26678 @Experimental 26668 @Experimental
26679 abstract class CustomBindingSyntax { 26669 abstract class CustomBindingSyntax {
26670 /**
26671 * This syntax method allows for a custom interpretation of the contents of
26672 * mustaches (`{{` ... `}}`).
26673 *
26674 * When a template is inserting an instance, it will invoke this method for
26675 * each mustache which is encountered. The function is invoked with four
26676 * arguments:
26677 *
26678 * - [model]: The data context for which this instance is being created.
26679 * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
26680 * - [name]: The context in which the mustache occurs. Within element
26681 * attributes, this will be the name of the attribute. Within text,
26682 * this will be 'text'.
26683 * - [node]: A reference to the node to which this binding will be created.
26684 *
26685 * If the method wishes to handle binding, it is required to return an object
26686 * which has at least a `value` property that can be observed. If it does,
26687 * then MDV will call [Node.bind on the node:
26688 *
26689 * node.bind(name, retval, 'value');
26690 *
26691 * If the 'getBinding' does not wish to override the binding, it should return
26692 * null.
26693 */
26680 // TODO(jmesserly): I had to remove type annotations from "name" and "node" 26694 // TODO(jmesserly): I had to remove type annotations from "name" and "node"
26681 // Normally they are String and Node respectively. But sometimes it will pass 26695 // Normally they are String and Node respectively. But sometimes it will pass
26682 // (int name, CompoundBinding node). That seems very confusing; we may want 26696 // (int name, CompoundBinding node). That seems very confusing; we may want
26683 // to change this API. 26697 // to change this API.
26684 getBinding(model, String path, name, node); 26698 getBinding(model, String path, name, node) => null;
26699
26700 /**
26701 * This syntax method allows a syntax to provide an alterate model than the
26702 * one the template would otherwise use when producing an instance.
26703 *
26704 * When a template is about to create an instance, it will invoke this method
26705 * The function is invoked with two arguments:
26706 *
26707 * - [template]: The template element which is about to create and insert an
26708 * instance.
26709 * - [model]: The data context for which this instance is being created.
26710 *
26711 * The template element will always use the return value of `getInstanceModel`
26712 * as the model for the new instance. If the syntax does not wish to override
26713 * the value, it should simply return the `model` value it was passed.
26714 */
26715 getInstanceModel(Element template, model) => model;
26716
26717 /**
26718 * This syntax method allows a syntax to provide an alterate expansion of
26719 * the [template] contents. When the template wants to create an instance,
26720 * it will call this method with the template element.
26721 *
26722 * By default this will call `template.createInstance()`.
26723 */
26724 getInstanceFragment(Element template) => template.createInstance();
26685 } 26725 }
26686 26726
26687 /** The callback used in the [CompoundBinding.combinator] field. */ 26727 /** The callback used in the [CompoundBinding.combinator] field. */
26688 @Experimental 26728 @Experimental
26689 typedef Object CompoundBindingCombinator(Map objects); 26729 typedef Object CompoundBindingCombinator(Map objects);
26690 26730
26691 /** Information about the instantiated template. */ 26731 /** Information about the instantiated template. */
26692 @Experimental 26732 @Experimental
26693 class TemplateInstance { 26733 class TemplateInstance {
26694 // TODO(rafaelw): firstNode & lastNode should be read-synchronous 26734 // TODO(rafaelw): firstNode & lastNode should be read-synchronous
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
27042 templateDescendents.forEach(bootstrap); 27082 templateDescendents.forEach(bootstrap);
27043 } 27083 }
27044 27084
27045 final String _allTemplatesSelectors = 'template, option[template], ' + 27085 final String _allTemplatesSelectors = 'template, option[template], ' +
27046 Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", "); 27086 Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
27047 27087
27048 void _addBindings(Node node, model, [CustomBindingSyntax syntax]) { 27088 void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
27049 if (node is Element) { 27089 if (node is Element) {
27050 _addAttributeBindings(node, model, syntax); 27090 _addAttributeBindings(node, model, syntax);
27051 } else if (node is Text) { 27091 } else if (node is Text) {
27052 _parseAndBind(node, node.text, 'text', model, syntax); 27092 _parseAndBind(node, 'text', node.text, model, syntax);
27053 } 27093 }
27054 27094
27055 for (var c = node.$dom_firstChild; c != null; c = c.nextNode) { 27095 for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
27056 _addBindings(c, model, syntax); 27096 _addBindings(c, model, syntax);
27057 } 27097 }
27058 } 27098 }
27059 27099
27060 27100
27061 void _addAttributeBindings(Element element, model, syntax) { 27101 void _addAttributeBindings(Element element, model, syntax) {
27062 element.attributes.forEach((name, value) { 27102 element.attributes.forEach((name, value) {
27063 if (value == '' && (name == 'bind' || name == 'repeat')) { 27103 if (value == '' && (name == 'bind' || name == 'repeat')) {
27064 value = '{{}}'; 27104 value = '{{}}';
27065 } 27105 }
27066 _parseAndBind(element, value, name, model, syntax); 27106 _parseAndBind(element, name, value, model, syntax);
27067 }); 27107 });
27068 } 27108 }
27069 27109
27070 void _parseAndBind(Node node, String text, String name, model, 27110 void _parseAndBind(Node node, String name, String text, model,
27071 CustomBindingSyntax syntax) { 27111 CustomBindingSyntax syntax) {
27072 27112
27073 var tokens = _parseMustacheTokens(text); 27113 var tokens = _parseMustacheTokens(text);
27074 if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) { 27114 if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
27075 return; 27115 return;
27076 } 27116 }
27077 27117
27078 if (tokens.length == 1 && tokens[0].isBinding) { 27118 if (tokens.length == 1 && tokens[0].isBinding) {
27079 _bindOrDelegate(node, name, model, tokens[0].value, syntax); 27119 _bindOrDelegate(node, name, model, tokens[0].value, syntax);
27080 return; 27120 return;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
27195 var templateIterator = child._templateIterator; 27235 var templateIterator = child._templateIterator;
27196 if (templateIterator != null) { 27236 if (templateIterator != null) {
27197 templateIterator.abandon(); 27237 templateIterator.abandon();
27198 child._templateIterator = null; 27238 child._templateIterator = null;
27199 } 27239 }
27200 } 27240 }
27201 child.remove(); 27241 child.remove();
27202 _removeAllBindingsRecursively(child); 27242 _removeAllBindingsRecursively(child);
27203 } 27243 }
27204 27244
27205 class _InstanceCursor {
27206 final Element _template;
27207 Node _terminator;
27208 Node _previousTerminator;
27209 int _previousIndex = -1;
27210 int _index = 0;
27211
27212 _InstanceCursor(this._template, [index]) {
27213 _terminator = _template;
27214 if (index != null) {
27215 while (index-- > 0) {
27216 next();
27217 }
27218 }
27219 }
27220
27221 void next() {
27222 _previousTerminator = _terminator;
27223 _previousIndex = _index;
27224 _index++;
27225
27226 while (_index > _terminator._instanceTerminatorCount) {
27227 _index -= _terminator._instanceTerminatorCount;
27228 _terminator = _terminator.nextNode;
27229 if (_terminator is Element && _terminator.tagName == 'TEMPLATE') {
27230 _index += _instanceCount(_terminator);
27231 }
27232 }
27233 }
27234
27235 void abandon() {
27236 assert(_instanceCount(_template) > 0);
27237 assert(_terminator._instanceTerminatorCount > 0);
27238 assert(_index > 0);
27239
27240 _terminator._instanceTerminatorCount--;
27241 _index--;
27242 }
27243
27244 void insert(fragment) {
27245 assert(_template.parentNode != null);
27246
27247 _previousTerminator = _terminator;
27248 _previousIndex = _index;
27249 _index++;
27250
27251 _terminator = fragment.$dom_lastChild;
27252 if (_terminator == null) _terminator = _previousTerminator;
27253 _template.parentNode.insertBefore(fragment, _previousTerminator.nextNode);
27254
27255 _terminator._instanceTerminatorCount++;
27256 if (_terminator != _previousTerminator) {
27257 while (_previousTerminator._instanceTerminatorCount >
27258 _previousIndex) {
27259 _previousTerminator._instanceTerminatorCount--;
27260 _terminator._instanceTerminatorCount++;
27261 }
27262 }
27263 }
27264
27265 void remove() {
27266 assert(_previousIndex != -1);
27267 assert(_previousTerminator != null &&
27268 (_previousIndex > 0 || _previousTerminator == _template));
27269 assert(_terminator != null && _index > 0);
27270 assert(_template.parentNode != null);
27271 assert(_instanceCount(_template) > 0);
27272
27273 if (_previousTerminator == _terminator) {
27274 assert(_index == _previousIndex + 1);
27275 _terminator._instanceTerminatorCount--;
27276 _terminator = _template;
27277 _previousTerminator = null;
27278 _previousIndex = -1;
27279 return;
27280 }
27281
27282 _terminator._instanceTerminatorCount--;
27283
27284 var parent = _template.parentNode;
27285 while (_previousTerminator.nextNode != _terminator) {
27286 _removeTemplateChild(parent, _previousTerminator.nextNode);
27287 }
27288 _removeTemplateChild(parent, _terminator);
27289
27290 _terminator = _previousTerminator;
27291 _index = _previousIndex;
27292 _previousTerminator = null;
27293 _previousIndex = -1; // 0?
27294 }
27295 }
27296
27297 27245
27298 class _TemplateIterator { 27246 class _TemplateIterator {
27299 final Element _templateElement; 27247 final Element _templateElement;
27300 int instanceCount = 0; 27248 final List<Node> terminators = [];
27249 final CompoundBinding inputs;
27301 List iteratedValue; 27250 List iteratedValue;
27302 bool observing = false;
27303 final CompoundBinding inputs;
27304 27251
27305 StreamSubscription _sub; 27252 StreamSubscription _sub;
27306 StreamSubscription _valueBinding; 27253 StreamSubscription _valueBinding;
27307 27254
27308 _TemplateIterator(this._templateElement) 27255 _TemplateIterator(this._templateElement)
27309 : inputs = new CompoundBinding(resolveInputs) { 27256 : inputs = new CompoundBinding(resolveInputs) {
27310 27257
27311 _valueBinding = new PathObserver(inputs, 'value').bindSync(valueChanged); 27258 _valueBinding = new PathObserver(inputs, 'value').bindSync(valueChanged);
27312 } 27259 }
27313 27260
(...skipping 22 matching lines...) Expand all
27336 if (value is Observable) { 27283 if (value is Observable) {
27337 _sub = value.changes.listen(_handleChanges); 27284 _sub = value.changes.listen(_handleChanges);
27338 } 27285 }
27339 27286
27340 int len = iteratedValue.length; 27287 int len = iteratedValue.length;
27341 if (len > 0) { 27288 if (len > 0) {
27342 _handleChanges([new ListChangeRecord(0, addedCount: len)]); 27289 _handleChanges([new ListChangeRecord(0, addedCount: len)]);
27343 } 27290 }
27344 } 27291 }
27345 27292
27346 // TODO(jmesserly): port MDV v3. 27293 Node getTerminatorAt(int index) {
27347 getInstanceModel(model, syntax) => model; 27294 if (index == -1) return _templateElement;
27348 getInstanceFragment(syntax) => _templateElement.createInstance(); 27295 var terminator = terminators[index];
27296 if (terminator is! Element) return terminator;
27297
27298 var subIterator = terminator._templateIterator;
27299 if (subIterator == null) return terminator;
27300
27301 return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
27302 }
27303
27304 void insertInstanceAt(int index, Node fragment) {
27305 var previousTerminator = getTerminatorAt(index - 1);
27306 var terminator = fragment.$dom_lastChild;
27307 if (terminator == null) terminator = previousTerminator;
27308
27309 terminators.insert(index, terminator);
27310 var parent = _templateElement.parentNode;
27311 parent.insertBefore(fragment, previousTerminator.nextNode);
27312 }
27313
27314 void removeInstanceAt(int index) {
27315 var previousTerminator = getTerminatorAt(index - 1);
27316 var terminator = getTerminatorAt(index);
27317 terminators.removeAt(index);
27318
27319 var parent = _templateElement.parentNode;
27320 while (terminator != previousTerminator) {
27321 var node = terminator;
27322 terminator = node.previousNode;
27323 _removeTemplateChild(parent, node);
27324 }
27325 }
27326
27327 void removeAllInstances() {
27328 if (terminators.length == 0) return;
27329
27330 var previousTerminator = _templateElement;
27331 var terminator = getTerminatorAt(terminators.length - 1);
27332 terminators.length = 0;
27333
27334 var parent = _templateElement.parentNode;
27335 while (terminator != previousTerminator) {
27336 var node = terminator;
27337 terminator = node.previousNode;
27338 _removeTemplateChild(parent, node);
27339 }
27340 }
27341
27342 void clear() {
27343 unobserve();
27344 removeAllInstances();
27345 iteratedValue = null;
27346 }
27347
27348 getInstanceModel(model, syntax) {
27349 if (syntax != null) {
27350 return syntax.getInstanceModel(_templateElement, model);
27351 }
27352 return model;
27353 }
27354
27355 getInstanceFragment(syntax) {
27356 if (syntax != null) {
27357 return syntax.getInstanceFragment(_templateElement);
27358 }
27359 return _templateElement.createInstance();
27360 }
27349 27361
27350 void _handleChanges(List<ListChangeRecord> splices) { 27362 void _handleChanges(List<ListChangeRecord> splices) {
27351 var syntax = TemplateElement.syntax[_templateElement.attributes['syntax']]; 27363 var syntax = TemplateElement.syntax[_templateElement.attributes['syntax']];
27352 27364
27353 for (var splice in splices) { 27365 for (var splice in splices) {
27354 if (splice is! ListChangeRecord) continue; 27366 if (splice is! ListChangeRecord) continue;
27355 27367
27356 for (int i = 0; i < splice.removedCount; i++) { 27368 for (int i = 0; i < splice.removedCount; i++) {
27357 var cursor = new _InstanceCursor(_templateElement, splice.index + 1); 27369 removeInstanceAt(splice.index);
27358 cursor.remove();
27359 instanceCount--;
27360 } 27370 }
27361 27371
27362 for (var addIndex = splice.index; 27372 for (var addIndex = splice.index;
27363 addIndex < splice.index + splice.addedCount; 27373 addIndex < splice.index + splice.addedCount;
27364 addIndex++) { 27374 addIndex++) {
27365 27375
27366 var model = getInstanceModel(iteratedValue[addIndex], syntax); 27376 var model = getInstanceModel(iteratedValue[addIndex], syntax);
27377
27367 var fragment = getInstanceFragment(syntax); 27378 var fragment = getInstanceFragment(syntax);
27368 27379
27369 _addBindings(fragment, model, syntax); 27380 _addBindings(fragment, model, syntax);
27370 _addTemplateInstanceRecord(fragment, model); 27381 _addTemplateInstanceRecord(fragment, model);
27371 27382
27372 var cursor = new _InstanceCursor(_templateElement, addIndex); 27383 insertInstanceAt(addIndex, fragment);
27373 cursor.insert(fragment);
27374 instanceCount++;
27375 } 27384 }
27376 } 27385 }
27377 } 27386 }
27378 27387
27379 void unobserve() { 27388 void unobserve() {
27380 if (_sub == null) return; 27389 if (_sub == null) return;
27381 _sub.cancel(); 27390 _sub.cancel();
27382 _sub = null; 27391 _sub = null;
27383 } 27392 }
27384 27393
27385 void clear() {
27386 unobserve();
27387
27388 iteratedValue = null;
27389 if (instanceCount == 0) return;
27390
27391 for (var i = 0; i < instanceCount; i++) {
27392 var cursor = new _InstanceCursor(_templateElement, 1);
27393 cursor.remove();
27394 }
27395
27396 instanceCount = 0;
27397 }
27398
27399 void abandon() { 27394 void abandon() {
27400 unobserve(); 27395 unobserve();
27401 _valueBinding.cancel(); 27396 _valueBinding.cancel();
27402 inputs.dispose(); 27397 inputs.dispose();
27403 } 27398 }
27404 } 27399 }
27405
27406 int _instanceCount(Element element) {
27407 var templateIterator = element._templateIterator;
27408 return templateIterator != null ? templateIterator.instanceCount : 0;
27409 }
27410 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 27400 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
27411 // for details. All rights reserved. Use of this source code is governed by a 27401 // for details. All rights reserved. Use of this source code is governed by a
27412 // BSD-style license that can be found in the LICENSE file. 27402 // BSD-style license that can be found in the LICENSE file.
27413 27403
27414 27404
27415 /** 27405 /**
27416 * Helper class to implement custom events which wrap DOM events. 27406 * Helper class to implement custom events which wrap DOM events.
27417 */ 27407 */
27418 class _WrappedEvent implements Event { 27408 class _WrappedEvent implements Event {
27419 final Event wrapped; 27409 final Event wrapped;
(...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after
28650 } 28640 }
28651 28641
28652 _send(msg) { 28642 _send(msg) {
28653 _sendToHelperIsolate(msg, _sendPort); 28643 _sendToHelperIsolate(msg, _sendPort);
28654 } 28644 }
28655 } 28645 }
28656 28646
28657 get _pureIsolateTimerFactoryClosure => 28647 get _pureIsolateTimerFactoryClosure =>
28658 ((int milliSeconds, void callback(Timer time), bool repeating) => 28648 ((int milliSeconds, void callback(Timer time), bool repeating) =>
28659 new _PureIsolateTimer(milliSeconds, callback, repeating)); 28649 new _PureIsolateTimer(milliSeconds, callback, repeating));
OLDNEW
« no previous file with comments | « sdk/lib/html/dart2js/html_dart2js.dart ('k') | tests/html/binding_syntax_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698