/* * file: RemoveTextAction.js * * @BEGINLICENSE * Copyright 2010 Brook Novak (email : brooknovak@seaweed-editor.com) * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * @ENDLICENSE */ // @DEPENDS: UndoMan bootstrap.provides("actions.RemoveTextAction"); _registerAction("RemoveText", { /** * Removes text within a single text node. * * @param {Node} textNode The text node to remove text from * * @param {Number} index The index at which to begin removing text from. * Ranges from 0 - textlength - 1 * * @param {Number} length The amount of charactors to remove start from the given index. Must be at least 1 */ exec : function(textNode, index, length) { debug.assert(index >= 0); debug.assert(length > 0); debug.assert(textNode.nodeType == Node.TEXT_NODE); debug.assert((index + length) <= textNode.nodeValue.length); // Avoid removing text from placeholders if (de.doc.isESPlaceHolder(textNode, false) || de.doc.isMNPlaceHolder(textNode, false)) { // Keep current cursor position if (this.flags & de.UndoMan.ExecFlag.UPDATE_SELECTION) { var cDesc = de.cursor.getCurrentCursorDesc(); if (cDesc) this.selAfter = {startNode : cDesc.domNode, startIndex : cDesc.relIndex + (cDesc.domNode.nodeType == Node.TEXT_NODE && cDesc.isRightOf ? 1 : 0)}; } return; } // Check for surrounding whitespace var convertLeftCA, convertRightCA; if (index == 0) { // Look for preceeding whitespace _visitAllNodes(docBody, textNode, false, function(domNode) { if (domNode == textNode) return; var ca = _getCommonAncestor(textNode, domNode); if (_findAncestor(domNode, ca, _isBlockLevel, true)) return false; if (domNode.nodeType == Node.TEXT_NODE && _nodeLength(domNode) > 0) { if (_isAllWhiteSpace(domNode.nodeValue.charAt(_nodeLength(domNode)-1))) { convertLeftCA = ca; return false; } } }); } else { if(_isAllWhiteSpace(textNode.nodeValue.charAt(index-1))) convertLeftCA = textNode; } if ((index + length) == _nodeLength(textNode)) { // Look for proceeding whitespace _visitAllNodes(docBody, textNode, true, function(domNode) { if (domNode == textNode) return; var ca = _getCommonAncestor(textNode, domNode); if (_isBlockLevel(domNode) || _findAncestor(textNode, ca, _isBlockLevel, true)) return false; if (_nodeLength(domNode, 0) > 0) { if (_isAllWhiteSpace(domNode.nodeValue.charAt(0))) { convertRightCA = ca; return false; } } }); } else { if (_isAllWhiteSpace(textNode.nodeValue.charAt(index + length))) convertRightCA = textNode; } var convertTarget = (convertLeftCA && convertRightCA && convertLeftCA != convertRightCA) ? _getCommonAncestor(convertLeftCA, convertRightCA, true) : convertLeftCA || convertRightCA; if (convertTarget) _convertWSToNBSP(convertTarget); // Remove the text _execOp(_Operation.REMOVE_TEXT, textNode, index, length); // Normalize converted white space if (convertTarget) _normalizeNBSP(convertTarget); // See if need to add a placeholder var ph, phParent = de.doc.getEditSectionContainer(textNode); if (phParent && _doesNeedESPlaceholder(phParent)) ph = de.doc.createESPlaceholder(phParent); else { phParent = _findAncestor(textNode, docBody, _isBlockLevel, true) || docBody; if (_doesNeedMNPlaceholder(phParent)) ph = de.doc.createMNPlaceholder(); } // Add the needed placeholder if (ph) _execOp(_Operation.INSERT_NODE, ph, phParent); // Update the selection if requested if (this.flags & de.UndoMan.ExecFlag.UPDATE_SELECTION) { var cDesc = ph ? de.cursor.createCursorDesc(ph, 0, false) : de.cursor.getNearestCursorDesc(textNode, index == 0 ? 0 : index-1, index > 0, false); if (cDesc) this.selAfter = {startNode : cDesc.domNode, startIndex : cDesc.relIndex + (cDesc.domNode.nodeType == Node.TEXT_NODE && cDesc.isRightOf ? 1 : 0)}; } // If the text node is left without text then get rid of it if (_nodeLength(textNode) == 0) _execOp(_Operation.REMOVE_NODE, textNode); } });