RGraph.common.dynamic.js 41 KB

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