/*
 * Copyright 2009 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.OptionElement;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.safehtml.shared.annotations.IsSafeHtml;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.impl.DOMImpl;

/**
 * This class provides a set of static methods that allow you to manipulate the
 * browser's Document Object Model (DOM). It contains methods for manipulating
 * both {@link com.google.gwt.user.client.Element elements} and
 * {@link com.google.gwt.user.client.Event events}.
 */
public class DOM {

  private static class NativePreview extends BaseListenerWrapper<EventPreview>
      implements Event.NativePreviewHandler {
    @Deprecated
    public static void add(EventPreview listener) {
      Event.addNativePreviewHandler(new NativePreview(listener));
    }

    public static void remove(EventPreview listener) {
      baseRemove(Event.handlers, listener, NativePreviewEvent.getType());
    }

    private NativePreview(EventPreview listener) {
      super(listener);
    }

    public void onPreviewNativeEvent(NativePreviewEvent event) {
      // The legacy EventHandler should only fire if it is on the top of the
      // stack (ie. the last one added).
      if (event.isFirstHandler()) {
        if (!listener.onEventPreview(Event.as(event.getNativeEvent()))) {
          event.cancel();
        }
      }
    }
  }

  // The current event being fired
  private static Event currentEvent = null;
  static final DOMImpl impl = GWT.create(DOMImpl.class);
  private static Element sCaptureElem;

  /**
   * Adds an event preview to the preview stack. As long as this preview remains
   * on the top of the stack, it will receive all events before they are fired
   * to their listeners. Note that the event preview will receive <u>all </u>
   * events, including those received due to bubbling, whereas normal event
   * handlers only receive explicitly sunk events.
   * 
   * @param preview the event preview to be added to the stack.
   * @deprecated replaced by
   *             {@link Event#addNativePreviewHandler(Event.NativePreviewHandler)}
   */
  @Deprecated
  public static void addEventPreview(EventPreview preview) {
    NativePreview.add(preview);
  }

  /**
   * Appends one element to another's list of children.
   * <p>
   * If the child element is a {@link com.google.gwt.user.client.ui.PotentialElement}, it is first
   * resolved.
   * </p>
   *
   * @param parent the parent element
   * @param child its new child
   * @see com.google.gwt.user.client.ui.PotentialElement#resolve(Element)
   */
  public static void appendChild(Element parent, Element child) {
    assert !isPotential(parent) : "Cannot append to a PotentialElement";

    // If child isn't a PotentialElement, resolve() returns
    // the Element itself.
    parent.appendChild(resolve(child));
  }

  /**
   * Clones an element.
   * 
   * @param elem the element to be cloned
   * @param deep should children be cloned as well?
   */
  public static com.google.gwt.user.client.Element clone(Element elem, boolean deep) {
    return elem.cloneNode(deep).cast();
  }

  /**
   * Compares two elements for equality. Note that this method is now deprecated
   * because reference identity accurately reports equality.
   * 
   * @param elem1 the first element to be compared
   * @param elem2 the second element to be compared
   * @return <code>true</code> if they are in fact the same element
   * @deprecated Use identity comparison.
   */
  @Deprecated
  public static boolean compare(Element elem1, Element elem2) {
    return elem1 == elem2;
  }

  /**
   * Creates an HTML A element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createAnchor() {
    return Document.get().createAnchorElement().cast();
  }

  /**
   * Creates an HTML BUTTON element.
   * 
   * @return the newly-created element
   */
  @SuppressWarnings("deprecation")
  public static com.google.gwt.user.client.Element createButton() {
    return Document.get().createButtonElement().cast();
  }

  /**
   * Creates an HTML CAPTION element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createCaption() {
    return Document.get().createCaptionElement().cast();
  }

  /**
   * Creates an HTML COL element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createCol() {
    return Document.get().createColElement().cast();
  }

  /**
   * Creates an HTML COLGROUP element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createColGroup() {
    return Document.get().createColGroupElement().cast();
  }

  /**
   * Creates an HTML DIV element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createDiv() {
    return Document.get().createDivElement().cast();
  }

  /**
   * Creates an HTML element.
   * 
   * @param tagName the HTML tag of the element to be created
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createElement(String tagName) {
    return Document.get().createElement(tagName).cast();
  }

  /**
   * Creates an HTML FIELDSET element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createFieldSet() {
    return Document.get().createFieldSetElement().cast();
  }

  /**
   * Creates an HTML FORM element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createForm() {
    return Document.get().createFormElement().cast();
  }

  /**
   * Creates an HTML IFRAME element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createIFrame() {
    return Document.get().createIFrameElement().cast();
  }

  /**
   * Creates an HTML IMG element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createImg() {
    return Document.get().createImageElement().cast();
  }

  /**
   * Creates an HTML INPUT type='CHECK' element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createInputCheck() {
    return Document.get().createCheckInputElement().cast();
  }

  /**
   * Creates an HTML INPUT type='PASSWORD' element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createInputPassword() {
    return Document.get().createPasswordInputElement().cast();
  }

  /**
   * Creates an HTML INPUT type='RADIO' element.
   * 
   * @param name the name of the group with which this radio button will be
   *          associated
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createInputRadio(String name) {
    return Document.get().createRadioInputElement(name).cast();
  }

  /**
   * Creates an HTML INPUT type='TEXT' element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createInputText() {
    return Document.get().createTextInputElement().cast();
  }

  /**
   * Creates an HTML LABEL element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createLabel() {
    return Document.get().createLabelElement().cast();
  }

  /**
   * Creates an HTML LEGEND element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createLegend() {
    return Document.get().createLegendElement().cast();
  }

  /**
   * Creates an HTML OPTION element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createOption() {
    return Document.get().createOptionElement().cast();
  }

  /**
   * Creates an HTML OPTIONS element.
   * 
   * @return the newly-created element
   * @deprecated there is no "options" element; use {@link #createOption()}
   *             instead
   */
  @Deprecated
  public static com.google.gwt.user.client.Element createOptions() {
    return Document.get().createElement("options").cast();
  }

