1 /**
  2  * Copyright (C) 2010-2014 KO GmbH <copyright@kogmbh.com>
  3  *
  4  * @licstart
  5  * This file is part of WebODF.
  6  *
  7  * WebODF is free software: you can redistribute it and/or modify it
  8  * under the terms of the GNU Affero General Public License (GNU AGPL)
  9  * as published by the Free Software Foundation, either version 3 of
 10  * the License, or (at your option) any later version.
 11  *
 12  * WebODF is distributed in the hope that it will be useful, but
 13  * WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU Affero General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Affero General Public License
 18  * along with WebODF.  If not, see <http://www.gnu.org/licenses/>.
 19  * @licend
 20  *
 21  * @source: http://www.webodf.org/
 22  * @source: https://github.com/kogmbh/WebODF/
 23  */
 24 
 25 /*global odf, core, Node, NodeFilter*/
 26 
 27 /**
 28  * Defines a set of rules for how elements can be collapsed based on whether they contain ODT content (e.g.,
 29  * text or character elements).
 30  * @constructor
 31  * @param {!Node} rootNode Root text element of the odtDocument
 32  */
 33 odf.CollapsingRules = function CollapsingRules(rootNode) {
 34     "use strict";
 35     var odfUtils = odf.OdfUtils,
 36         domUtils = core.DomUtils;
 37 
 38     /**
 39      * Returns NodeFilter value if a given node is odf node or a text node that has a odf parent.
 40      * @param {!Node} node
 41      * @return {!number}
 42      */
 43     function filterOdfNodesToRemove(node) {
 44         var isToRemove = odfUtils.isODFNode(node)
 45             || (node.localName === "br" && odfUtils.isLineBreak(node.parentNode))
 46             || (node.nodeType === Node.TEXT_NODE && odfUtils.isODFNode(/** @type {!Node}*/(node.parentNode)));
 47         return isToRemove ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
 48     }
 49 
 50     /**
 51      * Returns true if the supplied node should be automatically collapsed (i.e., removed) if it contains no
 52      * text or ODF character elements. The only element that should always be kept is a paragraph element.
 53      * Paragraph elements can only be deleted through merging
 54      * @param {!Node} node
 55      * @return {!boolean}
 56      */
 57     function isCollapsibleContainer(node) {
 58         return !odfUtils.isParagraph(node) && node !== rootNode && odfUtils.hasNoODFContent(node);
 59     }
 60 
 61     /**
 62      * Merge all child nodes into the node's parent and remove the node entirely
 63      * @param {!Node} targetNode Node to merge into parent
 64      * @return {?Node} Final parent node collapsing ended at
 65      */
 66     function mergeChildrenIntoParent(targetNode) {
 67         var parent;
 68         if (targetNode.nodeType === Node.TEXT_NODE) {
 69             parent = targetNode.parentNode;
 70             parent.removeChild(targetNode);
 71         } else {
 72             // removes all odf nodes
 73             parent = domUtils.removeUnwantedNodes(targetNode, filterOdfNodesToRemove);
 74         }
 75         if (parent && isCollapsibleContainer(parent)) {
 76             return mergeChildrenIntoParent(parent);
 77         }
 78         return parent;
 79     }
 80     this.mergeChildrenIntoParent = mergeChildrenIntoParent;
 81 };