From 07fb7c12cff3f05994750100aa4b82a24706ac46 Mon Sep 17 00:00:00 2001 From: Chris Jaekl Date: Sat, 11 Nov 2017 15:44:57 +0900 Subject: [PATCH] Adjust tooltip behaviour. Adds timeout before display, and centres the tip around the current mouse position. --- app/index.html | 2 +- app/lib.css | 2 +- app/lib.js | 95 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 79 insertions(+), 20 deletions(-) diff --git a/app/index.html b/app/index.html index 8bd44c4..61f182d 100644 --- a/app/index.html +++ b/app/index.html @@ -21,7 +21,7 @@ Showing 0 through 0 out of 0 matching books. -
(No books found)
+
(No books found)
(No information available)
diff --git a/app/lib.css b/app/lib.css index 843aded..97d6822 100644 --- a/app/lib.css +++ b/app/lib.css @@ -83,7 +83,7 @@ div.tooltip { display: none; margin: 4px 0px 0px 0px; padding: 3px 3px 3px 3px; - position: fixed; + position: absolute; left: 50; text-decoration: none; top: 50; diff --git a/app/lib.js b/app/lib.js index d59c350..0f70f32 100644 --- a/app/lib.js +++ b/app/lib.js @@ -4,18 +4,29 @@ g_state = { cache: [], count: 0, + mousePos: { // Last known position of the mouse cursor + x: undefined, + y: undefined + }, first: 0, ids: [], last: (-1), map: {}, // map from book.Id to index into cache[] - pageSize: 9, + pageSize: 48, tooltip: { bookId: undefined, milliSecs: 500, // time to wait before displaying tooltip + mousePos: { + x: undefined, + y: undefined + }, + threshold: 10, // number of pixels that mouse can move before tip is dismissed timer: undefined } } +document.onmousemove = onMouseMove; + function adjustPos(setting) { var value = parseInt(setting) @@ -24,7 +35,7 @@ function adjustPos(setting) { return; } - var maxFirst = g_state.count - g_state.pageSize; + var maxFirst = Math.max(0, g_state.count - g_state.pageSize); if (value < 0) { g_state.first = 0; @@ -56,7 +67,6 @@ function bookHtml(book) { } result += '' + '' + '

' + book.Title + '

' + '

' @@ -113,17 +123,55 @@ function constructSearchUrl() { // Set the book ID for the details pane, and then show it function displayDetails(bookId) { - console.log('displayDetails()', bookId); g_state.tooltip.bookId = bookId; showDetails(); } function hideDetails() { + g_state.tooltip.mousePos.x = undefined; + g_state.tooltip.mousePos.y = undefined; + var elem = document.getElementById('details'); - elem.innerHtml = ''; + elem.innerHTML = ''; elem.style.display = 'none'; } +function onMouseMove(event) { + if (typeof event === 'undefined') { + return; + } + + var x = event.pageX; + var y = event.pageY; + + if ( x === g_state.mousePos.x + && y === g_state.mousePos.y) + { + // No change from previous known position. + // Nothing to see (or do) here, move along. + return; + } + + // Remember current mouse (x,y) position + g_state.mousePos.x = x; + g_state.mousePos.y = y; + + // Is there an active tooltip? + if (typeof g_state.tooltip.mousePos.x === 'undefined') { + // No active tooltip, so nothing further to do + return; + } + + var deltaX = Math.abs(x - g_state.tooltip.mousePos.x); + var deltaY = Math.abs(y - g_state.tooltip.mousePos.y); + + if ( deltaX > g_state.tooltip.threshold + || deltaY > g_state.tooltip.threshold ) + { + hideDetails(); + } +} + function onNext() { if (g_state.last < (g_state.count - 1)) { adjustPos(g_state.first + g_state.pageSize); @@ -141,17 +189,12 @@ function onSlide(value) { } function onSearch() { - console.log('onSearch()'); - var url = constructSearchUrl(); - report('Loading data from server, please wait...') - console.log('Fetching: "' + url + '"...') - fetch(url, {method:'GET', cache:'default'}) .then(response => response.json()) .then((jsonValue) => { - console.log('JSON response: ', jsonValue); + // console.log('JSON response: ', jsonValue); g_state.ids = jsonValue g_state.count = g_state.ids.length; g_state.first = (-1) @@ -169,8 +212,6 @@ function onSearch() { } function refreshData() { - report('Loading details for books ' + g_state.first + ' through ' + g_state.last + ', please wait...'); - var i; var url = '/info/?ids='; g_state.map = {}; @@ -187,7 +228,6 @@ function refreshData() { .then(response => response.json()) .then((jsonValue) => { console.log('JSON response for info: ', jsonValue); - report(''); g_state.cache = jsonValue; refreshLayout(); }) @@ -218,8 +258,6 @@ function report(message) { } function showDetails() { - console.log('showDetails()', g_state.tooltip.bookId); - var id = g_state.tooltip.bookId; var elem = document.getElementById('details'); var index = g_state.map[id]; @@ -229,13 +267,33 @@ function showDetails() { + ce(book.Description) + ''; + // Remember the current mouse (x,y). + // If we move the mouse too far from this point, that will trigger hiding the tooltip. + g_state.tooltip.mousePos.x = g_state.mousePos.x; + g_state.tooltip.mousePos.y = g_state.mousePos.y; + elem.innerHTML = html; - elem.style.display = 'block'; + + elem.style.display = 'block'; // show, and calculate size, so that we can query it below + + var x = g_state.mousePos.x; + var y = g_state.mousePos.y; + + var bcr = elem.getBoundingClientRect(); + + var width = bcr.width; + var height = bcr.height; + + x = Math.max(x - (width / 2), 0); + y = Math.max(y - (height / 2), 0); + + elem.style.left = x + 'px'; + elem.style.top = y + 'px'; } function startTooltipTimer(bookId) { if (typeof g_state.tooltip.timer !== 'undefined') { - clearTimer(g_state.tooltip.timer); + clearTimeout(g_state.tooltip.timer); } g_state.tooltip.bookId = bookId; g_state.tooltip.timer = setTimeout(showDetails, g_state.tooltip.milliSecs); @@ -245,6 +303,7 @@ function stopTooltipTimer() { if (typeof g_state.tooltip.timer === 'undefined') { return; } + clearTimeout(g_state.tooltip.timer); g_state.tooltip.timer = undefined; hideDetails(); -- 2.30.2