1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/**
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * @fileoverview This file provides utility functions for position popups.
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochcr.define('cr.ui', function() {
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  /**
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * Type def for rects as returned by getBoundingClientRect.
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @typedef { {left: number, top: number, width: number, height: number,
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   *             right: number, bottom: number}}
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   */
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  var Rect;
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  /**
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * Enum for defining how to anchor a popup to an anchor element.
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @enum {number}
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   */
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const AnchorType = {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popup's right edge is aligned with the left edge of the anchor.
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popup's top edge is aligned with the top edge of the anchor's top
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * edge.
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BEFORE: 1,  // p: right, a: left, p: top, a: top
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popop's left edge is aligned with the right edge of the anchor.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popup's top edge is aligned with the top edge of the anchor's top
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * edge.
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AFTER: 2,  // p: left a: right, p: top, a: top
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popop's bottom edge is aligned with the top edge of the anchor.
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popup's left edge is aligned with the left edge of the anchor's top
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * edge.
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ABOVE: 3,  // p: bottom, a: top, p: left, a: left
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popop's top edge is aligned with the bottom edge of the anchor.
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The popup's left edge is aligned with the left edge of the anchor's top
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * edge.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BELOW: 4  // p: top, a: bottom, p: left, a: left
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  /**
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * Helper function for positionPopupAroundElement and positionPopupAroundRect.
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {!Rect} anchorRect The rect for the anchor.
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {!HTMLElement} popupElement The element used for the popup.
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {AnchorType} type The type of anchoring to do.
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   */
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  function positionPopupAroundRect(anchorRect, popupElement, type) {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    var popupRect = popupElement.getBoundingClientRect();
60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    var availRect;
61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    var ownerDoc = popupElement.ownerDocument;
62201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    var cs = ownerDoc.defaultView.getComputedStyle(popupElement);
63201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    var docElement = ownerDoc.documentElement;
64201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
65201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (cs.position == 'fixed') {
66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // For 'fixed' positioned popups, the available rectangle should be based
67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // on the viewport rather than the document.
68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      availRect = {
69201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        height: docElement.clientHeight,
70201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        width: docElement.clientWidth,
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        top: 0,
72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        bottom: docElement.clientHeight,
73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        left: 0,
74201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        right: docElement.clientWidth
75201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      };
76201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    } else {
77201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      availRect = popupElement.offsetParent.getBoundingClientRect();
78201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
79201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    var rtl = cs.direction == 'rtl';
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Flip BEFORE, AFTER based on RTL.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rtl) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (type == AnchorType.BEFORE)
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        type = AnchorType.AFTER;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      else if (type == AnchorType.AFTER)
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        type = AnchorType.BEFORE;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Flip type based on available size
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (type) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.BELOW:
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (anchorRect.bottom + popupRect.height > availRect.height &&
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            popupRect.height <= anchorRect.top) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          type = AnchorType.ABOVE;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.ABOVE:
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (popupRect.height > anchorRect.top &&
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            anchorRect.bottom + popupRect.height <= availRect.height) {
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          type = AnchorType.BELOW;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.AFTER:
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (anchorRect.right + popupRect.width > availRect.width &&
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            popupRect.width <= anchorRect.left) {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          type = AnchorType.BEFORE;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.BEFORE:
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (popupRect.width > anchorRect.left &&
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            anchorRect.right + popupRect.width <= availRect.width) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          type = AnchorType.AFTER;
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // flipping done
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    var style = popupElement.style;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Reset all directions.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    style.left = style.right = style.top = style.bottom = 'auto'
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Primary direction
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (type) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.BELOW:
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (anchorRect.bottom + popupRect.height <= availRect.height)
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.top = anchorRect.bottom + 'px';
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.bottom = '0';
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.ABOVE:
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (availRect.height - anchorRect.top >= 0)
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.bottom = availRect.height - anchorRect.top + 'px';
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.top = '0';
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.AFTER:
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (anchorRect.right + popupRect.width <= availRect.width)
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.left = anchorRect.right + 'px';
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.right = '0';
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.BEFORE:
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (availRect.width - anchorRect.left >= 0)
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.right = availRect.width - anchorRect.left + 'px';
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.left = '0';
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Secondary direction
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (type) {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.BELOW:
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.ABOVE:
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (rtl) {
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // align right edges
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (anchorRect.right - popupRect.width >= 0) {
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            style.right = availRect.width - anchorRect.right + 'px';
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // align left edges
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else if (anchorRect.left + popupRect.width <= availRect.width) {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            style.left = anchorRect.left + 'px';
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // not enough room on either side
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            style.right = '0';
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // align left edges
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (anchorRect.left + popupRect.width <= availRect.width) {
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            style.left = anchorRect.left + 'px';
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // align right edges
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else if (anchorRect.right - popupRect.width >= 0) {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            style.right = availRect.width - anchorRect.right + 'px';
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // not enough room on either side
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          } else {
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            style.left = '0';
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.AFTER:
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case AnchorType.BEFORE:
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // align top edges
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (anchorRect.top + popupRect.height <= availRect.height) {
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.top = anchorRect.top + 'px';
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // align bottom edges
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else if (anchorRect.bottom - popupRect.height >= 0) {
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.bottom = availRect.height - anchorRect.bottom + 'px';
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // not enough room on either side
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          style.top = '0';
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  /**
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * Positions a popup element relative to an anchor element. The popup element
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * should have position set to absolute and it should be a child of the body
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * element.
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {!HTMLElement} anchorElement The element that the popup is anchored
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   *     to.
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {!HTMLElement} popupElement The popup element we are positioning.
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {AnchorType} type The type of anchoring we want.
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   */
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  function positionPopupAroundElement(anchorElement, popupElement, type) {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    var anchorRect = anchorElement.getBoundingClientRect();
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    positionPopupAroundRect(anchorRect, popupElement, type);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  /**
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * Positions a popup around a point.
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {number} x The client x position.
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {number} y The client y position.
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {!HTMLElement} popupElement The popup element we are positioning.
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   */
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  function positionPopupAtPoint(x, y, popupElement) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    var rect = {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      left: x,
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top: y,
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width: 0,
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      height: 0,
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      right: x,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bottom: y
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    positionPopupAroundRect(rect, popupElement, AnchorType.BELOW);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Export
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AnchorType: AnchorType,
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    positionPopupAroundElement: positionPopupAroundElement,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    positionPopupAtPoint: positionPopupAtPoint
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch});
241