source: Dev/trunk/src/client/dojox/charting/action2d/MouseZoomAndPan.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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