OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
6 * This library exports all of the commonly used functions and types for | 6 * This library exports all of the commonly used functions and types for |
7 * building UI's. It is equivalent to the following imports: | 7 * building UI's. It is equivalent to the following imports: |
8 * | 8 * |
9 * import 'package:web_ui/observe.dart'; | 9 * import 'package:web_ui/observe.dart'; |
10 * import 'package:web_ui/safe_html.dart'; | 10 * import 'package:web_ui/safe_html.dart'; |
11 * import 'package:web_ui/templating.dart'; | 11 * import 'package:web_ui/templating.dart'; |
12 * import 'package:web_ui/watcher.dart'; | 12 * import 'package:web_ui/watcher.dart'; |
13 * import 'package:web_ui/web_ui.dart' show WebComponent; | 13 * import 'package:web_ui/web_ui.dart' show WebComponent; |
14 * | 14 * |
15 * Note that the [WebComponent] base class is defined in this library. | 15 * Note that the [WebComponent] base class is defined in this library. |
16 * | 16 * |
17 * See this article for more information: | 17 * See this article for more information: |
18 * <http://www.dartlang.org/articles/dart-web-components/>. | 18 * <http://www.dartlang.org/articles/dart-web-components/>. |
19 */ | 19 */ |
20 library web_ui; | 20 library web_ui; |
21 | 21 |
22 export 'observe.dart'; | 22 export 'observe.dart'; |
23 export 'safe_html.dart'; | 23 export 'safe_html.dart'; |
24 export 'templating.dart'; | 24 export 'templating.dart'; |
25 export 'watcher.dart'; | 25 export 'watcher.dart'; |
26 | 26 |
27 import 'dart:async'; | 27 import 'dart:async'; |
28 import 'dart:html'; | 28 import 'dart:html'; |
| 29 import 'dart:mirrors' show reflect; |
29 import 'package:meta/meta.dart'; | 30 import 'package:meta/meta.dart'; |
30 | 31 |
31 /** | 32 /** |
32 * The base class for all Dart web components. In addition to the [Element] | 33 * The base class for all Dart web components. In addition to the [Element] |
33 * interface, it also provides lifecycle methods: | 34 * interface, it also provides lifecycle methods: |
34 * - [created] | 35 * - [created] |
35 * - [inserted] | 36 * - [inserted] |
36 * - [attributeChanged] | 37 * - [attributeChanged] |
37 * - [removed] | 38 * - [removed] |
38 */ | 39 */ |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 void inserted() {} | 118 void inserted() {} |
118 | 119 |
119 /** Invoked when this component is removed from the DOM tree. */ | 120 /** Invoked when this component is removed from the DOM tree. */ |
120 void removed() {} | 121 void removed() {} |
121 | 122 |
122 // TODO(jmesserly): how do we implement this efficiently? | 123 // TODO(jmesserly): how do we implement this efficiently? |
123 // See https://github.com/dart-lang/web-ui/issues/37 | 124 // See https://github.com/dart-lang/web-ui/issues/37 |
124 /** Invoked when any attribute of the component is modified. */ | 125 /** Invoked when any attribute of the component is modified. */ |
125 void attributeChanged(String name, String oldValue, String newValue) {} | 126 void attributeChanged(String name, String oldValue, String newValue) {} |
126 | 127 |
127 get model => host.model; | |
128 | |
129 void set model(newModel) { | |
130 host.model = newModel; | |
131 } | |
132 | |
133 get templateInstance => host.templateInstance; | |
134 get isTemplate => host.isTemplate; | |
135 get ref => host.ref; | |
136 get content => host.content; | |
137 DocumentFragment createInstance(model, BindingDelegate delegate) => | |
138 host.createInstance(model, delegate); | |
139 createBinding(String name, model, String path) => | |
140 host.createBinding(name, model, path); | |
141 void bind(String name, model, String path) => host.bind(name, model, path); | |
142 void unbind(String name) => host.unbind(name); | |
143 void unbindAll() => host.unbindAll(); | |
144 get bindings => host.bindings; | |
145 BindingDelegate get bindingDelegate => host.bindingDelegate; | |
146 set bindingDelegate(BindingDelegate value) { host.bindingDelegate = value; } | |
147 | |
148 | 128 |
149 /** | 129 /** |
150 * **Note**: This is an implementation helper and should not need to be called | 130 * **Note**: This is an implementation helper and should not need to be called |
151 * from your code. | 131 * from your code. |
152 * | 132 * |
153 * If [ShadowRoot.supported] or [useShadowDom] is false, this distributes | 133 * If [ShadowRoot.supported] or [useShadowDom] is false, this distributes |
154 * children to the insertion points of the emulated ShadowRoot. | 134 * children to the insertion points of the emulated ShadowRoot. |
155 * This is an implementation helper and should not need to be called from your | 135 * This is an implementation helper and should not need to be called from your |
156 * code. | 136 * code. |
157 * | 137 * |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 return true; | 300 return true; |
321 } | 301 } |
322 | 302 |
323 /** Distribute the [nodes] in place of an existing [insertionPoint]. */ | 303 /** Distribute the [nodes] in place of an existing [insertionPoint]. */ |
324 static void _distribute(Element insertionPoint, Iterable<Node> nodes) { | 304 static void _distribute(Element insertionPoint, Iterable<Node> nodes) { |
325 assert(_isInsertionPoint(insertionPoint)); | 305 assert(_isInsertionPoint(insertionPoint)); |
326 insertionPoint.parent.insertAllBefore(nodes, insertionPoint); | 306 insertionPoint.parent.insertAllBefore(nodes, insertionPoint); |
327 insertionPoint.remove(); | 307 insertionPoint.remove(); |
328 } | 308 } |
329 | 309 |
330 // TODO(jmesserly): this forwarding is temporary until Dart supports | |
331 // subclassing Elements. | |
332 // TODO(jmesserly): we were missing the setter for title, are other things | |
333 // missing setters? | |
334 | |
335 List<Node> get nodes => host.nodes; | |
336 | |
337 set nodes(Iterable<Node> value) { host.nodes = value; } | |
338 | |
339 /** | |
340 * Replaces this node with another node. | |
341 */ | |
342 Node replaceWith(Node otherNode) { host.replaceWith(otherNode); } | |
343 | |
344 /** | |
345 * Removes this node from the DOM. | |
346 */ | |
347 void remove() => host.remove(); | |
348 | |
349 Node get nextNode => host.nextNode; | |
350 | |
351 String get nodeName => host.nodeName; | |
352 Document get document => host.document; | |
353 | |
354 Node get previousNode => host.previousNode; | |
355 | |
356 String get text => host.text; | |
357 | |
358 set text(String v) { host.text = v; } | |
359 | |
360 bool contains(Node other) => host.contains(other); | |
361 | |
362 bool hasChildNodes() => host.hasChildNodes(); | |
363 | |
364 Node insertBefore(Node newChild, Node refChild) => | |
365 host.insertBefore(newChild, refChild); | |
366 | |
367 Node insertAllBefore(Iterable<Node> newChild, Node refChild) => | |
368 host.insertAllBefore(newChild, refChild); | |
369 | |
370 Map<String, String> get attributes => host.attributes; | |
371 set attributes(Map<String, String> value) { | |
372 host.attributes = value; | |
373 } | |
374 | |
375 List<Element> get elements => host.children; | |
376 | |
377 set elements(List<Element> value) { | |
378 host.children = value; | |
379 } | |
380 | |
381 List<Element> get children => host.children; | |
382 | |
383 set children(List<Element> value) { | |
384 host.children = value; | |
385 } | |
386 | |
387 Set<String> get classes => host.classes; | |
388 | |
389 set classes(Iterable<String> value) { | |
390 host.classes = value; | |
391 } | |
392 | |
393 CssRect get contentEdge => host.contentEdge; | |
394 CssRect get paddingEdge => host.paddingEdge; | |
395 CssRect get borderEdge => host.borderEdge; | |
396 CssRect get marginEdge => host.marginEdge; | |
397 Point get documentOffset => host.documentOffset; | |
398 Point offsetTo(Element parent) => host.offsetTo(parent); | |
399 | |
400 Map<String, String> getNamespacedAttributes(String namespace) => | |
401 host.getNamespacedAttributes(namespace); | |
402 | |
403 CssStyleDeclaration getComputedStyle([String pseudoElement]) | |
404 => host.getComputedStyle(pseudoElement); | |
405 | |
406 Element clone(bool deep) => host.clone(deep); | |
407 | |
408 Element get parent => host.parent; | |
409 | |
410 Node get parentNode => host.parentNode; | |
411 | |
412 String get nodeValue => host.nodeValue; | |
413 | |
414 @deprecated | |
415 // TODO(sigmund): restore the old return type and call host.on when | |
416 // dartbug.com/8131 is fixed. | |
417 dynamic get on { throw new UnsupportedError('on is deprecated'); } | |
418 | |
419 String get contentEditable => host.contentEditable; | |
420 set contentEditable(String v) { host.contentEditable = v; } | |
421 | |
422 String get dir => host.dir; | |
423 set dir(String v) { host.dir = v; } | |
424 | |
425 bool get draggable => host.draggable; | |
426 set draggable(bool v) { host.draggable = v; } | |
427 | |
428 bool get hidden => host.hidden; | |
429 set hidden(bool v) { host.hidden = v; } | |
430 | |
431 String get id => host.id; | |
432 set id(String v) { host.id = v; } | |
433 | |
434 String get innerHTML => host.innerHtml; | |
435 | |
436 void set innerHTML(String v) { | |
437 host.innerHtml = v; | |
438 } | |
439 | |
440 String get innerHtml => host.innerHtml; | |
441 void set innerHtml(String v) { | |
442 host.innerHtml = v; | |
443 } | |
444 | |
445 bool get isContentEditable => host.isContentEditable; | |
446 | |
447 String get lang => host.lang; | |
448 set lang(String v) { host.lang = v; } | |
449 | |
450 String get outerHtml => host.outerHtml; | |
451 | |
452 bool get spellcheck => host.spellcheck; | |
453 set spellcheck(bool v) { host.spellcheck = v; } | |
454 | |
455 int get tabIndex => host.tabIndex; | |
456 set tabIndex(int i) { host.tabIndex = i; } | |
457 | |
458 String get title => host.title; | |
459 | |
460 set title(String value) { host.title = value; } | |
461 | |
462 bool get translate => host.translate; | |
463 set translate(bool v) { host.translate = v; } | |
464 | |
465 String get dropzone => host.dropzone; | |
466 set dropzone(String v) { host.dropzone = v; } | |
467 | |
468 void click() { host.click(); } | |
469 | |
470 InputMethodContext getInputContext() => host.getInputContext(); | |
471 | |
472 Element insertAdjacentElement(String where, Element element) => | |
473 host.insertAdjacentElement(where, element); | |
474 | |
475 void insertAdjacentHtml(String where, String html) { | |
476 host.insertAdjacentHtml(where, html); | |
477 } | |
478 | |
479 void insertAdjacentText(String where, String text) { | |
480 host.insertAdjacentText(where, text); | |
481 } | |
482 | |
483 Map<String, String> get dataset => host.dataset; | |
484 | |
485 set dataset(Map<String, String> value) { | |
486 host.dataset = value; | |
487 } | |
488 | |
489 Element get nextElementSibling => host.nextElementSibling; | |
490 | |
491 Element get offsetParent => host.offsetParent; | |
492 | |
493 Element get previousElementSibling => host.previousElementSibling; | |
494 | |
495 CssStyleDeclaration get style => host.style; | |
496 | |
497 String get tagName => host.tagName; | |
498 | |
499 String get pseudo => host.pseudo; | |
500 | |
501 void set pseudo(String value) { | |
502 host.pseudo = value; | |
503 } | |
504 | |
505 // Note: we are not polyfilling the shadow root here. This will be fixed when | |
506 // we migrate to the JS Shadow DOM polyfills. You can still use getShadowRoot | |
507 // to retrieve a node that behaves as the shadow root when Shadow DOM is not | |
508 // enabled. | |
509 ShadowRoot get shadowRoot => host.shadowRoot; | |
510 | |
511 void blur() { host.blur(); } | |
512 | |
513 void focus() { host.focus(); } | |
514 | |
515 void scrollByLines(int lines) { | |
516 host.scrollByLines(lines); | |
517 } | |
518 | |
519 void scrollByPages(int pages) { | |
520 host.scrollByPages(pages); | |
521 } | |
522 | |
523 void scrollIntoView([ScrollAlignment alignment]) { | |
524 host.scrollIntoView(alignment); | |
525 } | |
526 | |
527 bool matches(String selectors) => host.matches(selectors); | |
528 | |
529 @deprecated | |
530 void requestFullScreen(int flags) { requestFullscreen(); } | |
531 | |
532 void requestFullscreen() { host.requestFullscreen(); } | |
533 | |
534 void requestPointerLock() { host.requestPointerLock(); } | |
535 | |
536 Element query(String selectors) => host.query(selectors); | |
537 | |
538 ElementList queryAll(String selectors) => host.queryAll(selectors); | |
539 | |
540 HtmlCollection get $dom_children => host.$dom_children; | |
541 | |
542 int get $dom_childElementCount => host.$dom_childElementCount; | |
543 | |
544 String get className => host.className; | |
545 set className(String value) { host.className = value; } | |
546 | |
547 @deprecated | |
548 int get clientHeight => client.height; | |
549 | |
550 @deprecated | |
551 int get clientLeft => client.left; | |
552 | |
553 @deprecated | |
554 int get clientTop => client.top; | |
555 | |
556 @deprecated | |
557 int get clientWidth => client.width; | |
558 | |
559 Rect get client => host.client; | |
560 | |
561 Element get $dom_firstElementChild => host.$dom_firstElementChild; | |
562 | |
563 Element get $dom_lastElementChild => host.$dom_lastElementChild; | |
564 | |
565 @deprecated | |
566 int get offsetHeight => offset.height; | |
567 | |
568 @deprecated | |
569 int get offsetLeft => offset.left; | |
570 | |
571 @deprecated | |
572 int get offsetTop => offset.top; | |
573 | |
574 @deprecated | |
575 int get offsetWidth => offset.width; | |
576 | |
577 Rect get offset => host.offset; | |
578 | |
579 int get scrollHeight => host.scrollHeight; | |
580 | |
581 int get scrollLeft => host.scrollLeft; | |
582 | |
583 int get scrollTop => host.scrollTop; | |
584 | |
585 set scrollLeft(int value) { host.scrollLeft = value; } | |
586 | |
587 set scrollTop(int value) { host.scrollTop = value; } | |
588 | |
589 int get scrollWidth => host.scrollWidth; | |
590 | |
591 String $dom_getAttribute(String name) => | |
592 host.$dom_getAttribute(name); | |
593 | |
594 String $dom_getAttributeNS(String namespaceUri, String localName) => | |
595 host.$dom_getAttributeNS(namespaceUri, localName); | |
596 | |
597 String $dom_setAttributeNS( | |
598 String namespaceUri, String localName, String value) { | |
599 host.$dom_setAttributeNS(namespaceUri, localName, value); | |
600 } | |
601 | |
602 bool $dom_hasAttributeNS(String namespaceUri, String localName) => | |
603 host.$dom_hasAttributeNS(namespaceUri, localName); | |
604 | |
605 void $dom_removeAttributeNS(String namespaceUri, String localName) => | |
606 host.$dom_removeAttributeNS(namespaceUri, localName); | |
607 | |
608 Rect getBoundingClientRect() => host.getBoundingClientRect(); | |
609 | |
610 List<Rect> getClientRects() => host.getClientRects(); | |
611 | |
612 List<Node> getElementsByClassName(String name) => | |
613 host.getElementsByClassName(name); | |
614 | |
615 List<Node> $dom_getElementsByTagName(String name) => | |
616 host.$dom_getElementsByTagName(name); | |
617 | |
618 bool $dom_hasAttribute(String name) => | |
619 host.$dom_hasAttribute(name); | |
620 | |
621 List<Node> $dom_querySelectorAll(String selectors) => | |
622 host.$dom_querySelectorAll(selectors); | |
623 | |
624 void $dom_removeAttribute(String name) => | |
625 host.$dom_removeAttribute(name); | |
626 | |
627 void $dom_setAttribute(String name, String value) => | |
628 host.$dom_setAttribute(name, value); | |
629 | |
630 get $dom_attributes => host.$dom_attributes; | |
631 | |
632 List<Node> get $dom_childNodes => host.$dom_childNodes; | |
633 | |
634 Node get firstChild => host.firstChild; | |
635 | |
636 Node get lastChild => host.lastChild; | |
637 | |
638 String get localName => host.localName; | |
639 String get $dom_localName => host.$dom_localName; | |
640 | |
641 String get namespaceUri => host.namespaceUri; | |
642 String get $dom_namespaceUri => host.$dom_namespaceUri; | |
643 | |
644 int get nodeType => host.nodeType; | |
645 | |
646 void $dom_addEventListener(String type, EventListener listener, | |
647 [bool useCapture]) { | |
648 host.$dom_addEventListener(type, listener, useCapture); | |
649 } | |
650 | |
651 bool dispatchEvent(Event event) => host.dispatchEvent(event); | |
652 | |
653 Node $dom_removeChild(Node oldChild) => host.$dom_removeChild(oldChild); | |
654 | |
655 void $dom_removeEventListener(String type, EventListener listener, | |
656 [bool useCapture]) { | |
657 host.$dom_removeEventListener(type, listener, useCapture); | |
658 } | |
659 | |
660 Node $dom_replaceChild(Node newChild, Node oldChild) => | |
661 host.$dom_replaceChild(newChild, oldChild); | |
662 | |
663 get xtag => host.xtag; | |
664 | |
665 set xtag(value) { host.xtag = value; } | |
666 | |
667 Node append(Node e) => host.append(e); | |
668 | |
669 void appendText(String text) => host.appendText(text); | |
670 | |
671 void appendHtml(String html) => host.appendHtml(html); | |
672 | |
673 void $dom_scrollIntoView([bool alignWithTop]) { | |
674 if (alignWithTop == null) { | |
675 host.$dom_scrollIntoView(); | |
676 } else { | |
677 host.$dom_scrollIntoView(alignWithTop); | |
678 } | |
679 } | |
680 | |
681 void $dom_scrollIntoViewIfNeeded([bool centerIfNeeded]) { | |
682 if (centerIfNeeded == null) { | |
683 host.$dom_scrollIntoViewIfNeeded(); | |
684 } else { | |
685 host.$dom_scrollIntoViewIfNeeded(centerIfNeeded); | |
686 } | |
687 } | |
688 | |
689 String get regionOverset => host.regionOverset; | |
690 | |
691 List<Range> getRegionFlowRanges() => host.getRegionFlowRanges(); | |
692 | |
693 // TODO(jmesserly): rename "created" to "onCreated". | 310 // TODO(jmesserly): rename "created" to "onCreated". |
694 void onCreated() => created(); | 311 void onCreated() => created(); |
695 | 312 |
696 Stream<Event> get onAbort => host.onAbort; | 313 /** The rest of the [Element] API is handled by [host]. */ |
697 Stream<Event> get onBeforeCopy => host.onBeforeCopy; | 314 dynamic noSuchMethod(Invocation m) => reflect(host).delegate(m); |
698 Stream<Event> get onBeforeCut => host.onBeforeCut; | |
699 Stream<Event> get onBeforePaste => host.onBeforePaste; | |
700 Stream<Event> get onBlur => host.onBlur; | |
701 Stream<Event> get onChange => host.onChange; | |
702 Stream<MouseEvent> get onClick => host.onClick; | |
703 Stream<MouseEvent> get onContextMenu => host.onContextMenu; | |
704 Stream<Event> get onCopy => host.onCopy; | |
705 Stream<Event> get onCut => host.onCut; | |
706 Stream<Event> get onDoubleClick => host.onDoubleClick; | |
707 Stream<MouseEvent> get onDrag => host.onDrag; | |
708 Stream<MouseEvent> get onDragEnd => host.onDragEnd; | |
709 Stream<MouseEvent> get onDragEnter => host.onDragEnter; | |
710 Stream<MouseEvent> get onDragLeave => host.onDragLeave; | |
711 Stream<MouseEvent> get onDragOver => host.onDragOver; | |
712 Stream<MouseEvent> get onDragStart => host.onDragStart; | |
713 Stream<MouseEvent> get onDrop => host.onDrop; | |
714 Stream<Event> get onError => host.onError; | |
715 Stream<Event> get onFocus => host.onFocus; | |
716 Stream<Event> get onInput => host.onInput; | |
717 Stream<Event> get onInvalid => host.onInvalid; | |
718 Stream<KeyboardEvent> get onKeyDown => host.onKeyDown; | |
719 Stream<KeyboardEvent> get onKeyPress => host.onKeyPress; | |
720 Stream<KeyboardEvent> get onKeyUp => host.onKeyUp; | |
721 Stream<Event> get onLoad => host.onLoad; | |
722 Stream<MouseEvent> get onMouseDown => host.onMouseDown; | |
723 Stream<MouseEvent> get onMouseMove => host.onMouseMove; | |
724 Stream<Event> get onFullscreenChange => host.onFullscreenChange; | |
725 Stream<Event> get onFullscreenError => host.onFullscreenError; | |
726 Stream<Event> get onPaste => host.onPaste; | |
727 Stream<Event> get onReset => host.onReset; | |
728 Stream<Event> get onScroll => host.onScroll; | |
729 Stream<Event> get onSearch => host.onSearch; | |
730 Stream<Event> get onSelect => host.onSelect; | |
731 Stream<Event> get onSelectStart => host.onSelectStart; | |
732 Stream<Event> get onSubmit => host.onSubmit; | |
733 Stream<MouseEvent> get onMouseOut => host.onMouseOut; | |
734 Stream<MouseEvent> get onMouseOver => host.onMouseOver; | |
735 Stream<MouseEvent> get onMouseUp => host.onMouseUp; | |
736 Stream<TouchEvent> get onTouchCancel => host.onTouchCancel; | |
737 Stream<TouchEvent> get onTouchEnd => host.onTouchEnd; | |
738 Stream<TouchEvent> get onTouchEnter => host.onTouchEnter; | |
739 Stream<TouchEvent> get onTouchLeave => host.onTouchLeave; | |
740 Stream<TouchEvent> get onTouchMove => host.onTouchMove; | |
741 Stream<TouchEvent> get onTouchStart => host.onTouchStart; | |
742 Stream<TransitionEvent> get onTransitionEnd => host.onTransitionEnd; | |
743 | |
744 // TODO(sigmund): do the normal forwarding when dartbug.com/7919 is fixed. | |
745 Stream<WheelEvent> get onMouseWheel { | |
746 throw new UnsupportedError('onMouseWheel is not supported'); | |
747 } | |
748 } | 315 } |
749 | 316 |
750 /** | 317 /** |
751 * Maps CSS selectors (class and) to a mangled name and maps x-component name | 318 * Maps CSS selectors (class and) to a mangled name and maps x-component name |
752 * to [is='x-component']. | 319 * to [is='x-component']. |
753 */ | 320 */ |
754 class ScopedCssMapper { | 321 class ScopedCssMapper { |
755 final Map<String, String> _mapping; | 322 final Map<String, String> _mapping; |
756 | 323 |
757 ScopedCssMapper(this._mapping); | 324 ScopedCssMapper(this._mapping); |
(...skipping 14 matching lines...) Expand all Loading... |
772 } | 339 } |
773 | 340 |
774 /** | 341 /** |
775 * Set this to true to use native Shadow DOM if it is supported. | 342 * Set this to true to use native Shadow DOM if it is supported. |
776 * Note that this will change behavior of [WebComponent] APIs for tree | 343 * Note that this will change behavior of [WebComponent] APIs for tree |
777 * traversal. | 344 * traversal. |
778 */ | 345 */ |
779 bool useShadowDom = false; | 346 bool useShadowDom = false; |
780 | 347 |
781 bool get _realShadowRoot => useShadowDom && ShadowRoot.supported; | 348 bool get _realShadowRoot => useShadowDom && ShadowRoot.supported; |
OLD | NEW |