summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector/front-end/Popover.js
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:23:55 +0100
committerSteve Block <steveblock@google.com>2010-04-27 17:07:03 +0100
commit692e5dbf12901edacf14812a6fae25462920af42 (patch)
treed62802373a429e0a9dc093b6046c166b2c514285 /WebCore/inspector/front-end/Popover.js
parente24bea4efef1c414137d36a9778aa4e142e10c7d (diff)
downloadexternal_webkit-692e5dbf12901edacf14812a6fae25462920af42.zip
external_webkit-692e5dbf12901edacf14812a6fae25462920af42.tar.gz
external_webkit-692e5dbf12901edacf14812a6fae25462920af42.tar.bz2
Merge webkit.org at r55033 : Initial merge by git
Change-Id: I98a4af828067cc243ec3dc5e5826154dd88074b5
Diffstat (limited to 'WebCore/inspector/front-end/Popover.js')
-rw-r--r--WebCore/inspector/front-end/Popover.js147
1 files changed, 147 insertions, 0 deletions
diff --git a/WebCore/inspector/front-end/Popover.js b/WebCore/inspector/front-end/Popover.js
new file mode 100644
index 0000000..70e4ac9
--- /dev/null
+++ b/WebCore/inspector/front-end/Popover.js
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Popover = function(contentElement)
+{
+ this.element = document.createElement("div");
+ this.element.className = "popover";
+
+ this._popupArrowElement = document.createElement("div");
+ this._popupArrowElement.className = "arrow";
+ this.element.appendChild(this._popupArrowElement);
+
+ this.contentElement = contentElement;
+}
+
+WebInspector.Popover.prototype = {
+ show: function(anchor, preferredWidth, preferredHeight)
+ {
+ // This should not happen, but we hide previous popup to be on the safe side.
+ if (WebInspector.Popover._popoverElement)
+ document.body.removeChild(WebInspector.Popover._popoverElement);
+ WebInspector.Popover._popoverElement = this.element;
+
+ // Temporarily attach in order to measure preferred dimensions.
+ this.contentElement.positionAt(0, 0);
+ document.body.appendChild(this.contentElement);
+ var preferredWidth = preferredWidth || this.contentElement.offsetWidth;
+ var preferredHeight = preferredHeight || this.contentElement.offsetHeight;
+
+ this.contentElement.addStyleClass("content");
+ this.element.appendChild(this.contentElement);
+ document.body.appendChild(this.element);
+ this._positionElement(anchor, preferredWidth, preferredHeight);
+ },
+
+ hide: function()
+ {
+ delete WebInspector.Popover._popoverElement;
+ document.body.removeChild(this.element);
+ },
+
+ _positionElement: function(anchorElement, preferredWidth, preferredHeight)
+ {
+ const borderWidth = 25;
+ const scrollerWidth = 11;
+ const arrowHeight = 10;
+ const arrowOffset = 15;
+
+ // Skinny tooltips are not pretty, their arrow location is not nice.
+ preferredWidth = Math.max(preferredWidth, 50);
+ const totalWidth = window.innerWidth;
+ const totalHeight = window.innerHeight;
+
+ var anchorBox = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight};
+ while (anchorElement !== document.body) {
+ if (anchorElement.scrollLeft)
+ anchorBox.x -= anchorElement.scrollLeft;
+ if (anchorElement.scrollTop)
+ anchorBox.y -= anchorElement.scrollTop;
+ anchorElement = anchorElement.parentElement;
+ }
+
+ var newElementPosition = { x: 0, y: 0, width: preferredWidth + borderWidth * 2, height: preferredHeight + borderWidth * 2 };
+
+ var verticalAlignment;
+ var roomAbove = anchorBox.y;
+ var roomBelow = totalHeight - anchorBox.y - anchorBox.height;
+
+ if (roomAbove > roomBelow) {
+ // Positioning above the anchor.
+ if (anchorBox.y > newElementPosition.height)
+ newElementPosition.y = anchorBox.y - newElementPosition.height;
+ else {
+ newElementPosition.y = 0;
+ newElementPosition.height = anchorBox.y - newElementPosition.y;
+ // Reserve room for vertical scroller anyways.
+ newElementPosition.width += scrollerWidth;
+ }
+ verticalAlignment = "bottom";
+ } else {
+ // Positioning below the anchor.
+ newElementPosition.y = anchorBox.y + anchorBox.height;
+ if (newElementPosition.y + newElementPosition.height >= totalHeight) {
+ newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height;
+ // Reserve room for vertical scroller.
+ newElementPosition.width += scrollerWidth;
+ }
+ // Align arrow.
+ newElementPosition.y -= arrowHeight;
+ verticalAlignment = "top";
+ }
+
+ var horizontalAlignment;
+ if (anchorBox.x + newElementPosition.width < totalWidth) {
+ newElementPosition.x = Math.max(0, anchorBox.x) - borderWidth - arrowOffset;
+ horizontalAlignment = "left";
+ } else if (newElementPosition.width < totalWidth) {
+ newElementPosition.x = totalWidth - newElementPosition.width;
+ horizontalAlignment = "right";
+ // Position arrow accurately.
+ this._popupArrowElement.style.right = totalWidth - anchorBox.x - borderWidth - anchorBox.width + "px";
+ } else {
+ newElementPosition.x = 0;
+ newElementPosition.width = totalWidth;
+ horizontalAlignment = "left";
+ if (verticalAlignment === "bottom")
+ newElementPosition.y -= scrollerWidth;
+ // Position arrow accurately.
+ this._popupArrowElement.style.left = anchorBox.x - borderWidth + "px";
+ }
+
+ // Reserve room for horizontal scroller.
+ newElementPosition.height += scrollerWidth;
+
+ this.element.className = "popover " + verticalAlignment + "-" + horizontalAlignment + "-arrow";
+ this.element.positionAt(newElementPosition.x, newElementPosition.y);
+ this.element.style.width = newElementPosition.width + "px";
+ this.element.style.height = newElementPosition.height + "px";
+ }
+}