source: Dev/branches/rest-dojo-ui/client/dojox/charting/scaler/linear.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.6 KB
Line 
1define(["dojo/_base/lang", "./common"],
2        function(lang, common){
3        var linear = lang.getObject("dojox.charting.scaler.linear", true);
4       
5        var deltaLimit = 3,     // pixels
6                findString = common.findString,
7                getLabel = common.getNumericLabel;
8       
9        var calcTicks = function(min, max, kwArgs, majorTick, minorTick, microTick, span){
10                kwArgs = lang.delegate(kwArgs);
11                if(!majorTick){
12                        if(kwArgs.fixUpper == "major"){ kwArgs.fixUpper = "minor"; }
13                        if(kwArgs.fixLower == "major"){ kwArgs.fixLower = "minor"; }
14                }
15                if(!minorTick){
16                        if(kwArgs.fixUpper == "minor"){ kwArgs.fixUpper = "micro"; }
17                        if(kwArgs.fixLower == "minor"){ kwArgs.fixLower = "micro"; }
18                }
19                if(!microTick){
20                        if(kwArgs.fixUpper == "micro"){ kwArgs.fixUpper = "none"; }
21                        if(kwArgs.fixLower == "micro"){ kwArgs.fixLower = "none"; }
22                }
23                var lowerBound = findString(kwArgs.fixLower, ["major"]) ?
24                                Math.floor(kwArgs.min / majorTick) * majorTick :
25                                        findString(kwArgs.fixLower, ["minor"]) ?
26                                                Math.floor(kwArgs.min / minorTick) * minorTick :
27                                                        findString(kwArgs.fixLower, ["micro"]) ?
28                                                                Math.floor(kwArgs.min / microTick) * microTick : kwArgs.min,
29                        upperBound = findString(kwArgs.fixUpper, ["major"]) ?
30                                Math.ceil(kwArgs.max / majorTick) * majorTick :
31                                        findString(kwArgs.fixUpper, ["minor"]) ?
32                                                Math.ceil(kwArgs.max / minorTick) * minorTick :
33                                                        findString(kwArgs.fixUpper, ["micro"]) ?
34                                                                Math.ceil(kwArgs.max / microTick) * microTick : kwArgs.max;
35                                                               
36                if(kwArgs.useMin){ min = lowerBound; }
37                if(kwArgs.useMax){ max = upperBound; }
38               
39                var majorStart = (!majorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major"])) ?
40                                min : Math.ceil(min / majorTick) * majorTick,
41                        minorStart = (!minorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor"])) ?
42                                min : Math.ceil(min / minorTick) * minorTick,
43                        microStart = (! microTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor", "micro"])) ?
44                                min : Math.ceil(min / microTick) * microTick,
45                        majorCount = !majorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major"]) ?
46                                Math.round((max - majorStart) / majorTick) :
47                                Math.floor((max - majorStart) / majorTick)) + 1,
48                        minorCount = !minorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor"]) ?
49                                Math.round((max - minorStart) / minorTick) :
50                                Math.floor((max - minorStart) / minorTick)) + 1,
51                        microCount = !microTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor", "micro"]) ?
52                                Math.round((max - microStart) / microTick) :
53                                Math.floor((max - microStart) / microTick)) + 1,
54                        minorPerMajor  = minorTick ? Math.round(majorTick / minorTick) : 0,
55                        microPerMinor  = microTick ? Math.round(minorTick / microTick) : 0,
56                        majorPrecision = majorTick ? Math.floor(Math.log(majorTick) / Math.LN10) : 0,
57                        minorPrecision = minorTick ? Math.floor(Math.log(minorTick) / Math.LN10) : 0,
58                        scale = span / (max - min);
59                if(!isFinite(scale)){ scale = 1; }
60               
61                return {
62                        bounds: {
63                                lower:  lowerBound,
64                                upper:  upperBound,
65                                from:   min,
66                                to:             max,
67                                scale:  scale,
68                                span:   span
69                        },
70                        major: {
71                                tick:   majorTick,
72                                start:  majorStart,
73                                count:  majorCount,
74                                prec:   majorPrecision
75                        },
76                        minor: {
77                                tick:   minorTick,
78                                start:  minorStart,
79                                count:  minorCount,
80                                prec:   minorPrecision
81                        },
82                        micro: {
83                                tick:   microTick,
84                                start:  microStart,
85                                count:  microCount,
86                                prec:   0
87                        },
88                        minorPerMajor:  minorPerMajor,
89                        microPerMinor:  microPerMinor,
90                        scaler:                 linear
91                };
92        };
93       
94        return lang.mixin(linear, {
95                buildScaler: function(/*Number*/ min, /*Number*/ max, /*Number*/ span, /*Object*/ kwArgs){
96                        var h = {fixUpper: "none", fixLower: "none", natural: false};
97                        if(kwArgs){
98                                if("fixUpper" in kwArgs){ h.fixUpper = String(kwArgs.fixUpper); }
99                                if("fixLower" in kwArgs){ h.fixLower = String(kwArgs.fixLower); }
100                                if("natural"  in kwArgs){ h.natural  = Boolean(kwArgs.natural); }
101                        }
102                       
103                        // update bounds
104                        if("min" in kwArgs){ min = kwArgs.min; }
105                        if("max" in kwArgs){ max = kwArgs.max; }
106                        if(kwArgs.includeZero){
107                                if(min > 0){ min = 0; }
108                                if(max < 0){ max = 0; }
109                        }
110                        h.min = min;
111                        h.useMin = true;
112                        h.max = max;
113                        h.useMax = true;
114                       
115                        if("from" in kwArgs){
116                                min = kwArgs.from;
117                                h.useMin = false;
118                        }
119                        if("to" in kwArgs){
120                                max = kwArgs.to;
121                                h.useMax = false;
122                        }
123                       
124                        // check for erroneous condition
125                        if(max <= min){
126                                return calcTicks(min, max, h, 0, 0, 0, span);   // Object
127                        }
128                       
129                        var mag = Math.floor(Math.log(max - min) / Math.LN10),
130                                major = kwArgs && ("majorTickStep" in kwArgs) ? kwArgs.majorTickStep : Math.pow(10, mag),
131                                minor = 0, micro = 0, ticks;
132                               
133                        // calculate minor ticks
134                        if(kwArgs && ("minorTickStep" in kwArgs)){
135                                minor = kwArgs.minorTickStep;
136                        }else{
137                                do{
138                                        minor = major / 10;
139                                        if(!h.natural || minor > 0.9){
140                                                ticks = calcTicks(min, max, h, major, minor, 0, span);
141                                                if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
142                                        }
143                                        minor = major / 5;
144                                        if(!h.natural || minor > 0.9){
145                                                ticks = calcTicks(min, max, h, major, minor, 0, span);
146                                                if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
147                                        }
148                                        minor = major / 2;
149                                        if(!h.natural || minor > 0.9){
150                                                ticks = calcTicks(min, max, h, major, minor, 0, span);
151                                                if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
152                                        }
153                                        return calcTicks(min, max, h, major, 0, 0, span);       // Object
154                                }while(false);
155                        }
156       
157                        // calculate micro ticks
158                        if(kwArgs && ("microTickStep" in kwArgs)){
159                                micro = kwArgs.microTickStep;
160                                ticks = calcTicks(min, max, h, major, minor, micro, span);
161                        }else{
162                                do{
163                                        micro = minor / 10;
164                                        if(!h.natural || micro > 0.9){
165                                                ticks = calcTicks(min, max, h, major, minor, micro, span);
166                                                if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
167                                        }
168                                        micro = minor / 5;
169                                        if(!h.natural || micro > 0.9){
170                                                ticks = calcTicks(min, max, h, major, minor, micro, span);
171                                                if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
172                                        }
173                                        micro = minor / 2;
174                                        if(!h.natural || micro > 0.9){
175                                                ticks = calcTicks(min, max, h, major, minor, micro, span);
176                                                if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
177                                        }
178                                        micro = 0;
179                                }while(false);
180                        }
181       
182                        return micro ? ticks : calcTicks(min, max, h, major, minor, 0, span);   // Object
183                },
184                buildTicks: function(/*Object*/ scaler, /*Object*/ kwArgs){
185                        var step, next, tick,
186                                nextMajor = scaler.major.start,
187                                nextMinor = scaler.minor.start,
188                                nextMicro = scaler.micro.start;
189                        if(kwArgs.microTicks && scaler.micro.tick){
190                                step = scaler.micro.tick, next = nextMicro;
191                        }else if(kwArgs.minorTicks && scaler.minor.tick){
192                                step = scaler.minor.tick, next = nextMinor;
193                        }else if(scaler.major.tick){
194                                step = scaler.major.tick, next = nextMajor;
195                        }else{
196                                // no ticks
197                                return null;
198                        }
199                        // make sure that we have finite bounds
200                        var revScale = 1 / scaler.bounds.scale;
201                        if(scaler.bounds.to <= scaler.bounds.from || isNaN(revScale) || !isFinite(revScale) ||
202                                        step <= 0 || isNaN(step) || !isFinite(step)){
203                                // no ticks
204                                return null;
205                        }
206                        // loop over all ticks
207                        var majorTicks = [], minorTicks = [], microTicks = [];
208                        while(next <= scaler.bounds.to + revScale){
209                                if(Math.abs(nextMajor - next) < step / 2){
210                                        // major tick
211                                        tick = {value: nextMajor};
212                                        if(kwArgs.majorLabels){
213                                                tick.label = getLabel(nextMajor, scaler.major.prec, kwArgs);
214                                        }
215                                        majorTicks.push(tick);
216                                        nextMajor += scaler.major.tick;
217                                        nextMinor += scaler.minor.tick;
218                                        nextMicro += scaler.micro.tick;
219                                }else if(Math.abs(nextMinor - next) < step / 2){
220                                        // minor tick
221                                        if(kwArgs.minorTicks){
222                                                tick = {value: nextMinor};
223                                                if(kwArgs.minorLabels && (scaler.minMinorStep <= scaler.minor.tick * scaler.bounds.scale)){
224                                                        tick.label = getLabel(nextMinor, scaler.minor.prec, kwArgs);
225                                                }
226                                                minorTicks.push(tick);
227                                        }
228                                        nextMinor += scaler.minor.tick;
229                                        nextMicro += scaler.micro.tick;
230                                }else{
231                                        // micro tick
232                                        if(kwArgs.microTicks){
233                                                microTicks.push({value: nextMicro});
234                                        }
235                                        nextMicro += scaler.micro.tick;
236                                }
237                                next += step;
238                        }
239                        return {major: majorTicks, minor: minorTicks, micro: microTicks};       // Object
240                },
241                getTransformerFromModel: function(/*Object*/ scaler){
242                        var offset = scaler.bounds.from, scale = scaler.bounds.scale;
243                        return function(x){ return (x - offset) * scale; };     // Function
244                },
245                getTransformerFromPlot: function(/*Object*/ scaler){
246                        var offset = scaler.bounds.from, scale = scaler.bounds.scale;
247                        return function(x){ return x / scale + offset; };       // Function
248                }
249        });
250});
Note: See TracBrowser for help on using the repository browser.