Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 // TODO(jacobr): use Lists.dart to remove some of the duplicated functionality. | 5 // TODO(jacobr): use Lists.dart to remove some of the duplicated functionality. |
| 6 class _ChildrenElementList implements ElementList { | 6 class _ChildrenElementList implements ElementList { |
| 7 // Raw Element. | 7 // Raw Element. |
| 8 final _element; | 8 final _element; |
| 9 final _childElements; | 9 final _childElements; |
| 10 | 10 |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 404 EventListenerList get search() => _get("search"); | 404 EventListenerList get search() => _get("search"); |
| 405 EventListenerList get select() => _get("select"); | 405 EventListenerList get select() => _get("select"); |
| 406 EventListenerList get selectStart() => _get("selectstart"); | 406 EventListenerList get selectStart() => _get("selectstart"); |
| 407 EventListenerList get submit() => _get("submit"); | 407 EventListenerList get submit() => _get("submit"); |
| 408 EventListenerList get touchCancel() => _get("touchcancel"); | 408 EventListenerList get touchCancel() => _get("touchcancel"); |
| 409 EventListenerList get touchEnd() => _get("touchend"); | 409 EventListenerList get touchEnd() => _get("touchend"); |
| 410 EventListenerList get touchLeave() => _get("touchleave"); | 410 EventListenerList get touchLeave() => _get("touchleave"); |
| 411 EventListenerList get touchMove() => _get("touchmove"); | 411 EventListenerList get touchMove() => _get("touchmove"); |
| 412 EventListenerList get touchStart() => _get("touchstart"); | 412 EventListenerList get touchStart() => _get("touchstart"); |
| 413 EventListenerList get transitionEnd() => _get("webkitTransitionEnd"); | 413 EventListenerList get transitionEnd() => _get("webkitTransitionEnd"); |
| 414 EventListenerList get fullscreenChange() => _get("fullscreenchange"); | 414 EventListenerList get fullscreenChange() => _get("webkitfullscreenchange"); |
| 415 } | |
| 416 | |
| 417 class SimpleClientRect implements ClientRect { | |
| 418 final num left; | |
| 419 final num top; | |
| 420 final num width; | |
| 421 final num height; | |
| 422 num get right() => left + width; | |
| 423 num get bottom() => top + height; | |
| 424 | |
| 425 const SimpleClientRect(this.left, this.top, this.width, this.height); | |
| 426 | |
| 427 bool operator ==(ClientRect other) { | |
| 428 return other !== null && left == other.left && top == other.top | |
| 429 && width == other.width && height == other.height; | |
| 430 } | |
| 431 | |
| 432 String toString() => "($left, $top, $width, $height)"; | |
|
nweiz
2011/10/28 03:58:38
Might we want this to indicate that the object in
Jacob
2011/10/31 22:09:50
Chatted with the rest of the team over here are ou
nweiz
2011/11/01 00:49:22
In my experience, "what is this object I have?" is
Jacob
2011/11/01 02:42:39
Agreed. Lets take that discussion to the style gui
| |
| 433 } | |
| 434 | |
| 435 // TODO(jacobr): we cannot currently be lazy about calculating the client | |
| 436 // rects as we must perform all measurement queries at a safe point to avoid | |
| 437 // triggering unneeded layouts. | |
| 438 /** | |
| 439 * All your element measurement needs in one place | |
| 440 */ | |
| 441 class ElementRectWrappingImplementation implements ElementRect { | |
| 442 final ClientRect client; | |
| 443 final ClientRect offset; | |
| 444 final ClientRect scroll; | |
| 445 | |
| 446 // TODO(jacobr): should we move these outside of ElementRect to avoid the | |
| 447 // overhead of computing them every time even though they are rarely used. | |
| 448 // This should be type dom.ClientRect but that fails on dartium. b/5522629 | |
| 449 final _boundingClientRect; | |
| 450 // an exception due to a dartium bug. | |
| 451 final dom.ClientRectList _clientRects; | |
| 452 | |
| 453 ElementRectWrappingImplementation(dom.HTMLElement element) : | |
| 454 client = new SimpleClientRect(element.clientLeft, | |
| 455 element.clientTop, | |
|
nweiz
2011/10/28 03:58:38
Isn't the correct indentation four spaces farther
Jacob
2011/10/31 22:09:50
fixed the busted indentation.
I did a find and rep
| |
| 456 element.clientWidth, | |
| 457 element.clientHeight), | |
| 458 offset = new SimpleClientRect(element.offsetLeft, | |
| 459 element.offsetTop, | |
| 460 element.offsetWidth, | |
| 461 element.offsetHeight), | |
| 462 scroll = new SimpleClientRect(element.scrollLeft, | |
| 463 element.scrollTop, | |
| 464 element.scrollWidth, | |
| 465 element.scrollHeight), | |
| 466 _boundingClientRect = element.getBoundingClientRect(), | |
| 467 _clientRects = element.getClientRects(); | |
| 468 | |
| 469 ClientRect get bounding() => | |
| 470 LevelDom.wrapClientRect(_boundingClientRect); | |
| 471 | |
| 472 List<ClientRect> get clientRects() { | |
| 473 final out = new List(_clientRects.length); | |
| 474 for (num i = 0; i < _clientRects.length; i++) { | |
| 475 out[i] = LevelDom.wrapClientRect(_clientRects.item(i)); | |
| 476 } | |
| 477 return out; | |
| 478 } | |
| 415 } | 479 } |
| 416 | 480 |
| 417 class ElementWrappingImplementation extends NodeWrappingImplementation implement s Element { | 481 class ElementWrappingImplementation extends NodeWrappingImplementation implement s Element { |
| 482 | |
| 483 static final _START_TAG_REGEXP = const RegExp('<(\\w+)'); | |
| 484 static final _CUSTOM_PARENT_TAG_MAP = const { | |
| 485 'body' : 'html', | |
| 486 'head' : 'html', | |
| 487 'caption' : 'table', | |
| 488 'td': 'tr', | |
| 489 'tbody': 'table', | |
| 490 'colgroup': 'table', | |
| 491 'col' : 'colgroup', | |
| 492 'tr' : 'tbody', | |
| 493 'tbody' : 'table', | |
| 494 'tfoot' : 'table', | |
| 495 'thead' : 'table', | |
| 496 'track' : 'audio', | |
| 497 }; | |
| 418 | 498 |
| 419 factory ElementWrappingImplementation.html(String html) { | 499 factory ElementWrappingImplementation.html(String html) { |
| 420 final temp = dom.document.createElement('div'); | 500 // TODO(jacobr): this method can be made more robust and performant. |
| 501 // 1) Cache the dummy parent elements required to use innerHTML rather than | |
| 502 // creating them every call. | |
| 503 // 2) Verify that the html does not contain leading or trailing text nodes. | |
| 504 // 3) Verify that the html does not contain both <head> and <body> tags. | |
| 505 // 4) Detatch the created element from its dummy parent. | |
| 506 String parentTag = 'div'; | |
| 507 String tag; | |
| 508 final match = _START_TAG_REGEXP.firstMatch(html); | |
| 509 if (null != match) { | |
|
nweiz
2011/10/28 03:58:38
Style nit: match != null here and elsewhere.
Jacob
2011/10/31 22:09:50
null != foo is faster
than foo != null
I agree th
nweiz
2011/11/01 00:49:22
That definitely seems like a problem for the compi
| |
| 510 tag = match.group(1).toLowerCase(); | |
| 511 if (_CUSTOM_PARENT_TAG_MAP.containsKey(tag)) { | |
| 512 parentTag = _CUSTOM_PARENT_TAG_MAP[tag]; | |
| 513 } | |
| 514 } | |
| 515 final temp = dom.document.createElement(parentTag); | |
| 421 temp.innerHTML = html; | 516 temp.innerHTML = html; |
| 422 | 517 |
| 423 if (temp.childElementCount != 1) { | 518 if (temp.childElementCount == 1) { |
| 519 return LevelDom.wrapElement(temp.firstElementChild); | |
| 520 } else if (parentTag == 'html' && temp.childElementCount == 2) { | |
| 521 // Work around for edge case in WebKit and possibly other browsers where | |
| 522 // both body and head elements are created even though the inner html | |
| 523 // only contains a head or body element. | |
| 524 return LevelDom.wrapElement(temp.children.item(tag == 'head' ? 0 : 1)); | |
| 525 } else { | |
| 424 throw 'HTML had ${temp.childElementCount} top level elements but 1 expecte d'; | 526 throw 'HTML had ${temp.childElementCount} top level elements but 1 expecte d'; |
| 425 } | 527 } |
| 426 | |
| 427 return LevelDom.wrapElement(temp.firstElementChild); | |
| 428 } | 528 } |
| 429 | 529 |
| 430 factory ElementWrappingImplementation.tag(String tag) { | 530 factory ElementWrappingImplementation.tag(String tag) { |
| 431 return LevelDom.wrapElement(dom.document.createElement(tag)); | 531 return LevelDom.wrapElement(dom.document.createElement(tag)); |
| 432 } | 532 } |
| 433 | 533 |
| 434 ElementWrappingImplementation._wrap(ptr) : super._wrap(ptr); | 534 ElementWrappingImplementation._wrap(ptr) : super._wrap(ptr); |
| 435 | 535 |
| 436 ElementAttributeMap _elementAttributeMap; | 536 ElementAttributeMap _elementAttributeMap; |
| 437 ElementList _elements; | 537 ElementList _elements; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 } | 589 } |
| 490 | 590 |
| 491 void set dataAttributes(Map<String, String> value) { | 591 void set dataAttributes(Map<String, String> value) { |
| 492 Map<String, String> dataAttributes = this.dataAttributes; | 592 Map<String, String> dataAttributes = this.dataAttributes; |
| 493 dataAttributes.clear(); | 593 dataAttributes.clear(); |
| 494 for (String key in value.getKeys()) { | 594 for (String key in value.getKeys()) { |
| 495 dataAttributes[key] = value[key]; | 595 dataAttributes[key] = value[key]; |
| 496 } | 596 } |
| 497 } | 597 } |
| 498 | 598 |
| 499 int get clientHeight() => _ptr.clientHeight; | |
| 500 | |
| 501 int get clientLeft() => _ptr.clientLeft; | |
| 502 | |
| 503 int get clientTop() => _ptr.clientTop; | |
| 504 | |
| 505 int get clientWidth() => _ptr.clientWidth; | |
| 506 | |
| 507 String get contentEditable() => _ptr.contentEditable; | 599 String get contentEditable() => _ptr.contentEditable; |
| 508 | 600 |
| 509 void set contentEditable(String value) { _ptr.contentEditable = value; } | 601 void set contentEditable(String value) { _ptr.contentEditable = value; } |
| 510 | 602 |
| 511 String get dir() => _ptr.dir; | 603 String get dir() => _ptr.dir; |
| 512 | 604 |
| 513 void set dir(String value) { _ptr.dir = value; } | 605 void set dir(String value) { _ptr.dir = value; } |
| 514 | 606 |
| 515 bool get draggable() => _ptr.draggable; | 607 bool get draggable() => _ptr.draggable; |
| 516 | 608 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 533 bool get isContentEditable() => _ptr.isContentEditable; | 625 bool get isContentEditable() => _ptr.isContentEditable; |
| 534 | 626 |
| 535 String get lang() => _ptr.lang; | 627 String get lang() => _ptr.lang; |
| 536 | 628 |
| 537 void set lang(String value) { _ptr.lang = value; } | 629 void set lang(String value) { _ptr.lang = value; } |
| 538 | 630 |
| 539 Element get lastElementChild() => LevelDom.wrapElement(_ptr.lastElementChild); | 631 Element get lastElementChild() => LevelDom.wrapElement(_ptr.lastElementChild); |
| 540 | 632 |
| 541 Element get nextElementSibling() => LevelDom.wrapElement(_ptr.nextElementSibli ng); | 633 Element get nextElementSibling() => LevelDom.wrapElement(_ptr.nextElementSibli ng); |
| 542 | 634 |
| 543 int get offsetHeight() => _ptr.offsetHeight; | |
| 544 | |
| 545 int get offsetLeft() => _ptr.offsetLeft; | |
| 546 | |
| 547 Element get offsetParent() => LevelDom.wrapElement(_ptr.offsetParent); | 635 Element get offsetParent() => LevelDom.wrapElement(_ptr.offsetParent); |
| 548 | 636 |
| 549 int get offsetTop() => _ptr.offsetTop; | |
| 550 | |
| 551 int get offsetWidth() => _ptr.offsetWidth; | |
| 552 | |
| 553 String get outerHTML() => _ptr.outerHTML; | 637 String get outerHTML() => _ptr.outerHTML; |
| 554 | 638 |
| 555 Element get previousElementSibling() => LevelDom.wrapElement(_ptr.previousElem entSibling); | 639 Element get previousElementSibling() => LevelDom.wrapElement(_ptr.previousElem entSibling); |
| 556 | 640 |
| 557 int get scrollHeight() => _ptr.scrollHeight; | |
| 558 | |
| 559 int get scrollLeft() => _ptr.scrollLeft; | |
| 560 | |
| 561 void set scrollLeft(int value) { _ptr.scrollLeft = value; } | |
| 562 | |
| 563 int get scrollTop() => _ptr.scrollTop; | |
| 564 | |
| 565 void set scrollTop(int value) { _ptr.scrollTop = value; } | |
| 566 | |
| 567 int get scrollWidth() => _ptr.scrollWidth; | |
| 568 | |
| 569 bool get spellcheck() => _ptr.spellcheck; | 641 bool get spellcheck() => _ptr.spellcheck; |
| 570 | 642 |
| 571 void set spellcheck(bool value) { _ptr.spellcheck = value; } | 643 void set spellcheck(bool value) { _ptr.spellcheck = value; } |
| 572 | 644 |
| 573 CSSStyleDeclaration get style() => LevelDom.wrapCSSStyleDeclaration(_ptr.style ); | 645 CSSStyleDeclaration get style() => LevelDom.wrapCSSStyleDeclaration(_ptr.style ); |
| 574 | 646 |
| 575 int get tabIndex() => _ptr.tabIndex; | 647 int get tabIndex() => _ptr.tabIndex; |
| 576 | 648 |
| 577 void set tabIndex(int value) { _ptr.tabIndex = value; } | 649 void set tabIndex(int value) { _ptr.tabIndex = value; } |
| 578 | 650 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 591 } | 663 } |
| 592 | 664 |
| 593 bool contains(Node element) { | 665 bool contains(Node element) { |
| 594 return _ptr.contains(LevelDom.unwrap(element)); | 666 return _ptr.contains(LevelDom.unwrap(element)); |
| 595 } | 667 } |
| 596 | 668 |
| 597 void focus() { | 669 void focus() { |
| 598 _ptr.focus(); | 670 _ptr.focus(); |
| 599 } | 671 } |
| 600 | 672 |
| 601 ClientRect getBoundingClientRect() { | |
| 602 return LevelDom.wrapClientRect(_ptr.getBoundingClientRect()); | |
| 603 } | |
| 604 | |
| 605 List<ClientRect> getClientRects() { | |
| 606 var rects = _ptr.getClientRects(); | |
| 607 var out = new List(rects.length); | |
| 608 for (var i = 0; i < rects.length; i++) { | |
| 609 out.add(LevelDom.wrapClientRect(rects.item(i))); | |
| 610 } | |
| 611 return out; | |
| 612 } | |
| 613 | |
| 614 Element insertAdjacentElement([String where = null, Element element = null]) { | 673 Element insertAdjacentElement([String where = null, Element element = null]) { |
| 615 return LevelDom.wrapElement(_ptr.insertAdjacentElement(where, LevelDom.unwra p(element))); | 674 return LevelDom.wrapElement(_ptr.insertAdjacentElement(where, LevelDom.unwra p(element))); |
| 616 } | 675 } |
| 617 | 676 |
| 618 void insertAdjacentHTML([String position_OR_where = null, String text = null]) { | 677 void insertAdjacentHTML([String position_OR_where = null, String text = null]) { |
| 619 _ptr.insertAdjacentHTML(position_OR_where, text); | 678 _ptr.insertAdjacentHTML(position_OR_where, text); |
| 620 } | 679 } |
| 621 | 680 |
| 622 void insertAdjacentText([String where = null, String text = null]) { | 681 void insertAdjacentText([String where = null, String text = null]) { |
| 623 _ptr.insertAdjacentText(where, text); | 682 _ptr.insertAdjacentText(where, text); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 642 } | 701 } |
| 643 | 702 |
| 644 void scrollIntoView([bool centerIfNeeded = null]) { | 703 void scrollIntoView([bool centerIfNeeded = null]) { |
| 645 _ptr.scrollIntoViewIfNeeded(centerIfNeeded); | 704 _ptr.scrollIntoViewIfNeeded(centerIfNeeded); |
| 646 } | 705 } |
| 647 | 706 |
| 648 bool matchesSelector([String selectors = null]) { | 707 bool matchesSelector([String selectors = null]) { |
| 649 return _ptr.webkitMatchesSelector(selectors); | 708 return _ptr.webkitMatchesSelector(selectors); |
| 650 } | 709 } |
| 651 | 710 |
| 711 void set scrollLeft(int value) { _ptr.scrollLeft = value; } | |
| 712 | |
| 713 void set scrollTop(int value) { _ptr.scrollTop = value; } | |
| 714 | |
| 715 Future<ElementRect> get rect() { | |
| 716 return _createMeasurementFuture( | |
| 717 () => new ElementRectWrappingImplementation(_ptr), | |
| 718 new Completer<ElementRect>()); | |
| 719 } | |
| 720 | |
| 721 Future<CSSStyleDeclaration> get computedStyle() { | |
| 722 // TODO(jacobr): last param should be null, see b/5045788 | |
| 723 return getComputedStyle(''); | |
| 724 } | |
| 725 | |
| 726 Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) { | |
| 727 return _createMeasurementFuture(() => | |
| 728 LevelDom.wrapCSSStyleDeclaration( | |
| 729 dom.window.getComputedStyle(_ptr, pseudoElement)), | |
| 730 new Completer<CSSStyleDeclaration>()); | |
| 731 } | |
| 732 | |
| 652 ElementEvents get on() { | 733 ElementEvents get on() { |
| 653 if (_on === null) { | 734 if (_on === null) { |
| 654 _on = new ElementEventsImplementation._wrap(_ptr); | 735 _on = new ElementEventsImplementation._wrap(_ptr); |
| 655 } | 736 } |
| 656 return _on; | 737 return _on; |
| 657 } | 738 } |
| 658 } | 739 } |
| OLD | NEW |