RGraph.common.dynamic.js 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /**
  2. * o------------------------------------------------------------------------------o
  3. * | This file is part of the RGraph package - you can learn more at: |
  4. * | |
  5. * | http://www.rgraph.net |
  6. * | |
  7. * | This package is licensed under the RGraph license. For all kinds of business |
  8. * | purposes there is a small one-time licensing fee to pay and for non |
  9. * | commercial purposes it is free to use. You can read the full license here: |
  10. * | |
  11. * | http://www.rgraph.net/license |
  12. * o------------------------------------------------------------------------------o
  13. */
  14. /**
  15. * Initialise the various objects
  16. */
  17. if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'};
  18. /**
  19. * This is the window click event listener. It redraws all canvas tags on the page.
  20. */
  21. RGraph.InstallWindowMousedownListener = function (obj)
  22. {
  23. if (!window.__rgraph_mousedown_event_listener_installed__) {
  24. var func = function (e)
  25. {
  26. /**
  27. * For firefox add the window.event object
  28. */
  29. if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e;
  30. e = RGraph.FixEventObject(e);
  31. /**
  32. * First fire the user specified window.onmousedown_rgraph listener if there is any.
  33. */
  34. if (typeof(window.onmousedown_rgraph) == 'function') {
  35. window.onmousedown_rgraph(e);
  36. }
  37. if (RGraph.HideTooltip && RGraph.Registry.Get('chart.tooltip')) {
  38. RGraph.Clear(RGraph.Registry.Get('chart.tooltip').__canvas__);
  39. RGraph.Redraw();
  40. RGraph.HideTooltip();
  41. }
  42. }
  43. window.addEventListener('mousedown', func, false);
  44. // Set this so the event listener isnt repeatedly installed
  45. window.__rgraph_mousedown_event_listener_installed__ = func;
  46. }
  47. }
  48. /**
  49. * This is the window click event listener. It redraws all canvas tags on the page.
  50. */
  51. RGraph.InstallWindowMouseupListener = function (obj)
  52. {
  53. if (!window.__rgraph_mouseup_event_listener_installed__) {
  54. var func = function (e)
  55. {
  56. /**
  57. * For firefox add the window.event object
  58. */
  59. if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e;
  60. e = RGraph.FixEventObject(e);
  61. /**
  62. * Stop any annotating that may be going on
  63. */
  64. if (RGraph.Annotating_window_onmouseup) {
  65. RGraph.Annotating_window_onmouseup(e);
  66. return;
  67. }
  68. /**
  69. * First fire the user specified window.onmouseup_rgraph listener if there is any
  70. */
  71. if (typeof(window.onmouseup_rgraph) == 'function') {
  72. window.onmouseup_rgraph(e);
  73. }
  74. /**
  75. * End adjusting
  76. */
  77. if (RGraph.Registry.Get('chart.adjusting') || RGraph.Registry.Get('chart.adjusting.gantt')) {
  78. RGraph.FireCustomEvent(RGraph.Registry.Get('chart.adjusting'), 'onadjustend');
  79. }
  80. RGraph.Registry.Set('chart.adjusting', null);
  81. RGraph.Registry.Set('chart.adjusting.shape', null);
  82. RGraph.Registry.Set('chart.adjusting.gantt', null);
  83. // ==============================================
  84. // Finally, redraw the chart
  85. // ==============================================
  86. var tags = document.getElementsByTagName('canvas');
  87. for (var i=0; i<tags.length; ++i) {
  88. if (tags[i].__object__ && tags[i].__object__.isRGraph) {
  89. if (!tags[i].__object__.Get('chart.annotatable')) {
  90. if (!tags[i].__rgraph_trace_cover__ && !noredraw) {
  91. RGraph.Clear(tags[i]);
  92. } else {
  93. var noredraw = true;
  94. }
  95. }
  96. }
  97. }
  98. if (!noredraw) {
  99. RGraph.Redraw();
  100. }
  101. }
  102. window.addEventListener('mouseup', func, false);
  103. // Set this so the event listener isn't repeatedly installed
  104. window.__rgraph_mouseup_event_listener_installed__ = func;
  105. }
  106. }
  107. /**
  108. * This is the canvas mouseup event listener. It installs the mouseup event for the
  109. * canvas. The mouseup event then checks the relevant object.
  110. *
  111. * @param object obj The chart object
  112. */
  113. RGraph.InstallCanvasMouseupListener = function (obj)
  114. {
  115. if (!obj.canvas.__rgraph_mouseup_event_listener_installed__) {
  116. var func = function (e)
  117. {
  118. /**
  119. * For firefox add the window.event object
  120. */
  121. if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e;
  122. e = RGraph.FixEventObject(e);
  123. /**
  124. * First fire the user specified onmouseup listener if there is any
  125. */
  126. if (typeof(e.target.onmouseup_rgraph) == 'function') {
  127. e.target.onmouseup_rgraph(e);
  128. }
  129. // *************************************************************************
  130. // Tooltips
  131. // *************************************************************************
  132. // This causes things at the edge of the chart area - eg line chart hotspots - not to fire because the
  133. // cursor is out of the chart area
  134. var objects = RGraph.ObjectRegistry.getObjectsByXY(e);
  135. //var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id);
  136. if (objects) {
  137. for (var i=0; i<objects.length; ++i) {
  138. var obj = objects[i];
  139. var id = objects[i].id;
  140. // =========================================================================
  141. // Tooltips
  142. // ========================================================================
  143. if (!RGraph.is_null(obj) && RGraph.Tooltip) {
  144. var shape = obj.getShape(e);
  145. if (shape && shape['tooltip']) {
  146. var text = shape['tooltip'];
  147. if (text) {
  148. var type = shape['object'].type;
  149. if ( type == 'line'
  150. || type == 'rscatter'
  151. || (type == 'scatter' && !obj.Get('chart.boxplot'))
  152. || type == 'radar') {
  153. var canvasXY = RGraph.getCanvasXY(obj.canvas);
  154. var x = canvasXY[0] + shape['x'];
  155. var y = canvasXY[1] + shape['y'];
  156. } else {
  157. var x = e.pageX;
  158. var y = e.pageY;
  159. }
  160. // Taken out November 2012
  161. //if (obj.Get('chart.tooltips.coords.page')) {
  162. // var x = e.pageX;
  163. // var y = e.pageY;
  164. //}
  165. RGraph.Clear(obj.canvas);
  166. RGraph.Redraw();
  167. obj.Highlight(shape);
  168. RGraph.Registry.Set('chart.tooltip.shape', shape);
  169. RGraph.Tooltip(obj, text, x, y, shape['index'], e);
  170. // Add the shape that triggered the tooltip
  171. if (RGraph.Registry.Get('chart.tooltip')) {
  172. RGraph.Registry.Get('chart.tooltip').__shape__ = shape;
  173. RGraph.EvaluateCursor(e);
  174. }
  175. e.cancelBubble = true;
  176. e.stopPropagation();
  177. return false;
  178. }
  179. }
  180. }
  181. // =========================================================================
  182. // Adjusting
  183. // ========================================================================
  184. if (RGraph.Registry.Get('chart.adjusting') || RGraph.Registry.Get('chart.adjusting.gantt')) {
  185. RGraph.FireCustomEvent(RGraph.Registry.Get('chart.adjusting'), 'onadjustend');
  186. }
  187. RGraph.Registry.Set('chart.adjusting', null);
  188. RGraph.Registry.Set('chart.adjusting.shape', null);
  189. RGraph.Registry.Set('chart.adjusting.gantt', null);
  190. /**
  191. * If the mouse pointer is over a "front" chart this prevents charts behind it
  192. * from firing their events.
  193. */
  194. if (shape || (obj.overChartArea && obj.overChartArea(e)) ) {
  195. break;
  196. }
  197. }
  198. }
  199. }
  200. obj.canvas.addEventListener('mouseup', func, false);
  201. // Set this so the canvas mouseup event listener isn't repeatedly installed
  202. obj.canvas.__rgraph_mouseup_event_listener_installed__ = func;
  203. }
  204. }
  205. /**
  206. * This is the canvas mousemove event listener.
  207. *
  208. * @param object obj The chart object
  209. */
  210. RGraph.InstallCanvasMousemoveListener = function (obj)
  211. {
  212. if (!obj.canvas.__rgraph_mousemove_event_listener_installed__) {
  213. var func = function (e)
  214. {
  215. /**
  216. * For firefox add the window.event object
  217. */
  218. if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e;
  219. e = RGraph.FixEventObject(e);
  220. /**
  221. * First fire the user specified onmousemove listener if there is any
  222. */
  223. if (typeof(e.target.onmousemove_rgraph) == 'function') {
  224. e.target.onmousemove_rgraph(e);
  225. }
  226. /**
  227. * Go through all the objects and check them to see if anything needs doing
  228. */
  229. var objects = RGraph.ObjectRegistry.getObjectsByXY(e);
  230. //var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(e.target.id);
  231. if (objects && objects.length) {
  232. for (var i=0; i<objects.length; ++i) {
  233. var obj = objects[i];
  234. var id = obj.id;
  235. if (!obj.getShape) {
  236. continue;
  237. }
  238. var shape = obj.getShape(e);
  239. // ================================================================================================ //
  240. // This facilitates the chart.events.mousemove option
  241. // ================================================================================================ //
  242. var func = obj.Get('chart.events.mousemove');
  243. if (!func && typeof(obj.onmousemove) == 'function') {
  244. var func = obj.onmousemove;
  245. }
  246. /**
  247. *
  248. */
  249. if (shape) {
  250. var index = shape['object'].type == 'scatter' ? shape['index_adjusted'] : shape['index'];
  251. if (typeof(obj['$' + index]) == 'object' && typeof(obj['$' + index].onmousemove) == 'function') {
  252. var func2 = obj['$' + index].onmousemove;
  253. }
  254. }
  255. /**
  256. * This bit saves the current pointer style if there isn't one already saved
  257. */
  258. if (shape && (typeof(func) == 'function' || typeof(func2) == 'function')) {
  259. if (obj.Get('chart.events.mousemove.revertto') == null) {
  260. obj.Set('chart.events.mousemove.revertto', e.target.style.cursor);
  261. }
  262. if (typeof(func) == 'function') func(e, shape);
  263. if (typeof(func2) == 'function') func2(e, shape);
  264. //return;
  265. } else if (typeof(obj.Get('chart.events.mousemove.revertto')) == 'string') {
  266. RGraph.cursor.push('default');
  267. obj.Set('chart.events.mousemove.revertto', null);
  268. }
  269. // ================================================================================================ //
  270. // Tooltips
  271. // ================================================================================================ //
  272. if ( shape
  273. && (obj.Get('chart.tooltips') && obj.Get('chart.tooltips')[shape['index']] || shape['tooltip'])
  274. && (obj.Get('chart.tooltips.event') == 'onmousemove' || obj.Get('chart.tooltips.event') == 'mousemove')
  275. && (RGraph.is_null(RGraph.Registry.Get('chart.tooltip')) || RGraph.Registry.Get('chart.tooltip').__index__ != shape['index'] || (typeof(shape['dataset']) == 'number' && shape['dataset'] != RGraph.Registry.Get('chart.tooltip').__shape__['dataset']) || obj.uid != RGraph.Registry.Get('chart.tooltip').__object__.uid)
  276. ) {
  277. RGraph.Clear(obj.canvas);
  278. RGraph.Redraw();
  279. obj.canvas.__rgraph_mouseup_event_listener_installed__(e);
  280. return;
  281. }
  282. // ================================================================================================ //
  283. // Adjusting
  284. // ================================================================================================ //
  285. if (obj && obj.Get('chart.adjustable')) {
  286. obj.Adjusting_mousemove(e);
  287. }
  288. /**
  289. * This facilitates breaking out of the loop when a shape has been found -
  290. * ie the cursor is over a shape an upper chart
  291. */
  292. if (shape || (obj.overChartArea && obj.overChartArea(e) )) {
  293. break;
  294. }
  295. }
  296. }
  297. // ================================================================================================ //
  298. // Crosshairs
  299. // ================================================================================================ //
  300. if (e.target && e.target.__object__ && e.target.__object__.Get('chart.crosshairs')) {
  301. RGraph.DrawCrosshairs(e, e.target.__object__);
  302. }
  303. // ================================================================================================ //
  304. // Interactive key
  305. // ================================================================================================ //
  306. if (typeof(InteractiveKey_line_mousemove) == 'function') InteractiveKey_line_mousemove(e);
  307. if (typeof(InteractiveKey_pie_mousemove) == 'function') InteractiveKey_pie_mousemove(e);
  308. // ================================================================================================ //
  309. // Annotating
  310. // ================================================================================================ //
  311. if (e.target.__object__ && e.target.__object__.Get('chart.annotatable') && RGraph.Annotating_canvas_onmousemove) {
  312. RGraph.Annotating_canvas_onmousemove(e);
  313. }
  314. /**
  315. * Determine the pointer
  316. */
  317. RGraph.EvaluateCursor(e);
  318. }
  319. obj.canvas.addEventListener('mousemove', func, false);
  320. // Set this so the event listener isn't constantly added
  321. obj.canvas.__rgraph_mousemove_event_listener_installed__ = func;
  322. }
  323. }
  324. /**
  325. * This is the canvas mousedown event listener.
  326. *
  327. * @param object obj The chart object
  328. */
  329. RGraph.InstallCanvasMousedownListener = function (obj)
  330. {
  331. if (!obj.canvas.__rgraph_mousedown_event_listener_installed__) {
  332. var func = function (e)
  333. {
  334. /**
  335. * For firefox add the window.event object
  336. */
  337. if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e;
  338. e = RGraph.FixEventObject(e);
  339. /**
  340. * First fire the user specified onmousedown listener if there is any
  341. */
  342. if (typeof(e.target.onmousedown_rgraph) == 'function') {
  343. e.target.onmousedown_rgraph(e);
  344. }
  345. /**
  346. * Annotating
  347. */
  348. if (e.target.__object__ && e.target.__object__.Get('chart.annotatable') && RGraph.Annotating_canvas_onmousedown) {
  349. RGraph.Annotating_canvas_onmousedown(e);
  350. return;
  351. }
  352. var obj = RGraph.ObjectRegistry.getObjectByXY(e);
  353. if (obj) {
  354. var id = obj.id;
  355. /*************************************************************
  356. * Handle adjusting for all object types
  357. *************************************************************/
  358. if (obj && obj.isRGraph && obj.Get('chart.adjustable')) {
  359. /**
  360. * Check the cursor is in the correct area
  361. */
  362. var obj = RGraph.ObjectRegistry.getObjectByXY(e);
  363. if (obj && obj.isRGraph) {
  364. // If applicable, get the appropriate shape and store it in the registry
  365. switch (obj.type) {
  366. case 'bar': var shape = obj.getShapeByX(e); break;
  367. case 'gantt':
  368. var shape = obj.getShape(e);
  369. if (shape) {
  370. var mouseXY = RGraph.getMouseXY(e);
  371. RGraph.Registry.Set('chart.adjusting.gantt', {
  372. 'index': shape['index'],
  373. 'object': obj,
  374. 'mousex': mouseXY[0],
  375. 'mousey': mouseXY[1],
  376. 'event_start': obj.data[shape['index']][0],
  377. 'event_duration': obj.data[shape['index']][1],
  378. 'mode': (mouseXY[0] > (shape['x'] + shape['width'] - 5) ? 'resize' : 'move'),
  379. 'shape': shape
  380. });
  381. }
  382. break;
  383. case 'line': var shape = obj.getShape(e); break;
  384. default: var shape = null;
  385. }
  386. RGraph.Registry.Set('chart.adjusting.shape', shape);
  387. // Fire the onadjustbegin event
  388. RGraph.FireCustomEvent(obj, 'onadjustbegin');
  389. RGraph.Registry.Set('chart.adjusting', obj);
  390. // Liberally redraw the canvas
  391. RGraph.Clear(obj.canvas);
  392. RGraph.Redraw();
  393. // Call the mousemove event listener so that the canvas is adjusted even though the mouse isn't moved
  394. obj.canvas.__rgraph_mousemove_event_listener_installed__(e);
  395. }
  396. }
  397. RGraph.Clear(obj.canvas);
  398. RGraph.Redraw();
  399. }
  400. }
  401. obj.canvas.addEventListener('mousedown', func, false);
  402. obj.canvas.__rgraph_mousedown_event_listener_installed__ = func;
  403. }
  404. }
  405. /**
  406. * This is the canvas click event listener. Used by the pseudo event listener
  407. *
  408. * @param object obj The chart object
  409. */
  410. RGraph.InstallCanvasClickListener = function (obj)
  411. {
  412. if (!obj.canvas.__rgraph_click_event_listener_installed__) {
  413. var func = function (e)
  414. {
  415. /**
  416. * For firefox add the window.event object
  417. */
  418. if (navigator.userAgent.indexOf('Firefox') >= 0) window.event = e;
  419. e = RGraph.FixEventObject(e);
  420. /**
  421. * First fire the user specified onmousedown listener if there is any
  422. */
  423. if (typeof(e.target.onclick_rgraph) == 'function') {
  424. e.target.onclick_rgraph(e);
  425. }
  426. var objects = RGraph.ObjectRegistry.getObjectsByXY(e);
  427. for (var i=0; i<objects.length; ++i) {
  428. var obj = objects[i];
  429. var id = obj.id;
  430. var shape = obj.getShape(e);
  431. /**
  432. * This bit saves the current pointer style if there isn't one already saved
  433. */
  434. var func = obj.Get('chart.events.click');
  435. if (!func && typeof(obj.onclick) == 'function') {
  436. func = obj.onclick;
  437. }
  438. if (shape && typeof(func) == 'function') {
  439. func(e, shape);
  440. /**
  441. * If objects are layered on top of each other this return
  442. * stops objects underneath from firing once the "top"
  443. * objects user event has fired
  444. */
  445. return;
  446. }
  447. /**
  448. * The property takes priority over this.
  449. */
  450. if (shape) {
  451. var index = shape['object'].type == 'scatter' ? shape['index_adjusted'] : shape['index'];
  452. if (typeof(index) == 'number' && obj['$' + index]) {
  453. var func = obj['$' + index].onclick;
  454. if (typeof(func) == 'function') {
  455. func(e, shape);
  456. /**
  457. * If objects are layered on top of each other this return
  458. * stops objects underneath from firing once the "top"
  459. * objects user event has fired
  460. */
  461. return;
  462. }
  463. }
  464. }
  465. /**
  466. * This facilitates breaking out of the loop when a shape has been found -
  467. * ie the cursor is over a shape an upper chart
  468. */
  469. if (shape || (obj.overChartArea && obj.overChartArea(e)) ) {
  470. break;
  471. }
  472. }
  473. }
  474. obj.canvas.addEventListener('click', func, false);
  475. obj.canvas.__rgraph_click_event_listener_installed__ = func;
  476. }
  477. }
  478. /**
  479. * This function evaluates the various cursor settings and if there's one for pointer, changes it to that
  480. */
  481. RGraph.EvaluateCursor = function (e)
  482. {
  483. var mouseXY = RGraph.getMouseXY(e);
  484. var mouseX = mouseXY[0];
  485. var mouseY = mouseXY[1];
  486. var canvas = e.target;
  487. /**
  488. * Tooltips cause the mouse pointer to change
  489. */
  490. var objects = RGraph.ObjectRegistry.getObjectsByCanvasID(canvas.id);
  491. for (var i=0; i<objects.length; ++i) {
  492. if ((objects[i].getShape && objects[i].getShape(e)) || (objects[i].overChartArea && objects[i].overChartArea(e))) {
  493. var obj = objects[i];
  494. var id = obj.id;
  495. }
  496. }
  497. if (!RGraph.is_null(obj)) {
  498. if (obj.getShape && obj.getShape(e)) {
  499. var shape = obj.getShape(e);
  500. if (obj.Get('chart.tooltips')) {
  501. var text = RGraph.parseTooltipText(obj.Get('chart.tooltips'), shape['index']);
  502. if (!text && shape['object'].type == 'scatter' && shape['index_adjusted']) {
  503. text = RGraph.parseTooltipText(obj.Get('chart.tooltips'), shape['index_adjusted']);
  504. }
  505. /**
  506. * This essentially makes front charts "hide" the back charts
  507. */
  508. if (text) {
  509. var pointer = true;
  510. }
  511. }
  512. }
  513. /**
  514. * Now go through the key coords and see if it's over that.
  515. */
  516. if (!RGraph.is_null(obj) && obj.Get('chart.key.interactive')) {
  517. for (var j=0; j<obj.coords.key.length; ++j) {
  518. if (mouseX > obj.coords.key[j][0] && mouseX < (obj.coords.key[j][0] + obj.coords.key[j][2]) && mouseY > obj.coords.key[j][1] && mouseY < (obj.coords.key[j][1] + obj.coords.key[j][3])) {
  519. var pointer = true;
  520. }
  521. }
  522. }
  523. }
  524. /**
  525. * It can be specified in the user mousemove event - remember it can now be specified in THREE ways
  526. */
  527. if (!RGraph.is_null(shape) && !RGraph.is_null(obj)) {
  528. if (!RGraph.is_null(obj.Get('chart.events.mousemove')) && typeof(obj.Get('chart.events.mousemove')) == 'function') {
  529. var str = (obj.Get('chart.events.mousemove')).toString();
  530. if (str.match(/pointer/) && str.match(/cursor/) && str.match(/style/)) {
  531. var pointer = true;
  532. }
  533. }
  534. if (!RGraph.is_null(obj.onmousemove) && typeof(obj.onmousemove) == 'function') {
  535. var str = (obj.onmousemove).toString();
  536. if (str.match(/pointer/) && str.match(/cursor/) && str.match(/style/)) {
  537. var pointer = true;
  538. }
  539. }
  540. var index = shape['object'].type == 'scatter' ? shape['index_adjusted'] : shape['index'];
  541. if (!RGraph.is_null(obj['$' + index]) && typeof(obj['$' + index].onmousemove) == 'function') {
  542. var str = (obj['$' + index].onmousemove).toString();
  543. if (str.match(/pointer/) && str.match(/cursor/) && str.match(/style/)) {
  544. var pointer = true;
  545. }
  546. }
  547. }
  548. /**
  549. * Is the chart resizable? Go through all the objects again
  550. */
  551. var objects = RGraph.ObjectRegistry.objects.byCanvasID;
  552. for (var i=0; i<objects.length; ++i) {
  553. if (objects[i] && objects[i][1].Get('chart.resizable')) {
  554. var resizable = true;
  555. }
  556. }
  557. if (resizable && mouseX > (e.target.width - 32) && mouseY > (e.target.height - 16)) {
  558. pointer = true;
  559. }
  560. if (pointer) {
  561. e.target.style.cursor = 'pointer';
  562. } else if (e.target.style.cursor == 'pointer') {
  563. e.target.style.cursor = 'default';
  564. } else {
  565. e.target.style.cursor = null;
  566. }
  567. // =========================================================================
  568. // Resize cursor
  569. // =========================================================================
  570. if (resizable && mouseX >= (e.target.width - 15) && mouseY >= (e.target.height - 15)) {
  571. e.target.style.cursor = 'move';
  572. }
  573. // =========================================================================
  574. // Interactive key
  575. // =========================================================================
  576. if (typeof(mouse_over_key) == 'boolean' && mouse_over_key) {
  577. e.target.style.cursor = 'pointer';
  578. }
  579. // =========================================================================
  580. // Gantt chart adjusting
  581. // =========================================================================
  582. if (obj && obj.type == 'gantt' && obj.Get('chart.adjustable')) {
  583. if (obj.getShape && obj.getShape(e)) {
  584. e.target.style.cursor = 'ew-resize';
  585. } else {
  586. e.target.style.cursor = 'default';
  587. }
  588. }
  589. // =========================================================================
  590. // Line chart adjusting
  591. // =========================================================================
  592. if (obj && obj.type == 'line' && obj.Get('chart.adjustable')) {
  593. if (obj.getShape && obj.getShape(e)) {
  594. e.target.style.cursor = 'ns-resize';
  595. } else {
  596. e.target.style.cursor = 'default';
  597. }
  598. }
  599. // =========================================================================
  600. // Annotatable
  601. // =========================================================================
  602. if (e.target.__object__ && e.target.__object__.Get('chart.annotatable')) {
  603. e.target.style.cursor = 'crosshair';
  604. }
  605. }
  606. /**
  607. * This function handles the tooltip text being a string, function
  608. *
  609. * @param mixed tooltip This could be a string or a function. If it's a function it's called and
  610. * the return value is used as the tooltip text
  611. * @param numbr idx The index of the tooltip.
  612. */
  613. RGraph.parseTooltipText = function (tooltips, idx)
  614. {
  615. // No tooltips
  616. if (!tooltips) {
  617. return null;
  618. }
  619. // Get the tooltip text
  620. if (typeof(tooltips) == 'function') {
  621. var text = tooltips(idx);
  622. // A single tooltip. Only supported by the Scatter chart
  623. } else if (typeof(tooltips) == 'string') {
  624. var text = tooltips;
  625. } else if (typeof(tooltips) == 'object' && typeof(tooltips)[idx] == 'function') {
  626. var text = tooltips[idx](idx);
  627. } else if (typeof(tooltips)[idx] == 'string' && tooltips[idx]) {
  628. var text = tooltips[idx];
  629. } else {
  630. var text = '';
  631. }
  632. if (text == 'undefined') {
  633. text = '';
  634. } else if (text == 'null') {
  635. text = '';
  636. }
  637. // Conditional in case the tooltip file isn't included
  638. return RGraph.getTooltipTextFromDIV ? RGraph.getTooltipTextFromDIV(text) : text;
  639. }
  640. /**
  641. * Draw crosshairs if enabled
  642. *
  643. * @param object obj The graph object (from which we can get the context and canvas as required)
  644. */
  645. RGraph.DrawCrosshairs = function (e, obj)
  646. {
  647. var e = RGraph.FixEventObject(e);
  648. var width = obj.canvas.width;
  649. var height = obj.canvas.height;
  650. var mouseXY = RGraph.getMouseXY(e);
  651. var x = mouseXY[0];
  652. var y = mouseXY[1];
  653. var gutterLeft = obj.gutterLeft;
  654. var gutterRight = obj.gutterRight;
  655. var gutterTop = obj.gutterTop;
  656. var gutterBottom = obj.gutterBottom;
  657. var prop = obj.properties;
  658. RGraph.RedrawCanvas(obj.canvas);
  659. if ( x >= gutterLeft
  660. && y >= gutterTop
  661. && x <= (width - gutterRight)
  662. && y <= (height - gutterBottom)
  663. ) {
  664. var linewidth = prop['chart.crosshairs.linewidth'] ? prop['chart.crosshairs.linewidth'] : 1;
  665. obj.context.lineWidth = linewidth ? linewidth : 1;
  666. obj.context.beginPath();
  667. obj.context.strokeStyle = prop['chart.crosshairs.color'];
  668. /**
  669. * The chart.crosshairs.snap option
  670. */
  671. if (prop['chart.crosshairs.snap']) {
  672. // Linear search for the closest point
  673. var point = null;
  674. var dist = null;
  675. var len = null;
  676. if (obj.type == 'line') {
  677. for (var i=0; i<obj.coords.length; ++i) {
  678. var len = RGraph.getHypLength(obj.coords[i][0], obj.coords[i][1], x, y);
  679. // Check the mouse X coordinate
  680. if (typeof(dist) != 'number' || len < dist) {
  681. var point = i;
  682. var dist = len;
  683. }
  684. }
  685. x = obj.coords[point][0];
  686. y = obj.coords[point][1];
  687. // Get the dataset
  688. for (var dataset=0; dataset<obj.coords2.length; ++dataset) {
  689. for (var point=0; point<obj.coords2[dataset].length; ++point) {
  690. if (obj.coords2[dataset][point][0] == x && obj.coords2[dataset][point][1] == y) {
  691. obj.canvas.__crosshairs_snap_dataset__ = dataset;
  692. obj.canvas.__crosshairs_snap_point__ = point;
  693. }
  694. }
  695. }
  696. } else {
  697. for (var i=0; i<obj.coords.length; ++i) {
  698. for (var j=0; j<obj.coords[i].length; ++j) {
  699. // Check the mouse X coordinate
  700. var len = RGraph.getHypLength(obj.coords[i][j][0], obj.coords[i][j][1], x, y);
  701. if (typeof(dist) != 'number' || len < dist) {
  702. var dataset = i;
  703. var point = j;
  704. var dist = len;
  705. }
  706. }
  707. }
  708. obj.canvas.__crosshairs_snap_dataset__ = dataset;
  709. obj.canvas.__crosshairs_snap_point__ = point;
  710. x = obj.coords[dataset][point][0];
  711. y = obj.coords[dataset][point][1];
  712. }
  713. }
  714. // Draw a top vertical line
  715. if (prop['chart.crosshairs.vline']) {
  716. obj.context.moveTo(Math.round(x), Math.round(gutterTop));
  717. obj.context.lineTo(Math.round(x), Math.round(height - gutterBottom));
  718. }
  719. // Draw a horizontal line
  720. if (prop['chart.crosshairs.hline']) {
  721. obj.context.moveTo(Math.round(gutterLeft), Math.round(y));
  722. obj.context.lineTo(Math.round(width - gutterRight), Math.round(y));
  723. }
  724. obj.context.stroke();
  725. /**
  726. * Need to show the coords?
  727. */
  728. if (obj.type == 'scatter' && prop['chart.crosshairs.coords']) {
  729. var xCoord = (((x - gutterLeft) / (width - gutterLeft - gutterRight)) * (prop['chart.xmax'] - prop['chart.xmin'])) + prop['chart.xmin'];
  730. xCoord = xCoord.toFixed(prop['chart.scale.decimals']);
  731. var yCoord = obj.max - (((y - prop['chart.gutter.top']) / (height - gutterTop - gutterBottom)) * obj.max);
  732. if (obj.type == 'scatter' && obj.properties['chart.xaxispos'] == 'center') {
  733. yCoord = (yCoord - (obj.max / 2)) * 2;
  734. }
  735. yCoord = yCoord.toFixed(prop['chart.scale.decimals']);
  736. var div = RGraph.Registry.Get('chart.coordinates.coords.div');
  737. var mouseXY = RGraph.getMouseXY(e);
  738. var canvasXY = RGraph.getCanvasXY(obj.canvas);
  739. if (!div) {
  740. var div = document.createElement('DIV');
  741. div.__object__ = obj;
  742. div.style.position = 'absolute';
  743. div.style.backgroundColor = 'white';
  744. div.style.border = '1px solid black';
  745. div.style.fontFamily = 'Arial, Verdana, sans-serif';
  746. div.style.fontSize = '10pt'
  747. div.style.padding = '2px';
  748. div.style.opacity = 1;
  749. div.style.WebkitBorderRadius = '3px';
  750. div.style.borderRadius = '3px';
  751. div.style.MozBorderRadius = '3px';
  752. document.body.appendChild(div);
  753. RGraph.Registry.Set('chart.coordinates.coords.div', div);
  754. }
  755. // Convert the X/Y pixel coords to correspond to the scale
  756. div.style.opacity = 1;
  757. div.style.display = 'inline';
  758. if (!prop['chart.crosshairs.coords.fixed']) {
  759. div.style.left = Math.max(2, (e.pageX - div.offsetWidth - 3)) + 'px';
  760. div.style.top = Math.max(2, (e.pageY - div.offsetHeight - 3)) + 'px';
  761. } else {
  762. div.style.left = canvasXY[0] + gutterLeft + 3 + 'px';
  763. div.style.top = canvasXY[1] + gutterTop + 3 + 'px';
  764. }
  765. div.innerHTML = '<span style="color: #666">' + prop['chart.crosshairs.coords.labels.x'] + ':</span> ' + xCoord + '<br><span style="color: #666">' + prop['chart.crosshairs.coords.labels.y'] + ':</span> ' + yCoord;
  766. obj.canvas.addEventListener('mouseout', RGraph.HideCrosshairCoords, false);
  767. obj.canvas.__crosshairs_labels__ = div;
  768. obj.canvas.__crosshairs_x__ = xCoord;
  769. obj.canvas.__crosshairs_y__ = yCoord;
  770. } else if (prop['chart.crosshairs.coords']) {
  771. alert('[RGRAPH] Showing crosshair coordinates is only supported on the Scatter chart');
  772. }
  773. /**
  774. * Fire the oncrosshairs custom event
  775. */
  776. RGraph.FireCustomEvent(obj, 'oncrosshairs');
  777. } else {
  778. RGraph.HideCrosshairCoords();
  779. }
  780. }