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)
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;
}
result += '</a></td>'
+ '<td onclick="displayDetails(' + book.Id + ');" '
- + ' onmouseout="stopTooltipTimer(); hideDetails();" '
+ ' onmouseover="startTooltipTimer(' + book.Id + ');">'
+ '<p><b>' + book.Title + '</b></p>'
+ '<p>'
// 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);
}
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)
}
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 = {};
.then(response => response.json())
.then((jsonValue) => {
console.log('JSON response for info: ', jsonValue);
- report('');
g_state.cache = jsonValue;
refreshLayout();
})
}
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];
+ ce(book.Description)
+ '</div>';
+ // 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);
if (typeof g_state.tooltip.timer === 'undefined') {
return;
}
+
clearTimeout(g_state.tooltip.timer);
g_state.tooltip.timer = undefined;
hideDetails();