blob: 950075558259f2a00be4f3d681560210d390f319 [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.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;
}
}-*/;
}