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 gui, odf*/
 26 
 27 /**
 28  * Show ODF fields in an ODT document.
 29  *
 30  * @constructor
 31  * @implements {core.Destroyable}
 32  * @param {!odf.OdfCanvas} odfCanvas
 33  */
 34 gui.OdfFieldView = function(odfCanvas) {
 35     "use strict";
 36     var /**@type{!HTMLStyleElement}*/
 37         style,
 38         document = odfCanvas.getElement().ownerDocument;
 39 
 40     /**
 41      * @return {!HTMLStyleElement}
 42      */
 43     function newStyleSheet() {
 44         var head = document.getElementsByTagName('head').item(0),
 45             sheet = /**@type{!HTMLStyleElement}*/(document.createElement('style')),
 46             /**@type{!string}*/
 47             text = "";
 48 
 49         sheet.type = 'text/css';
 50         sheet.media = 'screen, print, handheld, projection';
 51         odf.Namespaces.forEachPrefix(function(prefix, ns) {
 52             text += "@namespace " + prefix + " url(" + ns + ");\n";
 53         });
 54         sheet.appendChild(document.createTextNode(text));
 55         head.appendChild(sheet);
 56         return sheet;
 57     }
 58 
 59     /**
 60      * @param {!HTMLStyleElement} style
 61      * @return {undefined}
 62      */
 63     function clearCSSStyleSheet(style) {
 64         var stylesheet = /**@type{!CSSStyleSheet}*/(style.sheet),
 65             cssRules = stylesheet.cssRules;
 66 
 67         while (cssRules.length) {
 68             stylesheet.deleteRule(cssRules.length - 1);
 69         }
 70     }
 71 
 72     /**
 73      * @param {!Array.<!string>} selectors
 74      * @param {!string} css
 75      * @return {!string}
 76      */
 77     function createRule(selectors, css) {
 78         return selectors.join(",\n") + "\n" + css + "\n";
 79     }
 80 
 81     /**
 82      * Applies a grey background to all ODF field containers as defined in the container definitions within
 83      * this class.
 84      *
 85      * @return {!string}
 86      */
 87     function generateFieldCSS() {
 88         var /**@type{!Array.<!string>}*/
 89             cssSelectors = odf.OdfSchema.getFields().map(function(prefixedName) { return prefixedName.replace(":", "|"); }),
 90             highlightFields = createRule(cssSelectors, "{ background-color: #D0D0D0; }"),
 91             emptyCssSelectors = cssSelectors.map(function(selector) { return selector + ":empty::after"; }),
 92             // Ensure fields are always visible even if they contain no content
 93             highlightEmptyFields = createRule(emptyCssSelectors, "{ content:' '; white-space: pre; }");
 94 
 95         return highlightFields + "\n" + highlightEmptyFields;
 96     }
 97 
 98     /**
 99      * @return {undefined}
100      */
101     this.showFieldHighlight = function() {
102         style.appendChild(document.createTextNode(generateFieldCSS()));
103     };
104 
105     /**
106      * @return {undefined}
107      */
108     this.hideFieldHighlight = function() {
109         clearCSSStyleSheet(style);
110     };
111 
112     /**
113      * Destroy the object.
114      * Do not access any member of this object after this call.
115      * @param {function(!Error=):undefined} callback
116      * @return {undefined}
117      */
118     this.destroy = function(callback) {
119         if (style.parentNode) {
120             style.parentNode.removeChild(style);
121         }
122         callback();
123     };
124 
125     function init() {
126         style = newStyleSheet();
127     }
128     init();
129 };