Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: client/html/src/ElementWrappingImplementation.dart

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

Powered by Google App Engine
This is Rietveld 408576698