// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of $LIBRARYNAME;

class _ChildrenElementList extends ListBase<Element>
    implements NodeListWrapper {
  // Raw Element.
  final Element _element;
  final HtmlCollection _childElements;

  _ChildrenElementList._wrap(Element element)
    : _childElements = element._children,
      _element = element;

  bool contains(Object element) => _childElements.contains(element);


  bool get isEmpty {
    return _element._firstElementChild == null;
  }

  int get length {
    return _childElements.length;
  }

  Element operator [](int index) {
    return _childElements[index];
  }

  void operator []=(int index, Element value) {
    _element._replaceChild(value, _childElements[index]);
  }

  void set length(int newLength) {
    // TODO(jacobr): remove children when length is reduced.
    throw new UnsupportedError('Cannot resize element lists');
  }

  Element add(Element value) {
    _element.append(value);
    return value;
  }

  Iterator<Element> get iterator => toList().iterator;

  void addAll(Iterable<Element> iterable) {
    if (iterable is _ChildNodeListLazy) {
      iterable = new List.from(iterable);
    }

    for (Element element in iterable) {
      _element.append(element);
    }
  }

  void sort([int compare(Element a, Element b)]) {
    throw new UnsupportedError('Cannot sort element lists');
  }

  void shuffle([Random random]) {
    throw new UnsupportedError('Cannot shuffle element lists');
  }

  void removeWhere(bool test(Element element)) {
    _filter(test, false);
  }

  void retainWhere(bool test(Element element)) {
    _filter(test, true);
  }

  void _filter(bool test(var element), bool retainMatching) {
    var removed;
    if (retainMatching) {
      removed = _element.children.where((e) => !test(e));
    } else {
      removed = _element.children.where(test);
    }
    for (var e in removed) e.remove();
  }

  void setRange(int start, int end, Iterable<Element> iterable,
                [int skipCount = 0]) {
    throw new UnimplementedError();
  }

  void replaceRange(int start, int end, Iterable<Element> iterable) {
    throw new UnimplementedError();
  }

  void fillRange(int start, int end, [Element fillValue]) {
    throw new UnimplementedError();
  }

  bool remove(Object object) {
    if (object is Element) {
      Element element = object;
      if (identical(element.parentNode, _element)) {
        _element._removeChild(element);
        return true;
      }
    }
    return false;
  }

  void insert(int index, Element element) {
    if (index < 0 || index > length) {
      throw new RangeError.range(index, 0, length);
    }
    if (index == length) {
      _element.append(element);
    } else {
      _element.insertBefore(element, this[index]);
    }
  }

  void setAll(int index, Iterable<Element> iterable) {
    throw new UnimplementedError();
  }

  void clear() {
    _element._clearChildren();
  }

  Element removeAt(int index) {
    final result = this[index];
    if (result != null) {
      _element._removeChild(result);
    }
    return result;
  }

  Element removeLast() {
    final result = this.last;
    if (result != null) {
      _element._removeChild(result);
    }
    return result;
  }

  Element get first {
    Element result = _element._firstElementChild;
    if (result == null) throw new StateError("No elements");
    return result;
  }


  Element get last {
    Element result = _element._lastElementChild;
    if (result == null) throw new StateError("No elements");
    return result;
  }

  Element get single {
    if (length > 1) throw new StateError("More than one element");
    return first;
  }

  List<Node> get rawList => _childElements;
}

/**
 * An immutable list containing HTML elements. This list contains some
 * additional methods when compared to regular lists for ease of CSS
 * manipulation on a group of elements.
 */
abstract class ElementList<T extends Element> extends ListBase<T> {
  /**
   * The union of all CSS classes applied to the elements in this list.
   *
   * This set makes it easy to add, remove or toggle (add if not present, remove
   * if present) the classes applied to a collection of elements.
   *
   *     htmlList.classes.add('selected');
   *     htmlList.classes.toggle('isOnline');
   *     htmlList.classes.remove('selected');
   */
  CssClassSet get classes;

  /** Replace the classes with `value` for every element in this list. */
  set classes(Iterable<String> value);

  /**
   * Access the union of all [CssStyleDeclaration]s that are associated with an
   * [ElementList].
   *
   * Grouping the style objects all together provides easy editing of specific
   * properties of a collection of elements. Setting a specific property value
   * will set that property in all [Element]s in the [ElementList]. Getting a
   * specific property value will return the value of the property of the first
   * element in the [ElementList].
   */
  CssStyleDeclarationBase get style;

  /**
   * Access dimensions and position of the Elements in this list.
   *
   * Setting the height or width properties will set the height or width
   * property for all elements in the list. This returns a rectangle with the
   * dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Getting the height or width returns the height or width of the
   * first Element in this list.
   *
   * Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not.
   */
  @Experimental()
  CssRect get contentEdge;