  /**
   * Creates a single-selection HTML SELECT element. Equivalent to
   * 
   * <pre>
   * createSelect(false)
   * </pre>
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createSelect() {
    return Document.get().createSelectElement().cast();
  }

  /**
   * Creates an HTML SELECT element.
   * 
   * @param multiple true if multiple selection of options is allowed
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createSelect(boolean multiple) {
    SelectElement selectElement = Document.get().createSelectElement();
    selectElement.setMultiple(multiple);
    return selectElement.cast();
  }

  /**
   * Creates an HTML SPAN element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createSpan() {
    return Document.get().createSpanElement().cast();
  }

  /**
   * Creates an HTML TABLE element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTable() {
    return Document.get().createTableElement().cast();
  }

  /**
   * Creates an HTML TBODY element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTBody() {
    return Document.get().createTBodyElement().cast();
  }

  /**
   * Creates an HTML TD element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTD() {
    return Document.get().createTDElement().cast();
  }

  /**
   * Creates an HTML TEXTAREA element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTextArea() {
    return Document.get().createTextAreaElement().cast();
  }

  /**
   * Creates an HTML TFOOT element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTFoot() {
    return Document.get().createTFootElement().cast();
  }

  /**
   * Creates an HTML TH element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTH() {
    return Document.get().createTHElement().cast();
  }

  /**
   * Creates an HTML THEAD element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTHead() {
    return Document.get().createTHeadElement().cast();
  }

  /**
   * Creates an HTML TR element.
   * 
   * @return the newly-created element
   */
  public static com.google.gwt.user.client.Element createTR() {
    return Document.get().createTRElement().cast();
  }

  /**
   * Generates a unique DOM id. The id is of the form "gwt-id-<unique integer>".
   * 
   * @return a unique DOM id
   */
  public static String createUniqueId() {
    return Document.get().createUniqueId();
  }

  /**
   * Cancels bubbling for the given event. This will stop the event from being
   * propagated to parent elements.
   * 
   * @param evt the event on which to cancel bubbling
   * @param cancel <code>true</code> to cancel bubbling
   */
  public static void eventCancelBubble(Event evt, boolean cancel) {
    impl.eventCancelBubble(evt, cancel);
  }

  /**
   * Gets whether the ALT key was depressed when the given event occurred.
   * 
   * @param evt the event to be tested
   * @return <code>true</code> if ALT was depressed when the event occurred
   * @deprecated Use {@link Event#getAltKey()} instead.
   */
  @Deprecated
  public static boolean eventGetAltKey(Event evt) {
    return evt.getAltKey();
  }

  /**
   * Gets the mouse buttons that were depressed when the given event occurred.
   * 
   * @param evt the event to be tested
   * @return a bit-field, defined by {@link Event#BUTTON_LEFT},
   *         {@link Event#BUTTON_MIDDLE}, and {@link Event#BUTTON_RIGHT}
   * @deprecated Use {@link Event#getButton()} instead.
   */
  @Deprecated
  public static int eventGetButton(Event evt) {
    return evt.getButton();
  }

  /**
   * Gets the mouse x-position within the browser window's client area.
   * 
   * @param evt the event to be tested
   * @return the mouse x-position
   * @deprecated Use {@link Event#getClientX()} instead.
   */
  @Deprecated
  public static int eventGetClientX(Event evt) {
    return evt.getClientX();
  }

  /**
   * Gets the mouse y-position within the browser window's client area.
   * 
   * @param evt the event to be tested
   * @return the mouse y-position
   * @deprecated Use {@link Event#getClientY()} instead.
   */
  @Deprecated
  public static int eventGetClientY(Event evt) {
    return evt.getClientY();
  }

  /**
   * Gets whether the CTRL key was depressed when the given event occurred.
   * 
   * @param evt the event to be tested
   * @return <code>true</code> if CTRL was depressed when the event occurred
   * @deprecated Use {@link Event#getCtrlKey()} instead.
   */
  @Deprecated
  public static boolean eventGetCtrlKey(Event evt) {
    return evt.getCtrlKey();
  }

