blob: 087e8a9c58def7c505d0e481a0781d35ee330152 [file] [log] [blame]
/*
* Copyright 2008 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.impl;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
/**
* Base implementation of {@link com.google.gwt.user.client.impl.DOMImpl} shared
* by those browsers that come a bit closer to supporting a common standard (ie,
* not IE).
*/
abstract class DOMImplStandard extends DOMImpl {
@SuppressWarnings("unused")
private static JavaScriptObject captureElem;
@SuppressWarnings("unused")
private static JavaScriptObject dispatchCapturedEvent;
@SuppressWarnings("unused")
private static JavaScriptObject dispatchCapturedMouseEvent;
@SuppressWarnings("unused")
private static JavaScriptObject dispatchEvent;
@SuppressWarnings("unused")
private static JavaScriptObject dispatchUnhandledEvent;
@Override
public Element eventGetFromElement(Event evt) {
if (evt.getType().equals("mouseover")) {
return evt.getRelatedEventTarget().cast();
}
if (evt.getType().equals("mouseout")) {
return evt.getEventTarget().cast();
}
return null;
}
@Override
public Element eventGetToElement(Event evt) {
if (evt.getType().equals("mouseover")) {
return evt.getEventTarget().cast();
}
if (evt.getType().equals("mouseout")) {
return evt.getRelatedEventTarget().cast();
}
return null;
}
@Override
public native Element getChild(Element elem, int index) /*-{
var count = 0, child = elem.firstChild;
while (child) {
if (child.nodeType == 1) {
if (index == count)
return child;
++count;
}
child = child.nextSibling;
}
return null;
}-*/;
@Override
public native int getChildCount(Element elem) /*-{
var count = 0, child = elem.firstChild;
while (child) {
if (child.nodeType == 1)
++count;
child = child.nextSibling;
}
return count;
}-*/;
@Override
public native int getChildIndex(Element parent, Element toFind) /*-{
var count = 0, child = parent.firstChild;
while (child) {
if (child === toFind) {
return count;
}
if (child.nodeType == 1) {
++count;
}
child = child.nextSibling;
}
return -1;
}-*/;
@Override
public native void insertChild(Element parent, Element toAdd, int index) /*-{
var count = 0, child = parent.firstChild, before = null;
while (child) {
if (child.nodeType == 1) {
if (count == index) {
before = child;
break;
}
++count;
}
child = child.nextSibling;
}
parent.insertBefore(toAdd, before);
}-*/;
@Override
public void releaseCapture(Element elem) {
maybeInitializeEventSystem();
releaseCaptureImpl(elem);
}
@Override
public void setCapture(Element elem) {
maybeInitializeEventSystem();
setCaptureImpl(elem);
}
@Override
public void sinkEvents(Element elem, int bits) {
maybeInitializeEventSystem();
sinkEventsImpl(elem, bits);
}
@Override
protected native void initEventSystem() /*-{
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent = $entry(function(evt) {
if (!@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)(evt)) {
evt.stopPropagation();
evt.preventDefault();
return false;
}
return true;
});
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent = $entry(function(evt) {
var listener, curElem = this;
while (curElem && !(listener = curElem.__listener)) {
curElem = curElem.parentNode;
}
if (curElem && curElem.nodeType != 1) {
curElem = null;
}
if (listener) {
if (@com.google.gwt.user.client.impl.DOMImpl::isMyListener(Ljava/lang/Object;)(listener)) {
@com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/user/client/Element;Lcom/google/gwt/user/client/EventListener;)(evt, curElem, listener);
}
}
});
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchUnhandledEvent = $entry(function(evt) {
this.__gwtLastUnhandledEvent = evt.type;
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent.call(this, evt);
});
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent = $entry(function(evt) {
var dispatchCapturedEventFn = @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent;
if (dispatchCapturedEventFn(evt)) {
var cap = @com.google.gwt.user.client.impl.DOMImplStandard::captureElem;
if (cap && cap.__listener) {
if (@com.google.gwt.user.client.impl.DOMImpl::isMyListener(Ljava/lang/Object;)(cap.__listener)) {
@com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/user/client/Element;Lcom/google/gwt/user/client/EventListener;)(evt, cap, cap.__listener);
evt.stopPropagation();
}
}
}
});
$wnd.addEventListener('click', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('dblclick', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('mousedown', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('mouseup', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('mousemove', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('mouseover', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('mouseout', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('mousewheel', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('keydown', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent, true);
$wnd.addEventListener('keyup', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent, true);
$wnd.addEventListener('keypress', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent, true);
// Touch and gesture events are not actually mouse events, but we treat
// them as such, so that DOM#setCapture() and DOM#releaseCapture() work.
$wnd.addEventListener('touchstart', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('touchmove', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('touchend', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('touchcancel', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('gesturestart', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('gesturechange', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
$wnd.addEventListener('gestureend', @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedMouseEvent, true);
}-*/;
protected native void sinkEventsImpl(Element elem, int bits) /*-{
var chMask = (elem.__eventBits || 0) ^ bits;
elem.__eventBits = bits;
if (!chMask) return;
if (chMask & 0x00001) elem.onclick = (bits & 0x00001) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00002) elem.ondblclick = (bits & 0x00002) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00004) elem.onmousedown = (bits & 0x00004) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00008) elem.onmouseup = (bits & 0x00008) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00010) elem.onmouseover = (bits & 0x00010) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00020) elem.onmouseout = (bits & 0x00020) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00040) elem.onmousemove = (bits & 0x00040) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00080) elem.onkeydown = (bits & 0x00080) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00100) elem.onkeypress = (bits & 0x00100) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00200) elem.onkeyup = (bits & 0x00200) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00400) elem.onchange = (bits & 0x00400) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x00800) elem.onfocus = (bits & 0x00800) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x01000) elem.onblur = (bits & 0x01000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x02000) elem.onlosecapture = (bits & 0x02000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x04000) elem.onscroll = (bits & 0x04000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x08000) elem.onload = (bits & 0x08000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchUnhandledEvent : null;
if (chMask & 0x10000) elem.onerror = (bits & 0x10000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x20000) elem.onmousewheel = (bits & 0x20000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x40000) elem.oncontextmenu = (bits & 0x40000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x80000) elem.onpaste = (bits & 0x80000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x100000) elem.ontouchstart = (bits & 0x100000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x200000) elem.ontouchmove = (bits & 0x200000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x400000) elem.ontouchend = (bits & 0x400000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x800000) elem.ontouchcancel= (bits & 0x800000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x1000000) elem.ongesturestart =(bits & 0x1000000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x2000000) elem.ongesturechange =(bits & 0x2000000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
if (chMask & 0x4000000) elem.ongestureend = (bits & 0x4000000) ?
@com.google.gwt.user.client.impl.DOMImplStandard::dispatchEvent : null;
}-*/;
private native void releaseCaptureImpl(Element elem) /*-{
if (elem === @com.google.gwt.user.client.impl.DOMImplStandard::captureElem) {
@com.google.gwt.user.client.impl.DOMImplStandard::captureElem = null;
}
}-*/;
private native void setCaptureImpl(Element elem) /*-{
@com.google.gwt.user.client.impl.DOMImplStandard::captureElem = elem;
}-*/;
}