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

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 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
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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698