initial commit
[home-automation.git] / libraries / RGraph.common.annotate.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     * The function which controls the annotate feature
20     * 
21     * @param object obj The graph object
22     */
23     RGraph.Annotate = function (obj)
24     {
25         /**
26         * This installs some event handlers
27         */
28         if (obj.Get('chart.annotatable')) {
29
30             var canvas  = obj.canvas;
31             var context = obj.context;
32             
33             /**
34             * Capture the mouse events so we can set whther the mouse is down or not
35             */
36                 canvas.onmousedown = function (e)
37                 {
38                     if (e.button == 0) {
39
40                         e.target.__object__.Set('chart.mousedown', true);
41
42                         // Get the context
43                         var obj = e.target.__object__;
44                         var context = obj.canvas.getContext('2d');
45
46                         // Don't want any "joining" lines or colour "bleeding"
47                         context.beginPath();
48
49                         // Accommodate Chrome
50                         var coords = RGraph.getMouseXY(e);
51                         var x      = coords[0];
52                         var y      = coords[1];
53                         
54                         // Clear the annotation recording
55                         RGraph.Registry.Set('annotate.actions', [obj.Get('chart.annotate.color')]);
56
57                         context.strokeStyle = obj.Get('chart.annotate.color');
58
59                         context.moveTo(x, y);
60                     
61                         // Set the lineWidth
62                         context.lineWidth = 1;
63                         
64                         RGraph.Registry.Set('started.annotating', false);
65                         
66                         /**
67                         * Fire the onannotatestart event
68                         */
69                         RGraph.FireCustomEvent(obj, 'onannotatestart');
70                     }
71                     
72                     return false;
73                 }
74                 
75                 /**
76                 * This cancels annotating for ALL canvases
77                 */
78                 window.onmouseup = function (e)
79                 {
80                     var tags = document.getElementsByTagName('canvas');
81
82                     for (var i=0; i<tags.length; ++i) {
83                         if (tags[i].__object__) {
84                             tags[i].__object__.Set('chart.mousedown', false);
85                         }
86                     }
87
88                     // Store the annotations in browser storage if it's available
89                     if (RGraph.Registry.Get('annotate.actions') && RGraph.Registry.Get('annotate.actions').length > 0 && window.localStorage) {
90
91                         var id = '__rgraph_annotations_' + e.target.id + '__';
92                         var annotations  = window.localStorage[id] ? window.localStorage[id] + '|' : '';
93                             annotations += RGraph.Registry.Get('annotate.actions');
94
95                         // Store the annotations information in HTML5 browser storage here
96                         window.localStorage[id] = annotations;
97                     }
98                     
99                     // Clear the recorded annotations
100                     RGraph.Registry.Set('annotate.actions', []);
101                     
102                     /**
103                     * Fire the annotate event
104                     */
105                     RGraph.FireCustomEvent(e.target.__object__, 'onannotateend');
106                 }
107                 
108                 canvas.onmouseup = function (e)
109                 {
110                     //window.onmouseup(e);
111                 }
112
113                 //canvas.onmouseout = window.onmouseup;
114
115             /**
116             * The canvas onmousemove function
117             */
118             canvas.onmousemove = function (e)
119             {
120                 var e      = RGraph.FixEventObject(e);
121                 var obj    = e.target.__object__;
122                 var coords = RGraph.getMouseXY(e);
123                 var x      = coords[0];
124                 var y      = coords[1];
125                 var gutter = obj.Get('chart.gutter');
126                 var width  = canvas.width;
127                 var height = canvas.height;
128
129                 obj.context.lineWidth = 1;
130
131                 // Don't allow annotating in the gutter
132                 //
133                 // CHANGED 20TH DECEMBER 2010 TO ALLOW ANNOTATING IN THE GUTTER
134                 if (true) {
135                 
136                     canvas.style.cursor = 'crosshair';
137                 
138                     if (obj.Get('chart.mousedown')) {
139                            
140                        // Special case for HBars and Gantts with their extra wide left gutter
141                        if ( (obj.type != 'hbar' && obj.type != 'gantt') || x > (3 * gutter)) {
142
143                            /**
144                            * This is here to stop annotating in the gutter
145                            */
146                             if (RGraph.Registry.Get('started.annotating') == false) {
147                                 context.moveTo(x, y);
148                                 RGraph.Registry.Set('started.annotating', true)
149                             }
150
151                             context.lineTo(x, y);
152
153                             RGraph.Registry.Set('annotate.actions', RGraph.Registry.Get('annotate.actions') + '|' + x + ',' + y);
154
155                             context.stroke();
156
157                             /**
158                             * Fire the annotate event
159                             */
160                             RGraph.FireCustomEvent(obj, 'onannotate');
161                         }
162                     }
163
164                 } else {
165                     canvas.style.cursor = 'default';
166                 }
167             }
168
169             RGraph.ReplayAnnotations(obj);
170         }
171     }
172
173
174     /**
175     * Shows the mini palette used for annotations
176     * 
177     * @param object e The event object
178     */
179     RGraph.Showpalette = function (e)
180     {
181         var isSafari = navigator.userAgent.indexOf('Safari') ? true : false;
182
183         e = RGraph.FixEventObject(e);
184
185         var canvas  = e.target.parentNode.__canvas__;
186         var context = canvas.getContext('2d');
187         var obj     = canvas.__object__;
188         var div     = document.createElement('DIV');
189         var coords  = RGraph.getMouseXY(e);
190         
191         div.__object__               = obj; // The graph object
192         div.className                = 'RGraph_palette';
193         div.style.position           = 'absolute';
194         div.style.backgroundColor    = 'white';
195         div.style.border             = '1px solid black';
196         div.style.left               = 0;
197         div.style.top                = 0;
198         div.style.padding            = '3px';
199         div.style.paddingBottom      = 0;
200         div.style.paddingRight       = 0;
201         div.style.opacity            = 0;
202         div.style.boxShadow          = 'rgba(96,96,96,0.5) 3px 3px 3px';
203         div.style.WebkitBoxShadow    = 'rgba(96,96,96,0.5) 3px 3px 3px';
204         div.style.MozBoxShadow       = 'rgba(96,96,96,0.5) 3px 3px 3px';
205         div.style.filter             = 'progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135)';
206         
207         var common_css       = 'padding: 1px; display: inline; display: inline-block; width: 15px; height: 15px; margin-right: 3px; cursor: pointer;' + (isSafari ? 'margin-bottom: 3px' : '');
208         var common_mouseover = ' onmouseover="this.style.border = \'1px black solid\'; this.style.padding = 0"';
209         var common_mouseout  = ' onmouseout="this.style.border = 0; this.style.padding = \'1px\'" ';
210
211         var str = '';
212
213         var colors = ['red', 'blue', 'green', 'black', 'yellow', 'magenta', 'pink', 'cyan', 'purple', '#ddf', 'gray', '#36905c'];
214
215         for (i=0; i<colors.length; ++i) {
216             str = str + '<span ' + common_mouseover + common_mouseout + ' style="background-color: ' + colors[i] + '; ' + common_css  + '" onclick="this.parentNode.__object__.Set(\'chart.annotate.color\', this.style.backgroundColor); this.parentNode.style.display = \'none\'">&nbsp;</span>';
217             
218             // This makes the colours go across two levels
219             if (i == 5) {
220                 str += '<br />';
221             }
222         }
223
224         div.innerHTML = str;
225         document.body.appendChild(div);
226         
227         /**
228         * Now the div has been added to the document, move it up and left and set the width and height
229         */
230         div.style.width  = (div.offsetWidth - (RGraph.isIE9up() ? 12 : 5)) + 'px';
231         div.style.height = (div.offsetHeight - (RGraph.isIE9up() ? 13 : 5)) + 'px';
232         div.style.left   = Math.max(0, e.pageX - div.offsetWidth - 2) + 'px';
233         div.style.top    = (e.pageY - div.offsetHeight - 2) + 'px';
234
235         /**
236         * Store the palette div in the registry
237         */
238         RGraph.Registry.Set('palette', div);
239         
240         setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.2", 50);
241         setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.4", 100);
242         setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.6", 150);
243         setTimeout("RGraph.Registry.Get('palette').style.opacity = 0.8", 200);
244         setTimeout("RGraph.Registry.Get('palette').style.opacity = 1", 250);
245
246         RGraph.HideContext();
247
248         window.onclick = function ()
249         {
250             RGraph.HidePalette();
251         }
252
253         // Should this be here? Yes. This function is being used as an event handler.
254         e.stopPropagation();
255         return false;
256     }
257     
258     
259     /**
260     * Clears any annotation data from global storage
261     * 
262     * @param string id The ID of the canvas
263     */
264     RGraph.ClearAnnotations = function (id)
265     {
266         if (window.localStorage && window.localStorage['__rgraph_annotations_' + id + '__'] && window.localStorage['__rgraph_annotations_' + id + '__'].length) {
267             window.localStorage['__rgraph_annotations_' + id + '__'] = [];
268         }
269     }
270
271
272     /**
273     * Replays stored annotations
274     * 
275     * @param object obj The graph object
276     */
277     RGraph.ReplayAnnotations = function (obj)
278     {
279         // Check for support
280         if (!window.localStorage) {
281             return;
282         }
283
284         var context     = obj.context;
285         var annotations = window.localStorage['__rgraph_annotations_' + obj.id + '__'];
286         var i, len, move, coords;
287
288         context.beginPath();
289         context.lineWidth = 2;
290
291         if (annotations && annotations.length) {
292             annotations = annotations.split('|');
293         } else {
294             return;
295         }
296
297         for (i=0, len=annotations.length; i<len; ++i) {
298             if (!annotations[i].match(/^[0-9]+,[0-9]+$/)) {
299                 context.stroke();
300                 context.beginPath();
301                 context.strokeStyle = annotations[i];
302                 move = true;
303                 continue;
304             }
305             
306             coords = annotations[i].split(',');
307
308             if (move) {
309                 context.moveTo(coords[0], coords[1]);
310                 move = false;
311             } else {
312                 context.lineTo(coords[0], coords[1]);
313             }
314         }
315         
316         context.stroke();
317     }