results.webkit.org: Fix tooltip with drawer
authorjbedard@apple.com <jbedard@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Oct 2019 03:14:44 +0000 (03:14 +0000)
committerjbedard@apple.com <jbedard@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Oct 2019 03:14:44 +0000 (03:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203527

Rubber-stamped by Aakash Jain.

The interaction between tooltips and drawers needs improvement, tooltips
are inconsistently under the drawer, do not treat the drawer as a boundary.

* resultsdbpy/resultsdbpy/view/static/css/tooltip.css:
(.tooltip): Use topZIndex variable.
* resultsdbpy/resultsdbpy/view/static/js/timeline.js:
(xAxisFromScale): Pass viewport to ToolTip.
(TimelineFromEndpoint): Ditto.
(TimelineFromEndpoint.prototype.update): Ditto.
(TimelineFromEndpoint.prototype.render): Ditto.
(TimelineFromEndpoint.prototype.render.onDotEnterFactory): Ditto.
* resultsdbpy/resultsdbpy/view/static/js/tooltip.js:
(_ToolTip.prototype.toString): Use passed viewport instead of the document size.
(_ToolTip.prototype.setByElement): Set the viewport based on the passed viewport.
* resultsdbpy/resultsdbpy/view/templates/search.html: Define the viewport as the
content element.
* resultsdbpy/resultsdbpy/view/templates/suite_results.html: Ditto.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251763 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/resultsdbpy/resultsdbpy/view/static/css/tooltip.css
Tools/resultsdbpy/resultsdbpy/view/static/js/timeline.js
Tools/resultsdbpy/resultsdbpy/view/static/js/tooltip.js
Tools/resultsdbpy/resultsdbpy/view/templates/search.html
Tools/resultsdbpy/resultsdbpy/view/templates/suite_results.html

index a96fce4..8ef6900 100644 (file)
@@ -1,3 +1,28 @@
+2019-10-29  Jonathan Bedard  <jbedard@apple.com>
+
+        results.webkit.org: Fix tooltip with drawer
+        https://bugs.webkit.org/show_bug.cgi?id=203527
+
+        Rubber-stamped by Aakash Jain.
+
+        The interaction between tooltips and drawers needs improvement, tooltips
+        are inconsistently under the drawer, do not treat the drawer as a boundary.
+
+        * resultsdbpy/resultsdbpy/view/static/css/tooltip.css:
+        (.tooltip): Use topZIndex variable.
+        * resultsdbpy/resultsdbpy/view/static/js/timeline.js:
+        (xAxisFromScale): Pass viewport to ToolTip.
+        (TimelineFromEndpoint): Ditto.
+        (TimelineFromEndpoint.prototype.update): Ditto.
+        (TimelineFromEndpoint.prototype.render): Ditto.
+        (TimelineFromEndpoint.prototype.render.onDotEnterFactory): Ditto.
+        * resultsdbpy/resultsdbpy/view/static/js/tooltip.js:
+        (_ToolTip.prototype.toString): Use passed viewport instead of the document size.
+        (_ToolTip.prototype.setByElement): Set the viewport based on the passed viewport.
+        * resultsdbpy/resultsdbpy/view/templates/search.html: Define the viewport as the
+        content element.
+        * resultsdbpy/resultsdbpy/view/templates/suite_results.html: Ditto.
+
 2019-10-29  Jiewen Tan  <jiewen_tan@apple.com>
 
         [WebAuthn] Add more information to _WKWebAuthenticationPanel
index c810429..e9f60cc 100644 (file)
@@ -24,7 +24,7 @@
  */
  
 .tooltip {
-    z-index: 50;
+    z-index: var(--topZIndex);
     position: absolute;
     opacity: 80%;
     width: 0;
index 2a45b13..7f4947d 100644 (file)
@@ -155,7 +155,7 @@ function repositoriesForCommits(commits) {
     return repositories;
 }
 
-function xAxisFromScale(scale, repository, updatesArray, isTop=false)
+function xAxisFromScale(scale, repository, updatesArray, isTop=false, viewport=null)
 {
     function scaleForRepository(scale) {
         return scale.map(node => {
@@ -197,6 +197,7 @@ function xAxisFromScale(scale, repository, updatesArray, isTop=false)
                     return {x: canvas.x + point.x, y: canvas.y + scrollDelta + point.y};
                 }),
                 (event) => {return onScaleClick(node);},
+                viewport,
             );
         },
         onScaleLeave: (event, canvas) => {
@@ -342,7 +343,7 @@ function combineResults() {
 }
 
 class TimelineFromEndpoint {
-    constructor(endpoint, suite = null) {
+    constructor(endpoint, suite = null, viewport = null) {
         this.endpoint = endpoint;
         this.displayAllCommits = true;
 
@@ -355,6 +356,7 @@ class TimelineFromEndpoint {
         this.timelineUpdate = null;
         this.notifyRerender = () => {};
         this.repositories = [];
+        this.viewport = viewport;
 
         const self = this;
 
@@ -398,7 +400,7 @@ class TimelineFromEndpoint {
             let components = [];
 
             newRepositories.forEach(repository => {
-                components.push(xAxisFromScale(scale, repository, this.xaxisUpdates, top));
+                components.push(xAxisFromScale(scale, repository, this.xaxisUpdates, top, this.viewport));
                 top = false;
             });
 
@@ -591,6 +593,7 @@ class TimelineFromEndpoint {
                     agregateData[key] = data[key];
                 });
                 agregateData['configuration'] = new Configuration(partialConfiguration);
+                ToolTip.unset();
                 InvestigateDrawer.expand(self.suite, agregateData, allData);
             }
         }
@@ -658,6 +661,7 @@ class TimelineFromEndpoint {
                         return {x: canvas.x + point.x, y: canvas.y + scrollDelta + point.y};
                     }),
                     (event) => {onDotClickFactory(configuration)(data);},
+                    self.viewport,
                 );
             }
         }
@@ -778,7 +782,7 @@ class TimelineFromEndpoint {
         self.xaxisUpdates = [];
         this.repositories = repositoriesForCommits(commits);
         this.repositories.forEach(repository => {
-            const xAxisComponent = xAxisFromScale(scale, repository, self.xaxisUpdates, top);
+            const xAxisComponent = xAxisFromScale(scale, repository, self.xaxisUpdates, top, self.viewport);
             if (top)
                 children.unshift(xAxisComponent);
             else
index 0f452a3..50976bb 100644 (file)
@@ -43,7 +43,7 @@ class _ToolTip {
     toString() {
         const self = this;
         this.ref = REF.createRef({
-            state: {content: null, points: null},
+            state: {content: null, points: null, viewport: null},
             onElementMount: (element) => {
                 element.addEventListener('mouseleave', (event) => {
                     if (element.style.display === 'none')
@@ -61,7 +61,7 @@ class _ToolTip {
                     DOM.inject(element, '');
                 }
 
-                if (stateDiff.points) {
+                if (stateDiff.points || stateDiff.viewport) {
                     element.style.left = '0px';
                     element.style.top = '0px';
 
@@ -69,8 +69,6 @@ class _ToolTip {
                     const lowerPoint = stateDiff.points.length > 1 && stateDiff.points[1].y > stateDiff.points[0].y ? stateDiff.points[1] : stateDiff.points[0];
                     const scrollDelta = document.documentElement.scrollTop || document.body.scrollTop;
                     const bounds = element.getBoundingClientRect();
-                    const viewportWitdh = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
-                    const viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
 
                     let direction = 'down';
                     let point = upperPoint;
@@ -83,7 +81,7 @@ class _ToolTip {
                         direction = 'left';
                         let tipX = leftPoint.x - 12 - bounds.width;
                         point = rightPoint;
-                        if (tipX < 0 || tipX + bounds.width + (rightPoint.x - leftPoint.x) / 2 < viewportWitdh / 2) {
+                        if (tipX < 0 || tipX + bounds.width + (rightPoint.x - leftPoint.x) / 2 < stateDiff.viewport.x + stateDiff.viewport.width / 2) {
                             direction = 'right';
                             tipX = rightPoint.x + 16;
                             point = rightPoint;
@@ -91,8 +89,8 @@ class _ToolTip {
                         element.style.left = `${tipX}px`;
 
                         let tipY = point.y - bounds.height / 2;
-                        if (tipY + bounds.height > scrollDelta + viewportHeight)
-                            tipY = scrollDelta + viewportHeight - bounds.height;
+                        if (tipY + bounds.height > scrollDelta + stateDiff.viewport.y + stateDiff.viewport.height)
+                            tipY = scrollDelta + stateDiff.viewport.y + stateDiff.viewport.height - bounds.height;
                         if (tipY < 0)
                             tipY = 0;
                         element.style.top = `${tipY}px`;
@@ -100,7 +98,7 @@ class _ToolTip {
                         // Make an effort to place the tooltip in the center of the viewport.
                         let tipY = upperPoint.y - 8 - bounds.height;
                         point = upperPoint;
-                        if (tipY < scrollDelta || tipY + bounds.height + (lowerPoint.y - upperPoint.y) / 2 < scrollDelta + viewportHeight / 2) {
+                        if (tipY < scrollDelta || tipY + bounds.height + (lowerPoint.y - upperPoint.y) / 2 < scrollDelta + stateDiff.viewport.y + stateDiff.viewport.height / 2) {
                             direction = 'up';
                             tipY = lowerPoint.y + 16;
                             point = lowerPoint;
@@ -108,8 +106,8 @@ class _ToolTip {
                         element.style.top = `${tipY}px`;
 
                         let tipX = point.x - bounds.width / 2;
-                        if (tipX + bounds.width > viewportWitdh)
-                            tipX = viewportWitdh - bounds.width;
+                        if (tipX + bounds.width > stateDiff.viewport.x + stateDiff.viewport.width)
+                            tipX = stateDiff.viewport.x + stateDiff.viewport.width - bounds.width;
                         if (tipX < 0)
                             tipX = 0;
                         element.style.left = `${tipX}px`;
@@ -168,7 +166,7 @@ class _ToolTip {
             <div class="tooltip-content" ref="${this.ref}">
             </div>`;
     }
-    set(content, points, onArrowClick = null) {
+    set(content, points, onArrowClick = null, viewport = null) {
         if (!this.ref) {
             console.error('Cannot set ToolTip content, no tooltip on the page');
             return;
@@ -178,9 +176,29 @@ class _ToolTip {
             return;
         }
         this.onArrowClick = onArrowClick;
-        this.ref.setState({content: content, points: points});
+
+        const windowWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
+        const windowHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
+        if (!viewport)
+            viewport = {
+                x: 0,
+                y: 0,
+                width: windowWidth,
+                height: windowHeight,
+            }
+        else {
+            let rect = viewport.getBoundingClientRect();
+            viewport = {
+                x: 0,
+                y: 0,
+                width: Math.min(windowWidth, rect.width),
+                height: Math.min(windowHeight, rect.height),
+            };
+        }
+        console.log(viewport);
+        this.ref.setState({content: content, points: points, viewport: viewport});
     }
-    setByElement(content, element, options) {
+    setByElement(content, element, options, viewport = null) {
         const bound = element.getBoundingClientRect();
         const orientation = options.orientation ? options.orientation : this.VERTICAL;
         const onArrowClick = options.onArrowClick ? options.onArrowClick : null;
@@ -194,12 +212,12 @@ class _ToolTip {
             this.set(content, [
                 {x: bound.right, y: (bound.top + bound.bottom) / 2 + scrollDelta},
                 {x: bound.left, y: (bound.top + bound.bottom) / 2 + scrollDelta},
-            ], onArrowClick);
+            ], onArrowClick, viewport);
         } else {
             this.set(content, [
                 {x: (bound.right + bound.left) / 2, y: bound.top + scrollDelta},
                 {x: (bound.right + bound.left) / 2, y: bound.bottom + scrollDelta},
-            ], onArrowClick);
+            ], onArrowClick, viewport);
         }
     }
     unset() {
index f14b469..d476d3f 100644 (file)
@@ -222,7 +222,7 @@ onLayoutChange.action(() => {
 window.onpopstate = event => {view.reload();};
 window.onpushstate = event => {view.reload();};
 
-
+let viewport = null;
 DOM.inject(
     document.getElementById('app'),
     `${ToolTip}
@@ -242,7 +242,14 @@ DOM.inject(
     ], () => onLayoutChange.add())}
 
     <div class="main right-sidebar under-topbar-with-actions">
-        <div class="content">
+        <div class="content" ref=${REF.createRef({
+                onElementMount: (element) => {
+                    view.ref.state.children.forEach((child) => {
+                        child.timeline.viewport = element;
+                    });
+                    viewport = element;
+                }
+            })}>
             ${SearchBar(function () {
                 const splitURL = document.URL.split('?');
                 let params = queryToParams(splitURL[1]);
@@ -259,7 +266,7 @@ DOM.inject(
                     let child = {
                         suite: arguments[i].suite,
                         test: arguments[i].test,
-                        timeline: new TimelineFromEndpoint(`api/results/${arguments[i].suite}/${arguments[i].test}`),
+                        timeline: new TimelineFromEndpoint(`api/results/${arguments[i].suite}/${arguments[i].test}`, null, viewport),
                     }
 
                     view.ref.setState({prepending: [child]});
index 1d04a06..5df0693 100644 (file)
@@ -184,7 +184,13 @@ ${Drawer([
     ConfigurationSelectors(() => {view.reload()}),
 ], () => onLayoutChange.add())}
 <div class="main right-sidebar under-topbar-with-actions">
-    <div class="content">
+    <div class="content" ref=${REF.createRef({
+            onElementMount: (element) => {
+                for (let suite in view.children) {
+                    view.children[suite].viewport = element;
+                }
+            }
+        })}>
         ${view}
     </div>
 </div>`);