blob: 122471f583ccdeca1784bcf689f0e9bbdeb37e3e [file] [log] [blame]
/*
* Copyright 2007 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.user.client.Element;
import com.google.gwt.user.client.Event;
/**
* Mozilla implementation of StandardBrowser. The main difference between
* Mozilla and others is that element comparison must be done using isSameNode()
* (== comparison doesn't always give you the right answer, probably because of
* its JavaScript wrappers for xpcom dom nodes).
*/
class DOMImplMozilla extends DOMImplStandard {
public native boolean compare(Element elem1, Element elem2) /*-{
if (!elem1 && !elem2) {
return true;
} else if (!elem1 || !elem2) {
return false;
}
return (elem1.isSameNode(elem2));
}-*/;
public native int eventGetButton(Event evt) /*-{
// Mozilla and IE disagree on what the button codes for buttons should be.
// Translating to match IE standard.
var button = evt.button;
if(button == 0) {
return 1;
} else if (button == 1) {
return 4;
}
return button || -1;
}-*/;
public native int eventGetMouseWheelVelocityY(Event evt) /*-{
return evt.detail || -1;
}-*/;
public native int getAbsoluteLeft(Element elem) /*-{
// We cannot use DOMImpl here because offsetLeft/Top return erroneous
// values when overflow is not visible. We have to difference screenX
// here due to a change in getBoxObjectFor which causes inconsistencies
// on whether the calculations are inside or outside of the element's
// border.
try {
return $doc.getBoxObjectFor(elem).screenX
- $doc.getBoxObjectFor($doc.documentElement).screenX;
} catch (e) {
// This works around a bug in the FF3 betas. The bug
// should be fixed before they release, so this can
// be removed at a later date.
// https://bugzilla.mozilla.org/show_bug.cgi?id=409111
// DOMException.WRONG_DOCUMENT_ERR == 4
if (e.code == 4) {
return 0;
}
throw e;
}
}-*/;
public native int getAbsoluteTop(Element elem) /*-{
// We cannot use DOMImpl here because offsetLeft/Top return erroneous
// values when overflow is not visible. We have to difference screenY
// here due to a change in getBoxObjectFor which causes inconsistencies
// on whether the calculations are inside or outside of the element's
// border.
try {
return $doc.getBoxObjectFor(elem).screenY
- $doc.getBoxObjectFor($doc.documentElement).screenY;
} catch (e) {
// This works around a bug in the FF3 betas. The bug
// should be fixed before they release, so this can
// be removed at a later date.
// https://bugzilla.mozilla.org/show_bug.cgi?id=409111
// DOMException.WRONG_DOCUMENT_ERR == 4
if (e.code == 4) {
return 0;
}
throw e;
}
}-*/;
public native int getChildIndex(Element parent, Element toFind) /*-{
var count = 0, child = parent.firstChild;
while (child) {
if (child.isSameNode(toFind)) {
return count;
}
if (child.nodeType == 1) {
++count;
}
child = child.nextSibling;
}
return -1;
}-*/;
public void init() {
super.init();
initMozilla();
}
public native boolean isOrHasChild(Element parent, Element child) /*-{
while (child) {
if (parent.isSameNode(child)) {
return true;
}
try {
child = child.parentNode;
} catch(e) {
// Give up on 'Permission denied to get property
// HTMLDivElement.parentNode'
// See https://bugzilla.mozilla.org/show_bug.cgi?id=208427
return false;
}
if (child && (child.nodeType != 1)) {
child = null;
}
}
return false;
}-*/;
public native void releaseCapture(Element elem) /*-{
if (elem.isSameNode($wnd.__captureElem)) {
$wnd.__captureElem = null;
}
}-*/;
public void sinkEvents(Element elem, int bits) {
super.sinkEvents(elem, bits);
sinkEventsMozilla(elem, bits);
}
public native void sinkEventsMozilla(Element elem, int bits) /*-{
if (bits & 0x20000) {
elem.addEventListener('DOMMouseScroll', $wnd.__dispatchEvent, false);
}
}-*/;
public native String toString(Element elem) /*-{
// Basic idea is to use the innerHTML property by copying the node into a
// div and getting the innerHTML
var temp = elem.cloneNode(true);
var tempDiv = $doc.createElement("DIV");
tempDiv.appendChild(temp);
outer = tempDiv.innerHTML;
temp.innerHTML = "";
return outer;
}-*/;
protected native void initMozilla() /*-{
$wnd.addEventListener(
'mouseout',
function(evt) {
var cap = $wnd.__captureElem;
if (cap && !evt.relatedTarget) {
// Mozilla has the interesting habit of sending a mouseout event
// with an 'html' element as the target when the mouse is released
// outside of the browser window.
if ('html' == evt.target.tagName.toLowerCase()) {
// When this occurs, we synthesize a mouseup event, which is
// useful for all sorts of dragging code (like in DialogBox).
var muEvent = $doc.createEvent('MouseEvents');
muEvent.initMouseEvent('mouseup', true, true, $wnd, 0,
evt.screenX, evt.screenY, evt.clientX, evt.clientY, evt.ctrlKey,
evt.altKey, evt.shiftKey, evt.metaKey, evt.button, null);
cap.dispatchEvent(muEvent);
}
}
},
true
);
$wnd.addEventListener('DOMMouseScroll', $wnd.__dispatchCapturedMouseEvent,
true);
}-*/;
}