001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client.impl;
017:
018: import com.google.gwt.user.client.Element;
019: import com.google.gwt.user.client.Event;
020:
021: /**
022: * Internet Explorer 6 implementation of
023: * {@link com.google.gwt.user.client.impl.DOMImpl}.
024: */
025: class DOMImplIE6 extends DOMImpl {
026:
027: private static Element currentEventTarget;
028:
029: private static native int getBodyClientLeft() /*-{
030: // Standard mode uses $doc.documentElement.clientLeft
031: // Quirks mode uses $doc.body.clientLeft
032: return $doc.documentElement.clientLeft || $doc.body.clientLeft;
033: }-*/;
034:
035: private static native int getBodyClientTop() /*-{
036: // Standards mode uses $doc.documentElement.clientTop
037: // Quirks mode uses $doc.body.clientTop
038: return $doc.documentElement.clientTop || $doc.body.clientTop;
039: }-*/;
040:
041: @Override
042: public native boolean compare(Element elem1, Element elem2) /*-{
043: if (!elem1 && !elem2)
044: return true;
045: else if (!elem1 || !elem2)
046: return false;
047: return (elem1.uniqueID == elem2.uniqueID);
048: }-*/;
049:
050: @Override
051: public native Element createInputRadioElement(String name) /*-{
052: return $doc.createElement("<INPUT type='RADIO' name='" + name + "'>");
053: }-*/;
054:
055: /**
056: * Supports creating a select control with the multiple attribute to work
057: * around a bug in IE6 where changing the multiple attribute in a setAttribute
058: * call can cause subsequent setSelected calls to misbehave. Although this bug
059: * is fixed in IE7, this DOMImpl specialization is used for both IE6 and IE7,
060: * but it should be harmless.
061: */
062: @Override
063: public native Element createSelectElement(boolean multiple) /*-{
064: var html = multiple ? "<SELECT MULTIPLE>" : "<SELECT>";
065: return $doc.createElement(html);
066: }-*/;
067:
068: @Override
069: public native int eventGetClientX(Event evt) /*-{
070: return evt.clientX -
071: @com.google.gwt.user.client.impl.DOMImplIE6::getBodyClientLeft()();
072: }-*/;
073:
074: @Override
075: public native int eventGetClientY(Event evt) /*-{
076: return evt.clientY -
077: @com.google.gwt.user.client.impl.DOMImplIE6::getBodyClientTop()();
078: }-*/;
079:
080: @Override
081: public native Element eventGetCurrentTarget(Event evt) /*-{
082: return @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget;
083: }-*/;
084:
085: @Override
086: public native Element eventGetFromElement(Event evt) /*-{
087: return evt.fromElement ? evt.fromElement : null;
088: }-*/;
089:
090: @Override
091: public native int eventGetMouseWheelVelocityY(Event evt) /*-{
092: return Math.round(-evt.wheelDelta / 40) || -1;
093: }-*/;
094:
095: @Override
096: public native Element eventGetTarget(Event evt) /*-{
097: return evt.srcElement || null;
098: }-*/;
099:
100: @Override
101: public native Element eventGetToElement(Event evt) /*-{
102: return evt.toElement || null;
103: }-*/;
104:
105: @Override
106: public native void eventPreventDefault(Event evt) /*-{
107: evt.returnValue = false;
108: }-*/;
109:
110: @Override
111: public native String eventToString(Event evt) /*-{
112: if (evt.toString) return evt.toString();
113: return "[object Event]";
114: }-*/;
115:
116: @Override
117: public native int getAbsoluteLeft(Element elem) /*-{
118: // Standard mode || Quirks mode.
119: var scrollLeft = $doc.documentElement.scrollLeft || $doc.body.scrollLeft;
120: return (elem.getBoundingClientRect().left + scrollLeft)
121: - @com.google.gwt.user.client.impl.DOMImplIE6::getBodyClientLeft()();
122: }-*/;
123:
124: @Override
125: public native int getAbsoluteTop(Element elem) /*-{
126: // Standard mode || Quirks mode.
127: var scrollTop = $doc.documentElement.scrollTop || $doc.body.scrollTop;
128: return (elem.getBoundingClientRect().top + scrollTop)
129: - @com.google.gwt.user.client.impl.DOMImplIE6::getBodyClientTop()();
130: }-*/;
131:
132: @Override
133: public native Element getChild(Element elem, int index) /*-{
134: var child = elem.children[index];
135: return child || null;
136: }-*/;
137:
138: @Override
139: public native int getChildCount(Element elem) /*-{
140: return elem.children.length;
141: }-*/;
142:
143: @Override
144: public native int getChildIndex(Element parent, Element child) /*-{
145: var count = parent.children.length;
146: for (var i = 0; i < count; ++i) {
147: if (child.uniqueID == parent.children[i].uniqueID)
148: return i;
149: }
150: return -1;
151: }-*/;
152:
153: @Override
154: public native Element getFirstChild(Element elem) /*-{
155: var child = elem.firstChild;
156: return child || null;
157: }-*/;
158:
159: /*
160: * The src may not be set yet because of funky logic in setImgSrc(). See
161: * setImgSrc().
162: */
163: @Override
164: public String getImgSrc(Element img) {
165: return ImageSrcIE6.getImgSrc(img);
166: }
167:
168: @Override
169: public native String getInnerText(Element elem) /*-{
170: var ret = elem.innerText;
171: return (ret == null) ? null : ret;
172: }-*/;
173:
174: @Override
175: public native Element getNextSibling(Element elem) /*-{
176: return elem.nextSibling || null;
177: }-*/;
178:
179: @Override
180: public native Element getParent(Element elem) /*-{
181: var parent = elem.parentElement;
182: return parent || null;
183: }-*/;
184:
185: public native String iframeGetSrc(Element elem) /*-{
186: return elem.src;
187: }-*/;
188:
189: @Override
190: public native void initEventSystem() /*-{
191: // Set up event dispatchers.
192: $wnd.__dispatchEvent = function() {
193: // IE doesn't define event.currentTarget, so we squirrel it away here. It
194: // also seems that IE won't allow you to add expandos to the event object,
195: // so we have to store it in a global. This is ok because only one event
196: // can actually be dispatched at a time.
197: var oldEventTarget = @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget;
198: @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget = this;
199:
200: if ($wnd.event.returnValue == null) {
201: $wnd.event.returnValue = true;
202: if (!@com.google.gwt.user.client.DOM::previewEvent(Lcom/google/gwt/user/client/Event;)($wnd.event)) {
203: @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget = oldEventTarget;
204: return;
205: }
206: }
207:
208: var listener, curElem = this;
209: while (curElem && !(listener = curElem.__listener))
210: curElem = curElem.parentElement;
211:
212: if (listener)
213: @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;)($wnd.event, curElem, listener);
214:
215: @com.google.gwt.user.client.impl.DOMImplIE6::currentEventTarget = oldEventTarget;
216: };
217:
218: $wnd.__dispatchDblClickEvent = function() {
219: var newEvent = $doc.createEventObject();
220: this.fireEvent('onclick', newEvent);
221: if (this.__eventBits & 2)
222: $wnd.__dispatchEvent.call(this);
223: };
224:
225: $doc.body.onclick =
226: $doc.body.onmousedown =
227: $doc.body.onmouseup =
228: $doc.body.onmousemove =
229: $doc.body.onmousewheel =
230: $doc.body.onkeydown =
231: $doc.body.onkeypress =
232: $doc.body.onkeyup =
233: $doc.body.onfocus =
234: $doc.body.onblur =
235: $doc.body.ondblclick = $wnd.__dispatchEvent;
236: }-*/;
237:
238: @Override
239: public native void insertChild(Element parent, Element child,
240: int index) /*-{
241: if (index >= parent.children.length)
242: parent.appendChild(child);
243: else
244: parent.insertBefore(child, parent.children[index]);
245: }-*/;
246:
247: @Override
248: public native void insertListItem(Element select, String text,
249: String value, int index) /*-{
250: // When we try to pass the populated option into this method, IE
251: // chokes, so we create the option here instead.
252: var newOption = new Option(text, value);
253: if (index == -1 || index > select.options.length - 1) {
254: select.add(newOption);
255: } else{
256: select.add(newOption, index);
257: }
258: }-*/;
259:
260: @Override
261: public native boolean isOrHasChild(Element parent, Element child) /*-{
262: while (child) {
263: if (parent.uniqueID == child.uniqueID)
264: return true;
265: child = child.parentElement;
266: }
267: return false;
268: }-*/;
269:
270: @Override
271: public void releaseCapture(Element elem) {
272: maybeInitializeEventSystem();
273: releaseCaptureImpl(elem);
274: }
275:
276: @Override
277: public void setCapture(Element elem) {
278: maybeInitializeEventSystem();
279: setCaptureImpl(elem);
280: }
281:
282: /**
283: * Works around an IE problem where multiple images trying to load at the same
284: * time will generate a request per image. We fix this by only allowing the
285: * first image of a given URL to set its source immediately, but simultaneous
286: * requests for the same URL don't actually get their source set until the
287: * original load is complete.
288: */
289: @Override
290: public void setImgSrc(Element img, String src) {
291: ImageSrcIE6.setImgSrc(img, src);
292: }
293:
294: @Override
295: public native void setInnerText(Element elem, String text) /*-{
296: elem.innerText = text || '';
297: }-*/;
298:
299: @Override
300: public void sinkEvents(Element elem, int bits) {
301: maybeInitializeEventSystem();
302: sinkEventsImpl(elem, bits);
303: }
304:
305: @Override
306: public native int windowGetClientHeight() /*-{
307: // IE standard mode || IE quirks mode.
308: return $doc.documentElement.clientHeight || $doc.body.clientHeight;
309: }-*/;
310:
311: @Override
312: public native int windowGetClientWidth() /*-{
313: // IE standard mode || IE quirks mode.
314: return $doc.documentElement.clientWidth || $doc.body.clientWidth;
315: }-*/;
316:
317: private native void releaseCaptureImpl(Element elem) /*-{
318: elem.releaseCapture();
319: }-*/;
320:
321: private native void setCaptureImpl(Element elem) /*-{
322: elem.setCapture();
323: }-*/;
324:
325: private native void sinkEventsImpl(Element elem, int bits) /*-{
326: elem.__eventBits = bits;
327:
328: elem.onclick = (bits & 0x00001) ? $wnd.__dispatchEvent : null;
329: // Add an ondblclick handler if onclick is desired to ensure that
330: // a user's double-click will result in two onclick events
331: elem.ondblclick = (bits & (0x00001 | 0x00002)) ? $wnd.__dispatchDblClickEvent : null;
332: elem.onmousedown = (bits & 0x00004) ? $wnd.__dispatchEvent : null;
333: elem.onmouseup = (bits & 0x00008) ? $wnd.__dispatchEvent : null;
334: elem.onmouseover = (bits & 0x00010) ? $wnd.__dispatchEvent : null;
335: elem.onmouseout = (bits & 0x00020) ? $wnd.__dispatchEvent : null;
336: elem.onmousemove = (bits & 0x00040) ? $wnd.__dispatchEvent : null;
337: elem.onkeydown = (bits & 0x00080) ? $wnd.__dispatchEvent : null;
338: elem.onkeypress = (bits & 0x00100) ? $wnd.__dispatchEvent : null;
339: elem.onkeyup = (bits & 0x00200) ? $wnd.__dispatchEvent : null;
340: elem.onchange = (bits & 0x00400) ? $wnd.__dispatchEvent : null;
341: elem.onfocus = (bits & 0x00800) ? $wnd.__dispatchEvent : null;
342: elem.onblur = (bits & 0x01000) ? $wnd.__dispatchEvent : null;
343: elem.onlosecapture = (bits & 0x02000) ? $wnd.__dispatchEvent : null;
344: elem.onscroll = (bits & 0x04000) ? $wnd.__dispatchEvent : null;
345: elem.onload = (bits & 0x08000) ? $wnd.__dispatchEvent : null;
346: elem.onerror = (bits & 0x10000) ? $wnd.__dispatchEvent : null;
347: elem.onmousewheel = (bits & 0x20000) ? $wnd.__dispatchEvent : null;
348: }-*/;
349:
350: }
|