/* * 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.wysiwyg.client.plugin.image.internal; import org.xwiki.gwt.dom.client.DOMUtils; import org.xwiki.gwt.dom.client.Element; import org.xwiki.gwt.user.client.StringUtils; import org.xwiki.gwt.wysiwyg.client.plugin.image.ImageConfig; import org.xwiki.gwt.wysiwyg.client.plugin.image.ImageConfigDOMWriter; import com.google.gwt.dom.client.ImageElement; import com.google.gwt.dom.client.Node; /** * Overwrites {@link ImageConfigDOMWriter} in order to fix some IE bugs. * * @version $Id: 2460578449e76d5c9fd5c73ada88aeb834f111cd $ */ public class IEImageConfigDOMWriter extends ImageConfigDOMWriter { @Override public void write(ImageConfig imageConfig, ImageElement image) { super.write(imageConfig, image); // Add a non-breaking space after the image if the image is the last visible node inside its closest block-level // ancestor. Without this space the user can't move the caret after the image to add new content inside the // current block-level container. // FIXME: This isn't the right place for this code because this method should affect only the given image. // Ensure that the image is attached, otherwise we can't add the space. if (image.getParentNode() != null && endsBlock(image)) { DOMUtils.getInstance().insertAfter(image.getOwnerDocument().createTextNode("\u00A0"), image); } } /** * @param node a DOM node * @return {@code true} if the given node is not followed by any visible node inside the same block-level container, * {@code false} otherwise */ private boolean endsBlock(Node node) { Node ancestor = node; // Look for an ancestor that is followed by a visible sibling. Stop when a block-level ancestor is found. do { if (getNextVisibleSibling(ancestor) != null) { return false; } ancestor = ancestor.getParentNode(); } while (ancestor != null && DOMUtils.getInstance().isInline(ancestor)); return true; } /** * @param node a DOM node * @return the next visible sibling of the given node * @see #isVisible(Node) */ private Node getNextVisibleSibling(Node node) { Node sibling = node; do { sibling = sibling.getNextSibling(); } while (sibling != null && !isVisible(sibling)); return sibling; } /** * @param node a DOM node * @return {@code true} if the give node is visible, {@code false} otherwise */ private boolean isVisible(Node node) { // We treat BR differently than other elements because it is visible even though it has 0 offset width. return (node.getNodeType() == Node.ELEMENT_NODE && ("br".equalsIgnoreCase(node.getNodeName()) || Element.as( node).getOffsetWidth() > 0)) || !StringUtils.isEmpty(node.getNodeValue()); } }