  /**
   * Access dimensions and position of the first Element's content + padding box
   * in this list.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not. This
   * can be used to retrieve jQuery's `innerHeight` value for an element. This
   * is also a rectangle equalling the dimensions of clientHeight and
   * clientWidth.
   */
  @Experimental()
  CssRect get paddingEdge;

  /**
   * Access dimensions and position of the first Element's content + padding +
   * border box in this list.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not. This
   * can be used to retrieve jQuery's `outerHeight` value for an element.
   */
  @Experimental()
  CssRect get borderEdge;

  /**
   * Access dimensions and position of the first Element's content + padding +
   * border + margin box in this list.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not. This
   * can be used to retrieve jQuery's `outerHeight` value for an element.
   */
  @Experimental()
  CssRect get marginEdge;
$!STREAM_GETTER_SIGNATURES
}

// TODO(jacobr): this is an inefficient implementation but it is hard to see
// a better option given that we cannot quite force NodeList to be an
// ElementList as there are valid cases where a NodeList JavaScript object
// contains Node objects that are not Elements.
class _FrozenElementList<T extends Element> extends ListBase<T>
    implements ElementList<T>, NodeListWrapper {
  final List<Node> _nodeList;
  // The subset of _nodeList that are Elements.
  List<Element> _elementList;

  _FrozenElementList._wrap(this._nodeList) {
    _elementList = _nodeList.where((e) => e is Element).toList();
  }

  int get length => _nodeList.length;

  Element operator [](int index) => _nodeList[index];

  void operator []=(int index, Element value) {
    throw new UnsupportedError('Cannot modify list');
  }

  void set length(int newLength) {
    throw new UnsupportedError('Cannot modify list');
  }

  void sort([Comparator<Element> compare]) {
    throw new UnsupportedError('Cannot sort list');
  }

  void shuffle([Random random]) {
    throw new UnsupportedError('Cannot shuffle list');
  }

  Element get first => _nodeList.first;

  Element get last => _nodeList.last;

  Element get single => _nodeList.single;

  CssClassSet get classes => new _MultiElementCssClassSet(_elementList);

  CssStyleDeclarationBase get style =>
      new _CssStyleDeclarationSet(_elementList);

  void set classes(Iterable<String> value) {
    _elementList.forEach((e) => e.classes = value);
  }

  CssRect get contentEdge => new _ContentCssListRect(_elementList);

  CssRect get paddingEdge => _elementList.first.paddingEdge;

  CssRect get borderEdge => _elementList.first.borderEdge;

  CssRect get marginEdge => _elementList.first.marginEdge;

  List<Node> get rawList => _nodeList;

$!ELEMENT_STREAM_GETTERS
}

