5e88238f91eaf13ba40d29c262d4ca47363fa3b2
[quanweb.git] / js / ToolTip.js
1 // =======
2 // ToolTip
3
4 var ToolTip = (function () {
5     // =================
6     // Private variables
7     var my = {},
8         bookId = undefined,
9         milliSecs = 500,     // time to wait before displaying tooltip
10         mousePos = {
11             x: undefined,
12             y: undefined
13         },
14         threshold = 10,        // number of pixels that mouse can move before tip is dismissed
15         timer = undefined;
16
17     // ================
18     // Public variables
19     my.booksModel = undefined;
20
21     // ==============
22     // Public Methods
23     
24     // Set the book ID for the details pane, and then show it
25     my.displayDetails = function (newBookId) {
26         bookId = newBookId;
27         my.showDetails();
28     };
29
30     // Hide the details pane, if it is currently visible
31     my.hideDetails = function () {
32         mousePos.x = undefined;
33         mousePos.y = undefined;
34         
35         var elem = document.getElementById('details');
36         elem.innerHTML = '';
37         elem.style.display = 'none';
38     };
39     
40     my.mouseMoved = function (x, y) {
41         // Is there an active tooltip?
42         if (typeof mousePos.x === 'undefined') {
43             // No active tooltip, so nothing further to do
44             return;
45         }
46         
47         var deltaX = Math.abs(x - mousePos.x);
48         var deltaY = Math.abs(y - mousePos.y);
49
50         if (  (deltaX > threshold)
51            || (deltaY > threshold) )
52         {
53             my.stopTooltipTimer();
54             my.hideDetails();
55         }
56     };
57
58     // Show the details pane
59     my.showDetails = function () {
60         var id = bookId;
61         var elem = document.getElementById('details');
62         var index = BooksModel.map[id];
63         var book = BooksModel.cache[index];
64         var html = '<div><p><b>' + book.Title + '</b></p>'
65         + '<p><i>' + ce(book.AuthorReading) + '<br/>' + ce(book.Series) + ' ' + ce(book.Volume) + '</i></p></div><div>'
66         + ce(book.Description)
67         + '</div>';
68
69         // Remember the current mouse (x,y).
70         // If we move the mouse too far from this point, that will trigger hiding the tooltip.
71         mousePos.x = g_state.mousePos.x;
72         mousePos.y = g_state.mousePos.y;
73
74         elem.innerHTML = html;
75
76         elem.style.display = 'block';    // show, and calculate size, so that we can query it below
77         
78         var x = mousePos.x;
79         var y = mousePos.y;
80         
81         var bcr = elem.getBoundingClientRect();
82         
83         var width = bcr.width;
84         var height = bcr.height;
85         
86         x = Math.max(x - (width / 2), 0);
87         y = Math.max(y - (height / 2), 0);
88         
89         elem.style.left = x + 'px';
90         elem.style.top = y + 'px';
91     };
92
93     my.startTooltipTimer = function (newBookId) {
94         if (typeof timer !== 'undefined') {
95             clearTimeout(timer);
96         }
97         bookId = newBookId;
98         timer = setTimeout(my.showDetails, milliSecs);
99     };
100
101     my.stopTooltipTimer = function () {
102         if (typeof timer === 'undefined') {
103             return;
104         }
105         
106         clearTimeout(timer);
107         timer = undefined;
108     };
109     
110     // ===============
111     // Private methods
112     
113     // ce(s):  "clear if empty()"
114     //         return s, unless it's undefined, in which case return an empty ("clear") string
115     function ce(s) {
116         if (typeof s !== 'undefined') {
117             return s;
118         }
119         return '';
120     }
121     
122     return my;
123 })();