PageRenderTime 115ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/files/rgraph/20131231/libraries/RGraph.common.tooltips.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 575 lines | 217 code | 92 blank | 266 comment | 78 complexity | fa6d54284a91bc47cf2e1840d9d0256a MD5 | raw file
  1. /**
  2. * o-------------------------------------------------------------------------------o
  3. * | This file is part of the RGraph package. RGraph is Free software, licensed |
  4. * | under the MIT license - so it's free to use for all purposes. Extended |
  5. * | support is available if required and donations are always welcome! You can |
  6. * | read more here: |
  7. * | http://www.rgraph.net/support |
  8. * o-------------------------------------------------------------------------------o
  9. */
  10. if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'};
  11. /**
  12. * This is used in two functions, hence it's here
  13. */
  14. RGraph.tooltips = {};
  15. RGraph.tooltips.padding = '3px';
  16. RGraph.tooltips.font_face = 'Tahoma';
  17. RGraph.tooltips.font_size = '10pt';
  18. /**
  19. * Shows a tooltip next to the mouse pointer
  20. *
  21. * @param canvas object The canvas element object
  22. * @param text string The tooltip text
  23. * @param int x The X position that the tooltip should appear at. Combined with the canvases offsetLeft
  24. * gives the absolute X position
  25. * @param int y The Y position the tooltip should appear at. Combined with the canvases offsetTop
  26. * gives the absolute Y position
  27. * @param int idx The index of the tooltip in the graph objects tooltip array
  28. * @param object e The event object
  29. */
  30. RGraph.Tooltip = function (obj, text, x, y, idx, e)
  31. {
  32. /**
  33. * chart.tooltip.override allows you to totally take control of rendering the tooltip yourself
  34. */
  35. if (typeof(obj.Get('chart.tooltips.override')) == 'function') {
  36. return obj.Get('chart.tooltips.override')(obj, text, x, y, idx);
  37. }
  38. /**
  39. * Save the X/Y coords
  40. */
  41. var originalX = x;
  42. var originalY = y;
  43. /**
  44. * This facilitates the "id:xxx" format
  45. */
  46. text = RGraph.getTooltipTextFromDIV(text);
  47. /**
  48. * First clear any exising timers
  49. */
  50. var timers = RGraph.Registry.Get('chart.tooltip.timers');
  51. if (timers && timers.length) {
  52. for (i=0; i<timers.length; ++i) {
  53. clearTimeout(timers[i]);
  54. }
  55. }
  56. RGraph.Registry.Set('chart.tooltip.timers', []);
  57. /**
  58. * Hide the context menu if it's currently shown
  59. */
  60. if (obj.Get('chart.contextmenu')) {
  61. RGraph.HideContext();
  62. }
  63. var effect = obj.Get('chart.tooltips.effect') ? obj.Get('chart.tooltips.effect').toLowerCase() : 'fade';
  64. /**
  65. * Show a tool tip
  66. */
  67. var tooltipObj = document.createElement('DIV');
  68. tooltipObj.className = obj.Get('chart.tooltips.css.class');
  69. tooltipObj.style.display = 'none';
  70. tooltipObj.style.position = RGraph.isFixed(obj.canvas) ? 'fixed' : 'absolute';
  71. tooltipObj.style.left = 0;
  72. tooltipObj.style.top = 0;
  73. tooltipObj.style.backgroundColor = 'rgb(255,255,239)';
  74. tooltipObj.style.color = 'black';
  75. if (!document.all) tooltipObj.style.border = '';
  76. tooltipObj.style.visibility = 'visible';
  77. tooltipObj.style.paddingLeft = RGraph.tooltips.padding;
  78. tooltipObj.style.paddingRight = RGraph.tooltips.padding;
  79. tooltipObj.style.fontFamily = RGraph.tooltips.font_face;
  80. tooltipObj.style.fontSize = RGraph.tooltips.font_size;
  81. tooltipObj.style.zIndex = 3;
  82. // Only apply a border if there's content
  83. if (RGraph.trim(text).length > 0) {
  84. tooltipObj.style.border = '1px #bbb solid';
  85. }
  86. tooltipObj.style.borderRadius = '5px';
  87. tooltipObj.style.MozBorderRadius = '5px';
  88. tooltipObj.style.WebkitBorderRadius = '5px';
  89. tooltipObj.style.WebkitBoxShadow = 'rgba(96,96,96,0.5) 0 0 15px';
  90. tooltipObj.style.MozBoxShadow = 'rgba(96,96,96,0.5) 0 0 15px';
  91. tooltipObj.style.boxShadow = 'rgba(96,96,96,0.5) 0 0 15px';
  92. tooltipObj.style.filter = 'progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135)';
  93. tooltipObj.style.opacity = 0;
  94. //tooltipObj.style.overflow = 'hidden';
  95. tooltipObj.innerHTML = text;
  96. tooltipObj.__text__ = text; // This is set because the innerHTML can change when it's set
  97. tooltipObj.__canvas__ = obj.canvas;
  98. tooltipObj.style.display = 'inline';
  99. tooltipObj.id = '__rgraph_tooltip_' + obj.canvas.id + '_' + obj.uid + '_'+ idx;
  100. tooltipObj.__event__ = obj.Get('chart.tooltips.event') || 'click';
  101. tooltipObj.__object__ = obj;
  102. if (typeof(idx) == 'number') {
  103. tooltipObj.__index__ = idx;
  104. origIdx = idx;
  105. }
  106. if (obj.type == 'line' || obj.type == 'radar') {
  107. for (var ds=0; ds<obj.data.length; ++ds) {
  108. if (idx >= obj.data[ds].length) {
  109. idx -= obj.data[ds].length;
  110. } else {
  111. break;
  112. }
  113. }
  114. tooltipObj.__dataset__ = ds;
  115. tooltipObj.__index2__ = idx;
  116. }
  117. document.body.appendChild(tooltipObj);
  118. var width = tooltipObj.offsetWidth;
  119. var height = tooltipObj.offsetHeight;
  120. /**
  121. * Set the width on the tooltip so it doesn't resize if the window is resized
  122. */
  123. tooltipObj.style.width = width + 'px';
  124. tooltipObj.style.top = (y - height - 2) + 'px';
  125. /**
  126. * If the function exists call the object specific tooltip positioning function
  127. */
  128. if (typeof(obj.positionTooltip) == 'function') {
  129. if (tooltipObj.innerHTML.length > 0) {
  130. obj.positionTooltip(obj, x, y, tooltipObj, origIdx ? origIdx : idx);
  131. if (obj.Get('chart.tooltips.coords.page')) {
  132. tooltipObj.style.left = e.pageX - (width / 2) - 4.25 + 'px';
  133. tooltipObj.style.top = e.pageY - height - 10 + 'px';
  134. document.getElementById('__rgraph_tooltip_pointer__').style.left = (parseInt(tooltipObj.offsetWidth) / 2) - 8.5 + 'px';
  135. }
  136. }
  137. } else {
  138. tooltipObj.style.left = e.pageX - (width / 2) - 4.25 + 'px';
  139. tooltipObj.style.top = e.pageY - height - 7 + 'px';
  140. }
  141. if (effect == 'fade' || effect == 'expand' || effect == 'contract' || effect == 'snap') {
  142. setTimeout(function () {tooltipObj.style.opacity = 0.1;}, 25);
  143. setTimeout(function () {tooltipObj.style.opacity = 0.2;}, 50);
  144. setTimeout(function () {tooltipObj.style.opacity = 0.3;}, 75);
  145. setTimeout(function () {tooltipObj.style.opacity = 0.4;}, 100);
  146. setTimeout(function () {tooltipObj.style.opacity = 0.5;}, 125);
  147. setTimeout(function () {tooltipObj.style.opacity = 0.6;}, 150);
  148. setTimeout(function () {tooltipObj.style.opacity = 0.7;}, 175);
  149. setTimeout(function () {tooltipObj.style.opacity = 0.8;}, 200);
  150. setTimeout(function () {tooltipObj.style.opacity = 0.9;}, 225);
  151. if (effect == 'expand' || effect == 'contract' || effect == 'snap') {
  152. console.log('[RGRAPH] The snap, expand and contract tooltip effects are deprecated. Available effects now are fade and none');
  153. }
  154. }
  155. setTimeout("if (RGraph.Registry.Get('chart.tooltip')) { RGraph.Registry.Get('chart.tooltip').style.opacity = 1;}", effect == 'none' ? 50 : 250);
  156. /**
  157. * If the tooltip it self is clicked, cancel it
  158. */
  159. tooltipObj.onmousedown = function (e){e.stopPropagation();}
  160. tooltipObj.onmouseup = function (e){e.stopPropagation();}
  161. tooltipObj.onclick = function (e){if (e.button == 0) {e.stopPropagation();}}
  162. /**
  163. * Keep a reference to the tooltip in the registry
  164. */
  165. RGraph.Registry.Set('chart.tooltip', tooltipObj);
  166. /**
  167. * Fire the tooltip event
  168. */
  169. RGraph.FireCustomEvent(obj, 'ontooltip');
  170. }
  171. /**
  172. *
  173. */
  174. RGraph.getTooltipTextFromDIV = function (text)
  175. {
  176. // This regex is duplicated firher down on roughly line 888
  177. var result = /^id:(.*)/.exec(text);
  178. if (result && result[1] && document.getElementById(result[1])) {
  179. text = document.getElementById(result[1]).innerHTML;
  180. } else if (result && result[1]) {
  181. text = '';
  182. }
  183. return text;
  184. }
  185. /**
  186. *
  187. */
  188. RGraph.getTooltipWidth = function (text, obj)
  189. {
  190. var div = document.createElement('DIV');
  191. div.className = obj.Get('chart.tooltips.css.class');
  192. div.style.paddingLeft = RGraph.tooltips.padding;
  193. div.style.paddingRight = RGraph.tooltips.padding;
  194. div.style.fontFamily = RGraph.tooltips.font_face;
  195. div.style.fontSize = RGraph.tooltips.font_size;
  196. div.style.visibility = 'hidden';
  197. div.style.position = 'absolute';
  198. div.style.top = '300px';
  199. div.style.left = 0;
  200. div.style.display = 'inline';
  201. div.innerHTML = RGraph.getTooltipTextFromDIV(text);
  202. document.body.appendChild(div);
  203. return div.offsetWidth;
  204. }
  205. /**
  206. * Hides the currently shown tooltip
  207. */
  208. RGraph.HideTooltip = function ()
  209. {
  210. var tooltip = RGraph.Registry.Get('chart.tooltip');
  211. var uid = arguments[0] && arguments[0].uid ? arguments[0].uid : null;
  212. if (tooltip && tooltip.parentNode && (!uid || uid == tooltip.__canvas__.uid)) {
  213. tooltip.parentNode.removeChild(tooltip);
  214. tooltip.style.display = 'none';
  215. tooltip.style.visibility = 'hidden';
  216. RGraph.Registry.Set('chart.tooltip', null);
  217. }
  218. }
  219. /**
  220. * This installs the window mousedown event listener. It clears any highlight that may
  221. * be present.
  222. *
  223. * @param object obj The chart object
  224. *
  225. RGraph.InstallWindowMousedownTooltipListener = function (obj)
  226. {
  227. if (RGraph.Registry.Get('__rgraph_event_listeners__')['window_mousedown']) {
  228. return;
  229. }
  230. // When the canvas is cleared, reset this flag so that the event listener is installed again
  231. RGraph.AddCustomEventListener(obj, 'onclear', function (obj) {RGraph.Registry.Get('__rgraph_event_listeners__')['window_mousedown'] = false;})
  232. // NOTE: Global on purpose
  233. rgraph_window_mousedown = function (e)
  234. {
  235. if (RGraph.Registry.Get('chart.tooltip')) {
  236. var obj = RGraph.Registry.Get('chart.tooltip').__object__;
  237. var canvas = obj.canvas;
  238. /**
  239. * Get rid of the tooltip and redraw all canvases on the page
  240. *
  241. RGraph.HideTooltip();
  242. /**
  243. * No need to clear if highlighting is disabled
  244. *
  245. * TODO Really, need to check ALL of the pertinent objects that
  246. * are drawing on the canvas using the ObjectRegistry -
  247. * ie RGraph.ObjectRegistry.getObjectsByCanvasID()
  248. *
  249. if (obj.Get('chart.tooltips.highlight')) {
  250. RGraph.RedrawCanvas(canvas);
  251. }
  252. }
  253. }
  254. window.addEventListener('mousedown', rgraph_window_mousedown, false);
  255. RGraph.AddEventListener('window_' + obj.id, 'mousedown', rgraph_window_mousedown);
  256. }
  257. */
  258. /**
  259. * This installs the canvas mouseup event listener. This is the function that
  260. * actually shows the appropriate (if any) tooltip.
  261. *
  262. * @param object obj The chart object
  263. *
  264. RGraph.InstallCanvasMouseupTooltipListener = function (obj)
  265. {
  266. if (RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mouseup']) {
  267. return;
  268. }
  269. RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mouseup'] = true;
  270. // When the canvas is cleared, reset this flag so that the event listener is installed again
  271. RGraph.AddCustomEventListener(obj, 'onclear', function (obj) {RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mouseup'] = false});
  272. // Install the onclick event handler for the tooltips
  273. //
  274. // // NOTE: Global on purpose
  275. rgraph_canvas_mouseup_func = function (e)
  276. {
  277. var x = arguments[1] ? arguments[1] : e.pageX;
  278. var y = arguments[2] ? arguments[2] : e.pageY;
  279. var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id);
  280. // It's important to go backwards through the array so that the front charts
  281. // are checked first, then the charts at the back
  282. for (var i=(objects.length - 1); i>=0; --i) {
  283. var shape = objects[i].getShape(e);
  284. if (shape && shape['object'] && !RGraph.Registry.Get('chart.tooltip')) {
  285. /**
  286. * This allows the Scatter chart funky tooltips style
  287. *
  288. if (objects[i].type == 'scatter' && shape['dataset'] > 0) {
  289. for (var j=0; j<(objects[i].data.length - 1); ++j) {
  290. shape['index'] += objects[i].data[j].length;
  291. }
  292. }
  293. var text = RGraph.parseTooltipText(objects[i].Get('chart.tooltips'), shape['index']);
  294. if (text) {
  295. if (shape['object'].Get('chart.tooltips.hotspot.xonly')) {
  296. var canvasXY = RGraph.getCanvasXY(objects[i].canvas);
  297. x = canvasXY[0] + shape[1];
  298. y = canvasXY[1] + shape[2];
  299. }
  300. RGraph.Tooltip(objects[i], text, x, y, shape['index']);
  301. objects[i].Highlight(shape);
  302. e.stopPropagation();
  303. e.cancelBubble = true;
  304. return false;
  305. }
  306. }
  307. }
  308. }
  309. obj.canvas.addEventListener('mouseup', rgraph_canvas_mouseup_func, false);
  310. RGraph.AddEventListener(obj.id, 'mouseup', rgraph_canvas_mouseup_func);
  311. }
  312. */
  313. /**
  314. * This installs the canvas mousemove event listener. This is the function that
  315. * changes the mouse pointer if need be.
  316. *
  317. * @param object obj The chart object
  318. *
  319. RGraph.InstallCanvasMousemoveTooltipListener = function (obj)
  320. {
  321. if (RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mousemove']) {
  322. return;
  323. }
  324. RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mousemove'] = true;
  325. // When the canvas is cleared, reset this flag so that the event listener is installed again
  326. RGraph.AddCustomEventListener(obj, 'onclear', function (obj) {RGraph.Registry.Get('__rgraph_event_listeners__')[obj.canvas.id + '_mousemove'] = false})
  327. // Install the mousemove event handler for the tooltips
  328. //
  329. // NOTE: Global on purpose
  330. rgraph_canvas_mousemove_func = function (e)
  331. {
  332. var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id);
  333. for (var i=0; i<objects.length; ++i) {
  334. var shape = objects[i].getShape(e);
  335. if (shape && shape['object']) {
  336. /**
  337. * This allows the Scatter chart funky tooltips style
  338. *
  339. if (objects[i].type == 'scatter' && shape['dataset'] > 0) {
  340. for (var j=0; j<(objects[i].data.length - 1); ++j) {
  341. shape['index'] += objects[i].data[j].length;
  342. }
  343. }
  344. var text = RGraph.parseTooltipText(objects[i].Get('chart.tooltips'), shape['index']);
  345. if (text) {
  346. e.target.style.cursor = 'pointer';
  347. /**
  348. * This facilitates the event triggering the tooltips being mousemove
  349. *
  350. if ( typeof(objects[i].Get('chart.tooltips.event')) == 'string'
  351. && objects[i].Get('chart.tooltips.event') == 'onmousemove'
  352. && (!RGraph.Registry.Get('chart.tooltip') || shape['index'] != RGraph.Registry.Get('chart.tooltip').__index__ || shape['object'].uid != RGraph.Registry.Get('chart.tooltip').__object__.uid)
  353. ) {
  354. // Hide any current tooltip
  355. rgraph_window_mousedown(e);
  356. rgraph_canvas_mouseup_func(e);
  357. }
  358. }
  359. }
  360. }
  361. }
  362. obj.canvas.addEventListener('mousemove', rgraph_canvas_mousemove_func, false);
  363. RGraph.AddEventListener(obj.id, 'mousemove', rgraph_canvas_mousemove_func);
  364. }
  365. */
  366. /**
  367. * This (as the name suggests preloads any images it can find in the tooltip text
  368. *
  369. * @param object obj The chart object
  370. */
  371. RGraph.PreLoadTooltipImages = function (obj)
  372. {
  373. var tooltips = obj.Get('chart.tooltips');
  374. if (RGraph.hasTooltips(obj)) {
  375. if (obj.type == 'rscatter') {
  376. tooltips = [];
  377. for (var i=0; i<obj.data.length; ++i) {
  378. tooltips.push(obj.data[3]);
  379. }
  380. }
  381. for (var i=0; i<tooltips.length; ++i) {
  382. // Add the text to an offscreen DIV tag
  383. var div = document.createElement('DIV');
  384. div.style.position = 'absolute';
  385. div.style.opacity = 0;
  386. div.style.top = '-100px';
  387. div.style.left = '-100px';
  388. div.innerHTML = tooltips[i];
  389. document.body.appendChild(div);
  390. // Now get the IMG tags and create them
  391. var img_tags = div.getElementsByTagName('IMG');
  392. // Create the image in an off-screen image tag
  393. for (var j=0; j<img_tags.length; ++j) {
  394. if (img_tags && img_tags[i]) {
  395. var img = document.createElement('IMG');
  396. img.style.position = 'absolute';
  397. img.style.opacity = 0;
  398. img.style.top = '-100px';
  399. img.style.left = '-100px';
  400. img.src = img_tags[i].src
  401. document.body.appendChild(img);
  402. setTimeout(function () {document.body.removeChild(img);}, 250);
  403. }
  404. }
  405. // Now remove the div
  406. document.body.removeChild(div);
  407. }
  408. }
  409. }
  410. /**
  411. * This is the tooltips canvas onmousemove listener
  412. */
  413. RGraph.Tooltips_mousemove = function (obj, e)
  414. {
  415. var shape = obj.getShape(e);
  416. var changeCursor_tooltips = false
  417. if ( shape
  418. && typeof(shape['index']) == 'number'
  419. && obj.Get('chart.tooltips')[shape['index']]
  420. ) {
  421. var text = RGraph.parseTooltipText(obj.Get('chart.tooltips'), shape['index']);
  422. if (text) {
  423. /**
  424. * Change the cursor
  425. */
  426. changeCursor_tooltips = true;
  427. if (obj.Get('chart.tooltips.event') == 'onmousemove') {
  428. // Show the tooltip if it's not the same as the one already visible
  429. if (
  430. !RGraph.Registry.Get('chart.tooltip')
  431. || RGraph.Registry.Get('chart.tooltip').__object__.uid != obj.uid
  432. || RGraph.Registry.Get('chart.tooltip').__index__ != shape['index']
  433. ) {
  434. RGraph.HideTooltip();
  435. RGraph.Clear(obj.canvas);
  436. RGraph.Redraw();
  437. RGraph.Tooltip(obj, text, e.pageX, e.pageY, shape['index']);
  438. obj.Highlight(shape);
  439. }
  440. }
  441. }
  442. /**
  443. * More highlighting
  444. */
  445. } else if (shape && typeof(shape['index']) == 'number') {
  446. var text = RGraph.parseTooltipText(obj.Get('chart.tooltips'), shape['index']);
  447. if (text) {
  448. changeCursor_tooltips = true
  449. }
  450. }
  451. return changeCursor_tooltips;
  452. }