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*/
 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 = new odf.OdfUtils(),
 36         domUtils = new core.DomUtils();
 37 
 38     /**
 39      * Returns true if a given node is odf node or a text node that has a odf parent.
 40      * @param {!Node} node
 41      * @return {!boolean}
 42      */
 43     function shouldRemove(node) {
 44         return odfUtils.isODFNode(node)
 45             || (node.localName === "br" && odfUtils.isLineBreak(node.parentNode))
 46             || (node.nodeType === Node.TEXT_NODE && odfUtils.isODFNode(/** @type {!Node}*/(node.parentNode)));
 47     }
 48 
 49     /**
 50      * Returns true if the supplied node should be automatically collapsed (i.e., removed) if it contains no
 51      * text or ODF character elements. The only element that should always be kept is a paragraph element.
 52      * Paragraph elements can only be deleted through merging
 53      * @param {!Node} node
 54      * @return {!boolean}
 55      */
 56     function isCollapsibleContainer(node) {
 57         return !odfUtils.isParagraph(node) && node !== rootNode && odfUtils.hasNoODFContent(node);
 58     }
 59 
 60     /**
 61      * Merge all child nodes into the node's parent and remove the node entirely
 62      * @param {!Node} targetNode Node to merge into parent
 63      * @return {?Node} Final parent node collapsing ended at
 64      */
 65     function mergeChildrenIntoParent(targetNode) {
 66         var parent;
 67         if (targetNode.nodeType === Node.TEXT_NODE) {
 68             parent = targetNode.parentNode;
 69             parent.removeChild(targetNode);
 70         } else {
 71             // removes all odf nodes
 72             parent = domUtils.removeUnwantedNodes(targetNode, shouldRemove);
 73         }
 74         if (parent && isCollapsibleContainer(parent)) {
 75             return mergeChildrenIntoParent(parent);
 76         }
 77         return parent;
 78     }
 79     this.mergeChildrenIntoParent = mergeChildrenIntoParent;
 80 };