  /**
   * Gets the current event that is being fired. The current event is only
   * available within the lifetime of the onBrowserEvent function. Once the
   * onBrowserEvent method returns, the current event is reset to null.
   * 
   * @return the current event
   */
  public static Event eventGetCurrentEvent() {
    return currentEvent;
  }

  /**
   * Gets the current target element of the given event. This is the element
   * whose listener fired last, not the element which fired the event initially.
   * 
   * @param evt the event
   * @return the event's current target element
   * @see DOM#eventGetTarget(Event)
   */
  public static com.google.gwt.user.client.Element eventGetCurrentTarget(Event evt) {
    return evt.getCurrentEventTarget().cast();
  }

  /**
   * Gets the element from which the mouse pointer was moved (valid for
   * {@link Event#ONMOUSEOVER} and {@link Event#ONMOUSEOUT}).
   * 
   * @param evt the event to be tested
   * @return the element from which the mouse pointer was moved
   */
  public static com.google.gwt.user.client.Element eventGetFromElement(Event evt) {
    return asOld(impl.eventGetFromElement(evt));
  }

  /**
   * Gets the key code associated with this event.
   * 
   * <p>
   * For {@link Event#ONKEYPRESS}, this method returns the Unicode value of the
   * character generated. For {@link Event#ONKEYDOWN} and {@link Event#ONKEYUP},
   * it returns the code associated with the physical key.
   * </p>
   * 
   * @param evt the event to be tested
   * @return the Unicode character or key code.
   * @see com.google.gwt.user.client.ui.KeyboardListener
   * @deprecated Use {@link Event#getKeyCode()} instead.
   */
  @Deprecated
  public static int eventGetKeyCode(Event evt) {
    return evt.getKeyCode();
  }

  /**
   * Gets whether the META key was depressed when the given event occurred.
   * 
   * @param evt the event to be tested
   * @return <code>true</code> if META was depressed when the event occurred
   * @deprecated Use {@link Event#getMetaKey()} instead.
   */
  @Deprecated
  public static boolean eventGetMetaKey(Event evt) {
    return evt.getMetaKey();
  }

  /**
   * Gets the velocity of the mouse wheel associated with the event along the Y
   * axis.
   * <p>
   * The velocity of the event is an artificial measurement for relative
   * comparisons of wheel activity. It is affected by some non-browser factors,
   * including choice of input hardware and mouse acceleration settings. The
   * sign of the velocity measurement agrees with the screen coordinate system;
   * negative values are towards the origin and positive values are away from
   * the origin. Standard scrolling speed is approximately ten units per event.
   * </p>
   * 
   * @param evt the event to be examined.
   * @return The velocity of the mouse wheel.
   * @deprecated Use {@link Event#getMouseWheelVelocityY()} instead.
   */
  @Deprecated
  public static int eventGetMouseWheelVelocityY(Event evt) {
    return evt.getMouseWheelVelocityY();
  }

  /**
   * Gets the key-repeat state of this event. Only IE supports this attribute.
   * 
   * @param evt the event to be tested
   * @return <code>true</code> if this key event was an auto-repeat
   * @deprecated not supported in any browser but IE
   */
  @Deprecated
  public static boolean eventGetRepeat(Event evt) {
    return impl.eventGetRepeat(evt);
  }

  /**
   * Gets the mouse x-position on the user's display.
   * 
   * @param evt the event to be tested
   * @return the mouse x-position
   * @deprecated Use {@link Event#getScreenX()} instead.
   */
  @Deprecated
  public static int eventGetScreenX(Event evt) {
    return evt.getScreenX();
  }

  /**
   * Gets the mouse y-position on the user's display.
   * 
   * @param evt the event to be tested
   * @return the mouse y-position
   * @deprecated Use {@link Event#getScreenY()} instead.
   */
  @Deprecated
  public static int eventGetScreenY(Event evt) {
    return evt.getScreenY();
  }

  /**
   * Gets whether the shift key was depressed when the given event occurred.
   * 
   * @param evt the event to be tested
   * @return <code>true</code> if shift was depressed when the event occurred
   * @deprecated Use {@link Event#getShiftKey()} instead.
   */
  @Deprecated
  public static boolean eventGetShiftKey(Event evt) {
    return evt.getShiftKey();
  }

  /**
   * Returns the element that was the actual target of the given event.
   * 
   * @param evt the event to be tested
   * @return the target element
   */
  public static com.google.gwt.user.client.Element eventGetTarget(Event evt) {
    return evt.getEventTarget().cast();
  }

  /**
   * Gets the element to which the mouse pointer was moved (only valid for
   * {@link Event#ONMOUSEOUT} and {@link Event#ONMOUSEOVER}).
   * 
   * @param evt the event to be tested
   * @return the element to which the mouse pointer was moved
   */
  public static com.google.gwt.user.client.Element eventGetToElement(Event evt) {
    return asOld(impl.eventGetToElement(evt));
  }

