| /* |
| * 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.ui.impl; |
| |
| import com.google.gwt.dom.client.Element; |
| import com.google.gwt.dom.client.Node; |
| import com.google.gwt.safehtml.shared.annotations.IsSafeHtml; |
| |
| /** |
| * IE6-specific implementation of rich-text editing. |
| */ |
| public class RichTextAreaImplIE8toIE10 extends RichTextAreaImplStandard { |
| |
| /** |
| * Helper method to allow {@link #insertHTML(String)} code to invoke |
| * {@link Node#isOrHasChild(Node)}, which is a JSO instance method. |
| */ |
| private static boolean isOrHasChild(Node parent, Node child) { |
| return parent.isOrHasChild(child); |
| } |
| |
| @Override |
| public Element createElement() { |
| Element elem = super.createElement(); |
| elem.setPropertyString("src", "about:blank"); |
| return elem; |
| } |
| |
| @Override |
| public native void initElement() /*-{ |
| var _this = this; |
| _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::onElementInitializing()(); |
| |
| setTimeout($entry(function() { |
| if (_this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::initializing == false) { |
| return; |
| } |
| |
| // Attempt to set the iframe document's body to 'contentEditable' mode. |
| // There's no way to know when the body will actually be available, so |
| // keep trying every so often until it is. |
| // Note: The body seems to be missing only rarely, so please don't remove |
| // this retry loop just because it's hard to reproduce. |
| var elem = _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| var doc = elem.contentWindow.document; |
| if (!doc.body) { |
| // Retry in 50 ms. Faster would run the risk of pegging the CPU. Slower |
| // would increase the probability of a user-visible delay. |
| setTimeout(arguments.callee, 50); |
| return; |
| } |
| doc.body.contentEditable = true; |
| |
| // Send notification that the iframe has reached design mode. |
| _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::onElementInitialized()(); |
| }, 1)); |
| }-*/; |
| |
| @Override |
| public native void insertHTML(@IsSafeHtml String html) /*-{ |
| try { |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| var doc = elem.contentWindow.document; |
| doc.body.focus(); |
| var tr = doc.selection.createRange(); |
| if (tr == null) { |
| return; |
| } |
| if (!@com.google.gwt.user.client.ui.impl.RichTextAreaImplIE8toIE10::isOrHasChild(*)(doc.body, tr.parentElement())) { |
| return; |
| } |
| tr.pasteHTML(html); |
| } |
| catch (e) { |
| return; |
| } |
| }-*/; |
| |
| @Override |
| protected native String getTextImpl() /*-{ |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| return elem.contentWindow.document.body.innerText; |
| }-*/; |
| |
| @Override |
| protected native void hookEvents() /*-{ |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| var body = elem.contentWindow.document.body; |
| |
| var handler = $entry(function(evt) { |
| // Weird: this code has the context of the script frame, but we need the |
| // event from the edit iframe's window. |
| // this code is shared with all IE implementations (see RichText.gwt.xml) |
| // the event can be passed in as argument (IE9) or from the content window (IE8/7/6) |
| evt = evt || elem.contentWindow.event; |
| @com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;)(evt, elem); |
| }); |
| |
| body.onkeydown = |
| body.onkeyup = |
| body.onkeypress = |
| body.onmousedown = |
| body.onmouseup = |
| body.onmousemove = |
| body.onmouseover = |
| body.onmouseout = |
| body.onclick = handler; |
| |
| elem.contentWindow.onfocus = |
| elem.contentWindow.onblur = handler; |
| }-*/; |
| |
| @Override |
| protected native boolean isEnabledImpl() /*-{ |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| return elem.contentWindow.document.body.contentEditable.toLowerCase() == 'true'; |
| }-*/; |
| |
| @Override |
| protected native void setEnabledImpl(boolean enabled) /*-{ |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| elem.contentWindow.document.body.contentEditable = enabled; |
| }-*/; |
| |
| @Override |
| protected native void setTextImpl(String text) /*-{ |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| elem.contentWindow.document.body.innerText = text; |
| }-*/; |
| |
| @Override |
| protected native void unhookEvents() /*-{ |
| var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; |
| var body = elem.contentWindow.document.body; |
| |
| if (body) { |
| // The body can be undefined in the relatively obscure case that the RTA |
| // is attached and detached before it has a chance to finish initializing. |
| body.onkeydown = |
| body.onkeyup = |
| body.onkeypress = |
| body.onmousedown = |
| body.onmouseup = |
| body.onmousemove = |
| body.onmouseover = |
| body.onmouseout = |
| body.onclick = null; |
| |
| elem.contentWindow.onfocus = |
| elem.contentWindow.onblur = null; |
| } |
| }-*/; |
| } |