source: Dev/branches/rest-dojo-ui/client/dojox/charting/action2d/MouseZoomAndPan.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 8.9 KB
Line 
1define(["dojo/_base/html", "dojo/_base/declare", "dojo/_base/window", "dojo/_base/array", "dojo/_base/event",
2        "dojo/_base/connect", "./ChartAction", "dojo/_base/sniff", "dojo/dom-prop", "dojo/keys"],
3        function(html, declare, win, arr, eventUtil, connect, ChartAction, has, domProp, keys){
4
5        /*=====
6        dojo.declare("dojox.charting.action2d.__MouseZoomAndPanCtorArgs", null, {
7                //      summary:
8                //              Additional arguments for mouse zoom and pan actions.
9       
10                //      axis: String?
11                //              Target axis name for this action.  Default is "x".
12                axis: "x",
13                //      scaleFactor: Number?
14                //              The scale factor applied on mouse wheel zoom.  Default is 1.2.
15                scaleFactor: 1.2,
16                //      maxScale: Number?
17                //              The max scale factor accepted by this chart action.  Default is 100.
18                maxScale: 100,
19                //      enableScroll: Boolean?
20                //              Whether mouse drag gesture should scroll the chart.  Default is true.
21                enableScroll: true,
22                //      enableDoubleClickZoom: Boolean?
23                //              Whether a double click gesture should toggle between fit and zoom on the chart.  Default is true.
24                enableDoubleClickZoom: true,
25                //      enableKeyZoom: Boolean?
26                //              Whether a keyZoomModifier + + or keyZoomModifier + - key press should zoom in our out on the chart.  Default is true.
27                enableKeyZoom: true,
28                //      keyZoomModifier: String?
29                //              Which keyboard modifier should used for keyboard zoom in and out. This should be one of "alt", "ctrl", "shift" or "none" for no modifier. Default is "ctrl".
30                keyZoomModifier: "ctrl"
31        });
32        var ChartAction = dojox.charting.action2d.ChartAction;
33        =====*/
34
35        var sUnit = has("mozilla") ? -3 : 120;
36        var keyTests = {
37                none: function(event){
38                        return !event.ctrlKey && !event.altKey && !event.shiftKey;
39                },
40                ctrl: function(event){
41                        return event.ctrlKey && !event.altKey && !event.shiftKey;
42                },
43                alt: function(event){
44                        return !event.ctrlKey && event.altKey && !event.shiftKey;
45                },
46                shift: function(event){
47                        return !event.ctrlKey && !event.altKey && event.shiftKey;
48                }
49        };
50
51        return declare("dojox.charting.action2d.MouseZoomAndPan", ChartAction, {
52                //      summary:
53                //              Create an mouse zoom and pan action.
54                //              You can zoom in or out the data window with mouse wheel. You can scroll using mouse drag gesture.
55                //              You can toggle between zoom and fit view using double click on the chart.
56
57                // the data description block for the widget parser
58                defaultParams: {
59                        axis: "x",
60                        scaleFactor: 1.2,       
61                        maxScale: 100,
62                        enableScroll: true,
63                        enableDoubleClickZoom: true,
64                        enableKeyZoom: true,
65                        keyZoomModifier: "ctrl"
66                },
67                optionalParams: {}, // no optional parameters
68               
69                constructor: function(chart, plot, kwArgs){
70                        //      summary:
71                        //              Create an mouse zoom and pan action and connect it.
72                        //      chart: dojox.charting.Chart
73                        //              The chart this action applies to.
74                        //      kwArgs: dojox.charting.action2d.__MouseZoomAndPanCtorArgs?
75                        //              Optional arguments for the chart action.
76                        this._listeners = [{eventName: !has("mozilla") ? "onmousewheel" : "DOMMouseScroll", methodName: "onMouseWheel"}];
77                        if(!kwArgs){ kwArgs = {}; }
78                        this.axis = kwArgs.axis ? kwArgs.axis : "x";
79                        this.scaleFactor = kwArgs.scaleFactor ? kwArgs.scaleFactor : 1.2;
80                        this.maxScale = kwArgs.maxScale ? kwArgs.maxScale : 100;
81                        this.enableScroll = kwArgs.enableScroll != undefined ? kwArgs.enableScroll : true;
82                        this.enableDoubleClickZoom = kwArgs.enableDoubleClickZoom != undefined ? kwArgs.enableDoubleClickZoom : true;
83                        this.enableKeyZoom = kwArgs.enableKeyZoom != undefined ? kwArgs.enableKeyZoom : true;
84                        this.keyZoomModifier = kwArgs.keyZoomModifier ? kwArgs.keyZoomModifier : "ctrl";
85                        if(this.enableScroll){
86                                this._listeners.push({eventName: "onmousedown", methodName: "onMouseDown"});
87                        }
88                        if(this.enableDoubleClickZoom){
89                                this._listeners.push({eventName: "ondblclick", methodName: "onDoubleClick"});
90                        }
91                        if(this.enableKeyZoom){
92                                this._listeners.push({eventName: "keypress", methodName: "onKeyPress"});                               
93                        }
94                        this._handles = [];
95                        this.connect();
96                },
97               
98                _disconnectHandles: function(){
99                        if(has("ie")){
100                                this.chart.node.releaseCapture();
101                        }
102                        arr.forEach(this._handles, connect.disconnect);
103                        this._handles = [];
104                },
105               
106                connect: function(){
107                        //      summary:
108                        //              Connect this action to the chart.
109                        this.inherited(arguments);
110                        if(this.enableKeyZoom){
111                                // we want to be able to get focus to receive key events
112                                domProp.set(this.chart.node, "tabindex", "0");
113                                // if one doesn't want a focus border he can do something like
114                                // dojo.style(this.chart.node, "outline", "none");
115                        }
116                },
117               
118                disconnect: function(){
119                        //      summary:
120                        //              Disconnect this action from the chart.
121                        this.inherited(arguments);
122                        if(this.enableKeyZoom){
123                                // we don't need anymore to be able to get focus to receive key events
124                                domProp.set(this.chart.node, "tabindex", "-1");
125                        }
126                        // in case we disconnect before the end of the action
127                        this._disconnectHandles();
128                },
129       
130                onMouseDown: function(event){
131                        //      summary:
132                        //              Called when mouse is down on the chart.
133                        var chart = this.chart, axis = chart.getAxis(this.axis);
134                        if(!axis.vertical){
135                                this._startCoord = event.pageX;
136                        }else{
137                                this._startCoord = event.pageY;
138                        }
139                        this._startOffset = axis.getWindowOffset();
140                        this._isPanning = true;
141                        // we now want to capture mouse move events everywhere to avoid
142                        // stop scrolling when going out of the chart window
143                        if(has("ie")){
144                                this._handles.push(connect.connect(this.chart.node, "onmousemove", this, "onMouseMove"));
145                                this._handles.push(connect.connect(this.chart.node, "onmouseup", this, "onMouseUp"));
146                                this.chart.node.setCapture();
147                        }else{
148                                this._handles.push(connect.connect(win.doc, "onmousemove", this, "onMouseMove"));
149                                this._handles.push(connect.connect(win.doc, "onmouseup", this, "onMouseUp"));
150                        }
151                        chart.node.focus();
152                        // prevent the browser from trying the drag on the "image"
153                        eventUtil.stop(event);
154                },
155       
156                onMouseMove: function(event){
157                        //      summary:
158                        //              Called when mouse is moved on the chart.
159                        if(this._isPanning){
160                                var chart = this.chart, axis = chart.getAxis(this.axis);
161                                var delta = axis.vertical?(this._startCoord- event.pageY):(event.pageX - this._startCoord);
162                               
163                                var bounds = axis.getScaler().bounds,
164                                        s = bounds.span / (bounds.upper - bounds.lower);
165               
166                                var scale = axis.getWindowScale();
167               
168                                chart.setAxisWindow(this.axis, scale, this._startOffset - delta / s / scale);
169                                chart.render();
170                        }
171                },
172       
173                onMouseUp: function(event){
174                        //      summary:
175                        //              Called when mouse is up on the chart.
176                        this._isPanning = false;
177                        this._disconnectHandles();
178                },
179               
180                onMouseWheel: function(event){
181                        //      summary:
182                        //              Called when mouse wheel is used on the chart.
183                        var scroll = event[(has("mozilla") ? "detail" : "wheelDelta")] / sUnit;
184                        // on Mozilla the sUnit might actually not always be 3
185                        // make sure we never have -1 < scroll < 1
186                        if(scroll > -1 && scroll < 0){
187                                scroll = -1;
188                        }else if(scroll > 0 && scroll < 1){
189                                scroll = 1;
190                        }
191                        this._onZoom(scroll, event);
192                },
193               
194                onKeyPress: function(event){
195                        //      summary:
196                        //              Called when a key is pressed on the chart.
197                        if(keyTests[this.keyZoomModifier](event)){
198                                if(event.keyChar == "+" || event.keyCode == keys.NUMPAD_PLUS){
199                                        this._onZoom(1, event);
200                                }else if(event.keyChar == "-" || event.keyCode == keys.NUMPAD_MINUS){
201                                        this._onZoom(-1, event);                                       
202                                }
203                        }
204                },
205               
206                onDoubleClick: function(event){
207                        //      summary:
208                        //              Called when the mouse is double is double clicked on the chart. Toggle between zoom and fit chart.
209                        var chart = this.chart, axis = chart.getAxis(this.axis);
210                        var scale = 1 / this.scaleFactor;
211                        // are we fit?
212                        if(axis.getWindowScale()==1){
213                                // fit => zoom
214                                var scaler = axis.getScaler(), start = scaler.bounds.from, end = scaler.bounds.to,
215                                oldMiddle = (start + end) / 2, newMiddle = this.plot.toData({x: event.pageX, y: event.pageY})[this.axis],
216                                newStart = scale * (start - oldMiddle) + newMiddle, newEnd = scale * (end - oldMiddle) + newMiddle;
217                                chart.zoomIn(this.axis, [newStart, newEnd]);
218                        }else{
219                                // non fit => fit
220                                chart.setAxisWindow(this.axis, 1, 0);
221                                chart.render();
222                        }
223                        eventUtil.stop(event);
224                },
225               
226                _onZoom: function(scroll, event){
227                        var scale = (scroll < 0 ? Math.abs(scroll)*this.scaleFactor :
228                                1 / (Math.abs(scroll)*this.scaleFactor));
229                        var chart = this.chart, axis = chart.getAxis(this.axis);
230                        // after wheel reset event position exactly if we could start a new scroll action
231                        var cscale = axis.getWindowScale();
232                        if(cscale / scale > this.maxScale){
233                                return;
234                        }
235                        var scaler = axis.getScaler(), start = scaler.bounds.from, end = scaler.bounds.to;
236                        // keep mouse pointer as transformation center if available otherwise center
237                        var middle = (event.type == "keypress") ? (start + end) / 2 :
238                                this.plot.toData({x: event.pageX, y: event.pageY})[this.axis];
239                        var newStart = scale * (start - middle) + middle, newEnd = scale * (end - middle) + middle;
240                        chart.zoomIn(this.axis, [newStart, newEnd]);
241                        // do not scroll browser
242                        eventUtil.stop(event);
243                }
244        });             
245});
Note: See TracBrowser for help on using the repository browser.