  /**
   * Gets the enumerated type of this event (as defined in {@link Event}).
   * 
   * @param evt the event to be tested
   * @return the event's enumerated type, or -1 if not defined
   */
  public static int eventGetType(Event evt) {
    return impl.eventGetTypeInt(evt);
  }

  /**
   * Gets the type of the given event as a string.
   * 
   * @param evt the event to be tested
   * @return the event's type name
   * @deprecated Use {@link Event#getType()} instead.
   */
  @Deprecated
  public static String eventGetTypeString(Event evt) {
    return evt.getType();
  }

  /**
   * Prevents the browser from taking its default action for the given event.
   * 
   * @param evt the event whose default action is to be prevented
   * @deprecated Use {@link Event#preventDefault()} instead.
   */
  @Deprecated
  public static void eventPreventDefault(Event evt) {
    evt.preventDefault();
  }

  /**
   * Sets the key code associated with the given keyboard event.
   * 
   * @param evt the event whose key code is to be set
   * @param key the new key code
   * @deprecated this method only works in IE and should not have been added to
   *             the API
   */
  @Deprecated
  public static void eventSetKeyCode(Event evt, char key) {
    impl.eventSetKeyCode(evt, key);
  }

  /**
   * Returns a stringized version of the event. This string is for debugging
   * purposes and will NOT be consistent on different browsers.
   * 
   * @param evt the event to stringize
   * @return a string form of the event
   * @deprecated Use {@link Event#getString()} instead.
   */
  @Deprecated
  public static String eventToString(Event evt) {
    return evt.getString();
  }

  /**
   * Gets an element's absolute left coordinate in the document's coordinate
   * system.
   * 
   * @param elem the element to be measured
   * @return the element's absolute left coordinate
   * @deprecated Use {@link Element#getAbsoluteLeft()} instead.
   */
  @Deprecated
  public static int getAbsoluteLeft(Element elem) {
    return elem.getAbsoluteLeft();
  }

  /**
   * Gets an element's absolute top coordinate in the document's coordinate
   * system.
   * 
   * @param elem the element to be measured
   * @return the element's absolute top coordinate
   * @deprecated Use {@link Element#getAbsoluteTop()} instead.
   */
  @Deprecated
  public static int getAbsoluteTop(Element elem) {
    return elem.getAbsoluteTop();
  }

  /**
   * Gets any named property from an element, as a string.
   *
   * @param elem the element whose property is to be retrieved
   * @param attr the name of the property
   * @return the property's value
   * @deprecated Use the more appropriately named
   *             {@link Element#getPropertyString(String)} instead.
   */
  @Deprecated
  public static String getAttribute(Element elem, String attr) {
    return elem.getPropertyString(attr);
  }

  /**
   * Gets a boolean property on the given element.
   *
   * @param elem the element whose property is to be set
   * @param attr the name of the property to be set
   * @return the property's value as a boolean
   * @deprecated Use the more appropriately named
   *             {@link Element#getPropertyBoolean(String)} instead.
   */
  @Deprecated
  public static boolean getBooleanAttribute(Element elem, String attr) {
    return elem.getPropertyBoolean(attr);
  }

  /**
   * Gets the element that currently has mouse capture.
   * 
   * @return a handle to the capture element, or <code>null</code> if none
   *         exists
   */
  public static com.google.gwt.user.client.Element getCaptureElement() {
    return asOld(sCaptureElem);
  }

  /**
   * Gets an element's n-th child element.
   * 
   * @param parent the element whose child is to be retrieved
   * @param index the index of the child element
   * @return the n-th child element
   */
  public static com.google.gwt.user.client.Element getChild(Element parent, int index) {
    return asOld(impl.getChild(parent, index));
  }

  /**
   * Gets the number of child elements present in a given parent element.
   * 
   * @param parent the element whose children are to be counted
   * @return the number of children
   */
  public static int getChildCount(Element parent) {
    return impl.getChildCount(parent);
  }

  /**
   * Gets the index of a given child element within its parent.
   * 
   * @param parent the parent element
   * @param child the child element
   * @return the child's index within its parent, or <code>-1</code> if it is
   *         not a child of the given parent
   */
  public static int getChildIndex(Element parent, Element child) {
    return impl.getChildIndex(parent, child);
  }

  /**
   * Gets the named attribute from the element.
   * 
   * @param elem the element whose property is to be retrieved
   * @param attr the name of the attribute
   * @return the value of the attribute
   * @deprecated Use {@link Element#getAttribute(String)} instead.
   */
  @Deprecated
  public static String getElementAttribute(Element elem, String attr) {
    return elem.getAttribute(attr);
  }

  /**
   * Gets the element associated with the given unique id within the entire
   * document.
   * 
   * @param id the id whose associated element is to be retrieved
   * @return the associated element, or <code>null</code> if none is found
   */
  public static com.google.gwt.user.client.Element getElementById(String id) {
    return asOld(Document.get().getElementById(id));
  }

  /**
   * Gets any named property from an element, as a string.
   * 
   * @param elem the element whose property is to be retrieved
   * @param prop the name of the property
   * @return the property's value
   * @deprecated Use {@link Element#getProperty(String)} instead.
   */
  @Deprecated
  public static String getElementProperty(Element elem, String prop) {
    return elem.getPropertyString(prop);
  }

