/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.gwt.dom.client.internal.ie; import org.xwiki.gwt.dom.client.Document; import org.xwiki.gwt.dom.client.internal.DefaultSelection; import org.xwiki.gwt.dom.client.internal.mozilla.NativeSelection; /** * Although Internet Explorer 9+ implements the Selection and Range API it still doesn't support separate selections per * window. If you have an in-line frame, any selection you make inside it will be lost when you focus its parent window. * The child and parent windows have different selection objects but these objects can't have rangeCount greater than 0 * at the same time. If one of them contains a range, the other is empty. * * @version $Id: b15a77bfe8e4133300d3388122eecb77eedb61a0 $ */ public class IESelection extends DefaultSelection { /** * The native selection used when the window is not focused. */ private NativeSelection fakeNativeSelection; /** * Creates a new instance that can be used to control the selection associated with the given document. * * @param document a DOM document */ public IESelection(Document document) { super(NativeSelection.getInstance(document)); fakeNativeSelection = getFakeNativeSelection(document); } @Override protected NativeSelection getNativeSelection() { if (fakeNativeSelection.getRangeCount() > 0) { return fakeNativeSelection; } else { return super.getNativeSelection(); } } /** * @param document a DOM document * @return a fake native selection object that can be used to read the selection of the given document while its * window doesn't have the focus */ private native NativeSelection getFakeNativeSelection(Document document) /*-{ var view = document.defaultView; if (!view.__fakeSelection) { view.__fakeSelection = { rangeCount : 0, addRange : function(range) { this.__savedRange = range; this.rangeCount = 1; }, getRangeAt : function(index) { return this.__savedRange; }, removeAllRanges : function() { this.__savedRange = undefined; this.rangeCount = 0; }, removeRange : function(range) { if (range == this.getRangeAt(0)) { this.removeAllRanges(); } }, __save : function() { if (view.getSelection().rangeCount > 0) { this.addRange(view.getSelection().getRangeAt(0)); } }, __restore : function() { if (this.rangeCount > 0) { view.getSelection().removeAllRanges(); view.getSelection().addRange(this.getRangeAt(0)); this.removeAllRanges(); } } }; var beforeActivateListener = function() { view.__fakeSelection.__restore(); }; // Note that both blur and focusOut are fired after the selection is lost so they are not useful here. var beforeDeactivateListener = function() { view.__fakeSelection.__save(); }; var unloadListener = function() { view.removeEventListener('beforeactivate', beforeActivateListener, false); view.removeEventListener('beforedeactivate', beforeDeactivateListener, false); view.removeEventListener('unload', arguments.callee, false); view = view.__fakeSelection = beforeActivateListener = beforeDeactivateListener = undefined; } view.addEventListener('beforeactivate', beforeActivateListener, false); view.addEventListener('beforedeactivate', beforeDeactivateListener, false); view.addEventListener('unload', unloadListener, false); } return view.__fakeSelection; }-*/; }