All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.dom.client.DOMImplStandardBase Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
/*
 * Copyright 2011 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.dom.client;

import com.google.gwt.core.client.JavaScriptObject;

/**
 * StandardBase implementation of {@link com.google.gwt.user.client.impl.DOMImpl}.
 */
class DOMImplStandardBase extends DOMImplStandard {

  private static class ClientRect extends JavaScriptObject {
    
    @SuppressWarnings("unused")
    protected ClientRect() {
    }

    public final native int getLeft() /*-{
      return this.left;
    }-*/;

    public final native int getTop() /*-{
      return this.top;
    }-*/;
  }

  private static native int getAbsoluteLeftUsingOffsets(Element elem) /*-{
    // Unattached elements and elements (or their ancestors) with style
    // 'display: none' have no offsetLeft.
    if (elem.offsetLeft == null) {
      return 0;
    }

    var left = 0;
    var doc = elem.ownerDocument;
    var curr = elem.parentNode;
    if (curr) {
      // This intentionally excludes body which has a null offsetParent.
      while (curr.offsetParent) {
        left -= curr.scrollLeft;

        // In RTL mode, offsetLeft is relative to the left edge of the
        // scrollable area when scrolled all the way to the right, so we need
        // to add back that difference.
        if (doc.defaultView.getComputedStyle(curr, '').getPropertyValue('direction') == 'rtl') {
          left += (curr.scrollWidth - curr.clientWidth);
        }

        curr = curr.parentNode;
      }
    }

    while (elem) {
      left += elem.offsetLeft;

      if (doc.defaultView.getComputedStyle(elem, '')['position'] == 'fixed') {
        left += doc.body.scrollLeft;
        return left;
      }

      // Safari 3 does not include borders with offsetLeft, so we need to add
      // the borders of the parent manually.
      var parent = elem.offsetParent;
      if (parent && $wnd.devicePixelRatio) {
        left += parseInt(doc.defaultView.getComputedStyle(parent, '').getPropertyValue('border-left-width'));
      }

      // Safari bug: a top-level absolutely positioned element includes the
      // body's offset position already.
      if (parent && (parent.tagName == 'BODY') &&
          (elem.style.position == 'absolute')) {
        break;
      }

      elem = parent;
    }
    return left;
  }-*/;

  private static native int getAbsoluteTopUsingOffsets(Element elem) /*-{
    // Unattached elements and elements (or their ancestors) with style
    // 'display: none' have no offsetTop.
    if (elem.offsetTop == null) {
      return 0;
    }

    var top = 0;
    var doc = elem.ownerDocument;
    var curr = elem.parentNode;
    if (curr) {
      // This intentionally excludes body which has a null offsetParent.
      while (curr.offsetParent) {
        top -= curr.scrollTop;
        curr = curr.parentNode;
      }
    }

    while (elem) {
      top += elem.offsetTop;

      if (doc.defaultView.getComputedStyle(elem, '')['position'] == 'fixed') {
        top += doc.body.scrollTop;
        return top;
      }

      // Safari 3 does not include borders with offsetTop, so we need to add the
      // borders of the parent manually.
      var parent = elem.offsetParent;
      if (parent && $wnd.devicePixelRatio) {
        top += parseInt(doc.defaultView.getComputedStyle(parent, '').getPropertyValue('border-top-width'));
      }

      // Safari bug: a top-level absolutely positioned element includes the
      // body's offset position already.
      if (parent && (parent.tagName == 'BODY') &&
          (elem.style.position == 'absolute')) {
        break;
      }

      elem = parent;
    }
    return top;
  }-*/;

  private static native ClientRect getBoundingClientRect(Element element) /*-{
    return element.getBoundingClientRect && element.getBoundingClientRect();
  }-*/;

  /**
   * The type property on a button element is read-only in safari, so we need to
   * set it using setAttribute.
   */
  @Override
  public native ButtonElement createButtonElement(Document doc, String type) /*-{
    var e = doc.createElement("BUTTON");
    e.setAttribute('type', type);
    return e;
  }-*/;

  @Override
  public native NativeEvent createKeyCodeEvent(Document doc, String type,
      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
      int keyCode) /*-{
    var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, type, true, true, ctrlKey, altKey, shiftKey, metaKey)
    evt.keyCode = keyCode;
    return evt;
  }-*/;