  /**
   * Gets any named property from an element, as a boolean.
   * 
   * @param elem the element whose property is to be retrieved
   * @param prop the name of the property
   * @return the property's value as a boolean
   * @deprecated Use {@link Element#getPropertyBoolean(String)} instead.
   */
  @Deprecated
  public static boolean getElementPropertyBoolean(Element elem, String prop) {
    return elem.getPropertyBoolean(prop);
  }

  /**
   * Gets any named property from an element, as an int.
   * 
   * @param elem the element whose property is to be retrieved
   * @param prop the name of the property
   * @return the property's value as an int
   * @deprecated Use {@link Element#getPropertyInt(String)} instead.
   */
  @Deprecated
  public static int getElementPropertyInt(Element elem, String prop) {
    return elem.getPropertyInt(prop);
  }

  /**
   * Gets the {@link EventListener} that will receive events for the given
   * element. Only one such listener may exist for a single element.
   * 
   * @param elem the element whose listener is to be set
   * @return the element's event listener
   */
  public static EventListener getEventListener(Element elem) {
    return DOMImpl.getEventListener(elem);
  }

  /**
   * Gets the current set of events sunk by a given element.
   * 
   * @param elem the element whose events are to be retrieved
   * @return a bitfield describing the events sunk on this element (its possible
   *         values are described in {@link Event})
   */
  public static int getEventsSunk(Element elem) {
    return impl.getEventsSunk(elem);
  }

  /**
   * Gets the first child element of the given element.
   * 
   * @param elem the element whose child is to be retrieved
   * @return the child element
   */
  public static com.google.gwt.user.client.Element getFirstChild(Element elem) {
    return asOld(elem.getFirstChildElement());
  }

  /**
   * Gets the src attribute of an img element. This method is paired with
   * {@link #setImgSrc(Element, String)} so that it always returns the correct
   * url.
   * 
   * @param img a non-null img whose src attribute is to be read.
   * @return the src url of the img
   */
  public static String getImgSrc(Element img) {
    return img.<ImageElement> cast().getSrc();
  }

  /**
   * Gets an HTML representation of an element's children.
   * 
   * @param elem the element whose HTML is to be retrieved
   * @return the HTML representation of the element's children
   * @deprecated Use {@link Element#getInnerHTML()} instead.
   */
  @Deprecated
  public static String getInnerHTML(Element elem) {
    return elem.getInnerHTML();
  }

  /**
   * Gets the text contained within an element. If the element has child
   * elements, only the text between them will be retrieved.
   * 
   * @param elem the element whose inner text is to be retrieved
   * @return the text inside this element
   * @deprecated Use {@link Element#getInnerText()} instead.
   */
  @Deprecated
  public static String getInnerText(Element elem) {
    return elem.getInnerText();
  }

  /**
   * Gets an integer property on a given element.
   *
   * @param elem the element whose property is to be retrieved
   * @param attr the name of the property to be retrieved
   * @return the property's value as an integer
   * @deprecated Use the more appropriately named
   *             {@link Element#getPropertyInt(String)} instead.
   */
  @Deprecated
  public static int getIntAttribute(Element elem, String attr) {
    return elem.getPropertyInt(attr);
  }

  /**
   * Gets an integer attribute on a given element's style.
   * 
   * @param elem the element whose style attribute is to be retrieved
   * @param attr the name of the attribute to be retrieved
   * @return the style attribute's value as an integer
   */
  public static native int getIntStyleAttribute(Element elem, String attr) /*-{
    return parseInt(elem.style[attr]) || 0;
  }-*/;

  /**
   * Gets an element's next sibling element.
   * 
   * @param elem the element whose sibling is to be retrieved
   * @return the sibling element
   */
  public static com.google.gwt.user.client.Element getNextSibling(Element elem) {
    return elem.getNextSibling().cast();
  }

  /**
   * Gets an element's parent element.
   * 
   * @param elem the element whose parent is to be retrieved
   * @return the parent element
   */
  public static com.google.gwt.user.client.Element getParent(Element elem) {
    return asOld(elem.getParentElement());
  }

  /**
   * Gets an attribute of the given element's style.
   * 
   * @param elem the element whose style attribute is to be retrieved
   * @param attr the name of the style attribute to be retrieved
   * @return the style attribute's value
   * @deprecated Use {@link Element#getStyle()} and
   *             {@link Style#getProperty(String)} instead.
   */
  @Deprecated
  public static String getStyleAttribute(Element elem, String attr) {
    return elem.getStyle().getProperty(attr);
  }

  /**
   * Inserts an element as a child of the given parent element, before another
   * child of that parent.
   * <p>
   * If the child element is a {@link com.google.gwt.user.client.ui.PotentialElement}, it is first
   * resolved.
   * </p>
   * 
   * @param parent the parent element
   * @param child the child element to add to <code>parent</code>
   * @param before an existing child element of <code>parent</code> before which
   *          <code>child</code> will be inserted
   * @see com.google.gwt.user.client.ui.PotentialElement#resolve(Element)
   */
  public static void insertBefore(Element parent, Element child, Element before) {
    assert !isPotential(parent) : "Cannot insert into a PotentialElement";

    // If child isn't a PotentialElement, resolve() returns
    // the Element itself.
    parent.insertBefore(resolve(child), before);
  }

  /**
   * Inserts an element as a child of the given parent element.
   * <p>
   * If the child element is a {@link com.google.gwt.user.client.ui.PotentialElement}, it is first
   * resolved.
   * </p>
   * 
   * @param parent the parent element
   * @param child the child element to add to <code>parent</code>
   * @param index the index before which the child will be inserted (any value
   *          greater than the number of existing children will cause the child
   *          to be appended)
   * @see com.google.gwt.user.client.ui.PotentialElement#resolve(Element)
   */
  public static void insertChild(Element parent, Element child, int index) {
    assert !isPotential(parent) : "Cannot insert into a PotentialElement";

    // If child isn't a PotentialElement, resolve() returns
    // the Element itself.
    impl.insertChild(parent, resolve(child), index);
  }

  /**
   * Creates an <code>&lt;option&gt;</code> element and inserts it as a child of
   * the specified <code>&lt;select&gt;</code> element. If the index is less
   * than zero, or greater than or equal to the length of the list, then the
   * option element will be appended to the end of the list.
   * 
   * @param selectElem the <code>&lt;select&gt;</code> element
   * @param item the text of the new item; cannot be <code>null</code>
   * @param value the <code>value</code> attribute for the new
   *          <code>&lt;option&gt;</code>; cannot be <code>null</code>
   * @param index the index at which to insert the child
   */
  public static void insertListItem(Element selectElem, String item,
      String value, int index) {
    assert !isPotential(selectElem) : "Cannot insert into a PotentialElement";

    SelectElement select = selectElem.<SelectElement> cast();
    OptionElement option = Document.get().createOptionElement();
    option.setText(item);
    option.setValue(value);

    if ((index == -1) || (index == select.getLength())) {
      select.add(option, null);
    } else {
      OptionElement before = select.getOptions().getItem(index);
      select.add(option, before);
    }
  }

  private static native boolean isPotential(JavaScriptObject o) /*-{
    try {
      return (!!o) &&  (!!o.__gwt_resolve);
    } catch (e) {
      return false;
    }
  }-*/;

  private static native Element resolve(Element maybePotential) /*-{
    return maybePotential.__gwt_resolve ? maybePotential.__gwt_resolve() : maybePotential;
  }-*/;
  /**
   * Determine whether one element is equal to, or the child of, another.
   * 
   * @param parent the potential parent element
   * @param child the potential child element
   * @return <code>true</code> if the relationship holds
   * @deprecated Use {@link Element#isOrHasChild(Element)} instead.
   */
  @Deprecated
  public static boolean isOrHasChild(Element parent, Element child) {
    return parent.isOrHasChild(child);
  }

  /**
   * Releases mouse/touch/gesture capture on the given element. Calling this
   * method has no effect if the element does not currently have
   * mouse/touch/gesture capture.
   * 
   * @param elem the element to release capture
   * @see #setCapture(Element)
   */
  public static void releaseCapture(Element elem) {
    if ((sCaptureElem != null) && elem == sCaptureElem) {
      sCaptureElem = null;
    }
    impl.releaseCapture(elem);
  }

  /**
   * Removes a child element from the given parent element.
   * 
   * @param parent the parent element
   * @param child the child element to be removed
   * @deprecated Use {@link Element#removeChild(Element)} instead.
   */
  @Deprecated
  public static void removeChild(Element parent, Element child) {
    parent.removeChild(child);
  }

  /**
   * Removes the named attribute from the given element.
   * 
   * @param elem the element whose attribute is to be removed
   * @param attr the name of the element to remove
   * @deprecated Use {@link Element#removeAttribute(String)} instead.
   */
  @Deprecated
  public static void removeElementAttribute(Element elem, String attr) {
    elem.removeAttribute(attr);
  }

  /**
   * Removes an element from the preview stack. This element will no longer
   * capture events, though any preview underneath it will begin to do so.
   * 
   * @param preview the event preview to be removed from the stack
   * @deprecated use {@link com.google.gwt.event.shared.HandlerRegistration}
   *             returned from
   *             {@link Event#addNativePreviewHandler(Event.NativePreviewHandler)}
   */
  @Deprecated
  public static void removeEventPreview(EventPreview preview) {
    NativePreview.remove(preview);
  }

  /**
   * Scrolls the given element into view.
   * 
   * <p>
   * This method crawls up the DOM hierarchy, adjusting the scrollLeft and
   * scrollTop properties of each scrollable element to ensure that the
   * specified element is completely in view. It adjusts each scroll position by
   * the minimum amount necessary.
   * </p>
   * 
   * @param elem the element to be made visible
   * @deprecated Use {@link Element#scrollIntoView()} instead.
   */
  @Deprecated
  public static void scrollIntoView(Element elem) {
    elem.scrollIntoView();
  }

  /**
   * Sets a property on the given element.
   *
   * @param elem the element whose property is to be set
   * @param attr the name of the property to be set
   * @param value the new property value
   * @deprecated Use the more appropriately named
   *             {@link Element#setPropertyString(String, String)} instead.
   */
  @Deprecated
  public static void setAttribute(Element elem, String attr, String value) {
    elem.setPropertyString(attr, value);
  }

  /**
   * Sets a boolean property on the given element.
   *
   * @param elem the element whose property is to be set
   * @param attr the name of the property to be set
   * @param value the property's new boolean value
   * @deprecated Use the more appropriately named
   *             {@link Element#setPropertyBoolean(String, boolean)}
   *             instead.
   */
  @Deprecated
  public static void setBooleanAttribute(Element elem, String attr,
      boolean value) {
    elem.setPropertyBoolean(attr, value);
  }

  /**
   * Sets mouse/touch/gesture capture on the given element. This element will
   * directly receive all mouse events until {@link #releaseCapture(Element)} is
   * called on it.
   * 
   * @param elem the element on which to set mouse/touch/gesture capture
   */
  public static void setCapture(Element elem) {
    sCaptureElem = elem;
    impl.setCapture(elem);
  }

  /**
   * Sets an attribute on a given element.
   * 
   * @param elem element whose attribute is to be set
   * @param attr the name of the attribute
   * @param value the value to which the attribute should be set
   * @deprecated Use {@link Element#setAttribute(String, String)} instead.
   */
  @Deprecated
  public static void setElementAttribute(Element elem, String attr, String value) {
    elem.setAttribute(attr, value);
  }

  /**
   * Sets a property on the given element.
   * 
   * @param elem the element whose property is to be set
   * @param prop the name of the property to be set
   * @param value the new property value
   * @deprecated Use {@link Element#setPropertyString(String, String)} instead.
   */
  @Deprecated
  public static void setElementProperty(Element elem, String prop, String value) {
    elem.setPropertyString(prop, value);
  }

  /**
   * Sets a boolean property on the given element.
   * 
   * @param elem the element whose property is to be set
   * @param prop the name of the property to be set
   * @param value the new property value as a boolean
   * @deprecated Use {@link Element#setPropertyBoolean(String, boolean)} instead.
   */
  @Deprecated
  public static void setElementPropertyBoolean(Element elem, String prop,
      boolean value) {
    elem.setPropertyBoolean(prop, value);
  }

  /**
   * Sets an int property on the given element.
   * 
   * @param elem the element whose property is to be set
   * @param prop the name of the property to be set
   * @param value the new property value as an int
   * @deprecated Use {@link Element#setPropertyInt(String, int)} instead.
   */
  @Deprecated
  public static void setElementPropertyInt(Element elem, String prop, int value) {
    elem.setPropertyInt(prop, value);
  }

  /**
   * Sets the {@link EventListener} to receive events for the given element.
   * Only one such listener may exist for a single element.
   * 
   * @param elem the element whose listener is to be set
   * @param listener the listener to receive {@link Event events}
   */
  public static void setEventListener(Element elem, EventListener listener) {
    DOMImpl.setEventListener(elem, listener);
  }

  /**
   * Sets the src attribute of an img element. This method ensures that imgs
   * only ever have their contents requested one single time from the server.
   * 
   * @param img a non-null img whose src attribute will be set.
   * @param src a non-null url for the img
   */
  public static void setImgSrc(Element img, String src) {
    img.<ImageElement> cast().setSrc(src);
  }

  /**
   * Sets the HTML contained within an element.
   *
   * @param elem the element whose inner HTML is to be set
   * @param html the new html
   * @deprecated Use {@link Element#setInnerHTML(String)} instead.
   */
  @Deprecated
  public static void setInnerHTML(Element elem, @IsSafeHtml String html) {
    elem.setInnerHTML(html);
  }

  /**
   * Sets the text contained within an element. If the element already has
   * children, they will be destroyed.
   * 
   * @param elem the element whose inner text is to be set
   * @param text the new text
   * @deprecated Use {@link Element#setInnerText(String)} instead.
   */
  @Deprecated
  public static void setInnerText(Element elem, String text) {
    elem.setInnerText(text);
  }

  /**
   * Sets an integer property on the given element.
   *
   * @param elem the element whose property is to be set
   * @param attr the name of the property to be set
   * @param value the property's new integer value
   * @deprecated Use the more appropriately named
   *             {@link Element#setPropertyInt(String, int)} instead.
   */
  @Deprecated
  public static void setIntAttribute(Element elem, String attr, int value) {
    elem.setPropertyInt(attr, value);
  }

  /**
   * Sets an integer attribute on the given element's style.
   * 
   * @param elem the element whose style attribute is to be set
   * @param attr the name of the style attribute to be set
   * @param value the style attribute's new integer value
   */
  public static void setIntStyleAttribute(Element elem, String attr, int value) {
    elem.getStyle().setProperty(attr, Integer.toString(value));
  }

