| OLD | NEW |
| 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 html; | 5 part of html; |
| 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/toolkitchen/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 /** | 13 /** |
| 14 * Model-Driven Views (MDV)'s native features enables a wide-range of use cases, | 14 * Model-Driven Views (MDV)'s native features enables a wide-range of use cases, |
| 15 * but (by design) don't attempt to implement a wide array of specialized | 15 * but (by design) don't attempt to implement a wide array of specialized |
| 16 * behaviors. | 16 * behaviors. |
| 17 * | 17 * |
| 18 * Enabling these features in MDV is a matter of implementing and registering an | 18 * Enabling these features in MDV is a matter of implementing and registering an |
| (...skipping 11 matching lines...) Expand all Loading... |
| 30 * class MySyntax extends CustomBindingSyntax { | 30 * class MySyntax extends CustomBindingSyntax { |
| 31 * getBinding(model, path, name, node) { | 31 * getBinding(model, path, name, node) { |
| 32 * // The magic happens here! | 32 * // The magic happens here! |
| 33 * } | 33 * } |
| 34 * } | 34 * } |
| 35 * | 35 * |
| 36 * ... | 36 * ... |
| 37 * | 37 * |
| 38 * TemplateElement.syntax['MySyntax'] = new MySyntax(); | 38 * TemplateElement.syntax['MySyntax'] = new MySyntax(); |
| 39 * | 39 * |
| 40 * See <https://github.com/toolkitchen/mdv/blob/master/docs/syntax.md> for more | 40 * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for m
ore |
| 41 * information about Custom Syntax. | 41 * information about Custom Syntax. |
| 42 */ | 42 */ |
| 43 // TODO(jmesserly): if this is just one method, a function type would make it | 43 // TODO(jmesserly): if this is just one method, a function type would make it |
| 44 // more Dart-friendly. | 44 // more Dart-friendly. |
| 45 @Experimental | 45 @Experimental |
| 46 abstract class CustomBindingSyntax { | 46 abstract class CustomBindingSyntax { |
| 47 /** | 47 /** |
| 48 * This syntax method allows for a custom interpretation of the contents of | 48 * This syntax method allows for a custom interpretation of the contents of |
| 49 * mustaches (`{{` ... `}}`). | 49 * mustaches (`{{` ... `}}`). |
| 50 * | 50 * |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 if (node == document || node.parentNode == document) return true; | 352 if (node == document || node.parentNode == document) return true; |
| 353 return document.documentElement.contains(node); | 353 return document.documentElement.contains(node); |
| 354 } | 354 } |
| 355 } | 355 } |
| 356 | 356 |
| 357 class _Bindings { | 357 class _Bindings { |
| 358 // TODO(jmesserly): not sure what kind of boolean conversion rules to | 358 // TODO(jmesserly): not sure what kind of boolean conversion rules to |
| 359 // apply for template data-binding. HTML attributes are true if they're | 359 // apply for template data-binding. HTML attributes are true if they're |
| 360 // present. However Dart only treats "true" as true. Since this is HTML we'll | 360 // present. However Dart only treats "true" as true. Since this is HTML we'll |
| 361 // use something closer to the HTML rules: null (missing) and false are false, | 361 // use something closer to the HTML rules: null (missing) and false are false, |
| 362 // everything else is true. See: https://github.com/toolkitchen/mdv/issues/59 | 362 // everything else is true. See: https://github.com/polymer-project/mdv/issues
/59 |
| 363 static bool _toBoolean(value) => null != value && false != value; | 363 static bool _toBoolean(value) => null != value && false != value; |
| 364 | 364 |
| 365 static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) { | 365 static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) { |
| 366 var clone = node.clone(false); // Shallow clone. | 366 var clone = node.clone(false); // Shallow clone. |
| 367 if (clone is Element && clone.isTemplate) { | 367 if (clone is Element && clone.isTemplate) { |
| 368 TemplateElement.decorate(clone, node); | 368 TemplateElement.decorate(clone, node); |
| 369 if (syntax != null) { | 369 if (syntax != null) { |
| 370 clone.attributes.putIfAbsent('syntax', () => syntax); | 370 clone.attributes.putIfAbsent('syntax', () => syntax); |
| 371 } | 371 } |
| 372 } | 372 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 } | 486 } |
| 487 | 487 |
| 488 static void _parseAndBind(Node node, String name, String text, model, | 488 static void _parseAndBind(Node node, String name, String text, model, |
| 489 CustomBindingSyntax syntax) { | 489 CustomBindingSyntax syntax) { |
| 490 | 490 |
| 491 var tokens = _parseMustacheTokens(text); | 491 var tokens = _parseMustacheTokens(text); |
| 492 if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) { | 492 if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) { |
| 493 return; | 493 return; |
| 494 } | 494 } |
| 495 | 495 |
| 496 // If this is a custom element, give the .xtag a change to bind. |
| 497 node = _nodeOrCustom(node); |
| 498 |
| 496 if (tokens.length == 1 && tokens[0].isBinding) { | 499 if (tokens.length == 1 && tokens[0].isBinding) { |
| 497 _bindOrDelegate(node, name, model, tokens[0].value, syntax); | 500 _bindOrDelegate(node, name, model, tokens[0].value, syntax); |
| 498 return; | 501 return; |
| 499 } | 502 } |
| 500 | 503 |
| 501 var replacementBinding = new CompoundBinding(); | 504 var replacementBinding = new CompoundBinding(); |
| 502 for (var i = 0; i < tokens.length; i++) { | 505 for (var i = 0; i < tokens.length; i++) { |
| 503 var token = tokens[i]; | 506 var token = tokens[i]; |
| 504 if (token.isBinding) { | 507 if (token.isBinding) { |
| 505 _bindOrDelegate(replacementBinding, i, model, token.value, syntax); | 508 _bindOrDelegate(replacementBinding, i, model, token.value, syntax); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 517 var value = values[i]; | 520 var value = values[i]; |
| 518 if (value != null) { | 521 if (value != null) { |
| 519 newValue.write(value); | 522 newValue.write(value); |
| 520 } | 523 } |
| 521 } | 524 } |
| 522 } | 525 } |
| 523 | 526 |
| 524 return newValue.toString(); | 527 return newValue.toString(); |
| 525 }; | 528 }; |
| 526 | 529 |
| 527 _nodeOrCustom(node).bind(name, replacementBinding, 'value'); | 530 node.bind(name, replacementBinding, 'value'); |
| 528 } | 531 } |
| 529 | 532 |
| 530 static void _bindOrDelegate(node, name, model, String path, | 533 static void _bindOrDelegate(node, name, model, String path, |
| 531 CustomBindingSyntax syntax) { | 534 CustomBindingSyntax syntax) { |
| 532 | 535 |
| 533 if (syntax != null) { | 536 if (syntax != null) { |
| 534 var delegateBinding = syntax.getBinding(model, path, name, node); | 537 var delegateBinding = syntax.getBinding(model, path, name, node); |
| 535 if (delegateBinding != null) { | 538 if (delegateBinding != null) { |
| 536 model = delegateBinding; | 539 model = delegateBinding; |
| 537 path = 'value'; | 540 path = 'value'; |
| 538 } | 541 } |
| 539 } | 542 } |
| 540 | 543 |
| 541 _nodeOrCustom(node).bind(name, model, path); | 544 node.bind(name, model, path); |
| 542 } | 545 } |
| 543 | 546 |
| 544 /** | 547 /** |
| 545 * Gets the [node]'s custom [Element.xtag] if present, otherwise returns | 548 * Gets the [node]'s custom [Element.xtag] if present, otherwise returns |
| 546 * the node. This is used so nodes can override [Node.bind], [Node.unbind], | 549 * the node. This is used so nodes can override [Node.bind], [Node.unbind], |
| 547 * and [Node.unbindAll] like InputElement does. | 550 * and [Node.unbindAll] like InputElement does. |
| 548 */ | 551 */ |
| 549 // TODO(jmesserly): remove this when we can extend Element for real. | 552 // TODO(jmesserly): remove this when we can extend Element for real. |
| 550 static _nodeOrCustom(node) => node is Element ? node.xtag : node; | 553 static _nodeOrCustom(node) => node is Element ? node.xtag : node; |
| 551 | 554 |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 _sub.cancel(); | 779 _sub.cancel(); |
| 777 _sub = null; | 780 _sub = null; |
| 778 } | 781 } |
| 779 | 782 |
| 780 void abandon() { | 783 void abandon() { |
| 781 unobserve(); | 784 unobserve(); |
| 782 _valueBinding.cancel(); | 785 _valueBinding.cancel(); |
| 783 inputs.dispose(); | 786 inputs.dispose(); |
| 784 } | 787 } |
| 785 } | 788 } |
| OLD | NEW |