initial commit
[home-automation.git] / libraries / RGraph.common.zoom.js
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.txt                       |
12     * o------------------------------------------------------------------------------o
13     */
14
15     if (typeof(RGraph) == 'undefined') RGraph = {isRGraph:true,type:'common'};
16
17
18     /**
19     * Installs the event handlers for zooming an area of the graph
20     * 
21     * @param object obj Your graph object
22     */
23     RGraph.ZoomArea = function (obj)
24     {
25         if (obj.Get('chart.zoom.mode') == 'area') {
26
27             var canvas  = obj.canvas;
28             var context = obj.context;
29             
30             obj.canvas.style.cursor = 'crosshair';
31             
32             RGraph.Register(obj);
33
34
35             canvas.onmousedown = function(e)
36             {
37                 var canvas = e.target;
38                 var coords = RGraph.getMouseXY(e);
39                 var obj    = canvas.__object__;
40                     
41                 if (RGraph.Registry.Get('chart.zoomed.area.div')) {
42                     RGraph.Registry.Get('chart.zoomed.area.div').style.display = 'none';
43                 }
44
45                 if (typeof(RGraph.Registry.Get('chart.zoomed.area.divs')) == null) {
46                     RGraph.Registry.Set('chart.zoomed.area.divs', []);
47
48                 } else {
49
50                     var divs = RGraph.Registry.Get('chart.zoomed.area.divs');
51                     
52                     if (divs && divs.length) {
53                         for (var i=0; i<divs.length; ++i) {
54                             if (divs[i]) {
55                                 divs[i].style.display = 'none';
56                                 divs[i] = null;
57                             }
58                         }
59                     }
60                 }
61
62                 /**
63                 * Create the indicator DIV
64                 */
65                 var canvasXY = RGraph.getCanvasXY(canvas);
66                 var areaDiv  = document.createElement('DIV');
67                     areaDiv.__canvas__     = canvas;
68                     areaDiv.style.position = 'absolute';
69                     areaDiv.style.left     = canvasXY[0] + coords[0] + 'px'
70                     areaDiv.style.top      = canvasXY[1] + coords[1] + 'px'
71                     areaDiv.style.width    = 0;
72                     areaDiv.style.height   = 0;
73                     areaDiv.style.border   = '1px solid black';
74                     areaDiv.style.backgroundColor = 'rgba(220,220,220,0.3)';
75                     areaDiv.style.display = 'none';
76
77                     areaDiv.onmouseover = function (e)
78                     {
79                         setTimeout(function () {e.target.style.opacity = 0.8;}, 50);
80                         setTimeout(function () {e.target.style.opacity = 0.6;}, 100);
81                         setTimeout(function () {e.target.style.opacity = 0.4;}, 150);
82                         setTimeout(function () {e.target.style.opacity = 0.2;}, 200);
83                         setTimeout(function () {e.target.style.opacity = 0;}, 250);
84                         setTimeout(function () {e.target.style.display = 'none';}, 300);
85                         setTimeout(function () {e.target = null;}, 350);
86                     }
87
88                 document.body.appendChild(areaDiv);
89
90
91                 RGraph.Registry.Set('chart.zoomed.area.div', null);
92                 RGraph.Registry.Set('chart.zoomed.area.mousedown', coords);
93                 RGraph.Registry.Set('chart.zoomed.area.areadiv', areaDiv);
94             }
95
96
97             canvas.onmousemove = function (e)
98             {
99                 var startCoords = RGraph.Registry.Get('chart.zoomed.area.mousedown');
100                 
101                 if (startCoords && startCoords.length) {
102
103                     var coords      = RGraph.getMouseXY(e);
104                     var canvasXY    = RGraph.getCanvasXY(e.target);
105                     var obj = e.target.__object__;
106                     var context = obj.context;
107                     var canvas  = obj.canvas;
108                     var startx  = startCoords[0];
109                     var starty  = startCoords[1];
110                     var endx    = coords[0];
111                     var endy    = coords[1];
112                     var width   = endx - startx;
113                     var height  = endy - starty;
114                     var areaDiv = RGraph.Registry.Get('chart.zoomed.area.areadiv');
115                     
116                     if (width >= 0 && height >= 0) {
117                     
118                         if (width > 5 && height > 5) {
119                             areaDiv.style.width = (width - 15) + 'px';
120                             areaDiv.style.height = (height - 15) + 'px';
121                             areaDiv.style.display = 'inline';
122                         } else {
123                             areaDiv.style.display = 'none';
124                         }
125
126                     } else if (width < -5 || height < -5) {
127
128                         var canvasCoords = RGraph.getCanvasXY(canvas);
129                         var noticeDiv = document.createElement('DIV');
130
131                         noticeDiv.style.position = 'absolute';
132                         noticeDiv.style.top  = 0;
133                         noticeDiv.style.left = 0;
134                         noticeDiv.style.zIndex = 99;
135                         noticeDiv.style.border = '1px dashed black';
136                         noticeDiv.style.backgroundColor = '#ffc1c1';
137                         noticeDiv.style.MozBoxShadow = '0 0 5px #999';
138                         noticeDiv.style.WebkitBoxShadow = '0 0 5px #999';
139                         noticeDiv.style.boxShadow = '0 0 5px #999';
140                         noticeDiv.style.padding = '2px';
141                         noticeDiv.innerHTML = 'Zoom goes right and down';
142                         document.body.appendChild(noticeDiv);
143
144                         // Reposition the warning
145                         noticeDiv.style.top  = canvasCoords[1] + startCoords[1] - noticeDiv.offsetHeight + 'px';
146                         noticeDiv.style.left = canvasCoords[0] + startCoords[0] - (noticeDiv.offsetWidth / 2) + 'px';
147                         noticeDiv.style.width = noticeDiv.offsetWidth + 'px';
148                         
149                         setTimeout(function () {noticeDiv.style.opacity = 0.8;}, 2100);
150                         setTimeout(function () {noticeDiv.style.opacity = 0.6;}, 2200);
151                         setTimeout(function () {noticeDiv.style.opacity = 0.4;}, 2300);
152                         setTimeout(function () {noticeDiv.style.opacity = 0.2;}, 2400);
153                         setTimeout(function () {noticeDiv.style.display = 'none';}, 2500);
154                         setTimeout(function () {noticeDiv = null;}, 2600);
155                     }
156                 }
157             }
158
159
160             canvas.onmouseup = function (e)
161             {
162                 RGraph.FixEventObject(e);
163
164                 var startCoords = RGraph.Registry.Get('chart.zoomed.area.mousedown');
165                 var coords      = RGraph.getMouseXY(e);
166
167                 // Do the zooming here
168                 if (RGraph.Registry.Get('chart.zoomed.area.mousedown')) {
169
170                     //RGraph.Redraw();
171                     
172                     RGraph.Registry.Get('chart.zoomed.area.areadiv').style.display = 'none';
173                     RGraph.Registry.Get('chart.zoomed.area.areadiv').style.left = '-1000px';
174                     RGraph.Registry.Get('chart.zoomed.area.areadiv').style.top = '-1000px';
175                     RGraph.Registry.Set('chart.zoomed.area.areadiv', null);
176
177                     if (coords[0] < startCoords[0] || coords[1] < startCoords[1]) {
178                         RGraph.Registry.Set('chart.zoomed.area.mousedown', false);
179                         return;
180                     }
181
182                     var canvas       = e.target;
183                     var obj          = canvas.__object__;
184                     var context      = obj.context;
185                     var canvasCoords = RGraph.getCanvasXY(e.target);
186                     var coords       = RGraph.getMouseXY(e);
187                     var startCoords  = RGraph.Registry.Get('chart.zoomed.area.mousedown');
188                     var startx       = startCoords[0];
189                     var starty       = startCoords[1];
190                     var endx         = coords[0] - 15;
191                     var endy         = coords[1] - 15;
192                     var width        = Math.abs(endx - startx);
193                     var height       = Math.abs(endy - starty);
194                     var factor       = obj.Get('chart.zoom.factor') - 1;
195                     
196                     var img = document.createElement('IMG');
197                     img.src = canvas.toDataURL();
198                     img.style.position = 'relative';
199                     img.style.left     = (factor + 1) * -1 * startx + 'px';
200                     img.style.top      = (factor + 1) * -1 * starty + 'px';
201                     img.width          = (factor + 1) * canvas.width;
202                     img.height         = (factor + 1) * canvas.height;
203
204                     var div            = document.createElement('DIV');
205                     div.__object__     = obj;
206                     div.className      = 'RGraph_zoomed_area';
207                     div.style.position = 'absolute';
208                     div.style.backgroundColor = 'white';
209                     div.style.cursor = 'move';
210
211                     div.style.top      = e.pageY + 'px';
212                     div.style.left     = e.pageX + 'px';
213                     div.origWidth      = width;
214                     div.origHeight     = height;
215                     div.style.width    = width + 'px';
216                     div.style.height   = height + 'px';
217                     div.style.border   = '1px solid black';                    
218                     div.style.boxShadow          = '0 0 15px black';
219                     div.style.MozBoxShadow       = '0 0 15px black';
220                     div.style.WebkitBoxShadow    = '0 0 15px black';
221                     div.style.overflow           = 'hidden';
222                     div.style.opacity            = 0;
223                     div.style.zIndex             = 99;
224                     
225                     document.body.appendChild(div);
226                     div.appendChild(img);
227
228
229                     /**
230                     * This facilitates expanding the zoomed area once visible (the double click)
231                     */
232                     div.ondblclick = function (event)
233                     {
234                         var event = RGraph.FixEventObject(event);
235                         var img   = event.target;
236                         var div   = event.target.parentNode;
237                         
238                         var current_width  = div.offsetWidth
239                         var current_height = div.offsetHeight
240                         var target_width   = img.offsetWidth;
241                         var target_height  = img.offsetHeight;
242                         var diff_width     = target_width - current_width;
243                         var diff_height    = target_height - current_height;
244                         
245                         var img_offset_left = parseInt(img.offsetLeft);
246                         var img_offset_top  = parseInt(img.offsetTop);
247                         
248                         // Global vars on purpose so the timers can access them
249                         __zoomed_div_style__ = div.style;
250                         __zoomed_img_style__ = img.style;
251                     
252                         setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 50);
253                         setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 100);
254                         setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 150);
255                         setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 200);
256                         setTimeout("__zoomed_div_style__.left = parseInt(__zoomed_div_style__.left) - " + (diff_width * 0.1) + " + 'px'", 250);
257                     
258                         setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 50);
259                         setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 100);
260                         setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 150);
261                         setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 200);
262                         setTimeout("__zoomed_div_style__.top = parseInt(__zoomed_div_style__.top) - " + (diff_height * 0.1) + " + 'px'", 250);
263                     
264                         setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 50);
265                         setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 100);
266                         setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 150);
267                         setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 200);
268                         setTimeout("__zoomed_div_style__.width = parseInt(__zoomed_div_style__.width) + " + (diff_width * 0.2) + " + 'px'", 250);
269                         
270                         setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 50);
271                         setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 100);
272                         setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 150);
273                         setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 200);
274                         setTimeout("__zoomed_div_style__.height = parseInt(__zoomed_div_style__.height) + " + (diff_height * 0.2) + " + 'px'", 250);
275                     
276                         // Move the image within the div
277                         setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.8) + " + 'px'", 50);
278                         setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.6) + " + 'px'", 100);
279                         setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.4) + " + 'px'", 150);
280                         setTimeout("__zoomed_img_style__.left = " + (img_offset_left * 0.2) + " + 'px'", 200);
281                         setTimeout("__zoomed_img_style__.left = 0", 250);
282                         
283                         setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.8) + " + 'px'", 50);
284                         setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.6) + " + 'px'", 100);
285                         setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.4) + " + 'px'", 150);
286                         setTimeout("__zoomed_img_style__.top = " + (img_offset_top * 0.2) + " + 'px'", 200);
287                         setTimeout("__zoomed_img_style__.top = 0", 250);
288                         
289                         div.ondblclick = null;
290                     }
291                     /**
292                     * Make the zoomed bit draggable
293                     */
294                     div.onmousedown = function (e)
295                     {
296                         e = RGraph.FixEventObject(e);
297                             
298                         var div = e.target.parentNode;
299                         var img = div.childNodes[0];
300                         
301                         if (e.button == 0 || e.button == 1  ) {
302                         
303                             div.__offsetx__       = e.offsetX + img.offsetLeft;
304                             div.__offsety__       = e.offsetY + img.offsetTop;
305                         
306                             RGraph.Registry.Set('chart.mousedown', div);
307                             RGraph.Registry.Set('chart.button', 0);
308                         
309                         } else {
310                         
311                             img.__startx__ = e.pageX;
312                             img.__starty__ = e.pageY;
313                             
314                             img.__originalx__ = img.offsetLeft;
315                             img.__originaly__ = img.offsetTop;
316
317                             RGraph.Registry.Set('chart.mousedown', img);
318                             RGraph.Registry.Set('chart.button', 2);
319                             
320                             /**
321                             * Don't show a context menu when the zoomed area is right-clicked on
322                             */
323                             window.oncontextmenu = function (e)
324                             {
325                                 e = RGraph.FixEventObject(e);
326
327                                 e.stopPropagation();
328                                 
329                                 // [18th July 2010] Is this reallly necessary?
330                                 window.oncontextmenu = function (e)
331                                 {
332                                     return true;
333                                 }
334                             
335
336                                 return false;
337                             }
338                         }
339
340                         e.stopPropagation();
341
342                         return false;
343                     }
344                     
345                     window.onmouseup = function (e)
346                     {
347                         RGraph.Registry.Set('chart.mousedown', false);
348                     }
349                     
350                     window.onmousemove = function (e)
351                     {
352                         if (RGraph.Registry.Get('chart.mousedown') && RGraph.Registry.Get('chart.button') == 0) {
353                             
354                             var div = RGraph.Registry.Get('chart.mousedown');
355                     
356                             var x = e.pageX - div.__offsetx__;
357                             var y = e.pageY - div.__offsety__;
358                     
359                             div.style.left = x + 'px';
360                             div.style.top = y + 'px';
361
362                         } else if (RGraph.Registry.Get('chart.mousedown') && RGraph.Registry.Get('chart.button') == 2) {
363                             
364                             var img = RGraph.Registry.Get('chart.mousedown');
365                     
366                             var x = img.__originalx__ + e.pageX - img.__startx__;
367                             var y = img.__originaly__ + e.pageY - img.__starty__;
368                     
369                             img.style.left = x + 'px';
370                             img.style.top  = y + 'px';
371                         }
372                     }
373                     // End dragging code
374
375
376                     var divs = RGraph.Registry.Get('chart.zoomed.area.divs');
377                     if (typeof(divs) == 'object') {
378                         divs.push(div);
379                     } else {
380                         RGraph.Registry.Set('chart.zoomed.area.divs', [div])
381                     }
382                     
383                     // Create the background
384                     var bg = document.createElement('DIV');
385                     bg.style.position        = 'fixed'
386                     bg.style.zIndex          = 98;
387                     bg.style.top             = 0;
388                     bg.style.left            = 0;
389                     bg.style.backgroundColor = '#999';
390                     bg.style.opacity         = 0;
391                     bg.style.width           = (screen.width + 100) + 'px';
392                     bg.style.height          = (screen.height + 100) + 'px';
393                     document.body.appendChild(bg);
394                     
395                     bg.onclick = function (e)
396                     {
397                         div.style.display = 'none';
398                         bg.style.display  = 'none';
399                         div = null;
400                         bg  = null;
401                     }
402                     
403
404                     setTimeout(function (){div.style.opacity = 0.2;}, 50);
405                     setTimeout(function (){div.style.opacity = 0.4;}, 100);
406                     setTimeout(function (){div.style.opacity = 0.6;}, 150);
407                     setTimeout(function (){div.style.opacity = 0.8;}, 200);
408                     setTimeout(function (){div.style.opacity = 1.0;}, 250);
409                     
410                     setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.1) + 'px'}, 50);
411                     setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.2) + 'px'}, 100);
412                     setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.3) + 'px'}, 150);
413                     setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.4) + 'px'}, 200);
414                     setTimeout(function () {div.style.left = canvasCoords[0] + startx - (width * factor * 0.5) + 'px'}, 250);
415
416                     setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.1) + 'px'}, 50);
417                     setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.2) + 'px'}, 100);
418                     setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.3) + 'px'}, 150);
419                     setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.4) + 'px'}, 200);
420                     setTimeout(function () {div.style.top = canvasCoords[1] + starty - (height * factor * 0.5) + 'px'}, 250);
421
422                     setTimeout(function () {div.style.width = width + (width * factor * 0.2) + 'px'}, 50);
423                     setTimeout(function () {div.style.width = width + (width * factor * 0.4) + 'px'}, 100);
424                     setTimeout(function () {div.style.width = width + (width * factor * 0.6) + 'px'}, 150);
425                     setTimeout(function () {div.style.width = width + (width * factor * 0.8) + 'px'}, 200);
426                     setTimeout(function () {div.style.width = width + (width * factor * 1.0) + 'px'}, 250);
427                     
428                     setTimeout(function () {div.style.height = height + (height * factor * 0.2) + 'px'}, 50);
429                     setTimeout(function () {div.style.height = height + (height * factor * 0.4) + 'px'}, 100);
430                     setTimeout(function () {div.style.height = height + (height * factor * 0.6) + 'px'}, 150);
431                     setTimeout(function () {div.style.height = height + (height * factor * 0.8) + 'px'}, 200);
432                     setTimeout(function () {div.style.height = height + (height * factor * 1.0) + 'px'}, 250);
433
434                     setTimeout(function (){bg.style.opacity = 0.1;}, 50);
435                     setTimeout(function (){bg.style.opacity = 0.2;}, 100);
436                     setTimeout(function (){bg.style.opacity = 0.3;}, 150);
437                     setTimeout(function (){bg.style.opacity = 0.4;}, 200);
438                     setTimeout(function (){bg.style.opacity = 0.5;}, 250);
439
440                     RGraph.Registry.Set('chart.zoomed.area.bg', bg);
441                     RGraph.Registry.Set('chart.zoomed.area.img', img);
442                     RGraph.Registry.Set('chart.zoomed.area.div', div);
443                     RGraph.Registry.Set('chart.zoomed.area.mousedown', null);
444                 }
445
446                 /**
447                 * Fire the zoom event
448                 */
449                 RGraph.FireCustomEvent(obj, 'onzoom');
450             }
451             
452             canvas.onmouseout = function (e)
453             {
454                 RGraph.Registry.Set('chart.zoomed.area.areadiv', null);
455                 RGraph.Registry.Set('chart.zoomed.area.mousedown', null);
456                 RGraph.Registry.Set('chart.zoomed.area.div', null);
457             }
458         }
459     }
460
461
462     /**
463     * This function sets up the zoom window if requested
464     * 
465     * @param obj object The graph object
466     */
467     RGraph.ShowZoomWindow = function (obj)
468     {
469         var gutter = obj.Get('chart.gutter');
470
471         if (obj.Get('chart.zoom.mode') == 'thumbnail') {
472             RGraph.ZoomWindow(obj.canvas);
473         }
474
475         if (obj.Get('chart.zoom.mode') == 'area') {
476             RGraph.ZoomArea(obj);
477         }
478     }
479
480
481     /**
482     * Installs the evnt handler for the zoom window/THUMBNAIL
483     */
484     RGraph.ZoomWindow = function (canvas)
485     {
486         canvas.onmousemove = function (e)
487         {
488             e = RGraph.FixEventObject(e);
489
490             var obj     = e.target.__object__;
491             var canvas  = obj.canvas;
492             var context = obj.context;
493             var coords  = RGraph.getMouseXY(e);
494             
495             /**
496             * Create the DIV
497             */
498             if (!RGraph.Registry.Get('chart.zoomed.div')) {
499
500                 var div = document.createElement('div');
501                 div.className    = 'RGraph_zoom_window';
502                 div.style.width  = obj.Get('chart.zoom.thumbnail.width') + 'px';
503                 div.style.height = obj.Get('chart.zoom.thumbnail.height') + 'px';
504                 
505                 // Added back in on the 17th December
506                 div.style.border = '2px dashed gray';
507
508                 div.style.position = 'absolute';
509                 div.style.overflow = 'hidden';
510                 div.style.backgroundColor = 'white';
511                 
512                 // Initially the zoomed layer should be off-screen
513                 div.style.left = '-1000px';
514                 div.style.top = '-1000px';
515
516                 // Should these be 0? No.
517                 div.style.borderRadius       = '5px';
518                 div.style.MozBorderRadius    = '5px';
519                 div.style.WebkitBorderRadius = '5px';
520
521                 if (obj.Get('chart.zoom.shadow')) {
522                     div.style.boxShadow       = 'rgba(0,0,0,0.5) 3px 3px 3px';
523                     div.style.MozBoxShadow    = 'rgba(0,0,0,0.5) 3px 3px 3px';
524                     div.style.WebkitBoxShadow = 'rgba(0,0,0,0.5) 3px 3px 3px';
525                 }
526
527                 //div.style.opacity = 0.2;
528                 div.__object__ = obj;
529                 document.body.appendChild(div);
530         
531                 /**
532                 * Get the canvas as an image
533                 */
534                 var img = document.createElement('img');
535                 img.width  = obj.canvas.width * obj.Get('chart.zoom.factor');
536                 img.height = obj.canvas.height * obj.Get('chart.zoom.factor');
537                 img.style.position = 'relative';
538                 img.style.backgroundColor = 'white';
539                 img.__object__ = obj;
540
541                 div.appendChild(img);
542
543                 RGraph.Registry.Set('chart.zoomed.div', div);
544                 RGraph.Registry.Set('chart.zoomed.img', img);
545                 
546                 // Fade the zoom in
547                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').__object__.canvas.onmouseover()", 5);
548
549             } else {
550
551                 div = RGraph.Registry.Get('chart.zoomed.div');
552                 img = RGraph.Registry.Get('chart.zoomed.img');
553             }
554
555             // Make sure the image is up-to-date
556             img.src = canvas.toDataURL();
557             
558             /**
559             * Ensure the div is visible
560             */
561             if (div && div.style.opacity < 1) {
562                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 1", 400);
563             }
564
565             /**
566             * Get the canvas x/y coords
567             */
568             var c = RGraph.getCanvasXY(obj.canvas);
569             var x = c[0];
570             var y = c[1];
571
572             /**
573             * Position the div and img
574             */
575             var offset = 7;
576
577             div.style.left = (e.pageX - obj.Get('chart.zoom.thumbnail.width') - offset) + 'px';
578             div.style.top = (e.pageY -  obj.Get('chart.zoom.thumbnail.height') - offset) + 'px';
579             
580             var l = (obj.Get('chart.zoom.thumbnail.width') / 2) - (coords[0] * obj.Get('chart.zoom.factor'));
581             var t = (obj.Get('chart.zoom.thumbnail.height') / 2) - (coords[1] * obj.Get('chart.zoom.factor'));
582
583             // More positioning
584             img.style.left = (l + ((obj.Get('chart.zoom.thumbnail.width') / 2) * obj.Get('chart.zoom.factor'))) + 'px';
585             img.style.top = (t + ((obj.Get('chart.zoom.thumbnail.height') / 2) * obj.Get('chart.zoom.factor'))) + 'px';
586             
587             /**
588             * Fire the onzoom event
589             */
590             RGraph.FireCustomEvent(obj, 'onzoom');
591         }
592         
593         /**
594         * The onmouseover event. Evidently. Fades the zoom window in
595         */
596         canvas.onmouseover = function (e)
597         {
598             var div = RGraph.Registry.Get('chart.zoomed.div');
599             
600             // ???
601             if (!div) return;
602
603             var obj = div.__object__;
604
605             // Used for the enlargement animation
606             var targetWidth  = obj.Get('chart.zoom.thumbnail.width');
607             var targetHeight = obj.Get('chart.zoom.thumbnail.height');
608
609             div.style.width  = 0;
610             div.style.height = 0;
611
612             if (obj.Get('chart.zoom.fade.in')) {
613                 
614                 RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.2;
615                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.4", 100);
616                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.6", 200);
617                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.8", 300);
618                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 1", 400);
619
620             } else {
621
622                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 1", 1);
623             }
624
625             // The enlargement animation frames
626             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (1/5) ) + "px'", 75);
627             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (2/5) ) + "px'", 150);
628             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (3/5) ) + "px'", 225);
629             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (4/5) ) + "px'", 300);
630             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.width = '" + (targetWidth * (5/5) ) + "px'", 325);
631             
632             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (1/5) ) + "px'", 75);
633             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (2/5) ) + "px'", 150);
634             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (3/5) ) + "px'", 225);
635             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (4/5) ) + "px'", 300);
636             setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.height = '" + (targetHeight * (5/5) ) + "px'", 375);
637         }
638         
639         canvas.onmouseout = function (e)
640         {
641             if (RGraph.Registry.Get('chart.zoomed.div') && RGraph.Registry.Get('chart.zoomed.div').__object__.Get('chart.zoom.fade.out')) {
642
643                 RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.8;
644                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.6", 100);
645                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.4", 200);
646                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.2", 300);
647                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0", 400);
648
649                 // Get rid of the zoom window
650                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 400);
651                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 400);
652             
653             } else {
654                 // Get rid of the zoom window
655                 if (RGraph.Registry.Get('chart.zoomed.div')) {
656                     setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 1);
657                     setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 41);
658                 }            }
659         }
660     }
661
662
663     /**
664     * A zoom in function
665     * 
666     * @param e object The event object
667     */
668     RGraph.Zoom = function (e)
669     {
670         e = RGraph.FixEventObject(e);
671
672         /**
673         * Show the zoom window
674         */
675         //if ((e.target.__canvas__ && e.target.__canvas__.__object__.Get('chart.zoom.mode') == 'thumbnail') || (e.target.parentNode.__canvas__ && e.target.parentNode.__canvas__.__object__.Get('chart.zoom.mode') == 'thumbnail') ) {
676         //    return RGraph.ZoomWindow(e);
677         //}
678
679         var canvas  = e.target.__canvas__;
680         var context = canvas.getContext('2d');
681         var obj     = canvas.__object__;
682         var dataurl = canvas.toDataURL();
683         var tmp     = canvas;
684         var coords = RGraph.getCanvasXY(canvas);
685         var factor = obj.Get('chart.zoom.factor') - 1;
686
687         var x = coords[0];
688         var y = coords[1];
689
690         var img = document.createElement('img');
691         img.className    = 'RGraph_zoomed_canvas';
692         img.style.border = '3px solid gray';
693         img.style.width  = canvas.width + 'px';
694         img.style.height = canvas.height + 'px';
695         img.style.position = 'absolute';
696         img.style.left = x + 'px';
697         img.style.top = y + 'px';
698         img.style.backgroundColor = 'white';
699         img.style.opacity = obj.Get('chart.zoom.fade.in') ? 0 : 1;
700         img.style.zIndex = 99;
701         img.src = dataurl;
702         document.body.appendChild(img);
703
704         //RGraph.Registry.Set('chart.zoomedimage', img);
705         // Store the zoomed image in a global var - NOT the registry
706         __zoomedimage__ = img;
707         __zoomedimage__.obj = obj;
708         
709         // Image onclick should not hide the image
710         img.onclick = function (e)
711         {
712             e = RGraph.FixEventObject(e);
713             e.stopPropagation();
714             return false;
715         }
716
717         setTimeout(function () {window.onclick = RGraph.HideZoomedCanvas;}, 1);
718         
719         var width = parseInt(canvas.width);
720         var height = parseInt(canvas.height);
721         var frames = obj.Get('chart.zoom.frames');
722         var delay  = obj.Get('chart.zoom.delay');
723
724         // Increase the width over 10 frames - center
725         if (obj.Get('chart.zoom.hdir') == 'center') {
726
727             for (var i=1; i<=frames; ++i) {
728                 var newWidth      = width * factor * (i/frames) + width;
729                 var rightHandEdge = x + canvas.width;
730                 var newLeft       = (x + (canvas.width / 2)) - (newWidth / 2);
731
732                 setTimeout("__zoomedimage__.style.width = '" + String(newWidth) + "px'; __zoomedimage__.style.left = '" + newLeft + "px'", i * delay);
733             }
734
735         // Left
736         } else if (obj.Get('chart.zoom.hdir') == 'left') {
737             for (var i=1; i<=frames; ++i) {
738                 var newWidth      = width * factor * (i/frames) + width;
739                 var rightHandEdge = x + canvas.width;
740                 var newLeft       = rightHandEdge - newWidth;
741
742                 setTimeout("__zoomedimage__.style.width = '" + String(newWidth) + "px'; __zoomedimage__.style.left = '" + newLeft + "px'", i * delay);
743             }
744             
745         // Right (default)
746         } else {
747             for (var i=1; i<=frames; ++i) {
748                 var newWidth      = width * factor * (i/frames) + width;
749                 setTimeout("__zoomedimage__.style.width = '" + String(newWidth) + "px'", i * delay);
750             }
751         }
752
753         // Increase the height over 10 frames - up
754         if (obj.Get('chart.zoom.vdir') == 'up') {
755             for (var i=1; i<=frames; ++i) {
756                 var newHeight  = (height * factor * (i/frames)) + height;
757                 var bottomEdge = y + canvas.height;
758                 var newTop       = bottomEdge - newHeight;
759         
760                 setTimeout("__zoomedimage__.style.height = '" + String(newHeight) + "px'; __zoomedimage__.style.top = '" + newTop + "px'", i * delay);
761             }
762         
763         // center
764         } else if (obj.Get('chart.zoom.vdir') == 'center') {
765             for (var i=1; i<=frames; ++i) {
766                 var newHeight  = (height * factor * (i/frames)) + height;
767                 var bottomEdge = (y + (canvas.height / 2)) + (newHeight / 2);
768                 var newTop       = bottomEdge - newHeight;
769
770                 setTimeout("__zoomedimage__.style.height = '" + String(newHeight) + "px'; __zoomedimage__.style.top = '" + newTop + "px'", i * delay);
771             }
772         
773         // Down (default
774         } else {
775             for (var i=1; i<=frames; ++i) {
776                 setTimeout("__zoomedimage__.style.height = '" + String(height * factor * (i/frames) + height) + "px'", i * delay);
777             }
778         }
779
780         // If enabled, increase the opactity over 10 frames
781         if (obj.Get('chart.zoom.fade.in')) {
782             for (var i=1; i<=frames; ++i) {
783                 setTimeout("__zoomedimage__.style.opacity = " + String(i / frames), i * delay);
784             }
785         }
786
787         // If stipulated, produce a shadow
788         if (obj.Get('chart.zoom.shadow')) {
789             for (var i=1; i<=frames; ++i) {
790                 setTimeout("__zoomedimage__.style.boxShadow = 'rgba(128,128,128," + Number(i / frames) / 2 + ") 0 0 15px'", i * delay);
791                 setTimeout("__zoomedimage__.style.MozBoxShadow = 'rgba(128,128,128," + Number(i / frames) / 2 + ") 0 0 15px'", i * delay);
792                 setTimeout("__zoomedimage__.style.WebkitBoxShadow = 'rgba(128,128,128," + Number(i / frames) / 2 + ") 0 0 15px'", i * delay);
793             }
794         }
795
796         /**
797         * The onmouseout event. Hides the zoom window. Fades the zoom out
798         */
799         canvas.onmouseout = function (e)
800         {
801             if (RGraph.Registry.Get('chart.zoomed.div') && RGraph.Registry.Get('chart.zoomed.div').__object__.Get('chart.zoom.fade.out')) {
802
803                 RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.8;
804                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.6", 100);
805                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.4", 200);
806                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0.2", 300);
807                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.opacity = 0", 400);
808
809                 // Get rid of the zoom window
810                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 400);
811                 setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 400);
812             
813             } else {
814
815                 // Get rid of the zoom window
816                 if (RGraph.Registry.Get('chart.zoomed.div')) {
817                     setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.left = '-400px'", 1);
818                     setTimeout("RGraph.Registry.Get('chart.zoomed.div').style.top = '-400px'", 1);
819                 }
820             }
821         }
822
823         // The background
824         if (obj.Get('chart.zoom.background')) {
825             var div = document.createElement('DIV');
826             div.style.backgroundColor = '#999';
827             div.style.opacity         = 0;
828             div.style.position        = 'fixed';
829             div.style.top             = 0;
830             div.style.left            = 0;
831             div.style.width           = (screen.width + 100) + 'px';
832             div.style.height          = (screen.height + 100) + 'px';
833             div.style.zIndex          = 98;
834
835             // Hides the zoomed caboodle
836             div.oncontextmenu = function (e)
837             {
838                 return RGraph.HideZoomedCanvas(e);
839             }
840
841             // 30th July 2010 - Is this necessary?
842             //for (var i=1; i<=frames; ++i) {
843             //  setTimeout('__zoomedbackground__.style.opacity = ' + Number(0.04 * i), i * delay);
844             //
845             //    //  MSIE doesn't support zoom
846             //    //setTimeout('__zoomedbackground__.style.filter = "progid:DXImageTransform.Microsoft.Shadow(color=#aaaaaa,direction=135); Alpha(opacity=10)"', 50);
847             //}
848             
849             div.origHeight = div.style.height;
850             
851             document.body.appendChild(div);
852
853             __zoomedbackground__ = div;
854             
855             // If the window is resized, hide the zoom
856             //window.onresize = RGraph.HideZoomedCanvas;
857
858             for (var i=1; i<=frames; ++i) {
859                 setTimeout("__zoomedbackground__.style.opacity = " + (Number(i / frames) * 0.5), i * delay);
860             }
861         }
862         
863         /**
864         * Fire the onzoom event
865         */
866         RGraph.FireCustomEvent(obj, 'onzoom');
867     }