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 {
    
    protected ClientRect() {
    }

    public final int getLeft() {
      return toInt32(getSubPixelLeft());
    }

    public final int getTop() {
      return toInt32(getSubPixelTop());
    }

    private final native double getSubPixelLeft() /*-{
      return this.left;
    }-*/;

    private final native double getSubPixelTop() /*-{
      return this.top;
    }-*/;
  }

  private static native double 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 double 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);
    double left = rect != null ? rect.getSubPixelLeft()
        + elem.getOwnerDocument().getBody().getScrollLeft()
        : getAbsoluteLeftUsingOffsets(elem);
    return toInt32(left);
  }

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

  @Override
  public native int getScrollLeft(Document doc) /*-{
    // Safari always applies document scrolling to the body element, even in strict mode.
    // The behavior of Chrome depends of the doctype mode.
    return doc.documentElement.scrollLeft || doc.body.scrollLeft;
  }-*/;

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

  @Override
  public native int getScrollTop(Document doc) /*-{
    // Safari always applies document scrolling to the body element, even in strict mode.
    // The behavior of Chrome depends of the doctype mode.
    return doc.documentElement.scrollTop || doc.body.scrollTop;
  }-*/;

  @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 void setScrollLeft(Document doc, int left) /*-{
    // Safari always applies document scrolling to the body element, even in strict mode. The
    // behavior of Chrome depends of the doctype mode.
    // This instruction will be ignored by safari and chrome in quirks mode.
    doc.documentElement.scrollLeft = left;
    // Will be ignored by chrome in strict mode.
    doc.body.scrollLeft = left;
  }-*/;

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

  @Override
  public native void setScrollTop(Document doc, int top) /*-{
    // Safari always applies document scrolling to the body element, even in strict mode. The
    // behavior of Chrome depends of the doctype mode.
    // This instruction will be ignored by safari and by chrome in quirks mode.
    doc.documentElement.scrollTop = top;
    // Will be ignored by chrome in strict mode.
    doc.body.scrollTop = 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