  /**
   * Sets the option text of the given select object.
   * 
   * @param select the select object whose option text is being set
   * @param text the text to set
   * @param index the index of the option whose text should be set
   */
  public static void setOptionText(Element select, String text, int index) {
    select.<SelectElement> cast().getOptions().getItem(index).setText(text);
  }

  /**
   * Sets an attribute on the given element's style.
   * 
   * @param elem the element whose style attribute is to be set
   * @param attr the name of the style attribute to be set
   * @param value the style attribute's new value
   * @deprecated Use {@link Element#getStyle()} and
   *             {@link Style#setProperty(String, String)} instead.
   */
  @Deprecated
  public static void setStyleAttribute(Element elem, String attr, String value) {
    elem.getStyle().setProperty(attr, value);
  }

  /**
   * Sinks a named event. Events will be fired to the nearest
   * {@link EventListener} specified on any of the element's parents.
   * 
   * @param elem the element whose events are to be retrieved
   * @param eventTypeName name of the event to sink on this element
   */
  public static void sinkBitlessEvent(Element elem, String eventTypeName) {
    impl.sinkBitlessEvent(elem, eventTypeName);
  }
  
  /**
   * Sets the current set of events sunk by a given element. These events will
   * be fired to the nearest {@link EventListener} specified on any of the
   * element's parents.
   * 
   * @param elem the element whose events are to be retrieved
   * @param eventBits a bitfield describing the events sunk on this element (its
   *          possible values are described in {@link Event})
   */
  public static void sinkEvents(Element elem, int eventBits) {
    impl.sinkEvents(elem, eventBits);
  }

  /**
   * Returns a stringized version of the element. This string is for debugging
   * purposes and will NOT be consistent on different browsers.
   * 
   * @param elem the element to stringize
   * @return a string form of the element
   * @deprecated Use {@link Element#getString()} instead.
   */
  @Deprecated
  public static String toString(Element elem) {
    return elem.getString();
  }

  /**
   * @deprecated As of GWT 1.5, replaced by {@link Window#getClientHeight()}
   */
  @Deprecated
  public static int windowGetClientHeight() {
    return Window.getClientHeight();
  }

  /**
   * @deprecated As of GWT 1.5, replaced by {@link Window#getClientWidth()}
   */
  @Deprecated
  public static int windowGetClientWidth() {
    return Window.getClientWidth();
  }

  /**
   * This method is called directly by native code when any event is fired.
   * 
   * @param evt the handle to the event being fired.
   * @param elem the handle to the element that received the event.
   * @param listener the listener associated with the element that received the
   *          event.
   */
  public static void dispatchEvent(Event evt, Element elem, EventListener listener) {
    // Preserve the current event in case we are in a reentrant event dispatch.
    Event prevCurrentEvent = currentEvent;
    currentEvent = evt;

    dispatchEventImpl(evt, elem, listener);

    currentEvent = prevCurrentEvent;
  }

  /**
   * This method is a similar to {@link #dispatchEvent(Event, Element, EventListener)} but only
   * dispatches if an event listener is set to element.
   *
   * @param evt the handle to the event being fired.
   * @param elem the handle to the element that received the event.
   * @return {@code true} if the event was dispatched
   */
  public static boolean dispatchEvent(Event evt, Element elem) {
    EventListener eventListener = getEventListener(elem);
    if (eventListener == null) {
      return false;
    }
    dispatchEvent(evt, elem, eventListener);
    return true;
  }

  /**
   * Initialize the event system if it has not already been initialized.
   */
  static void maybeInitializeEventSystem() {
    impl.maybeInitializeEventSystem();
  }

  /**
   * This method is called directly by native code when event preview is being
   * used.
   * 
   * @param evt a handle to the event being previewed
   * @return <code>false</code> to cancel the event
   */
  public static boolean previewEvent(Event evt) {
    // Fire a NativePreviewEvent to NativePreviewHandlers
    boolean ret = Event.fireNativePreviewEvent(evt);

    // If the preview cancels the event, stop it from bubbling and performing
    // its default action. Check for a null evt to allow unit tests to run.
    if (!ret && evt != null) {
      evt.stopPropagation();
      evt.preventDefault();
    }

    return ret;
  }

  private static void dispatchEventImpl(Event evt, Element elem,
      EventListener listener) {
    // If this element has capture...
    if (elem == sCaptureElem) {
      // ... and it's losing capture, clear sCaptureElem.
      if (eventGetType(evt) == Event.ONLOSECAPTURE) {
        sCaptureElem = null;
      }
    }

    // Pass the event to the listener.
    listener.onBrowserEvent(evt);
  }

  /**
   * Provided as a convenient way to upcast values statically typed as
   * {@link Element} to {@link com.google.gwt.user.client.Element}.
   * For easier upgrades in the future, it's recommended that this function
   * only be called within a <code>return</code> statement.
   * <p>
   * Does <em>not</em> throw a {@link NullPointerException} if elem is null.
   */
  public static com.google.gwt.user.client.Element asOld(Element elem) {
    return (com.google.gwt.user.client.Element) elem;
  }
}
