<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[161120] trunk/Tools</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/161120">161120</a></dd>
<dt>Author</dt> <dd>ap@apple.com</dd>
<dt>Date</dt> <dd>2013-12-29 09:24:57 -0800 (Sun, 29 Dec 2013)</dd>
</dl>
<h3>Log Message</h3>
<pre>Please display information about pending runs in build.webkit.org/dashboard
https://bugs.webkit.org/show_bug.cgi?id=122180
Reviewed by Timothy Hatcher.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotBuilderQueueView.js:
(BuildbotBuilderQueueView.prototype.update.appendBuilderQueueStatus): Added a semicolon at the end of a line.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotQueueView.js:
(BuildbotQueueView.prototype._latestFinishedIteration): Factored out of _appendPendingRevisionCount.
(BuildbotQueueView.prototype._appendPendingRevisionCount): Install a popover tracker over the element.
(BuildbotQueueView.prototype.lineForCommit): Build an element for a particular commit ot be shown in popover.
(BuildbotQueueView.prototype.presentPopoverForElement): Build and show popover content when PopoverTracker
asks us to.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js: Added.
Taken from WebInspector with minimal changes:
- Changed root name from WebInspector to Dashboard.
- Removed some unused functionality.
- Added Rect.containsPoint.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js: Added.
Popover has extensive changes compared to WebInspector version, only drawing code is the same:
- Fixed to work in scrollable pages - WebInspector version assumes that window
and document coordinates are the same, and also erroneously dismisses a scrollable
popover if scrolling cascades out of it after reaching a bound.
- Simplified API and implementation to Dashboard needs, it is no longer possible to
change content of an existing popover.
- Rewrote visibility tracking to be more complete, and not rely on external tracker
object so much.
- Added code to flash scroll bars when showing a scrollable popover.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js: Added.
Objects of this class show and hide popovers as appropriate for registered active elements.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/StatusLineView.js:
(StatusLineView.prototype.get messageElement): Added an accessor, so that we could
install a popover on message element. It's the only visible element in pending commit
line, but the line has different bounds, so we can't install a popover on it (it
would be incorrectly positioned if we did).
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Trac.js:
(Trac.prototype._convertCommitInfoElementToObject):
- Some trac installations report author in a different element, updated to support that.
- Changed to parse title out of description, because trac titles are ugly. Also,
we get a nice HTML with links from the description.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Utilities.js:
(Node.prototype.isAncestor): Copied from Web Inspector, only changing the form for
consistency with the rest of this file (add a property on prototype with assignment
instead of using Object.defineProperty).
(Node.prototype.isDescendant): Ditto.
(Node.prototype.isSelfOrAncestor): Ditto.
(Node.prototype.isSelfOrDescendant): Ditto.
(DOMTokenList.prototype.contains): Ditto.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css: Added.
Like JS counterpart, mostly lifted from Web Inspector.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/QueueView.css:
Added style rules for pending commits popover.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/StatusLineView.css:
(.status-line.no-bubble .message): Changed to display:inline-block, so that it fits
to content, and we can show the popover in a correct place.
* BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/index.html: Added new files.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsBuildbotBuilderQueueViewjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotBuilderQueueView.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsBuildbotQueueViewjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotQueueView.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsStatusLineViewjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/StatusLineView.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsTracjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Trac.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsUtilitiesjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Utilities.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardStylesQueueViewcss">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/QueueView.css</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardStylesStatusLineViewcss">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/StatusLineView.css</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardindexhtml">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/index.html</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsGeometryjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsPopoverjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsPopoverTrackerjs">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js</a></li>
<li><a href="#trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardStylesPopovercss">trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsBuildbotBuilderQueueViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotBuilderQueueView.js (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotBuilderQueueView.js        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotBuilderQueueView.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx">
</span><span class="cx"> function appendBuilderQueueStatus(queue)
</span><span class="cx"> {
</span><del>- this._appendPendingRevisionCount(queue)
</del><ins>+ this._appendPendingRevisionCount(queue);
</ins><span class="cx">
</span><span class="cx"> var firstRecentFailedIteration = queue.firstRecentFailedIteration;
</span><span class="cx"> if (firstRecentFailedIteration && firstRecentFailedIteration.loaded) {
</span></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsBuildbotQueueViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotQueueView.js (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotQueueView.js        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotQueueView.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -60,42 +60,116 @@
</span><span class="cx"> constructor: BuildbotQueueView,
</span><span class="cx"> __proto__: QueueView.prototype,
</span><span class="cx">
</span><del>- _appendPendingRevisionCount: function(queue)
</del><ins>+ _latestFinishedIteration: function(queue)
</ins><span class="cx"> {
</span><span class="cx"> for (var i = 0; i < queue.iterations.length; ++i) {
</span><span class="cx"> var iteration = queue.iterations[i];
</span><span class="cx"> if (!iteration.loaded || !iteration.finished)
</span><span class="cx"> continue;
</span><ins>+ return iteration;
+ }
+ return null;
+ },
</ins><span class="cx">
</span><del>- var latestRecordedOpenSourceRevisionNumber = webkitTrac.latestRecordedRevisionNumber;
- if (!latestRecordedOpenSourceRevisionNumber)
- return;
</del><ins>+ _appendPendingRevisionCount: function(queue)
+ {
+ var latestFinishedIteration = this._latestFinishedIteration(queue);
+ if (!latestFinishedIteration)
+ return;
</ins><span class="cx">
</span><del>- var openSourceRevisionsBehind = latestRecordedOpenSourceRevisionNumber - iteration.openSourceRevision;
- if (openSourceRevisionsBehind < 0)
- openSourceRevisionsBehind = 0;
</del><ins>+ var latestRecordedOpenSourceRevisionNumber = webkitTrac.latestRecordedRevisionNumber;
+ if (!latestRecordedOpenSourceRevisionNumber)
+ return;
</ins><span class="cx">
</span><del>- if (iteration.internalRevision) {
- var latestRecordedInternalRevisionNumber = internalTrac.latestRecordedRevisionNumber;
- if (!latestRecordedInternalRevisionNumber)
- return;
</del><ins>+ var openSourceRevisionsBehind = latestRecordedOpenSourceRevisionNumber - latestFinishedIteration.openSourceRevision;
+ if (openSourceRevisionsBehind < 0)
+ openSourceRevisionsBehind = 0;
</ins><span class="cx">
</span><del>- var internalRevisionsBehind = latestRecordedInternalRevisionNumber - iteration.internalRevision;
- if (internalRevisionsBehind < 0)
- internalRevisionsBehind = 0;
- if (openSourceRevisionsBehind || internalRevisionsBehind) {
- var message = openSourceRevisionsBehind + " \uff0b " + internalRevisionsBehind + " revisions behind";
- var status = new StatusLineView(message, StatusLineView.Status.NoBubble);
- this.element.appendChild(status.element);
- }
- } else if (openSourceRevisionsBehind) {
- var message = openSourceRevisionsBehind + " " + (openSourceRevisionsBehind === 1 ? "revision behind" : "revisions behind");
</del><ins>+ if (latestFinishedIteration.internalRevision) {
+ var latestRecordedInternalRevisionNumber = internalTrac.latestRecordedRevisionNumber;
+ if (!latestRecordedInternalRevisionNumber)
+ return;
+
+ var internalRevisionsBehind = latestRecordedInternalRevisionNumber - latestFinishedIteration.internalRevision;
+ if (internalRevisionsBehind < 0)
+ internalRevisionsBehind = 0;
+ if (openSourceRevisionsBehind || internalRevisionsBehind) {
+ var message = openSourceRevisionsBehind + " \uff0b " + internalRevisionsBehind + " revisions behind";
</ins><span class="cx"> var status = new StatusLineView(message, StatusLineView.Status.NoBubble);
</span><span class="cx"> this.element.appendChild(status.element);
</span><span class="cx"> }
</span><ins>+ } else if (openSourceRevisionsBehind) {
+ var message = openSourceRevisionsBehind + " " + (openSourceRevisionsBehind === 1 ? "revision behind" : "revisions behind");
+ var status = new StatusLineView(message, StatusLineView.Status.NoBubble);
+ this.element.appendChild(status.element);
+ }
</ins><span class="cx">
</span><del>- return;
</del><ins>+ if (status)
+ new PopoverTracker(status.messageElement, this, queue);
+ },
+
+ presentPopoverForElement: function(element, popover, queue)
+ {
+ var latestFinishedIteration = this._latestFinishedIteration(queue);
+ if (!latestFinishedIteration)
+ return false;
+
+ function lineForCommit(trac, commit)
+ {
+ var result = document.createElement("div");
+ result.className = "pending-commit";
+
+ var linkElement = document.createElement("a");
+ linkElement.className = "revision";
+ linkElement.href = trac.revisionURL(commit.revisionNumber);
+ linkElement.target = "_blank";
+ linkElement.textContent = "r" + commit.revisionNumber;
+ result.appendChild(linkElement);
+
+ var authorElement = document.createElement("span");
+ authorElement.className = "author";
+ authorElement.textContent = commit.author;
+ result.appendChild(authorElement);
+
+ var titleElement = document.createElement("span");
+ titleElement.className = "title";
+ titleElement.innerHTML = commit.title.innerHTML;
+ result.appendChild(titleElement);
+
+ return result;
</ins><span class="cx"> }
</span><ins>+
+ var content = document.createElement("div");
+ content.className = "pending-commits-popover";
+
+ for (var i = webkitTrac.recordedCommits.length - 1; i >= 0; --i) {
+ var commit = webkitTrac.recordedCommits[i];
+ if (commit.revisionNumber <= latestFinishedIteration.openSourceRevision)
+ break;
+
+ content.appendChild(lineForCommit(webkitTrac, commit));
+ }
+
+ if (latestFinishedIteration.internalRevision && internalTrac.latestRecordedRevisionNumber) {
+ if (latestFinishedIteration.internalRevision < internalTrac.latestRecordedRevisionNumber && content.hasChildNodes()) {
+ var divider = document.createElement("div");
+ divider.className = "divider";
+ content.appendChild(divider);
+ }
+
+ for (var i = internalTrac.recordedCommits.length - 1; i >= 0; --i) {
+ var commit = internalTrac.recordedCommits[i];
+ if (commit.revisionNumber <= latestFinishedIteration.internalRevision)
+ break;
+
+ content.appendChild(lineForCommit(internalTrac, commit));
+ }
+ }
+
+ var rect = Dashboard.Rect.rectFromClientRect(element.getBoundingClientRect());
+ popover.present(rect, content, [Dashboard.RectEdge.MIN_Y, Dashboard.RectEdge.MAX_Y, Dashboard.RectEdge.MAX_X, Dashboard.RectEdge.MIN_X]);
+
+ return true;
</ins><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> revisionLinksForIteration: function(iteration)
</span></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsGeometryjs"></a>
<div class="addfile"><h4>Added: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js (0 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js         (rev 0)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -0,0 +1,223 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+Dashboard.Point = function(x, y)
+{
+ this.x = x || 0;
+ this.y = y || 0;
+};
+
+Dashboard.Point.prototype = {
+ constructor: Dashboard.Point,
+
+ toString : function()
+ {
+ return "Dashboard.Point[" + this.x + "," + this.y + "]";
+ },
+
+ copy: function()
+ {
+ return new Dashboard.Point(this.x, this.y);
+ },
+
+ equals: function(anotherPoint)
+ {
+ return (this.x === anotherPoint.x && this.y === anotherPoint.y);
+ }
+};
+
+Dashboard.Size = function(width, height)
+{
+ this.width = width || 0;
+ this.height = height || 0;
+};
+
+Dashboard.Size.prototype = {
+ constructor: Dashboard.Size,
+
+ toString: function()
+ {
+ return "Dashboard.Size[" + this.width + "," + this.height + "]";
+ },
+
+ copy: function()
+ {
+ return new Dashboard.Size(this.width, this.height);
+ },
+
+ equals: function(anotherSize)
+ {
+ return (this.width === anotherSize.width && this.height === anotherSize.height);
+ }
+};
+
+Dashboard.Size.ZERO_SIZE = new Dashboard.Size(0, 0);
+
+
+Dashboard.Rect = function(x, y, width, height)
+{
+ this.origin = new Dashboard.Point(x || 0, y || 0);
+ this.size = new Dashboard.Size(width || 0, height || 0);
+};
+
+Dashboard.Rect.rectFromClientRect = function(clientRect)
+{
+ return new Dashboard.Rect(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
+};
+
+Dashboard.Rect.prototype = {
+ constructor: Dashboard.Rect,
+
+ toString: function()
+ {
+ return "Dashboard.Rect[" + [this.origin.x, this.origin.y, this.size.width, this.size.height].join(", ") + "]";
+ },
+
+ copy: function()
+ {
+ return new Dashboard.Rect(this.origin.x, this.origin.y, this.size.width, this.size.height);
+ },
+
+ equals: function(anotherRect)
+ {
+ return (this.origin.equals(anotherRect.origin) && this.size.equals(anotherRect.size));
+ },
+
+ inset: function(insets)
+ {
+ return new Dashboard.Rect(
+ this.origin.x + insets.left,
+ this.origin.y + insets.top,
+ this.size.width - insets.left - insets.right,
+ this.size.height - insets.top - insets.bottom
+ );
+ },
+
+ pad: function(padding)
+ {
+ return new Dashboard.Rect(
+ this.origin.x - padding,
+ this.origin.y - padding,
+ this.size.width + padding * 2,
+ this.size.height + padding * 2
+ );
+ },
+
+ minX: function()
+ {
+ return this.origin.x;
+ },
+
+ minY: function()
+ {
+ return this.origin.y;
+ },
+
+ midX: function()
+ {
+ return this.origin.x + (this.size.width / 2);
+ },
+
+ midY: function()
+ {
+ return this.origin.y + (this.size.height / 2);
+ },
+
+ maxX: function()
+ {
+ return this.origin.x + this.size.width;
+ },
+
+ maxY: function()
+ {
+ return this.origin.y + this.size.height;
+ },
+
+ intersectionWithRect: function(rect)
+ {
+ var x1 = Math.max(this.minX(), rect.minX());
+ var x2 = Math.min(this.maxX(), rect.maxX());
+ if (x1 > x2)
+ return Dashboard.Rect.ZERO_RECT;
+ var intersection = new Dashboard.Rect;
+ intersection.origin.x = x1;
+ intersection.size.width = x2 - x1;
+ var y1 = Math.max(this.minY(), rect.minY());
+ var y2 = Math.min(this.maxY(), rect.maxY());
+ if (y1 > y2)
+ return Dashboard.Rect.ZERO_RECT;
+ intersection.origin.y = y1;
+ intersection.size.height = y2 - y1;
+ return intersection;
+ },
+
+ containsPoint: function(point)
+ {
+ return point.x >= this.minX() && point.x <= this.maxX()
+ && point.y >= this.minY() && point.y <= this.maxY();
+ }
+};
+
+Dashboard.Rect.ZERO_RECT = new Dashboard.Rect(0, 0, 0, 0);
+
+
+Dashboard.EdgeInsets = function(top, right, bottom, left)
+{
+ console.assert(arguments.length === 1 || arguments.length === 4);
+
+ if (arguments.length === 1) {
+ this.top = top;
+ this.right = top;
+ this.bottom = top;
+ this.left = top;
+ } else if (arguments.length === 4) {
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ this.left = left;
+ }
+};
+
+Dashboard.EdgeInsets.prototype = {
+ constructor: Dashboard.EdgeInsets,
+
+ equals: function(anotherInset)
+ {
+ return (this.top === anotherInset.top && this.right === anotherInset.right &&
+ this.bottom === anotherInset.bottom && this.left === anotherInset.left);
+ },
+
+ copy: function()
+ {
+ return new Dashboard.EdgeInsets(this.top, this.right, this.bottom, this.left);
+ }
+};
+
+Dashboard.RectEdge = {
+ MIN_X : 0,
+ MIN_Y : 1,
+ MAX_X : 2,
+ MAX_Y : 3
+};
</ins><span class="cx">Property changes on: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsPopoverjs"></a>
<div class="addfile"><h4>Added: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js (0 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js         (rev 0)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -0,0 +1,506 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+Dashboard.Popover = function(delegate)
+{
+ BaseObject.call(this);
+
+ this.delegate = delegate;
+ this._edge = null;
+ this._frame = new Dashboard.Rect;
+ this._content = null;
+ this._targetFrame = new Dashboard.Rect;
+ this._preferredEdges = null;
+
+ this._element = document.createElement("div");
+ this._element.className = Dashboard.Popover.StyleClassName;
+ this._canvasId = "popover-" + (Dashboard.Popover.canvasId++);
+ this._element.style.backgroundImage = "-webkit-canvas(" + this._canvasId + ")";
+ this._element.addEventListener("transitionend", this, true);
+
+ this._container = this._element.appendChild(document.createElement("div"));
+ this._container.className = "container";
+};
+
+Dashboard.Popover.StyleClassName = "popover";
+Dashboard.Popover.VisibleClassName = "visible";
+Dashboard.Popover.StepInClassName = "step-in";
+Dashboard.Popover.FadeOutClassName = "fade-out";
+Dashboard.Popover.PreventDocumentScrollingClassName = "popover-prevent-document-scrolling";
+Dashboard.Popover.canvasId = 0;
+Dashboard.Popover.CornerRadius = 5;
+Dashboard.Popover.MinWidth = 40;
+Dashboard.Popover.MinHeight = 40;
+Dashboard.Popover.ShadowPadding = 5;
+Dashboard.Popover.ContentPadding = 5;
+Dashboard.Popover.AnchorSize = new Dashboard.Size(22, 11);
+Dashboard.Popover.ShadowEdgeInsets = new Dashboard.EdgeInsets(Dashboard.Popover.ShadowPadding);
+
+BaseObject.addConstructorFunctions(Dashboard.Popover);
+
+Dashboard.Popover.prototype = {
+ constructor: Dashboard.Popover,
+ __proto__: BaseObject.prototype,
+
+ // Public
+
+ get element()
+ {
+ return this._element;
+ },
+
+ get frame()
+ {
+ return this._frame;
+ },
+
+ set frame(frame)
+ {
+ this._element.style.left = window.scrollX + frame.origin.x + "px";
+ this._element.style.top = window.scrollY + frame.origin.y + "px";
+ this._element.style.width = frame.size.width + "px";
+ this._element.style.height = frame.size.height + "px";
+ this._element.style.backgroundSize = frame.size.width + "px " + frame.size.height + "px";
+ this._frame = frame;
+ },
+
+ get visible()
+ {
+ return this._element.parentNode === document.body
+ && !this._element.classList.contains(Dashboard.Popover.StepInClassName);
+ },
+
+ /**
+ * @param {Dashboard.Rect} targetFrame
+ * @param {Element} content
+ * @param {Dashboard.RectEdge}[] preferredEdges
+ */
+ present: function(targetFrame, content, preferredEdges)
+ {
+ console.assert(!this._content)
+
+ this._targetFrame = targetFrame;
+ this._content = content;
+ this._preferredEdges = preferredEdges;
+
+ window.addEventListener("mousedown", this, true);
+ window.addEventListener("scroll", this, true);
+
+ this._update();
+
+ this._element.classList.add(Dashboard.Popover.StepInClassName);
+
+ // Scrolling inside a popover should not cascade to document when reaching a bound, because that would make it disappear unexpectedly.
+ if (this._container.offsetHeight < this._container.scrollHeight) {
+ this._element.addEventListener("mouseenter", this, true);
+ this._element.addEventListener("mouseleave", this, true);
+ }
+ },
+
+ makeVisibleImmediately: function()
+ {
+ console.assert(this._content);
+
+ this._finalizePresentation();
+ },
+
+ dismiss: function()
+ {
+ if (this._element.parentNode !== document.body)
+ return;
+
+ this._element.classList.add(Dashboard.Popover.FadeOutClassName);
+ },
+
+ dismissImmediately: function()
+ {
+ if (this._element.parentNode !== document.body)
+ return;
+
+ this._finalizeDismissal();
+ },
+
+ handleEvent: function(event)
+ {
+ switch (event.type) {
+ case "mousedown":
+ case "scroll":
+ if (!this._element.contains(event.target))
+ this.dismissImmediately();
+ break;
+ case "transitionend":
+ if (this._element.classList.contains(Dashboard.Popover.StepInClassName))
+ this._finalizePresentation();
+ else if (this._element.classList.contains(Dashboard.Popover.FadeOutClassName))
+ this._finalizeDismissal();
+ break;
+ case "mouseenter":
+ document.body.classList.add(Dashboard.Popover.PreventDocumentScrollingClassName);
+ break;
+ case "mouseleave":
+ if (!this._element.isSelfOrAncestor(event.toElement))
+ document.body.classList.remove(Dashboard.Popover.PreventDocumentScrollingClassName);
+ break;
+ }
+ },
+
+ // Private
+
+ _update: function()
+ {
+ var targetFrame = this._targetFrame;
+ var preferredEdges = this._preferredEdges;
+
+ // Ensure our element is on display so that its metrics can be resolved
+ // or interrupt any pending transition to remove it from display.
+ if (this._element.parentNode !== document.body)
+ document.body.appendChild(this._element);
+ else
+ this._element.classList.remove(Dashboard.Popover.FadeOutClassName);
+
+ // Reset CSS properties on element so that the element may be sized to fit its content.
+ this._element.style.removeProperty("left");
+ this._element.style.removeProperty("top");
+ this._element.style.removeProperty("width");
+ this._element.style.removeProperty("height");
+ if (this._edge !== null)
+ this._element.classList.remove(this._cssClassNameForEdge());
+
+ // Add the content in place of the wrapper to get the raw metrics.
+ this._element.replaceChild(this._content, this._container);
+
+ // Get the ideal size for the popover to fit its content.
+ var popoverBounds = this._element.getBoundingClientRect();
+ this._preferredSize = new Dashboard.Size(Math.ceil(popoverBounds.width), Math.ceil(popoverBounds.height));
+
+ // The frame of the window with a little inset to make sure we have room for shadows.
+ var containerFrame = new Dashboard.Rect(0, 0, window.innerWidth, window.innerHeight);
+ containerFrame = containerFrame.inset(Dashboard.Popover.ShadowEdgeInsets);
+
+ // Work out the metrics for all edges.
+ var metrics = new Array(preferredEdges.length);
+ for (var edgeName in Dashboard.RectEdge) {
+ var edge = Dashboard.RectEdge[edgeName];
+ var item = {
+ edge: edge,
+ metrics: this._bestMetricsForEdge(this._preferredSize, targetFrame, containerFrame, edge)
+ };
+ var preferredIndex = preferredEdges.indexOf(edge);
+ if (preferredIndex !== -1)
+ metrics[preferredIndex] = item;
+ else
+ metrics.push(item);
+ }
+
+ function area(size)
+ {
+ return size.width * size.height;
+ }
+
+ // Find if any of those fit better than the frame for the preferred edge.
+ var bestEdge = metrics[0].edge;
+ var bestMetrics = metrics[0].metrics;
+ for (var i = 1; i < metrics.length; i++) {
+ var itemMetrics = metrics[i].metrics;
+ if (area(itemMetrics.contentSize) > area(bestMetrics.contentSize)) {
+ bestEdge = metrics[i].edge;
+ bestMetrics = itemMetrics;
+ }
+ }
+
+ var anchorPoint;
+ var bestFrame = bestMetrics.frame;
+
+ this.frame = bestFrame;
+ this._edge = bestEdge;
+
+ if (this.frame === Dashboard.Rect.ZERO_RECT) {
+ // The target for the popover is offscreen.
+ this.dismiss();
+ } else {
+ switch (bestEdge) {
+ case Dashboard.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
+ anchorPoint = new Dashboard.Point(bestFrame.size.width - Dashboard.Popover.ShadowPadding, targetFrame.midY() - bestFrame.minY());
+ break;
+ case Dashboard.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
+ anchorPoint = new Dashboard.Point(Dashboard.Popover.ShadowPadding, targetFrame.midY() - bestFrame.minY());
+ break;
+ case Dashboard.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
+ anchorPoint = new Dashboard.Point(targetFrame.midX() - bestFrame.minX(), bestFrame.size.height - Dashboard.Popover.ShadowPadding);
+ break;
+ case Dashboard.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
+ anchorPoint = new Dashboard.Point(targetFrame.midX() - bestFrame.minX(), Dashboard.Popover.ShadowPadding);
+ break;
+ }
+
+ this._element.classList.add(this._cssClassNameForEdge());
+
+ this._drawBackground(bestEdge, anchorPoint);
+
+ // Make sure content is centered in case either of the dimension is smaller than the minimal bounds.
+ if (this._preferredSize.width < Dashboard.Popover.MinWidth || this._preferredSize.height < Dashboard.Popover.MinHeight)
+ this._container.classList.add("center");
+ else
+ this._container.classList.remove("center");
+ }
+
+ // Wrap the content in the container so that it's located correctly.
+ this._container.textContent = "";
+ this._element.replaceChild(this._container, this._content);
+ this._container.appendChild(this._content);
+ },
+
+ _cssClassNameForEdge: function()
+ {
+ switch (this._edge) {
+ case Dashboard.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
+ return "arrow-right";
+ case Dashboard.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
+ return "arrow-left";
+ case Dashboard.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
+ return "arrow-down";
+ case Dashboard.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
+ return "arrow-up";
+ }
+ console.error("Unknown edge.");
+ return "arrow-up";
+ },
+
+ _drawBackground: function(edge, anchorPoint)
+ {
+ var scaleFactor = window.devicePixelRatio;
+
+ var width = this._frame.size.width;
+ var height = this._frame.size.height;
+ var scaledWidth = width * scaleFactor;
+ var scaledHeight = height * scaleFactor;
+
+ // Create a scratch canvas so we can draw the popover that will later be drawn into
+ // the final context with a shadow.
+ var scratchCanvas = document.createElement("canvas");
+ scratchCanvas.width = scaledWidth;
+ scratchCanvas.height = scaledHeight;
+
+ var ctx = scratchCanvas.getContext("2d");
+ ctx.scale(scaleFactor, scaleFactor);
+
+ // Bounds of the path don't take into account the arrow, but really only the tight bounding box
+ // of the content contained within the frame.
+ var bounds;
+ var arrowHeight = Dashboard.Popover.AnchorSize.height;
+ switch (edge) {
+ case Dashboard.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
+ bounds = new Dashboard.Rect(0, 0, width - arrowHeight, height);
+ break;
+ case Dashboard.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
+ bounds = new Dashboard.Rect(arrowHeight, 0, width - arrowHeight, height);
+ break;
+ case Dashboard.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
+ bounds = new Dashboard.Rect(0, 0, width, height - arrowHeight);
+ break;
+ case Dashboard.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
+ bounds = new Dashboard.Rect(0, arrowHeight, width, height - arrowHeight);
+ break;
+ }
+
+ bounds = bounds.inset(Dashboard.Popover.ShadowEdgeInsets);
+
+ // Clip the frame.
+ ctx.fillStyle = "black";
+ this._drawFrame(ctx, bounds, edge, anchorPoint);
+ ctx.clip();
+
+ // Gradient fill, top-to-bottom.
+ var fillGradient = ctx.createLinearGradient(0, 0, 0, height);
+ fillGradient.addColorStop(0, "rgba(255, 255, 255, 0.95)");
+ fillGradient.addColorStop(1, "rgba(235, 235, 235, 0.95)");
+ ctx.fillStyle = fillGradient;
+ ctx.fillRect(0, 0, width, height);
+
+ // Stroke.
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.25)";
+ ctx.lineWidth = 2;
+ this._drawFrame(ctx, bounds, edge, anchorPoint);
+ ctx.stroke();
+
+ // Draw the popover into the final context with a drop shadow.
+ var finalContext = document.getCSSCanvasContext("2d", this._canvasId, scaledWidth, scaledHeight);
+
+ finalContext.clearRect(0, 0, scaledWidth, scaledHeight);
+
+ finalContext.shadowOffsetX = 1;
+ finalContext.shadowOffsetY = 1;
+ finalContext.shadowBlur = 5;
+ finalContext.shadowColor = "rgba(0, 0, 0, 0.5)";
+
+ finalContext.drawImage(scratchCanvas, 0, 0, scaledWidth, scaledHeight);
+ },
+
+ _bestMetricsForEdge: function(preferredSize, targetFrame, containerFrame, edge)
+ {
+ var x, y;
+ var width = preferredSize.width + (Dashboard.Popover.ShadowPadding * 2) + (Dashboard.Popover.ContentPadding * 2);
+ var height = preferredSize.height + (Dashboard.Popover.ShadowPadding * 2) + (Dashboard.Popover.ContentPadding * 2);
+ var arrowLength = Dashboard.Popover.AnchorSize.height;
+
+ switch (edge) {
+ case Dashboard.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
+ width += arrowLength;
+ x = targetFrame.origin.x - width + Dashboard.Popover.ShadowPadding;
+ y = targetFrame.origin.y - (height - targetFrame.size.height) / 2;
+ break;
+ case Dashboard.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
+ width += arrowLength;
+ x = targetFrame.origin.x + targetFrame.size.width - Dashboard.Popover.ShadowPadding;
+ y = targetFrame.origin.y - (height - targetFrame.size.height) / 2;
+ break;
+ case Dashboard.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
+ height += arrowLength;
+ x = targetFrame.origin.x - (width - targetFrame.size.width) / 2;
+ y = targetFrame.origin.y - height + Dashboard.Popover.ShadowPadding;
+ break;
+ case Dashboard.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
+ height += arrowLength;
+ x = targetFrame.origin.x - (width - targetFrame.size.width) / 2;
+ y = targetFrame.origin.y + targetFrame.size.height - Dashboard.Popover.ShadowPadding;
+ break;
+ }
+
+ if (edge === Dashboard.RectEdge.MIN_X || edge === Dashboard.RectEdge.MAX_X) {
+ if (y < containerFrame.minY())
+ y = containerFrame.minY();
+ if (y + height > containerFrame.maxY())
+ y = containerFrame.maxY() - height;
+ } else {
+ if (x < containerFrame.minX())
+ x = containerFrame.minX();
+ if (x + width > containerFrame.maxX())
+ x = containerFrame.maxX() - width;
+ }
+
+ var preferredFrame = new Dashboard.Rect(x, y, width, height);
+ var bestFrame = preferredFrame.intersectionWithRect(containerFrame);
+
+ width = bestFrame.size.width - (Dashboard.Popover.ShadowPadding * 2);
+ height = bestFrame.size.height - (Dashboard.Popover.ShadowPadding * 2);
+
+ switch (edge) {
+ case Dashboard.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
+ case Dashboard.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
+ width -= arrowLength;
+ break;
+ case Dashboard.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
+ case Dashboard.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
+ height -= arrowLength;
+ break;
+ }
+
+ return {
+ frame: bestFrame,
+ contentSize: new Dashboard.Size(width, height)
+ };
+ },
+
+ _drawFrame: function(ctx, bounds, anchorEdge, anchorPoint)
+ {
+ var r = Dashboard.Popover.CornerRadius;
+ var arrowHalfLength = Dashboard.Popover.AnchorSize.width / 2;
+
+ ctx.beginPath();
+ switch (anchorEdge) {
+ case Dashboard.RectEdge.MIN_X: // Displayed on the left of the target, arrow points right.
+ ctx.moveTo(bounds.maxX(), bounds.minY() + r);
+ ctx.lineTo(bounds.maxX(), anchorPoint.y - arrowHalfLength);
+ ctx.lineTo(anchorPoint.x, anchorPoint.y);
+ ctx.lineTo(bounds.maxX(), anchorPoint.y + arrowHalfLength);
+ ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), r);
+ ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), r);
+ ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), r);
+ ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), r);
+ break;
+ case Dashboard.RectEdge.MAX_X: // Displayed on the right of the target, arrow points left.
+ ctx.moveTo(bounds.minX(), bounds.maxY() - r);
+ ctx.lineTo(bounds.minX(), anchorPoint.y + arrowHalfLength);
+ ctx.lineTo(anchorPoint.x, anchorPoint.y);
+ ctx.lineTo(bounds.minX(), anchorPoint.y - arrowHalfLength);
+ ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), r);
+ ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), r);
+ ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), r);
+ ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), r);
+ break;
+ case Dashboard.RectEdge.MIN_Y: // Displayed above the target, arrow points down.
+ ctx.moveTo(bounds.maxX() - r, bounds.maxY());
+ ctx.lineTo(anchorPoint.x + arrowHalfLength, bounds.maxY());
+ ctx.lineTo(anchorPoint.x, anchorPoint.y);
+ ctx.lineTo(anchorPoint.x - arrowHalfLength, bounds.maxY());
+ ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), r);
+ ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), r);
+ ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), r);
+ ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), r);
+ break;
+ case Dashboard.RectEdge.MAX_Y: // Displayed below the target, arrow points up.
+ ctx.moveTo(bounds.minX() + r, bounds.minY());
+ ctx.lineTo(anchorPoint.x - arrowHalfLength, bounds.minY());
+ ctx.lineTo(anchorPoint.x, anchorPoint.y);
+ ctx.lineTo(anchorPoint.x + arrowHalfLength, bounds.minY());
+ ctx.arcTo(bounds.maxX(), bounds.minY(), bounds.maxX(), bounds.maxY(), r);
+ ctx.arcTo(bounds.maxX(), bounds.maxY(), bounds.minX(), bounds.maxY(), r);
+ ctx.arcTo(bounds.minX(), bounds.maxY(), bounds.minX(), bounds.minY(), r);
+ ctx.arcTo(bounds.minX(), bounds.minY(), bounds.maxX(), bounds.minY(), r);
+ break;
+ }
+ ctx.closePath();
+ },
+
+ _finalizePresentation: function()
+ {
+ var wasVisible = this.visible;
+ this._element.classList.remove(Dashboard.Popover.StepInClassName);
+ this._element.classList.remove(Dashboard.Popover.FadeOutClassName);
+ this._element.classList.add(Dashboard.Popover.VisibleClassName);
+
+ // Make scroll bar flash if present, so that the user sees that scrolling is possible.
+ // FIXME: Is there a better way?
+ if (!wasVisible) {
+ this._container.scrollTop = 1;
+ this._container.scrollTop = 0;
+ }
+ },
+
+ _finalizeDismissal: function()
+ {
+ window.removeEventListener("mousedown", this, true);
+ window.removeEventListener("scroll", this, true);
+
+ document.body.removeChild(this._element);
+ document.body.classList.remove(Dashboard.Popover.PreventDocumentScrollingClassName);
+ this._element.classList.remove(Dashboard.Popover.VisibleClassName);
+ this._element.classList.remove(Dashboard.Popover.StepInClassName);
+ this._element.classList.remove(Dashboard.Popover.FadeOutClassName);
+ this._container.textContent = "";
+ if (this.delegate && typeof this.delegate.didDismissPopover === "function")
+ this.delegate.didDismissPopover(this);
+ }
+};
</ins><span class="cx">Property changes on: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsPopoverTrackerjs"></a>
<div class="addfile"><h4>Added: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js (0 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js         (rev 0)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -0,0 +1,102 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+PopoverTracker = function(element, delegate, context)
+{
+ BaseObject.call(this);
+
+ this._element = element;
+ this._delegate = delegate;
+ this._context = context;
+ this._active = false;
+
+ element.addEventListener("mouseenter", this._mouseEnteredPopoverOrElement.bind(this), true);
+ element.addEventListener("mouseleave", this._mouseExitedPopoverOrElement.bind(this), true);
+};
+
+PopoverTracker._popover = null; // Only one popover may be active at any time.
+
+BaseObject.addConstructorFunctions(PopoverTracker);
+
+PopoverTracker.prototype = {
+ constructor: PopoverTracker,
+ __proto__: BaseObject.prototype,
+
+ _mouseEnteredPopoverOrElement: function(event)
+ {
+ var popover = PopoverTracker._popover;
+ var popoverWasVisible = popover && popover.visible;
+ if (popover) {
+ // Abort fade-out when re-entering the same element or an existing popover.
+ if ((this._active && this._element.isSelfOrAncestor(event.toElement))
+ || popover.element.isSelfOrAncestor(event.toElement)) {
+ popover.makeVisibleImmediately();
+ return;
+ }
+
+ // We entered a different element, dismiss the old popover.
+ popover.dismissImmediately();
+ }
+ console.assert(!PopoverTracker._popover);
+
+ if (!this._delegate || !this._delegate.presentPopoverForElement || typeof this._delegate.presentPopoverForElement != "function")
+ return;
+
+ var popover = new Dashboard.Popover(this);
+ if (!this._delegate.presentPopoverForElement(event.target, popover, this._context))
+ return;
+
+ if (popoverWasVisible)
+ popover.makeVisibleImmediately();
+
+ this._active = true;
+ PopoverTracker._popover = popover;
+ popover.element.addEventListener("mouseenter", this._mouseEnteredPopoverOrElement.bind(this), true);
+ popover.element.addEventListener("mouseleave", this._mouseExitedPopoverOrElement.bind(this), true);
+ },
+
+ _mouseExitedPopoverOrElement: function(event)
+ {
+ var popover = PopoverTracker._popover;
+
+ if (!popover)
+ return;
+
+ if (this._element.isSelfOrAncestor(event.toElement) || popover.element.isSelfOrAncestor(event.toElement))
+ return;
+
+ if (popover.visible)
+ popover.dismiss();
+ else
+ popover.dismissImmediately();
+ },
+
+ didDismissPopover: function(popover)
+ {
+ console.assert(popover === PopoverTracker._popover);
+ this._active = false;
+ PopoverTracker._popover = null;
+ }
+};
</ins><span class="cx">Property changes on: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsStatusLineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/StatusLineView.js (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/StatusLineView.js        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/StatusLineView.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -160,5 +160,10 @@
</span><span class="cx"> } else {
</span><span class="cx"> this._messageElement.textContent = x;
</span><span class="cx"> }
</span><ins>+ },
+
+ get messageElement()
+ {
+ return this._messageElement;
</ins><span class="cx"> }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsTracjs"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Trac.js (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Trac.js        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Trac.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -70,13 +70,32 @@
</span><span class="cx"> var link = doc.evaluate("./link", commitElement, null, XPathResult.STRING_TYPE).stringValue;
</span><span class="cx"> var revisionNumber = parseInt(/\d+$/.exec(link))
</span><span class="cx">
</span><del>- var title = doc.evaluate("./title", commitElement, null, XPathResult.STRING_TYPE).stringValue;
- title = title.replace(/^Changeset \[\d+\]: /, "");
- var author = doc.evaluate("./author", commitElement, null, XPathResult.STRING_TYPE).stringValue;
</del><ins>+ function tracNSResolver(prefix)
+ {
+ if (prefix == "dc")
+ return "http://purl.org/dc/elements/1.1/";
+ return null;
+ }
+
+ var author = doc.evaluate("./author|dc:creator", commitElement, tracNSResolver, XPathResult.STRING_TYPE).stringValue;
</ins><span class="cx"> var date = doc.evaluate("./pubDate", commitElement, null, XPathResult.STRING_TYPE).stringValue;
</span><span class="cx"> date = new Date(Date.parse(date));
</span><span class="cx"> var description = doc.evaluate("./description", commitElement, null, XPathResult.STRING_TYPE).stringValue;
</span><span class="cx">
</span><ins>+ // The feed contains a <title>, but it's not parsed as well as what we are getting from description.
+ var parsedDescription = document.createElement("div");
+ parsedDescription.innerHTML = description;
+ var title = document.createElement("div");
+ var node = parsedDescription.firstChild.firstChild;
+ while (node && node.tagName != "BR") {
+ title.appendChild(node.cloneNode(true));
+ node = node.nextSibling;
+ }
+
+ // For some reason, trac titles start with a newline. Delete it.
+ if (title.firstChild && title.firstChild.nodeType == Node.TEXT_NODE && title.firstChild.textContent.length > 0 && title.firstChild.textContent[0] == "\n")
+ title.firstChild.textContent = title.firstChild.textContent.substring(1);
+
</ins><span class="cx"> return {
</span><span class="cx"> revisionNumber: revisionNumber,
</span><span class="cx"> link: link,
</span></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardScriptsUtilitiesjs"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Utilities.js (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Utilities.js        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Utilities.js        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -70,6 +70,36 @@
</span><span class="cx"> request.send();
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+Node.prototype.isAncestor = function(node)
+{
+ if (!node)
+ return false;
+
+ var currentNode = node.parentNode;
+ while (currentNode) {
+ if (this === currentNode)
+ return true;
+ currentNode = currentNode.parentNode;
+ }
+
+ return false;
+}
+
+Node.prototype.isDescendant = function(descendant)
+{
+ return !!descendant && descendant.isAncestor(this);
+}
+
+Node.prototype.isSelfOrAncestor = function(node)
+{
+ return !!node && (node === this || this.isAncestor(node));
+}
+
+Node.prototype.isSelfOrDescendant = function(node)
+{
+ return !!node && (node === this || this.isDescendant(node));
+}
+
</ins><span class="cx"> Element.prototype.removeChildren = function()
</span><span class="cx"> {
</span><span class="cx"> // This has been tested to be the fastest removal method.
</span><span class="lines">@@ -77,6 +107,15 @@
</span><span class="cx"> this.textContent = "";
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+DOMTokenList.prototype.contains = function(string)
+{
+ for (var i = 0, end = this.length; i < end; ++i) {
+ if (this.item(i) === string)
+ return true;
+ }
+ return false;
+}
+
</ins><span class="cx"> Array.prototype.contains = function(value)
</span><span class="cx"> {
</span><span class="cx"> return this.indexOf(value) >= 0;
</span></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardStylesPopovercss"></a>
<div class="addfile"><h4>Added: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css (0 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css         (rev 0)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -0,0 +1,107 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+.popover {
+ position: absolute;
+ min-width: 20px;
+ min-height: 20px;
+ box-sizing: border-box;
+ pointer-events: none;
+ z-index: 1000;
+ opacity: 0;
+}
+
+.popover.arrow-up {
+ padding: 16px 5px 5px 5px;
+}
+
+.popover.arrow-right {
+ padding: 5px 16px 5px 5px;
+}
+
+.popover.arrow-down {
+ padding: 5px 5px 16px 5px;
+}
+
+.popover.arrow-left {
+ padding: 5px 5px 5px 16px;
+}
+
+.popover.visible {
+ opacity: 1;
+}
+
+.popover.step-in {
+ transition: opacity 0ms;
+ transition-delay: 1s;
+ opacity: 1;
+}
+
+.popover.fade-out {
+ transition: opacity 350ms;
+ transition-delay: 1s;
+ opacity: 0;
+}
+
+.popover > .container {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ right: 5px;
+ bottom: 5px;
+
+ padding: 5px;
+
+ overflow-y: auto;
+ overflow-x: hidden;
+
+ pointer-events: auto;
+}
+
+.popover > .container.center {
+ display: -webkit-flex;
+ -webkit-justify-content: center;
+ -webkit-align-items: center;
+}
+
+.popover.arrow-up > .container {
+ top: 16px;
+}
+
+.popover.arrow-right > .container {
+ right: 16px;
+}
+
+.popover.arrow-down > .container {
+ bottom: 16px;
+}
+
+.popover.arrow-left > .container {
+ left: 16px;
+}
+
+body.popover-prevent-document-scrolling {
+ overflow: hidden;
+}
</ins><span class="cx">Property changes on: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardStylesQueueViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/QueueView.css (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/QueueView.css        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/QueueView.css        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -39,3 +39,25 @@
</span><span class="cx"> .queue-view .queueLabel:not(:first-child) {
</span><span class="cx"> margin-top: 10px;
</span><span class="cx"> }
</span><ins>+
+.pending-commits-popover > .pending-commit {
+ font-family: "HelveticaNeue-Light", "Helvetica Neue", sans-serif;
+ color: rgb(145, 135, 95);
+ font-size: 12px;
+ text-align: left;
+ padding: 1px 6px 1px 6px;
+ user-select: auto;
+}
+
+.pending-commits-popover > .pending-commit > .author {
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.pending-commits-popover > .pending-commit > .title {
+ color: black;
+}
+
+.pending-commits-popover > .divider {
+ height: 7px;
+}
</ins></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardStylesStatusLineViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/StatusLineView.css (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/StatusLineView.css        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/StatusLineView.css        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -109,6 +109,10 @@
</span><span class="cx"> line-height: 13px;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+.status-line.no-bubble .message {
+ display: inline-block; /* Fit block to content, so that popovers are positioned correctly. */
+}
+
</ins><span class="cx"> .status-line.neutral .label,
</span><span class="cx"> .status-line.neutral .message,
</span><span class="cx"> .status-line.no-bubble .label,
</span></span></pre></div>
<a id="trunkToolsBuildSlaveSupportbuildwebkitorgconfigpublic_htmldashboardindexhtml"></a>
<div class="modfile"><h4>Modified: trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/index.html (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/index.html        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/index.html        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> <title>WebKit Bot Watcher's Dashboard</title>
</span><span class="cx">
</span><span class="cx"> <link rel="stylesheet" href="Styles/Main.css"></link>
</span><ins>+ <link rel="stylesheet" href="Styles/Popover.css"></link>
</ins><span class="cx"> <link rel="stylesheet" href="Styles/QueueView.css"></link>
</span><span class="cx"> <link rel="stylesheet" href="Styles/StatusLineView.css"></link>
</span><span class="cx">
</span><span class="lines">@@ -41,6 +42,9 @@
</span><span class="cx"> <script src="Scripts/EWSQueue.js"></script>
</span><span class="cx"> <script src="Scripts/BuildbotIteration.js"></script>
</span><span class="cx"> <script src="Scripts/BuildbotTestResults.js"></script>
</span><ins>+ <script src="Scripts/Geometry.js"></script>
+ <script src="Scripts/Popover.js"></script>
+ <script src="Scripts/PopoverTracker.js"></script>
</ins><span class="cx"> <script src="Scripts/QueueView.js"></script>
</span><span class="cx"> <script src="Scripts/BuildbotQueueView.js"></script>
</span><span class="cx"> <script src="Scripts/BuildbotBuilderQueueView.js"></script>
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (161119 => 161120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2013-12-29 16:44:14 UTC (rev 161119)
+++ trunk/Tools/ChangeLog        2013-12-29 17:24:57 UTC (rev 161120)
</span><span class="lines">@@ -1,3 +1,73 @@
</span><ins>+2013-12-29 Alexey Proskuryakov <ap@apple.com>
+
+ Please display information about pending runs in build.webkit.org/dashboard
+ https://bugs.webkit.org/show_bug.cgi?id=122180
+
+ Reviewed by Timothy Hatcher.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotBuilderQueueView.js:
+ (BuildbotBuilderQueueView.prototype.update.appendBuilderQueueStatus): Added a semicolon at the end of a line.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/BuildbotQueueView.js:
+ (BuildbotQueueView.prototype._latestFinishedIteration): Factored out of _appendPendingRevisionCount.
+ (BuildbotQueueView.prototype._appendPendingRevisionCount): Install a popover tracker over the element.
+ (BuildbotQueueView.prototype.lineForCommit): Build an element for a particular commit ot be shown in popover.
+ (BuildbotQueueView.prototype.presentPopoverForElement): Build and show popover content when PopoverTracker
+ asks us to.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Geometry.js: Added.
+ Taken from WebInspector with minimal changes:
+ - Changed root name from WebInspector to Dashboard.
+ - Removed some unused functionality.
+ - Added Rect.containsPoint.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Popover.js: Added.
+ Popover has extensive changes compared to WebInspector version, only drawing code is the same:
+ - Fixed to work in scrollable pages - WebInspector version assumes that window
+ and document coordinates are the same, and also erroneously dismisses a scrollable
+ popover if scrolling cascades out of it after reaching a bound.
+ - Simplified API and implementation to Dashboard needs, it is no longer possible to
+ change content of an existing popover.
+ - Rewrote visibility tracking to be more complete, and not rely on external tracker
+ object so much.
+ - Added code to flash scroll bars when showing a scrollable popover.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/PopoverTracker.js: Added.
+ Objects of this class show and hide popovers as appropriate for registered active elements.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/StatusLineView.js:
+ (StatusLineView.prototype.get messageElement): Added an accessor, so that we could
+ install a popover on message element. It's the only visible element in pending commit
+ line, but the line has different bounds, so we can't install a popover on it (it
+ would be incorrectly positioned if we did).
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Trac.js:
+ (Trac.prototype._convertCommitInfoElementToObject):
+ - Some trac installations report author in a different element, updated to support that.
+ - Changed to parse title out of description, because trac titles are ugly. Also,
+ we get a nice HTML with links from the description.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Scripts/Utilities.js:
+ (Node.prototype.isAncestor): Copied from Web Inspector, only changing the form for
+ consistency with the rest of this file (add a property on prototype with assignment
+ instead of using Object.defineProperty).
+ (Node.prototype.isDescendant): Ditto.
+ (Node.prototype.isSelfOrAncestor): Ditto.
+ (Node.prototype.isSelfOrDescendant): Ditto.
+ (DOMTokenList.prototype.contains): Ditto.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/Popover.css: Added.
+ Like JS counterpart, mostly lifted from Web Inspector.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/QueueView.css:
+ Added style rules for pending commits popover.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/Styles/StatusLineView.css:
+ (.status-line.no-bubble .message): Changed to display:inline-block, so that it fits
+ to content, and we can show the popover in a correct place.
+
+ * BuildSlaveSupport/build.webkit.org-config/public_html/dashboard/index.html: Added new files.
+
</ins><span class="cx"> 2013-12-27 Gavin Barraclough <barraclough@apple.com>
</span><span class="cx">
</span><span class="cx"> Merge PageVisibilityState & ViewState::IsVisible in WebKit2
</span></span></pre>
</div>
</div>
</body>
</html>