/* * DomUtilsIE10Impl.java * * Copyright (C) 2009-12 by RStudio, Inc. * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ package org.rstudio.core.client.dom.impl; import com.google.gwt.core.client.JsArrayInteger; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import org.rstudio.core.client.Rectangle; import org.rstudio.core.client.dom.ElementEx; public class DomUtilsIE10Impl implements DomUtilsImpl { public void focus(Element element, boolean alwaysDriveSelection) { ElementEx el = (ElementEx) element; el.focus(); } public native final void collapseSelection(boolean toStart) /*-{ var rng = document.selection.createRange(); rng.collapse(toStart); }-*/; public native final boolean isSelectionCollapsed() /*-{ var rng = document.selection.createRange(); var testRng = rng.duplicate(); testRng.collapse(true); return rng.isEqual(testRng); }-*/; public native final boolean isSelectionInElement(Element element) /*-{ var rng = element.ownerDocument.selection.createRange(); var el = rng.parentElement(); while (el != null) { if (el === element) return true ; el = el.parentNode ; } return false ; }-*/; private native String getSelectionType() /*-{ return document.selection.type; }-*/; public boolean selectionExists() { return !("None".equals(getSelectionType())) && !isSelectionCollapsed(); } public Rectangle getCursorBounds(Document doc) { JsArrayInteger result = getSelectionBoundsInternal(doc); return new Rectangle( result.get(0), result.get(1), result.get(2), result.get(3) ); } private native JsArrayInteger getSelectionBoundsInternal(Document doc) /*-{ var rng = doc.selection.createRange(); return [ rng.boundingLeft, rng.boundingTop, rng.boundingWidth, rng.boundingHeight]; }-*/; private native final Element getSelectionParentElement(Document doc) /*-{ return doc.selection.createRange().parentElement(); }-*/; public native final String replaceSelection(Document doc, String text) /*-{ var rng = doc.selection.createRange(); var orig = rng.text; var html = @org.rstudio.core.client.dom.DomUtils::textToHtml(Ljava/lang/String;)(text); rng.pasteHTML(html); rng.select(); return orig; }-*/; public native final String getSelectionText(Document document) /*-{ var rng = doc.selection.createRange(); return rng.text; }-*/; public int[] getSelectionOffsets(Element container) { if (!isSelectionInElement(container)) return null; JsArrayInteger results = getSelectionOffsetsJs(container); if (results == null) return null; else return new int[] {results.get(0), results.get(1)}; } private native final JsArrayInteger getSelectionOffsetsJs( Element container) /*-{ var rng = container.ownerDocument.body.createTextRange(); rng.moveToElementText(container); rng.collapse(true); var sel = container.ownerDocument.selection.createRange(); var startOffset = 0; var endOffset = 0; // Ideally this would be a binary search instead of linear probing while (rng.compareEndPoints("EndToEnd", sel) < 0) { rng.moveEnd("character"); startOffset++; } while (rng.compareEndPoints("StartToStart", sel) < 0) { rng.moveStart("character"); endOffset++; } if (!rng.isEqual(sel)) return null; else return [startOffset, endOffset]; }-*/; public native final void setSelectionOffsets(Element container, int start, int end) /*-{ var rng = container.ownerDocument.body.createTextRange(); rng.moveToElementText(container); for (var i = 0; i < end; i++) rng.moveEnd('character'); for (var j = 0; j < start; j++) rng.moveStart('character'); var containerRng = container.ownerDocument.body.createTextRange(); containerRng.moveToElementText(container); if (rng.compareEndPoints('EndToEnd', containerRng) > 0) { rng.setEndPoint('EndToEnd', containerRng); } rng.select(); container.focus(); }-*/; public boolean isSelectionAsynchronous() { return true; } @Override public void selectElement(Element el) { throw new UnsupportedOperationException("DomUtilsIE8Impl.selectElement not implemented"); } }