@DocsEditable()
$(ANNOTATIONS)abstract class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {

  /**
   * Creates an HTML element from a valid fragment of HTML.
   *
   *     var element = new Element.html('<div class="foo">content</div>');
   *
   * The HTML fragment should contain only one single root element, any
   * leading or trailing text nodes will be removed.
   *
   * The HTML fragment is parsed as if it occurred within the context of a
   * `<body>` tag, this means that special elements such as `<caption>` which
   * must be parsed within the scope of a `<table>` element will be dropped. Use
   * [createFragment] to parse contextual HTML fragments.
   *
   * Unless a validator is provided this will perform the default validation
   * and remove all scriptable elements and attributes.
   *
   * See also:
   *
   * * [NodeValidator]
   *
   */
  factory Element.html(String html,
      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
    var fragment = document.body.createFragment(html, validator: validator,
        treeSanitizer: treeSanitizer);

    return fragment.nodes.where((e) => e is Element).single;
  }

  /**
   * Custom element creation constructor.
   *
   * This constructor is used by the DOM when a custom element has been
   * created. It can only be invoked by subclasses of Element from
   * that classes created constructor.
   *
   *     class CustomElement extends Element {
   *       factory CustomElement() => new Element.tag('x-custom');
   *
   *       CustomElement.created() : super.created() {
   *          // Perform any element initialization.
   *       }
   *     }
   *     document.register('x-custom', CustomElement);
   */
  Element.created() : super._created() {
    // Validate that this is a custom element & perform any additional
    // initialization.
    _initializeCustomElement(this);
  }

  /**
   * Creates the HTML element specified by the tag name.
   *
   * This is similar to [Document.createElement].
   * [tag] should be a valid HTML tag name. If [tag] is an unknown tag then
   * this will create an [UnknownElement].
   *
   *     var divElement = new Element.tag('div');
   *     print(divElement is DivElement); // 'true'
   *     var myElement = new Element.tag('unknownTag');
   *     print(myElement is UnknownElement); // 'true'
   *
   * For standard elements it is more preferable to use the type constructors:
   *     var element = new DivElement();
   *
   * See also:
   *
   * * [isTagSupported]
   */
  factory $CLASSNAME.tag(String tag, [String typeExtention]) =>
      _$(CLASSNAME)FactoryProvider.createElement_tag(tag, typeExtention);

  /// Creates a new `<a>` element.
  ///
  /// This is identical to calling `new Element.tag('a')`.
  factory Element.a() => new Element.tag('a');

  /// Creates a new `<article>` element.
  ///
  /// This is identical to calling `new Element.tag('article')`.
  factory Element.article() => new Element.tag('article');

  /// Creates a new `<aside>` element.
  ///
  /// This is identical to calling `new Element.tag('aside')`.
  factory Element.aside() => new Element.tag('aside');

  /// Creates a new `<audio>` element.
  ///
  /// This is identical to calling `new Element.tag('audio')`.
  factory Element.audio() => new Element.tag('audio');

  /// Creates a new `<br>` element.
  ///
  /// This is identical to calling `new Element.tag('br')`.
  factory Element.br() => new Element.tag('br');

  /// Creates a new `<canvas>` element.
  ///
  /// This is identical to calling `new Element.tag('canvas')`.
  factory Element.canvas() => new Element.tag('canvas');

  /// Creates a new `<div>` element.
  ///
  /// This is identical to calling `new Element.tag('div')`.
  factory Element.div() => new Element.tag('div');

  /// Creates a new `<footer>` element.
  ///
  /// This is identical to calling `new Element.tag('footer')`.
  factory Element.footer() => new Element.tag('footer');

  /// Creates a new `<header>` element.
  ///
  /// This is identical to calling `new Element.tag('header')`.
  factory Element.header() => new Element.tag('header');

  /// Creates a new `<hr>` element.
  ///
  /// This is identical to calling `new Element.tag('hr')`.
  factory Element.hr() => new Element.tag('hr');

  /// Creates a new `<iframe>` element.
  ///
  /// This is identical to calling `new Element.tag('iframe')`.
  factory Element.iframe() => new Element.tag('iframe');

  /// Creates a new `<img>` element.
  ///
  /// This is identical to calling `new Element.tag('img')`.
  factory Element.img() => new Element.tag('img');

  /// Creates a new `<li>` element.
  ///
  /// This is identical to calling `new Element.tag('li')`.
  factory Element.li() => new Element.tag('li');

  /// Creates a new `<nav>` element.
  ///
  /// This is identical to calling `new Element.tag('nav')`.
  factory Element.nav() => new Element.tag('nav');

  /// Creates a new `<ol>` element.
  ///
  /// This is identical to calling `new Element.tag('ol')`.
  factory Element.ol() => new Element.tag('ol');

  /// Creates a new `<option>` element.
  ///
  /// This is identical to calling `new Element.tag('option')`.
  factory Element.option() => new Element.tag('option');

  /// Creates a new `<p>` element.
  ///
  /// This is identical to calling `new Element.tag('p')`.
  factory Element.p() => new Element.tag('p');

  /// Creates a new `<pre>` element.
  ///
  /// This is identical to calling `new Element.tag('pre')`.
  factory Element.pre() => new Element.tag('pre');

  /// Creates a new `<section>` element.
  ///
  /// This is identical to calling `new Element.tag('section')`.
  factory Element.section() => new Element.tag('section');

  /// Creates a new `<select>` element.
  ///
  /// This is identical to calling `new Element.tag('select')`.
  factory Element.select() => new Element.tag('select');

  /// Creates a new `<span>` element.
  ///
  /// This is identical to calling `new Element.tag('span')`.
  factory Element.span() => new Element.tag('span');

  /// Creates a new `<svg>` element.
  ///
  /// This is identical to calling `new Element.tag('svg')`.
  factory Element.svg() => new Element.tag('svg');

  /// Creates a new `<table>` element.
  ///
  /// This is identical to calling `new Element.tag('table')`.
  factory Element.table() => new Element.tag('table');

  /// Creates a new `<td>` element.
  ///
  /// This is identical to calling `new Element.tag('td')`.
  factory Element.td() => new Element.tag('td');

  /// Creates a new `<textarea>` element.
  ///
  /// This is identical to calling `new Element.tag('textarea')`.
  factory Element.textarea() => new Element.tag('textarea');

  /// Creates a new `<th>` element.
  ///
  /// This is identical to calling `new Element.tag('th')`.
  factory Element.th() => new Element.tag('th');

  /// Creates a new `<tr>` element.
  ///
  /// This is identical to calling `new Element.tag('tr')`.
  factory Element.tr() => new Element.tag('tr');

  /// Creates a new `<ul>` element.
  ///
  /// This is identical to calling `new Element.tag('ul')`.
  factory Element.ul() => new Element.tag('ul');

  /// Creates a new `<video>` element.
  ///
  /// This is identical to calling `new Element.tag('video')`.
  factory Element.video() => new Element.tag('video');

  /**
   * All attributes on this element.
   *
   * Any modifications to the attribute map will automatically be applied to
   * this element.
   *
   * This only includes attributes which are not in a namespace
   * (such as 'xlink:href'), additional attributes can be accessed via
   * [getNamespacedAttributes].
   */
  Map<String, String> get attributes => new _ElementAttributeMap(this);

  void set attributes(Map<String, String> value) {
    Map<String, String> attributes = this.attributes;
    attributes.clear();
    for (String key in value.keys) {
      attributes[key] = value[key];
    }
  }

  /**
   * List of the direct children of this element.
   *
   * This collection can be used to add and remove elements from the document.
   *
   *     var item = new DivElement();
   *     item.text = 'Something';
   *     document.body.children.add(item) // Item is now displayed on the page.
   *     for (var element in document.body.children) {
   *       element.style.background = 'red'; // Turns every child of body red.
   *     }
   */
  List<Element> get children => new _ChildrenElementList._wrap(this);

  void set children(List<Element> value) {
    // Copy list first since we don't want liveness during iteration.
    List copy = new List.from(value);
    var children = this.children;
    children.clear();
    children.addAll(copy);
  }

  /**
   * Finds all descendent elements of this element that match the specified
   * group of selectors.
   *
   * [selectors] should be a string using CSS selector syntax.
   *
   *     var items = element.querySelectorAll('.itemClassName');
   *
   * For details about CSS selector syntax, see the
   * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
   */
  @DomName('Element.querySelectorAll')
  ElementList querySelectorAll(String selectors) =>
    new _FrozenElementList._wrap(_querySelectorAll(selectors));

  /**
   * Alias for [querySelector]. Note this function is deprecated because its
   * semantics will be changing in the future.
   */
  @deprecated
  @DomName('Element.querySelector')
  @Experimental()
  Element query(String relativeSelectors) => querySelector(relativeSelectors);

  /**
   * Alias for [querySelectorAll]. Note this function is deprecated because its
   * semantics will be changing in the future.
   */
  @deprecated
  @DomName('Element.querySelectorAll')
  @Experimental()
  ElementList queryAll(String relativeSelectors) =>
      querySelectorAll(relativeSelectors);

  /**
   * The set of CSS classes applied to this element.
   *
   * This set makes it easy to add, remove or toggle the classes applied to
   * this element.
   *
   *     element.classes.add('selected');
   *     element.classes.toggle('isOnline');
   *     element.classes.remove('selected');
   */
  CssClassSet get classes => new _ElementCssClassSet(this);

  void set classes(Iterable<String> value) {
    CssClassSet classSet = classes;
    classSet.clear();
    classSet.addAll(value);
  }

  /**
   * Allows access to all custom data attributes (data-*) set on this element.
   *
   * The keys for the map must follow these rules:
   *
   * * The name must not begin with 'xml'.
   * * The name cannot contain a semi-colon (';').
   * * The name cannot contain any capital letters.
   *
   * Any keys from markup will be converted to camel-cased keys in the map.
   *
   * For example, HTML specified as:
   *
   *     <div data-my-random-value='value'></div>
   *
   * Would be accessed in Dart as:
   *
   *     var value = element.dataset['myRandomValue'];
   *
   * See also:
   *
   * * [Custom data attributes](http://www.w3.org/TR/html5/global-attributes.html#custom-data-attribute)
   */
  Map<String, String> get dataset =>
    new _DataAttributeMap(attributes);

  void set dataset(Map<String, String> value) {
    final data = this.dataset;
    data.clear();
    for (String key in value.keys) {
      data[key] = value[key];
    }
  }

  /**
   * Gets a map for manipulating the attributes of a particular namespace.
   *
   * This is primarily useful for SVG attributes such as xref:link.
   */
  Map<String, String> getNamespacedAttributes(String namespace) {
    return new _NamespacedAttributeMap(this, namespace);
  }

  /**
   * The set of all CSS values applied to this element, including inherited
   * and default values.
   *
   * The computedStyle contains values that are inherited from other
   * sources, such as parent elements or stylesheets. This differs from the
   * [style] property, which contains only the values specified directly on this
   * element.
   *
   * PseudoElement can be values such as `::after`, `::before`, `::marker`,
   * `::line-marker`.
   *
   * See also:
   *
   * * [CSS Inheritance and Cascade](http://docs.webplatform.org/wiki/tutorials/inheritance_and_cascade)
   * * [Pseudo-elements](http://docs.webplatform.org/wiki/css/selectors/pseudo-elements)
   */
  CssStyleDeclaration getComputedStyle([String pseudoElement]) {
    if (pseudoElement == null) {
      pseudoElement = '';
    }
    // TODO(jacobr): last param should be null, see b/5045788
    return window._getComputedStyle(this, pseudoElement);
  }

  /**
   * Gets the position of this element relative to the client area of the page.
   */
  Rectangle get client => new Rectangle(clientLeft, clientTop, clientWidth,
      clientHeight);

  /**
   * Gets the offset of this element relative to its offsetParent.
   */
  Rectangle get offset => new Rectangle(offsetLeft, offsetTop, offsetWidth,
      offsetHeight);

  /**
   * Adds the specified text after the last child of this element.
   */
  void appendText(String text) {
    this.insertAdjacentText('beforeend', text);
  }

  /**
   * Parses the specified text as HTML and adds the resulting node after the
   * last child of this element.
   */
  void appendHtml(String text) {
    this.insertAdjacentHtml('beforeend', text);
  }

  /**
   * Checks to see if the tag name is supported by the current platform.
   *
   * The tag should be a valid HTML tag name.
   */
  static bool isTagSupported(String tag) {
    var e = _ElementFactoryProvider.createElement_tag(tag, null);
    return e is Element && !(e is UnknownElement);
  }

  /**
   * Called by the DOM when this element has been inserted into the live
   * document.
   */
  @Experimental()
  void enteredView() {}

  /**
   * Called by the DOM when this element has been removed from the live
   * document.
   */
  @Experimental()
  void leftView() {}

  /**
   * Called by the DOM whenever an attribute on this has been changed.
   */
  void attributeChanged(String name, String oldValue, String newValue) {}

  // Hooks to support custom WebComponents.

$if DART2JS
  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
$endif
  Element _xtag;

  /**
   * Experimental support for [web components][wc]. This field stores a
   * reference to the component implementation. It was inspired by Mozilla's
   * [x-tags][] project. Please note: in the future it may be possible to
   * `extend Element` from your class, in which case this field will be
   * deprecated.
   *
   * If xtag has not been set, it will simply return `this` [Element].
   *
   * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
   * [x-tags]: http://x-tags.org/
   */
  // Note: return type is `dynamic` for convenience to suppress warnings when
  // members of the component are used. The actual type is a subtype of Element.
  get xtag => _xtag != null ? _xtag : this;

  void set xtag(Element value) {
    _xtag = value;
  }

  @DomName('Element.localName')
  @DocsEditable()
  String get localName => _localName;

  /**
   * A URI that identifies the XML namespace of this element.
   *
   * `null` if no namespace URI is specified.
   *
   * ## Other resources
   *
   * * [Node.namespaceURI]
   * (http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-NodeNSname) from W3C.
   */
  @DomName('Element.namespaceUri')
  String get namespaceUri => _namespaceUri;

  /**
   * The string representation of this element.
   *
   * This is equivalent to reading the [localName] property.
   */
  String toString() => localName;

  /**
   * Scrolls this element into view.
   *
   * Only one of of the alignment options may be specified at a time.
   *
   * If no options are specified then this will attempt to scroll the minimum
   * amount needed to bring the element into view.
   *
   * Note that alignCenter is currently only supported on WebKit platforms. If
   * alignCenter is specified but not supported then this will fall back to
   * alignTop.
   *
   * See also:
   *
   * * [scrollIntoView](http://docs.webplatform.org/wiki/dom/methods/scrollIntoView)
   * * [scrollIntoViewIfNeeded](http://docs.webplatform.org/wiki/dom/methods/scrollIntoViewIfNeeded)
   */
  void scrollIntoView([ScrollAlignment alignment]) {
    var hasScrollIntoViewIfNeeded = true;
$if DART2JS
    hasScrollIntoViewIfNeeded =
        JS('bool', '!!(#.scrollIntoViewIfNeeded)', this);
$endif
    if (alignment == ScrollAlignment.TOP) {
      this._scrollIntoView(true);
    } else if (alignment == ScrollAlignment.BOTTOM) {
      this._scrollIntoView(false);
    } else if (hasScrollIntoViewIfNeeded) {
      if (alignment == ScrollAlignment.CENTER) {
        this._scrollIntoViewIfNeeded(true);
      } else {
        this._scrollIntoViewIfNeeded();
      }
    } else {
      this._scrollIntoView();
    }
  }

$if DART2JS
  /**
   * Static factory designed to expose `mousewheel` events to event
   * handlers that are not necessarily instances of [Element].
   *
   * See [EventStreamProvider] for usage information.
   */
  @DomName('Element.mouseWheelEvent')
  static const EventStreamProvider<WheelEvent> mouseWheelEvent =
      const _CustomEventStreamProvider<WheelEvent>(
        Element._determineMouseWheelEventType);

  static String _determineMouseWheelEventType(EventTarget e) {
    if (JS('bool', '#.onwheel !== undefined', e)) {
      // W3C spec, and should be IE9+, but IE has a bug exposing onwheel.
      return 'wheel';
    } else if (JS('bool', '#.onmousewheel !== undefined', e)) {
      // Chrome & IE
      return 'mousewheel';
    } else {
      // Firefox
      return 'DOMMouseScroll';
    }
  }

  /**
   * Static factory designed to expose `transitionend` events to event
   * handlers that are not necessarily instances of [Element].
   *
   * See [EventStreamProvider] for usage information.
   */
  @DomName('Element.transitionEndEvent')
  static const EventStreamProvider<TransitionEvent> transitionEndEvent =
      const _CustomEventStreamProvider<TransitionEvent>(
        Element._determineTransitionEventType);

  static String _determineTransitionEventType(EventTarget e) {
    // Unfortunately the normal 'ontransitionend' style checks don't work here.
    if (Device.isWebKit) {
      return 'webkitTransitionEnd';
    } else if (Device.isOpera) {
      return 'oTransitionEnd';
    }
    return 'transitionend';
  }
  /**
   * Inserts text into the DOM at the specified location.
   *
   * To see the possible values for [where], read the doc for
   * [insertAdjacentHtml].
   *
   * See also:
   *
   * * [insertAdjacentHtml]
   */
  void insertAdjacentText(String where, String text) {
    if (JS('bool', '!!#.insertAdjacentText', this)) {
      _insertAdjacentText(where, text);
    } else {
      _insertAdjacentNode(where, new Text(text));
    }
  }

  @JSName('insertAdjacentText')
  void _insertAdjacentText(String where, String text) native;

  /**
   * Parses text as an HTML fragment and inserts it into the DOM at the
   * specified location.
   *
   * The [where] parameter indicates where to insert the HTML fragment:
   *
   * * 'beforeBegin': Immediately before this element.
   * * 'afterBegin': As the first child of this element.
   * * 'beforeEnd': As the last child of this element.
   * * 'afterEnd': Immediately after this element.
   *
   *     var html = '<div class="something">content</div>';
   *     // Inserts as the first child
   *     document.body.insertAdjacentHtml('afterBegin', html);
   *     var createdElement = document.body.children[0];
   *     print(createdElement.classes[0]); // Prints 'something'
   *
   * See also:
   *
   * * [insertAdjacentText]
   * * [insertAdjacentElement]
   */
  void insertAdjacentHtml(String where, String html) {
    if (JS('bool', '!!#.insertAdjacentHTML', this)) {
      _insertAdjacentHtml(where, html);
    } else {
      _insertAdjacentNode(where, new DocumentFragment.html(html));
    }
  }

  @JSName('insertAdjacentHTML')
  void _insertAdjacentHtml(String where, String text) native;

  /**
   * Inserts [element] into the DOM at the specified location.
   *
   * To see the possible values for [where], read the doc for
   * [insertAdjacentHtml].
   *
   * See also:
   *
   * * [insertAdjacentHtml]
   */
  Element insertAdjacentElement(String where, Element element) {
    if (JS('bool', '!!#.insertAdjacentElement', this)) {
      _insertAdjacentElement(where, element);
    } else {
      _insertAdjacentNode(where, element);
    }
    return element;
  }

  @JSName('insertAdjacentElement')
  void _insertAdjacentElement(String where, Element element) native;

  void _insertAdjacentNode(String where, Node node) {
    switch (where.toLowerCase()) {
      case 'beforebegin':
        this.parentNode.insertBefore(node, this);
        break;
      case 'afterbegin':
        var first = this.nodes.length > 0 ? this.nodes[0] : null;
        this.insertBefore(node, first);
        break;
      case 'beforeend':
        this.append(node);
        break;
      case 'afterend':
        this.parentNode.insertBefore(node, this.nextNode);
        break;
      default:
        throw new ArgumentError("Invalid position ${where}");
    }
  }

  /**
   * Checks if this element matches the CSS selectors.
   */
  @Experimental()
  bool matches(String selectors) {
    if (JS('bool', '!!#.matches', this)) {
      return JS('bool', '#.matches(#)', this, selectors);
    } else if (JS('bool', '!!#.webkitMatchesSelector', this)) {
      return JS('bool', '#.webkitMatchesSelector(#)', this, selectors);
    } else if (JS('bool', '!!#.mozMatchesSelector', this)) {
      return JS('bool', '#.mozMatchesSelector(#)', this, selectors);
    } else if (JS('bool', '!!#.msMatchesSelector', this)) {
      return JS('bool', '#.msMatchesSelector(#)', this, selectors);
    } else if (JS('bool', '!!#.oMatchesSelector', this)) {
      return JS('bool', '#.oMatchesSelector(#)', this, selectors);
    } else {
      throw new UnsupportedError("Not supported on this platform");
    }
  }
$else
$endif

  /** Checks if this element or any of its parents match the CSS selectors. */
  @Experimental()
  bool matchesWithAncestors(String selectors) {
    var elem = this;
    do {
      if (elem.matches(selectors)) return true;
      elem = elem.parent;
    } while(elem != null);
    return false;
  }

$if DART2JS
  /**
   * Creates a new shadow root for this shadow host.
   *
   * ## Other resources
   *
   * * [Shadow DOM 101]
   * (http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/)
   * from HTML5Rocks.
   * * [Shadow DOM specification]
   * (http://www.w3.org/TR/shadow-dom/) from W3C.
   */
  @DomName('Element.createShadowRoot')
  @SupportedBrowser(SupportedBrowser.CHROME, '25')
  @Experimental()
  ShadowRoot createShadowRoot() {
    return JS('ShadowRoot',
      '(#.createShadowRoot || #.webkitCreateShadowRoot).call(#)',
      this, this, this);
  }

  /**
   * The shadow root of this shadow host.
   *
   * ## Other resources
   *
   * * [Shadow DOM 101]
   * (http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/)
   * from HTML5Rocks.
   * * [Shadow DOM specification]
   * (http://www.w3.org/TR/shadow-dom/) from W3C.
   */
  @DomName('Element.shadowRoot')
  @SupportedBrowser(SupportedBrowser.CHROME, '25')
  @Experimental()
  ShadowRoot get shadowRoot =>
      JS('ShadowRoot|Null', '#.shadowRoot || #.webkitShadowRoot', this, this);
$endif

  /**
   * Access this element's content position.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not.
   *
   * _Important_ _note_: use of this method _will_ perform CSS calculations that
   * can trigger a browser reflow. Therefore, use of this property _during_ an
   * animation frame is discouraged. See also:
   * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
   */
  @Experimental()
  CssRect get contentEdge => new _ContentCssRect(this);

  /**
   * Access the dimensions and position of this element's content + padding box.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not. This
   * can be used to retrieve jQuery's
   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element.
   * This is also a rectangle equalling the dimensions of clientHeight and
   * clientWidth.
   *
   * _Important_ _note_: use of this method _will_ perform CSS calculations that
   * can trigger a browser reflow. Therefore, use of this property _during_ an
   * animation frame is discouraged. See also:
   * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
   */
  @Experimental()
  CssRect get paddingEdge => new _PaddingCssRect(this);

  /**
   * Access the dimensions and position of this element's content + padding +
   * border box.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not. This
   * can be used to retrieve jQuery's
   * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
   *
   * _Important_ _note_: use of this method _will_ perform CSS calculations that
   * can trigger a browser reflow. Therefore, use of this property _during_ an
   * animation frame is discouraged. See also:
   * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
   */
  @Experimental()
  CssRect get borderEdge => new _BorderCssRect(this);

  /**
   * Access the dimensions and position of this element's content + padding +
   * border + margin box.
   *
   * This returns a rectangle with the dimenions actually available for content
   * in this element, in pixels, regardless of this element's box-sizing
   * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
   * will return the same numerical height if the element is hidden or not. This
   * can be used to retrieve jQuery's
   * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
   *
   * _Important_ _note_: use of this method will perform CSS calculations that
   * can trigger a browser reflow. Therefore, use of this property _during_ an
   * animation frame is discouraged. See also:
   * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
   */
  @Experimental()
  CssRect get marginEdge => new _MarginCssRect(this);

  /**
   * Provides the coordinates of the element relative to the top of the
   * document.
   *
   * This method is the Dart equivalent to jQuery's
   * [offset](http://api.jquery.com/offset/) method.
   */
  @Experimental()
  Point get documentOffset => offsetTo(document.documentElement);

  /**
   * Provides the offset of this element's [borderEdge] relative to the
   * specified [parent].
   *
   * This is the Dart equivalent of jQuery's
   * [position](http://api.jquery.com/position/) method. Unlike jQuery's
   * position, however, [parent] can be any parent element of `this`,
   * rather than only `this`'s immediate [offsetParent]. If the specified
   * element is _not_ an offset parent or transitive offset parent to this
   * element, an [ArgumentError] is thrown.
   */
  @Experimental()
  Point offsetTo(Element parent) {
    return Element._offsetToHelper(this, parent);
  }

  static Point _offsetToHelper(Element current, Element parent) {
    // We're hopping from _offsetParent_ to offsetParent (not just parent), so
    // offsetParent, "tops out" at BODY. But people could conceivably pass in
    // the document.documentElement and I want it to return an absolute offset,
    // so we have the special case checking for HTML.
    bool foundAsParent = identical(current, parent) || parent.tagName == 'HTML';
    if (current == null || identical(current, parent)) {
      if (foundAsParent) return new Point(0, 0);
      throw new ArgumentError("Specified element is not a transitive offset "
          "parent of this element.");
    }
    Element parentOffset = current.offsetParent;
    Point p = Element._offsetToHelper(parentOffset, parent);
    return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
  }

  static HtmlDocument _parseDocument;
  static Range _parseRange;
  static NodeValidatorBuilder _defaultValidator;
  static _ValidatingTreeSanitizer _defaultSanitizer;

  /**
   * Create a DocumentFragment from the HTML fragment and ensure that it follows
   * the sanitization rules specified by the validator or treeSanitizer.
   *
   * If the default validation behavior is too restrictive then a new
   * NodeValidator should be created, either extending or wrapping a default
   * validator and overriding the validation APIs.
   *
   * The treeSanitizer is used to walk the generated node tree and sanitize it.
   * A custom treeSanitizer can also be provided to perform special validation
   * rules but since the API is more complex to implement this is discouraged.
   *
   * The returned tree is guaranteed to only contain nodes and attributes which
   * are allowed by the provided validator.
   *
   * See also:
   *
   * * [NodeValidator]
   * * [NodeTreeSanitizer]
   */
  DocumentFragment createFragment(String html,
      {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
    if (treeSanitizer == null) {
      if (validator == null) {
        if (_defaultValidator == null) {
          _defaultValidator = new NodeValidatorBuilder.common();
        }
        validator = _defaultValidator;
      }
      if (_defaultSanitizer == null) {
        _defaultSanitizer = new _ValidatingTreeSanitizer(validator);
      } else {
        _defaultSanitizer.validator = validator;
      }
      treeSanitizer = _defaultSanitizer;
    } else if (validator != null) {
      throw new ArgumentError(
          'validator can only be passed if treeSanitizer is null');
    }

    if (_parseDocument == null) {
      _parseDocument = document.implementation.createHtmlDocument('');
      _parseRange = _parseDocument.createRange();

      // Workaround for Chrome bug 229142- URIs are not resolved in new doc.
      var base = _parseDocument.createElement('base');
      base.href = document._baseUri;
      _parseDocument.head.append(base);
    }
    var contextElement;
    if (this is BodyElement) {
      contextElement = _parseDocument.body;
    } else {
      contextElement = _parseDocument.createElement(tagName);
      _parseDocument.body.append(contextElement);
    }
    var fragment;
    if (Range.supportsCreateContextualFragment) {
      _parseRange.selectNodeContents(contextElement);
      fragment = _parseRange.createContextualFragment(html);
    } else {
      contextElement._innerHtml = html;

      fragment = _parseDocument.createDocumentFragment();
      while (contextElement.firstChild != null) {
        fragment.append(contextElement.firstChild);
      }
    }
    if (contextElement != _parseDocument.body) {
      contextElement.remove();
    }

    treeSanitizer.sanitizeTree(fragment);
    // Copy the fragment over to the main document (fix for 14184)
    document.adoptNode(fragment);

    return fragment;
  }

  /**
   * Parses the HTML fragment and sets it as the contents of this element.
   *
   * This uses the default sanitization behavior to sanitize the HTML fragment,
   * use [setInnerHtml] to override the default behavior.
   */
  void set innerHtml(String html) {
    this.setInnerHtml(html);
  }

  /**
   * Parses the HTML fragment and sets it as the contents of this element.
   * This ensures that the generated content follows the sanitization rules
   * specified by the validator or treeSanitizer.
   *
   * If the default validation behavior is too restrictive then a new
   * NodeValidator should be created, either extending or wrapping a default
   * validator and overriding the validation APIs.
   *
   * The treeSanitizer is used to walk the generated node tree and sanitize it.
   * A custom treeSanitizer can also be provided to perform special validation
   * rules but since the API is more complex to implement this is discouraged.
   *
   * The resulting tree is guaranteed to only contain nodes and attributes which
   * are allowed by the provided validator.
   *
   * See also:
   *
   * * [NodeValidator]
   * * [NodeTreeSanitizer]
   */
  void setInnerHtml(String html,
    {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) {
    text = null;
    append(createFragment(
        html, validator: validator, treeSanitizer: treeSanitizer));
  }
  String get innerHtml => _innerHtml;

  /**
   * This is an ease-of-use accessor for event streams which should only be
   * used when an explicit accessor is not available.
   */
  ElementEvents get on => new ElementEvents(this);

$!MEMBERS
}


class _ElementFactoryProvider {

  @DomName('Document.createElement')
$if DART2JS
  // Optimization to improve performance until the dart2js compiler inlines this
  // method.
  static dynamic createElement_tag(String tag, String typeExtension) {
    // Firefox may return a JS function for some types (Embed, Object).
    if (typeExtension != null) {
      return JS('Element|=Object', 'document.createElement(#, #)',
          tag, typeExtension);
    }
    // Should be able to eliminate this and just call the two-arg version above
    // with null typeExtension, but Chrome treats the tag as case-sensitive if
    // typeExtension is null.
    // https://code.google.com/p/chromium/issues/detail?id=282467
    return JS('Element|=Object', 'document.createElement(#)', tag);
  }

$else
  static Element createElement_tag(String tag, String typeExtension) =>
      document.createElement(tag, typeExtension);
$endif
}


/**
 * Options for Element.scrollIntoView.
 */
class ScrollAlignment {
  final _value;
  const ScrollAlignment._internal(this._value);
  toString() => 'ScrollAlignment.$_value';

  /// Attempt to align the element to the top of the scrollable area.
  static const TOP = const ScrollAlignment._internal('TOP');
  /// Attempt to center the element in the scrollable area.
  static const CENTER = const ScrollAlignment._internal('CENTER');
  /// Attempt to align the element to the bottom of the scrollable area.
  static const BOTTOM = const ScrollAlignment._internal('BOTTOM');
}
