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 runtime, odf, gui, core, Node*/
 26 
 27 /**
 28  * Helper functions to retrieve information about an ODF document using a step iterator
 29  * @constructor
 30  */
 31 gui.GuiStepUtils = function GuiStepUtils() {
 32     "use strict";
 33     var odfUtils = new odf.OdfUtils(),
 34         stepUtils = new odf.StepUtils(),
 35         domUtils = new core.DomUtils();
 36 
 37     /**
 38      * Returns the client rectangle for the content bounds at the step iterator's current position.
 39      * Note, if the selected content is really collapsed whitespace, this function will return null.
 40      *
 41      * @param {!core.StepIterator} stepIterator
 42      * @return {?ClientRect}
 43      */
 44     function getContentRect(stepIterator) {
 45         var bounds = stepUtils.getContentBounds(stepIterator),
 46             range,
 47             rect = null;
 48 
 49         if (bounds) {
 50             if (bounds.container.nodeType === Node.TEXT_NODE) {
 51                 range = bounds.container.ownerDocument.createRange();
 52                 range.setStart(bounds.container, bounds.startOffset);
 53                 range.setEnd(bounds.container, bounds.endOffset);
 54                 // *MUST* use the BCR here rather than the individual client rects, as the individual client rects
 55                 // don't support subpixel accuracy. Most browsers *do* support subpixel values for the BCR though
 56                 // (FF, Chrome + IE!!)
 57                 rect = range.getClientRects().length > 0 ? range.getBoundingClientRect() : null;
 58                 if (rect
 59                     && /**@type{!Text}*/(bounds.container).data.substring(bounds.startOffset, bounds.endOffset) === " "
 60                     && rect.width <= 1) {
 61                     // In Chrome, collapsed whitespace still reports a width of 1px. In FF, they report as 0px.
 62                     // Consumers of this function are really wanting the cursor position for a given
 63                     // step, which will actually be the next step in this instance.
 64                     rect = null;
 65                 }
 66                 range.detach();
 67             } else if (odfUtils.isCharacterElement(bounds.container) || odfUtils.isCharacterFrame(bounds.container)) {
 68                 // Want to ignore some invisible document content elements such as annotation anchors.
 69                 rect = domUtils.getBoundingClientRect(bounds.container);
 70             }
 71         }
 72 
 73         return rect;
 74     }
 75     this.getContentRect = getContentRect;
 76 };