/** * Copyright (c) 2013-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getRangeBoundingClientRect * @format * @flow */ 'use strict'; var getRangeClientRects = require('./getRangeClientRects'); export type FakeClientRect = { left: number; width: number; right: number; top: number; bottom: number; height: number; }; /** * Like range.getBoundingClientRect() but normalizes for browser bugs. */ function getRangeBoundingClientRect(range: Range): FakeClientRect { // "Return a DOMRect object describing the smallest rectangle that includes // the first rectangle in list and all of the remaining rectangles of which // the height or width is not zero." // http://www.w3.org/TR/cssom-view/#dom-range-getboundingclientrect var rects = getRangeClientRects(range); var top = 0; var right = 0; var bottom = 0; var left = 0; if (rects.length) { // If the first rectangle has 0 width, we use the second, this is needed // because Chrome renders a 0 width rectangle when the selection contains // a line break. if (rects.length > 1 && rects[0].width === 0) { ({ top, right, bottom, left } = rects[1]); } else { ({ top, right, bottom, left } = rects[0]); } for (var ii = 1; ii < rects.length; ii++) { var rect = rects[ii]; if (rect.height !== 0 && rect.width !== 0) { top = Math.min(top, rect.top); right = Math.max(right, rect.right); bottom = Math.max(bottom, rect.bottom); left = Math.min(left, rect.left); } } } return { top, right, bottom, left, width: right - left, height: bottom - top }; } module.exports = getRangeBoundingClientRect;