  @Override
  @Deprecated
  public native NativeEvent createKeyEvent(Document doc, String type,
      boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
      boolean shiftKey, boolean metaKey, int keyCode, int charCode) /*-{
    var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, type, canBubble, cancelable, ctrlKey, altKey, shiftKey, metaKey)
    evt.keyCode = keyCode;
    evt.charCode = charCode;
    return evt;
  }-*/;

  @Override
  public native NativeEvent createKeyPressEvent(Document doc,
      boolean ctrlKey, boolean altKey, boolean shiftKey, boolean metaKey,
      int charCode) /*-{
    var evt = [email protected]::createKeyEvent(Lcom/google/gwt/dom/client/Document;Ljava/lang/String;ZZZZZZ)(doc, 'keypress', true, true, ctrlKey, altKey, shiftKey, metaKey)
    evt.charCode = charCode;
    return evt;
  }-*/;

  /**
   * Safari 2 does not support {@link ScriptElement#setText(String)}.
   */
  @Override
  public ScriptElement createScriptElement(Document doc, String source) {
    ScriptElement elem = (ScriptElement) createElement(doc, "script");
    elem.setInnerText(source);
    return elem;
  }

  @Override
  public native EventTarget eventGetCurrentTarget(NativeEvent event) /*-{
    return event.currentTarget || $wnd;
  }-*/;

  @Override
  public native int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
    return Math.round(-evt.wheelDelta / 40) || 0;
  }-*/;

  @Override
  public int getAbsoluteLeft(Element elem) {
    ClientRect rect = getBoundingClientRect(elem);
    return rect != null ? rect.getLeft()
        + elem.getOwnerDocument().getBody().getScrollLeft()
        : getAbsoluteLeftUsingOffsets(elem);
  }

  @Override
  public int getAbsoluteTop(Element elem) {
    ClientRect rect = getBoundingClientRect(elem);
    return rect != null ? rect.getTop()
        + elem.getOwnerDocument().getBody().getScrollTop()
        : getAbsoluteTopUsingOffsets(elem);
  }

  @Override
  public int getScrollLeft(Document doc) {
    // Safari always applies document scrolling to the body element, even in
    // strict mode.
    return doc.getBody().getScrollLeft();
  }

  @Override
  public int getScrollLeft(Element elem) {
    if (isRTL(elem)) {
      return super.getScrollLeft(elem)
          - (elem.getScrollWidth() - elem.getClientWidth());
    }
    return super.getScrollLeft(elem);
  }

  @Override
  public int getScrollTop(Document doc) {
    // Safari always applies document scrolling to the body element, even in
    // strict mode.
    return doc.getBody().getScrollTop();
  }

  @Override
  public native int getTabIndex(Element elem) /*-{ 
    // tabIndex is undefined for divs and other non-focusable elements prior to
    // Safari 4.
    return typeof elem.tabIndex != 'undefined' ? elem.tabIndex : -1;
  }-*/;

  @Override
  public native boolean isOrHasChild(Node parent, Node child) /*-{
    while (child) {
      if (parent == child) {
        return true;
      }
      child = child.parentNode;
      if (child && (child.nodeType != 1)) {
        child = null;
      }
    }
    return false;
  }-*/;

  @Override
  public void setScrollLeft(Document doc, int left) {
    // Safari always applies document scrolling to the body element, even in
    // strict mode.
    doc.getBody().setScrollLeft(left);
  }

  @Override
  public void setScrollLeft(Element elem, int left) {
    if (isRTL(elem)) {
      left += elem.getScrollWidth() - elem.getClientWidth();
    }
    super.setScrollLeft(elem, left);
  }

  @Override
  public void setScrollTop(Document doc, int top) {
    // Safari always applies document scrolling to the body element, even in
    // strict mode.
    doc.getBody().setScrollTop(top);
  }

  protected native boolean isRTL(Element elem) /*-{
    return elem.ownerDocument.defaultView.getComputedStyle(elem, '').direction == 'rtl';
  }-*/;

  private native NativeEvent createKeyEvent(Document doc, String type,
      boolean canBubble, boolean cancelable, boolean ctrlKey, boolean altKey,
      boolean shiftKey, boolean metaKey) /*-{
    // WebKit's KeyboardEvent cannot set or even initialize charCode, keyCode, etc.
    // And UIEvent's charCode and keyCode are read-only.
    // So we "fake" an event using a raw Event and expandos
    var evt = doc.createEvent('Event');
    evt.initEvent(type, canBubble, cancelable);
    evt.ctrlKey = ctrlKey;
    evt.altKey = altKey;
    evt.shiftKey = shiftKey;
    evt.metaKey = metaKey;
    return evt;
  }-*/;
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy