1 | define(["dojo/_base/lang", "dojo/_base/array", "dojo/_base/declare", "./CartesianBase", "./_PlotEvents", "./common", |
---|
2 | "../axis2d/common", "dojox/gfx", "dojox/lang/utils", "dojox/gfx/fx", "dojo/has"], |
---|
3 | function(lang, array, declare, CartesianBase, _PlotEvents, dcpc, dcac, gfx, du, fx, has){ |
---|
4 | |
---|
5 | // all the code below should be removed when http://trac.dojotoolkit.org/ticket/11299 will be available |
---|
6 | var getBoundingBox = function(shape){ |
---|
7 | return getTextBBox(shape, shape.getShape().text); |
---|
8 | }; |
---|
9 | var getTextBBox = function(s, t){ |
---|
10 | var c = s.declaredClass; |
---|
11 | var w, h; |
---|
12 | if(c.indexOf("svg")!=-1){ |
---|
13 | // try/catch the FF native getBBox error. cheaper than walking up in the DOM |
---|
14 | // hierarchy to check the conditions (bench show /10 ) |
---|
15 | try { |
---|
16 | return lang.mixin({}, s.rawNode.getBBox()); |
---|
17 | }catch (e){ |
---|
18 | return null; |
---|
19 | } |
---|
20 | }else if(c.indexOf("vml")!=-1){ |
---|
21 | var rawNode = s.rawNode, _display = rawNode.style.display; |
---|
22 | rawNode.style.display = "inline"; |
---|
23 | w = gfx.pt2px(parseFloat(rawNode.currentStyle.width)); |
---|
24 | h = gfx.pt2px(parseFloat(rawNode.currentStyle.height)); |
---|
25 | var sz = {x: 0, y: 0, width: w, height: h}; |
---|
26 | // in VML, the width/height we get are in view coordinates |
---|
27 | // in our case we don't zoom the view so that is ok |
---|
28 | // It's impossible to get the x/y from the currentStyle.left/top, |
---|
29 | // because all negative coordinates are 'clipped' to 0. |
---|
30 | // (x:0 + translate(-100) -> x=0 |
---|
31 | computeLocation(s, sz); |
---|
32 | rawNode.style.display = _display; |
---|
33 | return sz; |
---|
34 | }else if(c.indexOf("silverlight")!=-1){ |
---|
35 | var bb = {width: s.rawNode.actualWidth, height: s.rawNode.actualHeight}; |
---|
36 | return computeLocation(s, bb, 0.75); |
---|
37 | }else if(s.getTextWidth){ |
---|
38 | // canvas |
---|
39 | w = s.getTextWidth(); |
---|
40 | var font = s.getFont(); |
---|
41 | var fz = font ? font.size : gfx.defaultFont.size; |
---|
42 | h = gfx.normalizedLength(fz); |
---|
43 | sz = {width: w, height: h}; |
---|
44 | computeLocation(s, sz, 0.75); |
---|
45 | return sz; |
---|
46 | } |
---|
47 | return null; |
---|
48 | }; |
---|
49 | var computeLocation = function(s, sz, coef){ |
---|
50 | var width = sz.width, height = sz.height, sh = s.getShape(), align = sh.align; |
---|
51 | switch (align) { |
---|
52 | case "end": |
---|
53 | sz.x = sh.x - width; |
---|
54 | break; |
---|
55 | case "middle": |
---|
56 | sz.x = sh.x - width / 2; |
---|
57 | break; |
---|
58 | case "start": |
---|
59 | default: |
---|
60 | sz.x = sh.x; |
---|
61 | break; |
---|
62 | } |
---|
63 | coef = coef || 1; |
---|
64 | sz.y = sh.y - height*coef; // rough approximation of the ascent!... |
---|
65 | return sz; |
---|
66 | }; |
---|
67 | |
---|
68 | /*===== |
---|
69 | declare("dojox.charting.plot2d.__IndicatorCtorArgs", dojox.charting.plot2d.__CartesianCtorArgs, { |
---|
70 | // summary: |
---|
71 | // A special keyword arguments object that is specific to a indicator "plot". |
---|
72 | |
---|
73 | // lines: Boolean? |
---|
74 | // Whether the indicator lines are visible or not. The lines are displayed for each of the |
---|
75 | // 'values' of the indicator. Default is true. |
---|
76 | lines: true, |
---|
77 | |
---|
78 | // labels: String? |
---|
79 | // Describes how the indicator labels are displayed. |
---|
80 | // Possible values are: |
---|
81 | // `"line"` for displaying the value of each indicator line, |
---|
82 | // `"marker"` for displaying the values of the markers of each indicator line, |
---|
83 | // `"trend"` for displaying the percentage variation from the first to the last indicator line, |
---|
84 | // `"none"` to prevent any label to display. |
---|
85 | // Default is "line". |
---|
86 | labels: "line", |
---|
87 | |
---|
88 | // markers: Boolean? |
---|
89 | // Whether the markers on the indicator lines are visible or not. The markers are displayed for each |
---|
90 | // of the indicator lines using the series attached to the indicator plot. Default is true. |
---|
91 | markers: true, |
---|
92 | |
---|
93 | // values: Boolean |
---|
94 | // The data values at which each of the indicator line is drawn. For a single value a Number can be provided |
---|
95 | // otherwise an Array of Number is required. fault is []. |
---|
96 | values: [], |
---|
97 | |
---|
98 | // offset: {x, y}? |
---|
99 | // A pair of (x, y) pixel coordinate to specifiy the offset between the end of the indicator line and the |
---|
100 | // position at which the labels are rendered. Default is no offset. |
---|
101 | offset: {}, |
---|
102 | |
---|
103 | // start: Boolean? |
---|
104 | // Whether the label is rendered at the start or end of the indicator line. Default is false meaning end of |
---|
105 | // the line. |
---|
106 | start: false, |
---|
107 | |
---|
108 | // animate: Boolean?|Number? |
---|
109 | // Whether or not to animate the chart to place. When a Number it specifies the duration of the animation. |
---|
110 | // Default is false. |
---|
111 | animate: false, |
---|
112 | |
---|
113 | // vertical: Boolean? |
---|
114 | // Whether the indicator is vertical or not. Default is true. |
---|
115 | vertical: true, |
---|
116 | |
---|
117 | // fixed: Boolean? |
---|
118 | // Whether a fixed precision must be applied to data values for display. Default is true. |
---|
119 | fixed: true, |
---|
120 | |
---|
121 | // precision: Number? |
---|
122 | // The precision at which to round data values for display. Default is 0. |
---|
123 | precision: 0, |
---|
124 | |
---|
125 | // lineStroke: dojo/gfx/Stroke? |
---|
126 | // An optional stroke to use for indicator line. |
---|
127 | lineStroke: {}, |
---|
128 | |
---|
129 | // lineOutline: dojo/gfx/Stroke? |
---|
130 | // An optional outline to use for indicator line. |
---|
131 | lineOutline: {}, |
---|
132 | |
---|
133 | // lineShadow: dojo/gfx/Stroke? |
---|
134 | // An optional shadow to use for indicator line. |
---|
135 | lineShadow: {}, |
---|
136 | |
---|
137 | // stroke: dojo.gfx.Stroke? |
---|
138 | // An optional stroke to use for indicator label background. |
---|
139 | stroke: {}, |
---|
140 | |
---|
141 | // outline: dojo.gfx.Stroke? |
---|
142 | // An optional outline to use for indicator label background. |
---|
143 | outline: {}, |
---|
144 | |
---|
145 | // shadow: dojo.gfx.Stroke? |
---|
146 | // An optional shadow to use for indicator label background. |
---|
147 | shadow: {}, |
---|
148 | |
---|
149 | // fill: dojo.gfx.Fill? |
---|
150 | // An optional fill to use for indicator label background. |
---|
151 | fill: {}, |
---|
152 | |
---|
153 | // fillFunc: Function? |
---|
154 | // An optional function to use to compute label background fill. It takes precedence over |
---|
155 | // fill property when available. |
---|
156 | // | function fillFunc(index, values, data) {} |
---|
157 | // `index` is the index in the values array of the label being drawn. |
---|
158 | // `values` is the entire array of values. |
---|
159 | // `data` is the entire array of marker values. |
---|
160 | fillFunc: null, |
---|
161 | |
---|
162 | // labelFunc: Function? |
---|
163 | // An optional function to use to compute label text. It takes precedence over |
---|
164 | // the default text when available. |
---|
165 | // | function labelFunc(index, values, data, fixed, precision, labels) {} |
---|
166 | // `index` is the index in the values array of the label being drawn. |
---|
167 | // `values` is the entire array of values. |
---|
168 | // `data` is the entire array of marker values. |
---|
169 | // `fixed` is true if fixed precision must be applied. |
---|
170 | // `precision` is the requested precision to be applied. |
---|
171 | // `labels` is the labels mode of the indicator. |
---|
172 | labelFunc: null, |
---|
173 | |
---|
174 | // font: String? |
---|
175 | // A font definition to use for indicator label background. |
---|
176 | font: "", |
---|
177 | |
---|
178 | // fontColor: String|dojo.Color? |
---|
179 | // The color to use for indicator label background. |
---|
180 | fontColor: "", |
---|
181 | |
---|
182 | // markerStroke: dojo.gfx.Stroke? |
---|
183 | // An optional stroke to use for indicator marker. |
---|
184 | markerStroke: {}, |
---|
185 | |
---|
186 | // markerOutline: dojo.gfx.Stroke? |
---|
187 | // An optional outline to use for indicator marker. |
---|
188 | markerOutline: {}, |
---|
189 | |
---|
190 | // markerShadow: dojo.gfx.Stroke? |
---|
191 | // An optional shadow to use for indicator marker. |
---|
192 | markerShadow: {}, |
---|
193 | |
---|
194 | // markerFill: dojo.gfx.Fill? |
---|
195 | // An optional fill to use for indicator marker. |
---|
196 | markerFill: {}, |
---|
197 | |
---|
198 | // markerSymbol: String? |
---|
199 | // An optional symbol string to use for indicator marker. |
---|
200 | markerSymbol: "", |
---|
201 | }); |
---|
202 | =====*/ |
---|
203 | |
---|
204 | var Indicator = declare("dojox.charting.plot2d.Indicator", [CartesianBase, _PlotEvents], { |
---|
205 | // summary: |
---|
206 | // A "faux" plot that can be placed behind or above other plots to represent a line or multi-line |
---|
207 | // threshold on the chart. |
---|
208 | defaultParams: { |
---|
209 | vertical: true, |
---|
210 | fixed: true, |
---|
211 | precision: 0, |
---|
212 | lines: true, |
---|
213 | labels: "line", // "line" | "trend" | "markers" | "none" |
---|
214 | markers: true |
---|
215 | }, |
---|
216 | optionalParams: { |
---|
217 | lineStroke: {}, |
---|
218 | outlineStroke: {}, |
---|
219 | shadowStroke: {}, |
---|
220 | lineFill: {}, |
---|
221 | stroke: {}, |
---|
222 | outline: {}, |
---|
223 | shadow: {}, |
---|
224 | fill: {}, |
---|
225 | fillFunc: null, |
---|
226 | labelFunc: null, |
---|
227 | font: "", |
---|
228 | fontColor: "", |
---|
229 | markerStroke: {}, |
---|
230 | markerOutline: {}, |
---|
231 | markerShadow: {}, |
---|
232 | markerFill: {}, |
---|
233 | markerSymbol: "", |
---|
234 | values: [], |
---|
235 | offset: {}, |
---|
236 | start: false, |
---|
237 | animate: false |
---|
238 | }, |
---|
239 | |
---|
240 | constructor: function(chart, kwArgs){ |
---|
241 | // summary: |
---|
242 | // Create the faux Grid plot. |
---|
243 | // chart: dojox/charting/Chart |
---|
244 | // The chart this plot belongs to. |
---|
245 | // kwArgs: dojox.charting.plot2d.__GridCtorArgs? |
---|
246 | // An optional keyword arguments object to help define the parameters of the underlying grid. |
---|
247 | this.opt = lang.clone(this.defaultParams); |
---|
248 | du.updateWithObject(this.opt, kwArgs); |
---|
249 | if(typeof kwArgs.values == "number"){ |
---|
250 | kwArgs.values = [ kwArgs.values ]; |
---|
251 | } |
---|
252 | du.updateWithPattern(this.opt, kwArgs, this.optionalParams); |
---|
253 | this.animate = this.opt.animate; |
---|
254 | }, |
---|
255 | render: function(dim, offsets){ |
---|
256 | if(this.zoom){ |
---|
257 | return this.performZoom(dim, offsets); |
---|
258 | } |
---|
259 | |
---|
260 | if(!this.isDirty()){ |
---|
261 | return this; |
---|
262 | } |
---|
263 | |
---|
264 | this.cleanGroup(null, true); |
---|
265 | |
---|
266 | if(!this.opt.values){ |
---|
267 | return this; |
---|
268 | } |
---|
269 | |
---|
270 | this._updateIndicator(); |
---|
271 | return this; |
---|
272 | }, |
---|
273 | _updateIndicator: function(){ |
---|
274 | var t = this.chart.theme; |
---|
275 | var hn = this._hAxis.name, vn = this._vAxis.name, |
---|
276 | hb = this._hAxis.getScaler().bounds, vb = this._vAxis.getScaler().bounds; |
---|
277 | var o = {}; |
---|
278 | o[hn] = hb.from; |
---|
279 | o[vn] = vb.from; |
---|
280 | var min = this.toPage(o); |
---|
281 | o[hn] = hb.to; |
---|
282 | o[vn] = vb.to; |
---|
283 | var max = this.toPage(o); |
---|
284 | var events = this.events(); |
---|
285 | var results = array.map(this.opt.values, function(value, index){ |
---|
286 | return this._renderIndicator(value, index, hn, vn, min, max, events, this.animate); |
---|
287 | }, this); |
---|
288 | var length = results.length; |
---|
289 | if(this.opt.labels == "trend"){ |
---|
290 | var v = this.opt.vertical; |
---|
291 | var first = this._data[0][0]; |
---|
292 | var last = this._data[length - 1][0]; |
---|
293 | var delta = last-first; |
---|
294 | var text = this.opt.labelFunc?this.opt.labelFunc(-1, this.values, this._data, this.opt.fixed, this.opt.precision): |
---|
295 | (dcpc.getLabel(delta, this.opt.fixed, this.opt.precision)+" ("+dcpc.getLabel(100*delta/first, true, 2)+"%)"); |
---|
296 | this._renderText(this.getGroup(), text, this.chart.theme, v?(results[0].x+results[length - 1].x)/2:results[1].x, |
---|
297 | v?results[0].y:(results[1].y+results[length - 1].y)/2, -1, this.opt.values, this._data); |
---|
298 | } |
---|
299 | var lineFill = this.opt.lineFill!=undefined?this.opt.lineFill:t.indicator.lineFill; |
---|
300 | if(lineFill && length > 1){ |
---|
301 | var x0 = Math.min(results[0].x1, results[length - 1].x1); |
---|
302 | var y0 = Math.min(results[0].y1, results[length - 1].y1); |
---|
303 | var r = this.getGroup().createRect({x: x0, y: y0, width: Math.max(results[0].x2, results[length - 1].x2) - x0, |
---|
304 | height: Math.max(results[0].y2, results[length - 1].y2) - y0}). |
---|
305 | setFill(lineFill); |
---|
306 | r.moveToBack(); |
---|
307 | } |
---|
308 | }, |
---|
309 | _renderIndicator: function(coord, index, hn, vn, min, max, events, animate){ |
---|
310 | var t = this.chart.theme, c = this.chart.getCoords(), v = this.opt.vertical; |
---|
311 | |
---|
312 | var g = this.getGroup().createGroup(); |
---|
313 | var mark = {}; |
---|
314 | mark[hn] = v?coord:0; |
---|
315 | mark[vn] = v?0:coord; |
---|
316 | if(has("dojo-bidi")){ |
---|
317 | mark.x = this._getMarkX(mark.x); |
---|
318 | } |
---|
319 | mark = this.toPage(mark); |
---|
320 | var visible = v?mark.x >= min.x && mark.x <= max.x:mark.y >= max.y && mark.y <= min.y; |
---|
321 | |
---|
322 | var cx = mark.x - c.x, cy = mark.y - c.y; |
---|
323 | var x1 = v?cx:min.x - c.x, y1 = v?min.y - c.y:cy, x2 = v?x1:max.x - c.x, y2 = v?max.y - c.y:y1; |
---|
324 | |
---|
325 | if(this.opt.lines && visible){ |
---|
326 | var sh = this.opt.hasOwnProperty("lineShadow")?this.opt.lineShadow:t.indicator.lineShadow, |
---|
327 | ls = this.opt.hasOwnProperty("lineStroke")?this.opt.lineStroke:t.indicator.lineStroke, |
---|
328 | ol = this.opt.hasOwnProperty("lineOutline")?this.opt.lineOutline:t.indicator.lineOutline; |
---|
329 | if(sh){ |
---|
330 | g.createLine({x1: x1 + sh.dx, y1: y1 + sh.dy, x2: x2 + sh.dx, y2: y2 + sh.dy}).setStroke(sh); |
---|
331 | } |
---|
332 | if(ol){ |
---|
333 | ol = dcpc.makeStroke(ol); |
---|
334 | ol.width = 2 * ol.width + (ls?ls.width:0); |
---|
335 | g.createLine({x1: x1, y1: y1, x2: x2, y2: y2}).setStroke(ol); |
---|
336 | } |
---|
337 | g.createLine({x1: x1, y1: y1, x2: x2, y2: y2}).setStroke(ls); |
---|
338 | } |
---|
339 | |
---|
340 | // series items represent markers on the indicator |
---|
341 | var data; |
---|
342 | if(this.opt.markers && visible){ |
---|
343 | var d = this._data[index]; |
---|
344 | var self = this; |
---|
345 | if(d){ |
---|
346 | data = array.map(d, function(value, index){ |
---|
347 | mark[hn] = v?coord:value; |
---|
348 | mark[vn] = v?value:coord; |
---|
349 | if(has("dojo-bidi")){ |
---|
350 | mark.x = self._getMarkX(mark.x); |
---|
351 | } |
---|
352 | mark = this.toPage(mark); |
---|
353 | if(v?mark.y <= min.y && mark.y >= max.y:mark.x >= min.x && mark.x <= max.x){ |
---|
354 | cx = mark.x - c.x |
---|
355 | cy = mark.y - c.y; |
---|
356 | var ms = this.opt.markerSymbol?this.opt.markerSymbol:t.indicator.markerSymbol, |
---|
357 | path = "M" + cx + " " + cy + " " + ms; |
---|
358 | sh = this.opt.markerShadow!=undefined?this.opt.markerShadow:t.indicator.markerShadow; |
---|
359 | ls = this.opt.markerStroke!=undefined?this.opt.markerStroke:t.indicator.markerStroke; |
---|
360 | ol = this.opt.markerOutline!=undefined?this.opt.markerOutline:t.indicator.markerOutline; |
---|
361 | if(sh){ |
---|
362 | var sp = "M" + (cx + sh.dx) + " " + (cy + sh.dy) + " " + ms; |
---|
363 | g.createPath(sp).setFill(sh.color).setStroke(sh); |
---|
364 | } |
---|
365 | if(ol){ |
---|
366 | ol = dcpc.makeStroke(ol); |
---|
367 | ol.width = 2 * ol.width + (ls?ls.width:0); |
---|
368 | g.createPath(path).setStroke(ol); |
---|
369 | } |
---|
370 | |
---|
371 | var shape = g.createPath(path); |
---|
372 | var sf = this._shapeFill(this.opt.markerFill != undefined?this.opt.markerFill:t.indicator.markerFill, shape.getBoundingBox()); |
---|
373 | shape.setFill(sf).setStroke(ls); |
---|
374 | } |
---|
375 | return value; |
---|
376 | }, this); |
---|
377 | } |
---|
378 | } |
---|
379 | var ctext; |
---|
380 | if(this.opt.start){ |
---|
381 | ctext = { |
---|
382 | x: v?x1:x1, |
---|
383 | y: v?y1:y2 |
---|
384 | }; |
---|
385 | }else{ |
---|
386 | ctext = { |
---|
387 | x: v?x1:x2, |
---|
388 | y: v?y2:y1 |
---|
389 | }; |
---|
390 | } |
---|
391 | |
---|
392 | if(this.opt.labels && this.opt.labels != "trend" && visible){ |
---|
393 | var text; |
---|
394 | if(this.opt.labelFunc){ |
---|
395 | text = this.opt.labelFunc(index, this.opt.values, this._data, |
---|
396 | this.opt.fixed, this.opt.precision, this.opt.labels); |
---|
397 | }else{ |
---|
398 | if(this.opt.labels == "markers"){ |
---|
399 | text = array.map(data, function(value){ |
---|
400 | return dcpc.getLabel(value, this.opt.fixed, this.opt.precision); |
---|
401 | }, this); |
---|
402 | text = text.length != 1 ? "[ "+text.join(", ")+" ]" : text[0]; |
---|
403 | }else{ |
---|
404 | text = dcpc.getLabel(coord, this.opt.fixed, this.opt.precision); |
---|
405 | } |
---|
406 | } |
---|
407 | this._renderText(g, text, t, ctext.x, ctext.y, index, this.opt.values, this._data); |
---|
408 | } |
---|
409 | |
---|
410 | if(events){ |
---|
411 | this._connectEvents({ |
---|
412 | element: "indicator", |
---|
413 | run: this.run?this.run[index]:undefined, |
---|
414 | shape: g, |
---|
415 | value: coord |
---|
416 | }); |
---|
417 | } |
---|
418 | |
---|
419 | if(animate){ |
---|
420 | this._animateIndicator(g, v, v?y1:x1, v?(y1 + y2):(x1 + x2), animate); |
---|
421 | } |
---|
422 | |
---|
423 | return lang.mixin(ctext, {x1: x1, y1: y1, x2: x2, y2: y2}); |
---|
424 | }, |
---|
425 | _animateIndicator: function(shape, vertical, offset, size, animate){ |
---|
426 | var transStart = vertical ? [0, offset] : [offset, 0]; |
---|
427 | var scaleStart = vertical ? [1, 1 / size] : [1 / size, 1]; |
---|
428 | fx.animateTransform(lang.delegate({ |
---|
429 | shape: shape, |
---|
430 | duration: 1200, |
---|
431 | transform: [ |
---|
432 | {name: "translate", start: transStart, end: [0, 0]}, |
---|
433 | {name: "scale", start: scaleStart, end: [1, 1]}, |
---|
434 | {name: "original"} |
---|
435 | ] |
---|
436 | }, animate)).play(); |
---|
437 | }, |
---|
438 | clear: function(){ |
---|
439 | this.inherited(arguments); |
---|
440 | this._data = []; |
---|
441 | }, |
---|
442 | addSeries: function(run){ |
---|
443 | this.inherited(arguments); |
---|
444 | this._data.push(run.data); |
---|
445 | }, |
---|
446 | _renderText: function(g, text, t, x, y, index, values, data){ |
---|
447 | if(this.opt.offset){ |
---|
448 | x += this.opt.offset.x; |
---|
449 | y += this.opt.offset.y; |
---|
450 | } |
---|
451 | var label = dcac.createText.gfx( |
---|
452 | this.chart, |
---|
453 | g, |
---|
454 | x, y, |
---|
455 | "middle", |
---|
456 | text, this.opt.font?this.opt.font:t.indicator.font, this.opt.fontColor?this.opt.fontColor:t.indicator.fontColor); |
---|
457 | var b = getBoundingBox(label); |
---|
458 | b.x-=2; b.y-=1; b.width+=4; b.height+=2; b.r = this.opt.radius?this.opt.radius:t.indicator.radius; |
---|
459 | var sh = this.opt.shadow!=undefined?this.opt.shadow:t.indicator.shadow, |
---|
460 | ls = this.opt.stroke!=undefined?this.opt.stroke:t.indicator.stroke, |
---|
461 | ol = this.opt.outline!=undefined?this.opt.outline:t.indicator.outline; |
---|
462 | if(sh){ |
---|
463 | g.createRect(b).setFill(sh.color).setStroke(sh); |
---|
464 | } |
---|
465 | if(ol){ |
---|
466 | ol = dcpc.makeStroke(ol); |
---|
467 | ol.width = 2 * ol.width + (ls?ls.width:0); |
---|
468 | g.createRect(b).setStroke(ol); |
---|
469 | } |
---|
470 | var f = this.opt.fillFunc?this.opt.fillFunc(index, values, data):(this.opt.fill!=undefined?this.opt.fill:t.indicator.fill); |
---|
471 | g.createRect(b).setFill(this._shapeFill(f, b)).setStroke(ls); |
---|
472 | label.moveToFront(); |
---|
473 | }, |
---|
474 | getSeriesStats: function(){ |
---|
475 | // summary: |
---|
476 | // Returns default stats (irrelevant for this type of plot). |
---|
477 | // returns: Object |
---|
478 | // {hmin, hmax, vmin, vmax} min/max in both directions. |
---|
479 | return lang.delegate(dcpc.defaultStats); |
---|
480 | } |
---|
481 | }); |
---|
482 | if(has("dojo-bidi")){ |
---|
483 | Indicator.extend({ |
---|
484 | _getMarkX: function(x){ |
---|
485 | if(this.chart.isRightToLeft()){ |
---|
486 | return this.chart.axes.x.scaler.bounds.to + this.chart.axes.x.scaler.bounds.from - x; |
---|
487 | } |
---|
488 | return x; |
---|
489 | } |
---|
490 | }); |
---|
491 | } |
---|
492 | return Indicator; |
---|
493 | }); |
---|