| OLD | NEW |
| 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 16349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16360 void add(Node value) { | 16360 void add(Node value) { |
| 16361 _this.append(value); | 16361 _this.append(value); |
| 16362 } | 16362 } |
| 16363 | 16363 |
| 16364 void addAll(Iterable<Node> iterable) { | 16364 void addAll(Iterable<Node> iterable) { |
| 16365 if (iterable is _ChildNodeListLazy) { | 16365 if (iterable is _ChildNodeListLazy) { |
| 16366 _ChildNodeListLazy otherList = iterable; | 16366 _ChildNodeListLazy otherList = iterable; |
| 16367 if (!identical(otherList._this, _this)) { | 16367 if (!identical(otherList._this, _this)) { |
| 16368 // Optimized route for copying between nodes. | 16368 // Optimized route for copying between nodes. |
| 16369 for (var i = 0, len = otherList.length; i < len; ++i) { | 16369 for (var i = 0, len = otherList.length; i < len; ++i) { |
| 16370 // Should use $dom_firstChild, Bug 8886. | 16370 _this.append(otherList._this.firstChild); |
| 16371 _this.append(otherList[0]); | |
| 16372 } | 16371 } |
| 16373 } | 16372 } |
| 16374 return; | 16373 return; |
| 16375 } | 16374 } |
| 16376 for (Node node in iterable) { | 16375 for (Node node in iterable) { |
| 16377 _this.append(node); | 16376 _this.append(node); |
| 16378 } | 16377 } |
| 16379 } | 16378 } |
| 16380 | 16379 |
| 16381 void insert(int index, Node node) { | 16380 void insert(int index, Node node) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16419 Node node = object; | 16418 Node node = object; |
| 16420 if (!identical(_this, node.parentNode)) return false; | 16419 if (!identical(_this, node.parentNode)) return false; |
| 16421 _this.$dom_removeChild(node); | 16420 _this.$dom_removeChild(node); |
| 16422 return true; | 16421 return true; |
| 16423 } | 16422 } |
| 16424 | 16423 |
| 16425 void _filter(bool test(Node node), bool removeMatching) { | 16424 void _filter(bool test(Node node), bool removeMatching) { |
| 16426 // This implementation of removeWhere/retainWhere is more efficient | 16425 // This implementation of removeWhere/retainWhere is more efficient |
| 16427 // than the default in ListBase. Child nodes can be removed in constant | 16426 // than the default in ListBase. Child nodes can be removed in constant |
| 16428 // time. | 16427 // time. |
| 16429 Node child = _this.$dom_firstChild; | 16428 Node child = _this.firstChild; |
| 16430 while (child != null) { | 16429 while (child != null) { |
| 16431 Node nextChild = child.nextNode; | 16430 Node nextChild = child.nextNode; |
| 16432 if (test(child) == removeMatching) { | 16431 if (test(child) == removeMatching) { |
| 16433 _this.$dom_removeChild(child); | 16432 _this.$dom_removeChild(child); |
| 16434 } | 16433 } |
| 16435 child = nextChild; | 16434 child = nextChild; |
| 16436 } | 16435 } |
| 16437 } | 16436 } |
| 16438 | 16437 |
| 16439 void removeWhere(bool test(Node node)) { | 16438 void removeWhere(bool test(Node node)) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16537 */ | 16536 */ |
| 16538 Node insertAllBefore(Iterable<Node> newNodes, Node refChild) { | 16537 Node insertAllBefore(Iterable<Node> newNodes, Node refChild) { |
| 16539 if (newNodes is _ChildNodeListLazy) { | 16538 if (newNodes is _ChildNodeListLazy) { |
| 16540 _ChildNodeListLazy otherList = newNodes; | 16539 _ChildNodeListLazy otherList = newNodes; |
| 16541 if (identical(otherList._this, this)) { | 16540 if (identical(otherList._this, this)) { |
| 16542 throw new ArgumentError(newNodes); | 16541 throw new ArgumentError(newNodes); |
| 16543 } | 16542 } |
| 16544 | 16543 |
| 16545 // Optimized route for copying between nodes. | 16544 // Optimized route for copying between nodes. |
| 16546 for (var i = 0, len = otherList.length; i < len; ++i) { | 16545 for (var i = 0, len = otherList.length; i < len; ++i) { |
| 16547 // Should use $dom_firstChild, Bug 8886. | 16546 this.insertBefore(otherList._this.firstChild, refChild); |
| 16548 this.insertBefore(otherList[0], refChild); | |
| 16549 } | 16547 } |
| 16550 } else { | 16548 } else { |
| 16551 for (var node in newNodes) { | 16549 for (var node in newNodes) { |
| 16552 this.insertBefore(node, refChild); | 16550 this.insertBefore(node, refChild); |
| 16553 } | 16551 } |
| 16554 } | 16552 } |
| 16555 } | 16553 } |
| 16556 | 16554 |
| 16557 /** | 16555 /** |
| 16558 * Print out a String representation of this Node. | 16556 * Print out a String representation of this Node. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16635 @DocsEditable | 16633 @DocsEditable |
| 16636 static const int TEXT_NODE = 3; | 16634 static const int TEXT_NODE = 3; |
| 16637 | 16635 |
| 16638 @JSName('childNodes') | 16636 @JSName('childNodes') |
| 16639 @DomName('Node.childNodes') | 16637 @DomName('Node.childNodes') |
| 16640 @DocsEditable | 16638 @DocsEditable |
| 16641 @Returns('NodeList') | 16639 @Returns('NodeList') |
| 16642 @Creates('NodeList') | 16640 @Creates('NodeList') |
| 16643 final List<Node> $dom_childNodes; | 16641 final List<Node> $dom_childNodes; |
| 16644 | 16642 |
| 16645 @JSName('firstChild') | |
| 16646 @DomName('Node.firstChild') | 16643 @DomName('Node.firstChild') |
| 16647 @DocsEditable | 16644 @DocsEditable |
| 16648 final Node $dom_firstChild; | 16645 final Node firstChild; |
| 16649 | 16646 |
| 16650 @JSName('lastChild') | |
| 16651 @DomName('Node.lastChild') | 16647 @DomName('Node.lastChild') |
| 16652 @DocsEditable | 16648 @DocsEditable |
| 16653 final Node $dom_lastChild; | 16649 final Node lastChild; |
| 16654 | 16650 |
| 16655 @JSName('localName') | 16651 @JSName('localName') |
| 16656 @DomName('Node.localName') | 16652 @DomName('Node.localName') |
| 16657 @DocsEditable | 16653 @DocsEditable |
| 16658 // http://dom.spec.whatwg.org/#dom-node-localname | 16654 // http://dom.spec.whatwg.org/#dom-node-localname |
| 16659 @deprecated // deprecated | 16655 @deprecated // deprecated |
| 16660 final String $dom_localName; | 16656 final String $dom_localName; |
| 16661 | 16657 |
| 16662 @JSName('namespaceURI') | 16658 @JSName('namespaceURI') |
| 16663 @DomName('Node.namespaceURI') | 16659 @DomName('Node.namespaceURI') |
| (...skipping 11394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 28058 | 28054 |
| 28059 static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) { | 28055 static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) { |
| 28060 var clone = node.clone(false); // Shallow clone. | 28056 var clone = node.clone(false); // Shallow clone. |
| 28061 if (clone is Element && clone.isTemplate) { | 28057 if (clone is Element && clone.isTemplate) { |
| 28062 TemplateElement.decorate(clone, node); | 28058 TemplateElement.decorate(clone, node); |
| 28063 if (syntax != null) { | 28059 if (syntax != null) { |
| 28064 clone.attributes.putIfAbsent('syntax', () => syntax); | 28060 clone.attributes.putIfAbsent('syntax', () => syntax); |
| 28065 } | 28061 } |
| 28066 } | 28062 } |
| 28067 | 28063 |
| 28068 for (var c = node.$dom_firstChild; c != null; c = c.nextNode) { | 28064 for (var c = node.firstChild; c != null; c = c.nextNode) { |
| 28069 clone.append(_createDeepCloneAndDecorateTemplates(c, syntax)); | 28065 clone.append(_createDeepCloneAndDecorateTemplates(c, syntax)); |
| 28070 } | 28066 } |
| 28071 return clone; | 28067 return clone; |
| 28072 } | 28068 } |
| 28073 | 28069 |
| 28074 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#
dfn-template-contents-owner | 28070 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#
dfn-template-contents-owner |
| 28075 static Document _getTemplateContentsOwner(HtmlDocument doc) { | 28071 static Document _getTemplateContentsOwner(HtmlDocument doc) { |
| 28076 if (doc.window == null) { | 28072 if (doc.window == null) { |
| 28077 return doc; | 28073 return doc; |
| 28078 } | 28074 } |
| 28079 var d = doc._templateContentsOwner; | 28075 var d = doc._templateContentsOwner; |
| 28080 if (d == null) { | 28076 if (d == null) { |
| 28081 // TODO(arv): This should either be a Document or HTMLDocument depending | 28077 // TODO(arv): This should either be a Document or HTMLDocument depending |
| 28082 // on doc. | 28078 // on doc. |
| 28083 d = doc.implementation.createHtmlDocument(''); | 28079 d = doc.implementation.createHtmlDocument(''); |
| 28084 while (d.$dom_lastChild != null) { | 28080 while (d.lastChild != null) { |
| 28085 d.$dom_lastChild.remove(); | 28081 d.lastChild.remove(); |
| 28086 } | 28082 } |
| 28087 doc._templateContentsOwner = d; | 28083 doc._templateContentsOwner = d; |
| 28088 } | 28084 } |
| 28089 return d; | 28085 return d; |
| 28090 } | 28086 } |
| 28091 | 28087 |
| 28092 static Element _cloneAndSeperateAttributeTemplate(Element templateElement) { | 28088 static Element _cloneAndSeperateAttributeTemplate(Element templateElement) { |
| 28093 var clone = templateElement.clone(false); | 28089 var clone = templateElement.clone(false); |
| 28094 var attributes = templateElement.attributes; | 28090 var attributes = templateElement.attributes; |
| 28095 for (var name in attributes.keys.toList()) { | 28091 for (var name in attributes.keys.toList()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 28107 } | 28103 } |
| 28108 | 28104 |
| 28109 return clone; | 28105 return clone; |
| 28110 } | 28106 } |
| 28111 | 28107 |
| 28112 static void _liftNonNativeChildrenIntoContent(Element templateElement) { | 28108 static void _liftNonNativeChildrenIntoContent(Element templateElement) { |
| 28113 var content = templateElement.content; | 28109 var content = templateElement.content; |
| 28114 | 28110 |
| 28115 if (!templateElement._isAttributeTemplate) { | 28111 if (!templateElement._isAttributeTemplate) { |
| 28116 var child; | 28112 var child; |
| 28117 while ((child = templateElement.$dom_firstChild) != null) { | 28113 while ((child = templateElement.firstChild) != null) { |
| 28118 content.append(child); | 28114 content.append(child); |
| 28119 } | 28115 } |
| 28120 return; | 28116 return; |
| 28121 } | 28117 } |
| 28122 | 28118 |
| 28123 // For attribute templates we copy the whole thing into the content and | 28119 // For attribute templates we copy the whole thing into the content and |
| 28124 // we move the non template attributes into the content. | 28120 // we move the non template attributes into the content. |
| 28125 // | 28121 // |
| 28126 // <tr foo template> | 28122 // <tr foo template> |
| 28127 // | 28123 // |
| 28128 // becomes | 28124 // becomes |
| 28129 // | 28125 // |
| 28130 // <tr template> | 28126 // <tr template> |
| 28131 // + #document-fragment | 28127 // + #document-fragment |
| 28132 // + <tr foo> | 28128 // + <tr foo> |
| 28133 // | 28129 // |
| 28134 var newRoot = _cloneAndSeperateAttributeTemplate(templateElement); | 28130 var newRoot = _cloneAndSeperateAttributeTemplate(templateElement); |
| 28135 var child; | 28131 var child; |
| 28136 while ((child = templateElement.$dom_firstChild) != null) { | 28132 while ((child = templateElement.firstChild) != null) { |
| 28137 newRoot.append(child); | 28133 newRoot.append(child); |
| 28138 } | 28134 } |
| 28139 content.append(newRoot); | 28135 content.append(newRoot); |
| 28140 } | 28136 } |
| 28141 | 28137 |
| 28142 static void _bootstrapTemplatesRecursivelyFrom(Node node) { | 28138 static void _bootstrapTemplatesRecursivelyFrom(Node node) { |
| 28143 void bootstrap(template) { | 28139 void bootstrap(template) { |
| 28144 if (!TemplateElement.decorate(template)) { | 28140 if (!TemplateElement.decorate(template)) { |
| 28145 _bootstrapTemplatesRecursivelyFrom(template.content); | 28141 _bootstrapTemplatesRecursivelyFrom(template.content); |
| 28146 } | 28142 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 28158 static final String _allTemplatesSelectors = 'template, option[template], ' + | 28154 static final String _allTemplatesSelectors = 'template, option[template], ' + |
| 28159 Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", "); | 28155 Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", "); |
| 28160 | 28156 |
| 28161 static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) { | 28157 static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) { |
| 28162 if (node is Element) { | 28158 if (node is Element) { |
| 28163 _addAttributeBindings(node, model, syntax); | 28159 _addAttributeBindings(node, model, syntax); |
| 28164 } else if (node is Text) { | 28160 } else if (node is Text) { |
| 28165 _parseAndBind(node, 'text', node.text, model, syntax); | 28161 _parseAndBind(node, 'text', node.text, model, syntax); |
| 28166 } | 28162 } |
| 28167 | 28163 |
| 28168 for (var c = node.$dom_firstChild; c != null; c = c.nextNode) { | 28164 for (var c = node.firstChild; c != null; c = c.nextNode) { |
| 28169 _addBindings(c, model, syntax); | 28165 _addBindings(c, model, syntax); |
| 28170 } | 28166 } |
| 28171 } | 28167 } |
| 28172 | 28168 |
| 28173 static void _addAttributeBindings(Element element, model, syntax) { | 28169 static void _addAttributeBindings(Element element, model, syntax) { |
| 28174 element.attributes.forEach((name, value) { | 28170 element.attributes.forEach((name, value) { |
| 28175 if (value == '' && (name == 'bind' || name == 'repeat')) { | 28171 if (value == '' && (name == 'bind' || name == 'repeat')) { |
| 28176 value = '{{}}'; | 28172 value = '{{}}'; |
| 28177 } | 28173 } |
| 28178 _parseAndBind(element, name, value, model, syntax); | 28174 _parseAndBind(element, name, value, model, syntax); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 28274 | 28270 |
| 28275 var value = s.substring(lastIndex, index).trim(); | 28271 var value = s.substring(lastIndex, index).trim(); |
| 28276 result.add(new _BindingToken(value, isBinding: true)); | 28272 result.add(new _BindingToken(value, isBinding: true)); |
| 28277 lastIndex = index + 2; | 28273 lastIndex = index + 2; |
| 28278 } | 28274 } |
| 28279 } | 28275 } |
| 28280 return result; | 28276 return result; |
| 28281 } | 28277 } |
| 28282 | 28278 |
| 28283 static void _addTemplateInstanceRecord(fragment, model) { | 28279 static void _addTemplateInstanceRecord(fragment, model) { |
| 28284 if (fragment.$dom_firstChild == null) { | 28280 if (fragment.firstChild == null) { |
| 28285 return; | 28281 return; |
| 28286 } | 28282 } |
| 28287 | 28283 |
| 28288 var instanceRecord = new TemplateInstance( | 28284 var instanceRecord = new TemplateInstance( |
| 28289 fragment.$dom_firstChild, fragment.$dom_lastChild, model); | 28285 fragment.firstChild, fragment.lastChild, model); |
| 28290 | 28286 |
| 28291 var node = instanceRecord.firstNode; | 28287 var node = instanceRecord.firstNode; |
| 28292 while (node != null) { | 28288 while (node != null) { |
| 28293 node._templateInstance = instanceRecord; | 28289 node._templateInstance = instanceRecord; |
| 28294 node = node.nextNode; | 28290 node = node.nextNode; |
| 28295 } | 28291 } |
| 28296 } | 28292 } |
| 28297 | 28293 |
| 28298 static void _removeAllBindingsRecursively(Node node) { | 28294 static void _removeAllBindingsRecursively(Node node) { |
| 28299 _nodeOrCustom(node).unbindAll(); | 28295 _nodeOrCustom(node).unbindAll(); |
| 28300 for (var c = node.$dom_firstChild; c != null; c = c.nextNode) { | 28296 for (var c = node.firstChild; c != null; c = c.nextNode) { |
| 28301 _removeAllBindingsRecursively(c); | 28297 _removeAllBindingsRecursively(c); |
| 28302 } | 28298 } |
| 28303 } | 28299 } |
| 28304 | 28300 |
| 28305 static void _removeChild(Node parent, Node child) { | 28301 static void _removeChild(Node parent, Node child) { |
| 28306 child._templateInstance = null; | 28302 child._templateInstance = null; |
| 28307 if (child is Element && (child as Element).isTemplate) { | 28303 if (child is Element && (child as Element).isTemplate) { |
| 28308 Element childElement = child; | 28304 Element childElement = child; |
| 28309 // Make sure we stop observing when we remove an element. | 28305 // Make sure we stop observing when we remove an element. |
| 28310 var templateIterator = childElement._templateIterator; | 28306 var templateIterator = childElement._templateIterator; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 28380 if (terminator is! Element) return terminator; | 28376 if (terminator is! Element) return terminator; |
| 28381 | 28377 |
| 28382 var subIterator = terminator._templateIterator; | 28378 var subIterator = terminator._templateIterator; |
| 28383 if (subIterator == null) return terminator; | 28379 if (subIterator == null) return terminator; |
| 28384 | 28380 |
| 28385 return subIterator.getTerminatorAt(subIterator.terminators.length - 1); | 28381 return subIterator.getTerminatorAt(subIterator.terminators.length - 1); |
| 28386 } | 28382 } |
| 28387 | 28383 |
| 28388 void insertInstanceAt(int index, Node fragment) { | 28384 void insertInstanceAt(int index, Node fragment) { |
| 28389 var previousTerminator = getTerminatorAt(index - 1); | 28385 var previousTerminator = getTerminatorAt(index - 1); |
| 28390 var terminator = fragment.$dom_lastChild; | 28386 var terminator = fragment.lastChild; |
| 28391 if (terminator == null) terminator = previousTerminator; | 28387 if (terminator == null) terminator = previousTerminator; |
| 28392 | 28388 |
| 28393 terminators.insert(index, terminator); | 28389 terminators.insert(index, terminator); |
| 28394 var parent = _templateElement.parentNode; | 28390 var parent = _templateElement.parentNode; |
| 28395 parent.insertBefore(fragment, previousTerminator.nextNode); | 28391 parent.insertBefore(fragment, previousTerminator.nextNode); |
| 28396 } | 28392 } |
| 28397 | 28393 |
| 28398 void removeInstanceAt(int index) { | 28394 void removeInstanceAt(int index) { |
| 28399 var previousTerminator = getTerminatorAt(index - 1); | 28395 var previousTerminator = getTerminatorAt(index - 1); |
| 28400 var terminator = getTerminatorAt(index); | 28396 var terminator = getTerminatorAt(index); |
| (...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 29605 _position = nextPosition; | 29601 _position = nextPosition; |
| 29606 return true; | 29602 return true; |
| 29607 } | 29603 } |
| 29608 _current = null; | 29604 _current = null; |
| 29609 _position = _array.length; | 29605 _position = _array.length; |
| 29610 return false; | 29606 return false; |
| 29611 } | 29607 } |
| 29612 | 29608 |
| 29613 T get current => _current; | 29609 T get current => _current; |
| 29614 } | 29610 } |
| OLD | NEW |