RGraph.common.resizing.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  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. if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'};
  15. /**
  16. * This is an array of CSS properties that should be preserved when adding theplaceholder DIV
  17. */
  18. __rgraph_resizing_preserve_css_properties__ = [];
  19. /**
  20. * This function can be used to allow resizing
  21. *
  22. * @param object obj Your graph object
  23. */
  24. RGraph.AllowResizing = function (obj)
  25. {
  26. if (obj.Get('chart.resizable')) {
  27. var canvas = obj.canvas;
  28. var context = obj.context;
  29. var resizeHandle = 15;
  30. RGraph.Resizing.canvas = canvas;
  31. RGraph.Resizing.placeHolders = [];
  32. /**
  33. * Add the original width and height to the canvas
  34. */
  35. if (!canvas.__original_width__ && !canvas.__original_height__) {
  36. canvas.__original_width__ = canvas.width;
  37. canvas.__original_height__ = canvas.height;
  38. }
  39. var adjustX = (typeof(obj.Get('chart.resize.handle.adjust')) == 'object' && typeof(obj.Get('chart.resize.handle.adjust')[0]) == 'number' ? obj.Get('chart.resize.handle.adjust')[0] : 0);
  40. var adjustY = (typeof(obj.Get('chart.resize.handle.adjust')) == 'object' && typeof(obj.Get('chart.resize.handle.adjust')[1]) == 'number' ? obj.Get('chart.resize.handle.adjust')[1] : 0);
  41. /**
  42. * Draw the resize handle
  43. */
  44. var textWidth = context.measureText('Reset').width + 2;
  45. // Draw the white background for the resize handle - OPTIONAL default is rgba(0,0,0,0);
  46. var bgcolor = obj.Get('chart.resize.handle.background');
  47. if (!bgcolor) {
  48. bgcolor = 'rgba(0,0,0,0)';
  49. }
  50. context.beginPath();
  51. context.fillStyle = bgcolor;
  52. context.moveTo(canvas.width - resizeHandle - resizeHandle + adjustX, canvas.height - resizeHandle);
  53. context.rect(canvas.width - resizeHandle - resizeHandle + adjustX, canvas.height - resizeHandle + adjustY, 2 * resizeHandle, resizeHandle);
  54. context.fill();
  55. obj.context.beginPath();
  56. obj.context.strokeStyle = 'gray';
  57. obj.context.fillStyle = 'rgba(0,0,0,0)';
  58. obj.context.lineWidth = 1;
  59. //obj.context.rect(obj.canvas.width - resizeHandle + adjustX, obj.canvas.height - resizeHandle - 2 + adjustY, resizeHandle, resizeHandle + 2);
  60. //obj.context.rect(obj.canvas.width - resizeHandle - textWidth + adjustX, obj.canvas.height - resizeHandle + adjustY, resizeHandle + textWidth, resizeHandle + 2);
  61. // Draw the arrows
  62. // Vertical line
  63. obj.context.moveTo(Math.round(obj.canvas.width - (resizeHandle / 2) + adjustX), obj.canvas.height - resizeHandle + adjustY);
  64. obj.context.lineTo(Math.round(obj.canvas.width - (resizeHandle / 2) + adjustX), obj.canvas.height + adjustY);
  65. // Horizontal line
  66. obj.context.moveTo(obj.canvas.width + adjustX, Math.round(obj.canvas.height - (resizeHandle / 2) + adjustY));
  67. obj.context.lineTo(obj.canvas.width - resizeHandle + adjustX, Math.round(obj.canvas.height - (resizeHandle / 2) + adjustY));
  68. context.stroke();
  69. context.fill();
  70. // Top arrow head
  71. context.fillStyle = 'gray';
  72. context.beginPath();
  73. context.moveTo(canvas.width - (resizeHandle / 2) + adjustX, canvas.height - resizeHandle + adjustY);
  74. context.lineTo(canvas.width - (resizeHandle / 2) + 3 + adjustX, canvas.height - resizeHandle + 3 + adjustY);
  75. context.lineTo(canvas.width - (resizeHandle / 2) - 3 + adjustX, canvas.height - resizeHandle + 3 + adjustY);
  76. context.closePath();
  77. context.fill();
  78. // Bottom arrow head
  79. context.beginPath();
  80. context.moveTo(canvas.width - (resizeHandle / 2) + adjustX, canvas.height + adjustY);
  81. context.lineTo(canvas.width - (resizeHandle / 2) + 3 + adjustX, canvas.height - 3 + adjustY);
  82. context.lineTo(canvas.width - (resizeHandle / 2) - 3 + adjustX, canvas.height - 3 + adjustY);
  83. context.closePath();
  84. context.fill();
  85. // Left arrow head
  86. context.beginPath();
  87. context.moveTo(canvas.width - resizeHandle + adjustX, canvas.height - (resizeHandle / 2) + adjustY);
  88. context.lineTo(canvas.width - resizeHandle + 3 + adjustX, canvas.height - (resizeHandle / 2) + 3 + adjustY);
  89. context.lineTo(canvas.width - resizeHandle + 3 + adjustX, canvas.height - (resizeHandle / 2) - 3 + adjustY);
  90. context.closePath();
  91. context.fill();
  92. // Right arrow head
  93. context.beginPath();
  94. context.moveTo(canvas.width + adjustX, canvas.height - (resizeHandle / 2) + adjustY);
  95. context.lineTo(canvas.width - 3 + adjustX, canvas.height - (resizeHandle / 2) + 3 + adjustY);
  96. context.lineTo(canvas.width - 3 + adjustX, canvas.height - (resizeHandle / 2) - 3 + adjustY);
  97. context.closePath();
  98. context.fill();
  99. // Square at the centre of the arrows
  100. context.beginPath();
  101. context.fillStyle = 'white';
  102. context.moveTo(canvas.width + adjustX, canvas.height - (resizeHandle / 2) + adjustY);
  103. context.rect(canvas.width - (resizeHandle / 2) - 2 + adjustX, canvas.height - (resizeHandle / 2) - 2 + adjustY, 4, 4);
  104. context.rect(canvas.width - (resizeHandle / 2) - 2 + adjustX, canvas.height - (resizeHandle / 2) - 2 + adjustY, 4, 4);
  105. context.stroke();
  106. context.fill();
  107. // Draw the "Reset" button
  108. context.beginPath();
  109. context.fillStyle = 'gray';
  110. context.moveTo(Math.round(canvas.width - resizeHandle - 3 + adjustX), canvas.height - resizeHandle / 2 + adjustY);
  111. context.lineTo(Math.round(canvas.width - resizeHandle - resizeHandle + adjustX), canvas.height - (resizeHandle / 2) + adjustY);
  112. context.lineTo(canvas.width - resizeHandle - resizeHandle + 2 + adjustX, canvas.height - (resizeHandle / 2) - 2 + adjustY);
  113. context.lineTo(canvas.width - resizeHandle - resizeHandle + 2 + adjustX, canvas.height - (resizeHandle / 2) + 2 + adjustY);
  114. context.lineTo(canvas.width - resizeHandle - resizeHandle + adjustX, canvas.height - (resizeHandle / 2) + adjustY);
  115. context.stroke();
  116. context.fill();
  117. context.beginPath();
  118. context.moveTo(Math.round(canvas.width - resizeHandle - resizeHandle - 1 + adjustX), canvas.height - (resizeHandle / 2) - 3 + adjustY);
  119. context.lineTo(Math.round(canvas.width - resizeHandle - resizeHandle - 1 + adjustX), canvas.height - (resizeHandle / 2) + 3 + adjustY);
  120. context.stroke();
  121. context.fill();
  122. var window_onmousemove = function (e)
  123. {
  124. e = RGraph.FixEventObject(e);
  125. var canvas = RGraph.Resizing.canvas;
  126. var newWidth = RGraph.Resizing.originalw - (RGraph.Resizing.originalx - e.pageX);// - 5
  127. var newHeight = RGraph.Resizing.originalh - (RGraph.Resizing.originaly - e.pageY);// - 5
  128. if (RGraph.Resizing.mousedown) {
  129. if (newWidth > (canvas.__original_width__ / 2)) RGraph.Resizing.div.style.width = newWidth + 'px';
  130. if (newHeight > (canvas.__original_height__ / 2)) RGraph.Resizing.div.style.height = newHeight + 'px';
  131. RGraph.FireCustomEvent(canvas.__object__, 'onresize');
  132. }
  133. }
  134. // Install the function as an event listener - but only once
  135. if (typeof(canvas.rgraph_resize_window_mousemove_listener_installed) != 'boolean') {
  136. window.addEventListener('mousemove', window_onmousemove, false);
  137. canvas.rgraph_resize_window_mousemove_listener_installed = true;
  138. }
  139. /**
  140. * The window onmouseup function
  141. */
  142. var MouseupFunc = function (e)
  143. {
  144. if (!RGraph.Resizing || !RGraph.Resizing.div || !RGraph.Resizing.mousedown) {
  145. return;
  146. }
  147. if (RGraph.Resizing.div) {
  148. var div = RGraph.Resizing.div;
  149. var canvas = div.__canvas__;
  150. var coords = RGraph.getCanvasXY(div.__canvas__);
  151. var parentNode = canvas.parentNode;
  152. if (canvas.style.position != 'absolute') {
  153. // Create a DIV to go in the canvases place
  154. var placeHolderDIV = document.createElement('DIV');
  155. placeHolderDIV.style.width = RGraph.Resizing.originalw + 'px';
  156. placeHolderDIV.style.height = RGraph.Resizing.originalh + 'px';
  157. //placeHolderDIV.style.backgroundColor = 'red';
  158. placeHolderDIV.style.display = 'inline-block'; // Added 5th Nov 2010
  159. placeHolderDIV.style.position = canvas.style.position;
  160. placeHolderDIV.style.left = canvas.style.left;
  161. placeHolderDIV.style.top = canvas.style.top;
  162. placeHolderDIV.style.cssFloat = canvas.style.cssFloat;
  163. parentNode.insertBefore(placeHolderDIV, canvas);
  164. }
  165. // Now set the canvas to be positioned absolutely
  166. canvas.style.backgroundColor = 'white';
  167. canvas.style.position = 'absolute';
  168. canvas.style.border = '1px dashed gray';
  169. canvas.style.left = (RGraph.Resizing.originalCanvasX - 1) + 'px';
  170. canvas.style.top = (RGraph.Resizing.originalCanvasY - 1) + 'px';
  171. canvas.width = parseInt(div.style.width);
  172. canvas.height = parseInt(div.style.height);
  173. /**
  174. * Because resizing the canvas resets any tranformation - the antialias fix needs to be reapplied.
  175. */
  176. canvas.getContext('2d').translate(0.5,0.5);
  177. /**
  178. * Fire the onresize event
  179. */
  180. RGraph.FireCustomEvent(canvas.__object__, 'onresizebeforedraw');
  181. RGraph.RedrawCanvas(canvas);
  182. // Get rid of transparent semi-opaque DIV
  183. RGraph.Resizing.mousedown = false;
  184. div.style.display = 'none';
  185. document.body.removeChild(div);
  186. }
  187. /**
  188. * If there is zoom enabled in thumbnail mode, lose the zoom image
  189. */
  190. if (RGraph.Registry.Get('chart.zoomed.div') || RGraph.Registry.Get('chart.zoomed.img')) {
  191. RGraph.Registry.Set('chart.zoomed.div', null);
  192. RGraph.Registry.Set('chart.zoomed.img', null);
  193. }
  194. /**
  195. * Fire the onresize event
  196. */
  197. RGraph.FireCustomEvent(canvas.__object__, 'onresizeend');
  198. }
  199. var window_onmouseup = MouseupFunc;
  200. // Install the function as an event listener - but only once
  201. if (typeof(canvas.rgraph_resize_window_mouseup_listener_installed) != 'boolean') {
  202. window.addEventListener('mouseup', window_onmouseup, false);
  203. canvas.rgraph_resize_window_mouseup_listener_installed = true;
  204. }
  205. var canvas_onmousemove = function (e)
  206. {
  207. e = RGraph.FixEventObject(e);
  208. var coords = RGraph.getMouseXY(e);
  209. var obj = e.target.__object__;
  210. var canvas = e.target;
  211. var context = canvas.getContext('2d');
  212. var cursor = canvas.style.cursor;
  213. // Save the original cursor
  214. if (!RGraph.Resizing.original_cursor) {
  215. RGraph.Resizing.original_cursor = cursor;
  216. }
  217. if ( (coords[0] > (canvas.width - resizeHandle)
  218. && coords[0] < canvas.width
  219. && coords[1] > (canvas.height - resizeHandle)
  220. && coords[1] < canvas.height)) {
  221. canvas.style.cursor = 'move';
  222. } else if ( coords[0] > (canvas.width - resizeHandle - resizeHandle)
  223. && coords[0] < canvas.width - resizeHandle
  224. && coords[1] > (canvas.height - resizeHandle)
  225. && coords[1] < canvas.height) {
  226. canvas.style.cursor = 'pointer';
  227. } else {
  228. if (RGraph.Resizing.original_cursor) {
  229. canvas.style.cursor = RGraph.Resizing.original_cursor;
  230. RGraph.Resizing.original_cursor = null;
  231. } else {
  232. canvas.style.cursor = 'default';
  233. }
  234. }
  235. }
  236. // Install the function as an event listener - but only once
  237. if (typeof(canvas.rgraph_resize_mousemove_listener_installed) != 'boolean') {
  238. canvas.addEventListener('mousemove', canvas_onmousemove, false);
  239. canvas.rgraph_resize_mousemove_listener_installed = true;
  240. }
  241. var canvas_onmouseout = function (e)
  242. {
  243. e.target.style.cursor = 'default';
  244. e.target.title = '';
  245. }
  246. // Install the function as an event listener - but only once
  247. if (typeof(canvas.rgraph_resize_mouseout_listener_installed) != 'boolean') {
  248. canvas.addEventListener('mouseout', canvas_onmouseout, false);
  249. canvas.rgraph_resize_mouseout_listener_installed = true;
  250. }
  251. var canvas_onmousedown = function (e)
  252. {
  253. e = RGraph.FixEventObject(e);
  254. var coords = RGraph.getMouseXY(e);
  255. var canvasCoords = RGraph.getCanvasXY(e.target);
  256. var canvas = e.target;
  257. if ( coords[0] > (obj.canvas.width - resizeHandle)
  258. && coords[0] < obj.canvas.width
  259. && coords[1] > (obj.canvas.height - resizeHandle)
  260. && coords[1] < obj.canvas.height) {
  261. RGraph.FireCustomEvent(obj, 'onresizebegin');
  262. // Save the existing border
  263. if (canvas.__original_css_border__ == null) {
  264. canvas.__original_css_border__ = canvas.style.border;
  265. }
  266. RGraph.Resizing.mousedown = true;
  267. /**
  268. * Create the semi-opaque DIV
  269. */
  270. var div = document.createElement('DIV');
  271. div.style.position = 'absolute';
  272. div.style.left = canvasCoords[0] + 'px';
  273. div.style.top = canvasCoords[1] + 'px';
  274. div.style.width = canvas.width + 'px';
  275. div.style.height = canvas.height + 'px';
  276. div.style.border = '1px dotted black';
  277. div.style.backgroundColor = 'gray';
  278. div.style.opacity = 0.5;
  279. div.__canvas__ = e.target;
  280. document.body.appendChild(div);
  281. RGraph.Resizing.div = div;
  282. RGraph.Resizing.placeHolders.push(div);
  283. // Hide the previous resize indicator layers. This is only necessary it seems for the Meter chart
  284. for (var i=0; i<(RGraph.Resizing.placeHolders.length - 1); ++i) {
  285. RGraph.Resizing.placeHolders[i].style.display = 'none';
  286. }
  287. // This is a repetition of the window.onmouseup function (No need to use DOM2 here)
  288. div.onmouseup = function (e)
  289. {
  290. MouseupFunc(e);
  291. }
  292. // No need to use DOM2 here
  293. RGraph.Resizing.div.onmouseover = function (e)
  294. {
  295. e = RGraph.FixEventObject(e);
  296. e.stopPropagation();
  297. }
  298. // The mouse
  299. RGraph.Resizing.originalx = e.pageX;
  300. RGraph.Resizing.originaly = e.pageY;
  301. RGraph.Resizing.originalw = obj.canvas.width;
  302. RGraph.Resizing.originalh = obj.canvas.height;
  303. RGraph.Resizing.originalCanvasX = RGraph.getCanvasXY(obj.canvas)[0];
  304. RGraph.Resizing.originalCanvasY = RGraph.getCanvasXY(obj.canvas)[1];
  305. }
  306. /**
  307. * This facilitates the reset button
  308. */
  309. if ( coords[0] > (canvas.width - resizeHandle - resizeHandle)
  310. && coords[0] < canvas.width - resizeHandle
  311. && coords[1] > (canvas.height - resizeHandle)
  312. && coords[1] < canvas.height) {
  313. /**
  314. * Fire the onresizebegin event
  315. */
  316. RGraph.FireCustomEvent(canvas.__object__, 'onresizebegin');
  317. // Restore the original width and height
  318. canvas.width = canvas.__original_width__;
  319. canvas.height = canvas.__original_height__;
  320. // Lose the border
  321. canvas.style.border = canvas.__original_css_border__;
  322. //canvas.__original_css_border__ = null;
  323. // Add 1 pixel to the top/left because the border is going
  324. canvas.style.left = (parseInt(canvas.style.left)) + 'px';
  325. canvas.style.top = (parseInt(canvas.style.top)) + 'px';
  326. /**
  327. * Because resetting the canvas resizes it - and so loses any translation - need to reapply the
  328. * antialiasing translation
  329. */
  330. canvas.getContext('2d').translate(0.5,0.5);
  331. RGraph.FireCustomEvent(canvas.__object__, 'onresizebeforedraw');
  332. // Redraw the canvas
  333. RGraph.Redraw();
  334. // Set the width and height on the DIV
  335. if (RGraph.Resizing.div) {
  336. RGraph.Resizing.div.style.width = canvas.__original_width__ + 'px';
  337. RGraph.Resizing.div.style.height = canvas.__original_height__ + 'px';
  338. }
  339. /**
  340. * Fire the resize event
  341. */
  342. RGraph.FireCustomEvent(canvas.__object__, 'onresize');
  343. RGraph.FireCustomEvent(canvas.__object__, 'onresizeend');
  344. }
  345. }
  346. // Install the function as an event listener - but only once
  347. if (typeof(canvas.rgraph_resize_mousedown_listener_installed) != 'boolean') {
  348. canvas.addEventListener('mousedown', canvas_onmousedown, false);
  349. canvas.rgraph_resize_mousedown_listener_installed = true;
  350. }
  351. /**
  352. * This function facilitates the reset button
  353. *
  354. * NOTE: 31st December 2010 - doesn't appear to be being used any more
  355. */
  356. /*
  357. canvas.onclick = function (e)
  358. {
  359. var coords = RGraph.getMouseXY(e);
  360. var canvas = e.target;
  361. if ( coords[0] > (canvas.width - resizeHandle - resizeHandle)
  362. && coords[0] < canvas.width - resizeHandle
  363. && coords[1] > (canvas.height - resizeHandle)
  364. && coords[1] < canvas.height) {
  365. // Restore the original width and height
  366. canvas.width = canvas.__original_width__;
  367. canvas.height = canvas.__original_height__;
  368. // Lose the border
  369. canvas.style.border = '';
  370. // Add 1 pixel to the top/left because the border is going
  371. canvas.style.left = (parseInt(canvas.style.left) + 1) + 'px';
  372. canvas.style.top = (parseInt(canvas.style.top) + 1) + 'px';
  373. // Fire the onresizebeforedraw event
  374. RGraph.FireCustomEvent(canvas.__object__, 'onresizebeforedraw');
  375. // Redraw the canvas
  376. canvas.__object__.Draw();
  377. // Set the width and height on the DIV
  378. RGraph.Resizing.div.style.width = canvas.__original_width__ + 'px';
  379. RGraph.Resizing.div.style.height = canvas.__original_height__ + 'px';
  380. // Fire the resize event
  381. RGraph.FireCustomEvent(canvas.__object__, 'onresize');
  382. }
  383. }
  384. */
  385. }
  386. }