| OLD | NEW |
| 1 Sky DOM APIs | 1 Sky DOM APIs |
| 2 ============ | 2 ============ |
| 3 | 3 |
| 4 ```dart | 4 ```dart |
| 5 SKY MODULE | 5 SKY MODULE |
| 6 <!-- part of sky:core --> | 6 <!-- part of sky:core --> |
| 7 | 7 |
| 8 <script> | 8 <script> |
| 9 // ELEMENT TREE API | 9 // ELEMENT TREE API |
| 10 | 10 |
| 11 abstract class Node extends EventTarget { | 11 abstract class Node extends EventTarget { |
| 12 @override | 12 @override |
| 13 external List<EventTarget> getEventDispatchChain(); // O(N) in number of ances
tors across shadow trees | 13 external List<EventTarget> getEventDispatchChain(); // O(N) in number of ances
tors across shadow trees |
| 14 // implements EventTarget.getEventDispatchChain() | 14 // implements EventTarget.getEventDispatchChain() |
| 15 // returns the event dispatch chain (including handling shadow trees) | 15 // returns the event dispatch chain (including handling shadow trees) |
| 16 | 16 |
| 17 external Root get owner; // O(1) | 17 external Root get owner; // O(1) |
| 18 | 18 |
| 19 external ParentNode get parentNode; // O(1) | 19 external ParentNode get parentNode; // O(1) |
| 20 external Element get parentElement; // O(1) // if parentNode isn't an element,
returns null | 20 Element get parentElement => { |
| 21 if (parentNode is Element) |
| 22 return parentNode as Element; |
| 23 return null; |
| 24 } |
| 25 |
| 21 external Node get previousSibling; // O(1) | 26 external Node get previousSibling; // O(1) |
| 27 Element get previousElementSibling => { |
| 28 var result = previousSibling; |
| 29 while (result != null && result is! Element) |
| 30 result = result.previousSibling; |
| 31 return result as Element; |
| 32 } |
| 33 |
| 22 external Node get nextSibling; // O(1) | 34 external Node get nextSibling; // O(1) |
| 35 Element get nextElementSibling => { |
| 36 var result = nextSibling; |
| 37 while (result != null && result is! Element) |
| 38 result = result.nextSibling; |
| 39 return result as Element; |
| 40 } |
| 23 | 41 |
| 24 // the following all throw if parentNode is null | 42 external void _insertBefore(Node node); // O(N) in number of descendants |
| 25 external void insertBefore(List nodes); // O(N) in number of arguments plus al
l their descendants | 43 // node must be Text or Element, parentNode must be non-null |
| 26 external void insertAfter(List nodes); // O(N) in number of arguments plus all
their descendants | 44 void insertBefore(List nodes) { |
| 27 // TODO(ianh): rename insertBefore() and insertAfter() since the Web has an in
sertBefore() that means | 45 List.forEach((node) { |
| 28 // something else. What's a good name, though? | 46 if (node is String) |
| 29 external void replaceWith(List nodes); // O(N) in number of descendants plus a
rguments plus all their descendants | 47 node = new Text(node); |
| 30 // nodes must be String, Text, or Element | 48 _insertBefore(node); |
| 49 }); |
| 50 } |
| 51 |
| 52 void _insertAfter(Node node); // O(N) in number of arguments plus all their de
scendants |
| 53 // node must be Text or Element, parentNode must be non-null |
| 54 void insertAfter(List nodes) { |
| 55 var lastNode = this; |
| 56 List.forEach((node) { |
| 57 if (node is String) |
| 58 node = new Text(node); |
| 59 lastNode._insertAfter(node); |
| 60 lastNode = node; |
| 61 }); |
| 62 } |
| 63 |
| 64 void replaceWith(List nodes) { |
| 65 if (nextSibling != null) { |
| 66 var anchor = nextSibling; |
| 67 remove(); // parentNode can't be null here, so this won't throw |
| 68 anchor.insertBefore(nodes); |
| 69 } else { |
| 70 var anchor = parentNode; |
| 71 remove(); // throws if parentNode is null |
| 72 anchor.append(nodes); |
| 73 } |
| 74 } |
| 31 | 75 |
| 32 external void remove(); // O(N) in number of descendants | 76 external void remove(); // O(N) in number of descendants |
| 77 // parentNode must be non-null |
| 33 | 78 |
| 34 // called when parentNode changes | 79 // called when parentNode changes |
| 35 // this is why insertBefore(), append(), et al, are O(N) -- the whole affected
subtree is walked | 80 // this is why insertBefore(), append(), et al, are O(N) -- the whole affected
subtree is walked |
| 36 // mutating the element tree from within this is strongly discouraged, since i
t will result in the | 81 // mutating the element tree from within this is strongly discouraged, since i
t will result in the |
| 37 // callbacks being invoked while the element tree is in a different state than
implied by the callbacks | 82 // callbacks being invoked while the element tree is in a different state than
implied by the callbacks |
| 38 external void parentChangeCallback(ParentNode oldParent, ParentNode newParent,
Node previousSibling, Node nextSibling); // O(N) in descendants | 83 external void parentChangeCallback(ParentNode oldParent, ParentNode newParent,
Node previousSibling, Node nextSibling); // O(N) in descendants |
| 39 // default implementation calls attached/detached | 84 // default implementation calls attached/detached |
| 40 void attachedCallback() { } | 85 void attachedCallback() { } |
| 41 void detachedCallback() { } | 86 void detachedCallback() { } |
| 42 | 87 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 63 void resetLayoutManager() { // O(1) | 108 void resetLayoutManager() { // O(1) |
| 64 if (renderNode != null) { | 109 if (renderNode != null) { |
| 65 renderNode._layoutManager = null; | 110 renderNode._layoutManager = null; |
| 66 renderNode._needsManager = true; | 111 renderNode._needsManager = true; |
| 67 } | 112 } |
| 68 } | 113 } |
| 69 } | 114 } |
| 70 | 115 |
| 71 abstract class ParentNode extends Node { | 116 abstract class ParentNode extends Node { |
| 72 external Node get firstChild; // O(1) | 117 external Node get firstChild; // O(1) |
| 118 Element get firstElementChild => { |
| 119 var result = firstChild; |
| 120 while (result != null && result is! Element) |
| 121 result = result.nextSibling; |
| 122 return result as Element; |
| 123 } |
| 124 |
| 73 external Node get lastChild; // O(1) | 125 external Node get lastChild; // O(1) |
| 126 Element get lastElementChild => { |
| 127 var result = lastChild; |
| 128 while (result != null && result is! Element) |
| 129 result = result.previousSibling; |
| 130 return result as Element; |
| 131 } |
| 74 | 132 |
| 75 // Returns a new List every time. | 133 // Returns a new List every time. |
| 76 external List<Node> getChildren(); // O(N) in number of child nodes | 134 external List<Node> getChildren(); // O(N) in number of child nodes |
| 77 external List<Element> getChildElements(); // O(N) in number of child nodes | 135 List<Element> getChildElements() { |
| 78 // TODO(ianh): might not be necessary if we have the parser drop unnecessary w
hitespace text nodes | 136 // that the following works without a cast is absurd |
| 137 return getChildren().where((node) => node is Element).toList(); |
| 138 } |
| 79 | 139 |
| 80 external void append(List nodes); // O(N) in number of arguments plus all thei
r descendants | 140 external void _appendChild(Node node); // O(N) in number of descendants |
| 81 external void appendChild(Node child); // O(N) in number of descandants | 141 // node must be Text or Element |
| 82 external void prepend(List nodes); // O(N) in number of arguments plus all the
ir descendants | 142 void appendChild(Node node) { |
| 83 external void replaceChildrenWith(List nodes); // O(N) in number of descendant
s plus arguments plus all their descendants | 143 if (node is String) |
| 84 // nodes must be String, Text, or Element | 144 node = new Text(node); |
| 145 _appendChild(node); |
| 146 } |
| 147 void append(List nodes) { |
| 148 nodes.forEach(appendChild); |
| 149 } |
| 150 |
| 151 external void _prependChild(Node node); // O(N) in number of descendants |
| 152 // node must be Text or Element |
| 153 void prependChild(Node node) { |
| 154 if (node is String) |
| 155 node = new Text(node); |
| 156 _prependChild(node); |
| 157 } |
| 158 void prepend(List nodes) { |
| 159 // note: not implemented in terms of _prependChild() |
| 160 if (firstChild != null) |
| 161 firstChild.insertBefore(nodes); |
| 162 else |
| 163 append(nodes); |
| 164 } |
| 165 |
| 166 external void removeChildren(); // O(N) in number of descendants |
| 167 void setChild(Node node) { |
| 168 removeChildren(); |
| 169 appendChild(node); |
| 170 } |
| 171 void setChildren(List nodes) { |
| 172 removeChildren(); |
| 173 append(nodes); |
| 174 } |
| 85 } | 175 } |
| 86 | 176 |
| 87 class Attr { | 177 class Attr { |
| 88 const Attr (this.name, [this.value = '']); // O(1) | 178 const Attr (this.name, [this.value = '']); // O(1) |
| 89 final String name; // O(1) | 179 final String name; // O(1) |
| 90 final String value; // O(1) | 180 final String value; // O(1) |
| 91 } | 181 } |
| 92 | 182 |
| 93 // @tagname annotation for registering elements | 183 // @tagname annotation for registering elements |
| 94 // only useful when placed on classes that inherit from Element | 184 // only useful when placed on classes that inherit from Element |
| 95 class tagname extends AutomaticMetadata { | 185 class tagname extends AutomaticMetadata { |
| 96 const tagname(this.name); | 186 const tagname(this.name); |
| 97 final String name; | 187 final String name; |
| 98 void init(DeclarationMirror target, Module module) { | 188 void init(DeclarationMirror target, Module module) { |
| 99 assert(target is ClassMirror); | 189 assert(target is ClassMirror); |
| 100 if (!target.isSubclassOf(reflectClass(Element))) | 190 if (!target.isSubclassOf(reflectClass(Element))) |
| 101 throw Error('@tagname can only be used on descendants of Element'); | 191 throw Error('@tagname can only be used on descendants of Element'); |
| 102 module.registerElement(name, (target as ClassMirror).reflectedType); | 192 module.registerElement(name, (target as ClassMirror).reflectedType); |
| 103 } | 193 } |
| 104 } | 194 } |
| 105 | 195 |
| 106 abstract class Element extends ParentNode with Node { | 196 abstract class Element extends ParentNode with Node { |
| 107 external Element({Map<String, String> attributes: null, | 197 external Element({Map<String, String> attributes: null, |
| 108 List children: null, | 198 List children: null, |
| 109 Module hostModule: null}); // O(M+N), M = number of attribute
s, N = number of children nodes plus all their descendants | 199 Module hostModule: null}); // O(M+N), M = number of attribute
s, N = number of children nodes plus all their descendants |
| 110 // initialises the internal attributes table | 200 // initialises the internal attributes table, which is a ordered list |
| 111 // appends the given children nodes | 201 // appends the given children nodes |
| 112 // children must be String, Text, or Element | 202 // children must be String, Text, or Element |
| 113 // if this.needsShadow, creates a shadow tree | 203 // if this.needsShadow, creates a shadow tree |
| 114 | 204 |
| 115 String get tagName { // O(N) in number of annotations on the class | 205 String get tagName { // O(N) in number of annotations on the class |
| 116 // throws a StateError if the class doesn't have an @tagname annotation | 206 // throws a StateError if the class doesn't have an @tagname annotation |
| 117 var tagnameClass = reflectClass(tagname); | 207 var tagnameClass = reflectClass(tagname); |
| 118 return (reflectClass(this.runtimeType).metadata.singleWhere((mirror) => mirr
or.type == tagnameClass).reflectee as tagname).value; | 208 return (reflectClass(this.runtimeType).metadata.singleWhere((mirror) => mirr
or.type == tagnameClass).reflectee as tagname).value; |
| 119 } | 209 } |
| 120 | 210 |
| 121 external bool hasAttribute(String name); // O(N) in number of attributes | 211 external bool hasAttribute(String name); // O(N) in number of attributes |
| 122 external String getAttribute(String name); // O(N) in number of attributes | 212 external String getAttribute(String name); // O(N) in number of attributes |
| 123 external void setAttribute(String name, [String value = '']); // O(N) in numbe
r of attributes | 213 external void setAttribute(String name, [String value = '']); // O(N) in numbe
r of attributes |
| 124 external void removeAttribute(String name); // O(N) in number of attributes | 214 external void removeAttribute(String name); // O(N) in number of attributes |
| 125 // calling setAttribute() with a null value removes the attribute | 215 // calling setAttribute() with a null value removes the attribute |
| 126 // (calling it without a value sets it to the empty string) | 216 // (calling it without a value sets it to the empty string) |
| 127 | 217 |
| 128 // Returns a new Array and new Attr instances every time. | 218 // Returns a new Array and new Attr instances every time. |
| 129 external List<Attr> getAttributes(); // O(N) in number of attributes | 219 external List<Attr> getAttributes(); // O(N) in number of attributes |
| 130 | 220 |
| 131 get bool needsShadow => false; // O(1) | 221 get bool needsShadow => false; // O(1) |
| 132 external Root get shadowRoot; // O(1) | 222 external final Root shadowRoot; // O(1) |
| 133 // returns the shadow root | 223 // returns the shadow root |
| 134 // TODO(ianh): Should this be mutable? It would help explain how it gets set..
. | |
| 135 | 224 |
| 136 void endTagParsedCallback() { } | 225 void endTagParsedCallback() { } |
| 137 void attributeChangeCallback(String name, String oldValue, String newValue) {
} | 226 void attributeChangeCallback(String name, String oldValue, String newValue) {
} |
| 138 // name will never be null when this is called by sky | 227 // name will never be null when this is called by sky |
| 139 | 228 |
| 140 // TODO(ianh): does a node ever need to know when it's been redistributed? | 229 // TODO(ianh): does a node ever need to know when it's been redistributed? |
| 141 | 230 |
| 142 @override | 231 @override |
| 143 Type getLayoutManager() { // O(1) | 232 Type getLayoutManager() { // O(1) |
| 144 if (renderNode) | 233 if (renderNode) |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 external bool matches(Element element); // O(F()) | 381 external bool matches(Element element); // O(F()) |
| 293 external Element find(node root); // O(N*F())+O(M) where N is the number of de
scendants and M the average depth of the tree | 382 external Element find(node root); // O(N*F())+O(M) where N is the number of de
scendants and M the average depth of the tree |
| 294 external List<Element> findAll(Node root); // O(N*F())+O(N*M) where N is the n
umber of descendants and M the average depth of the tree | 383 external List<Element> findAll(Node root); // O(N*F())+O(N*M) where N is the n
umber of descendants and M the average depth of the tree |
| 295 // find() and findAll() throw if the root is not one of the following: | 384 // find() and findAll() throw if the root is not one of the following: |
| 296 // - Element | 385 // - Element |
| 297 // - Fragment | 386 // - Fragment |
| 298 // - Root | 387 // - Root |
| 299 } | 388 } |
| 300 </script> | 389 </script> |
| 301 ``` | 390 ``` |
| OLD | NEW |