Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('series-plot-util', function (Y, NAME) {
2
 
3
/**
4
 * Provides functionality for drawing plots in a series.
5
 *
6
 * @module charts
7
 * @submodule series-plot-util
8
 */
9
var Y_Lang = Y.Lang,
10
    _getClassName = Y.ClassNameManager.getClassName,
11
    SERIES_MARKER = _getClassName("seriesmarker");
12
 
13
/**
14
 * Utility class used for drawing markers.
15
 *
16
 * @class Plots
17
 * @constructor
18
 * @submodule series-plot-util
19
 */
20
function Plots(cfg)
21
{
22
    var attrs = {
23
        markers: {
24
            getter: function()
25
            {
26
                return this._markers;
27
            }
28
        }
29
    };
30
    this.addAttrs(attrs, cfg);
31
}
32
 
33
Plots.prototype = {
34
    /**
35
     * Storage for default marker styles.
36
     *
37
     * @property _plotDefaults
38
     * @type Object
39
     * @private
40
     */
41
    _plotDefaults: null,
42
 
43
    /**
44
     * Draws the markers
45
     *
46
     * @method drawPlots
47
     * @protected
48
     */
49
    drawPlots: function()
50
    {
51
        if(!this.get("xcoords") || this.get("xcoords").length < 1)
52
		{
53
			return;
54
		}
55
        var isNumber = Y_Lang.isNumber,
56
            style = this._copyObject(this.get("styles").marker),
57
            w = style.width,
58
            h = style.height,
59
            xcoords = this.get("xcoords"),
60
            ycoords = this.get("ycoords"),
61
            i = 0,
62
            len = xcoords.length,
63
            top = ycoords[0],
64
            left,
65
            marker,
66
            offsetWidth = w/2,
67
            offsetHeight = h/2,
68
            xvalues,
69
            yvalues,
70
            fillColors = null,
71
            borderColors = null,
72
            graphOrder = this.get("graphOrder"),
73
            groupMarkers = this.get("groupMarkers");
74
        if(groupMarkers)
75
        {
76
            xvalues = [];
77
            yvalues = [];
78
            for(; i < len; ++i)
79
            {
80
                xvalues.push(parseFloat(xcoords[i] - offsetWidth));
81
                yvalues.push(parseFloat(ycoords[i] - offsetHeight));
82
            }
83
            this._createGroupMarker({
84
                xvalues: xvalues,
85
                yvalues: yvalues,
86
                fill: style.fill,
87
                border: style.border,
88
                dimensions: {
89
                    width: w,
90
                    height: h
91
                },
92
                graphOrder: graphOrder,
93
                shape: style.shape
94
            });
95
            return;
96
        }
97
        if(Y_Lang.isArray(style.fill.color))
98
        {
99
            fillColors = style.fill.color.concat();
100
        }
101
        if(Y_Lang.isArray(style.border.color))
102
        {
103
            borderColors = style.border.color.concat();
104
        }
105
        this._createMarkerCache();
106
        for(; i < len; ++i)
107
        {
108
            top = parseFloat(ycoords[i] - offsetHeight);
109
            left = parseFloat(xcoords[i] - offsetWidth);
110
            if(!isNumber(left) || !isNumber(top))
111
            {
112
                this._markers.push(null);
113
                continue;
114
            }
115
            if(fillColors)
116
            {
117
                style.fill.color = fillColors[i % fillColors.length];
118
            }
119
            if(borderColors)
120
            {
121
                style.border.color = borderColors[i % borderColors.length];
122
            }
123
 
124
            style.x = left;
125
            style.y = top;
126
            marker = this.getMarker(style, graphOrder, i);
127
        }
128
        this._clearMarkerCache();
129
    },
130
 
131
    /**
132
     * Pre-defined group shapes.
133
     *
134
     * @property _groupShapes
135
     * @private
136
     */
137
    _groupShapes: {
138
        circle: Y.CircleGroup,
139
        rect: Y.RectGroup,
140
        ellipse: Y.EllipseGroup,
141
        diamond: Y.DiamondGroup
142
    },
143
 
144
    /**
145
     * Returns the correct group shape class.
146
     *
147
     * @method _getGroupShape
148
     * @param {Shape | String} shape Indicates which shape class.
149
     * @return Function
150
     * @protected
151
     */
152
    _getGroupShape: function(shape)
153
    {
154
        if(Y_Lang.isString(shape))
155
        {
156
            shape = this._groupShapes[shape];
157
        }
158
        return shape;
159
    },
160
 
161
    /**
162
     * Gets the default values for series that use the utility. This method is used by
163
     * the class' `styles` attribute's getter to get build default values.
164
     *
165
     * @method _getPlotDefaults
166
     * @return Object
167
     * @protected
168
     */
169
    _getPlotDefaults: function()
170
    {
171
        var defs = {
172
            fill:{
173
                type: "solid",
174
                alpha: 1,
175
                colors:null,
176
                alphas: null,
177
                ratios: null
178
            },
179
            border:{
180
                weight: 1,
181
                alpha: 1
182
            },
183
            width: 10,
184
            height: 10,
185
            shape: "circle"
186
        };
187
        defs.fill.color = this._getDefaultColor(this.get("graphOrder"), "fill");
188
        defs.border.color = this._getDefaultColor(this.get("graphOrder"), "border");
189
        return defs;
190
    },
191
 
192
    /**
193
     * Collection of markers to be used in the series.
194
     *
195
     * @property _markers
196
     * @type Array
197
     * @private
198
     */
199
    _markers: null,
200
 
201
    /**
202
     * Collection of markers to be re-used on a series redraw.
203
     *
204
     * @property _markerCache
205
     * @type Array
206
     * @private
207
     */
208
    _markerCache: null,
209
 
210
    /**
211
     * Gets and styles a marker. If there is a marker in cache, it will use it. Otherwise
212
     * it will create one.
213
     *
214
     * @method getMarker
215
     * @param {Object} styles Hash of style properties.
216
     * @param {Number} order Order of the series.
217
     * @param {Number} index Index within the series associated with the marker.
218
     * @return Shape
219
     * @protected
220
     */
221
    getMarker: function(styles, order, index)
222
    {
223
        var marker,
224
            border = styles.border;
225
        styles.id = this._getChart().get("id") + "_" + order + "_" + index;
226
        //fix name differences between graphic layer
227
        border.opacity = border.alpha;
228
        styles.stroke = border;
229
        styles.fill.opacity = styles.fill.alpha;
230
        if(this._markerCache.length > 0)
231
        {
232
            while(!marker)
233
            {
234
                if(this._markerCache.length < 1)
235
                {
236
                    marker = this._createMarker(styles);
237
                    break;
238
                }
239
                marker = this._markerCache.shift();
240
 
241
            }
242
            marker.set(styles);
243
        }
244
        else
245
        {
246
            marker = this._createMarker(styles);
247
        }
248
        this._markers.push(marker);
249
        return marker;
250
    },
251
 
252
    /**
253
     * Creates a shape to be used as a marker.
254
     *
255
     * @method _createMarker
256
     * @param {Object} styles Hash of style properties.
257
     * @return Shape
258
     * @private
259
     */
260
    _createMarker: function(styles)
261
    {
262
        var graphic = this.get("graphic"),
263
            marker,
264
            cfg = this._copyObject(styles);
265
        cfg.type = cfg.shape;
266
        marker = graphic.addShape(cfg);
267
        marker.addClass(SERIES_MARKER);
268
        return marker;
269
    },
270
 
271
    /**
272
     * Creates a cache of markers for reuse.
273
     *
274
     * @method _createMarkerCache
275
     * @private
276
     */
277
    _createMarkerCache: function()
278
    {
279
        if(this._groupMarker)
280
        {
281
            this._groupMarker.destroy();
282
            this._groupMarker = null;
283
        }
284
        if(this._markers && this._markers.length > 0)
285
        {
286
            this._markerCache = this._markers.concat();
287
        }
288
        else
289
        {
290
            this._markerCache = [];
291
        }
292
        this._markers = [];
293
    },
294
 
295
    /**
296
     * Draws a series of markers in a single shape instance.
297
     *
298
     * @method _createGroupMarkers
299
     * @param {Object} styles Set of configuration properties used to create the markers.
300
     * @protected
301
     */
302
    _createGroupMarker: function(styles)
303
    {
304
        var marker,
305
            markers = this.get("markers"),
306
            border = styles.border,
307
            graphic,
308
            cfg,
309
            shape;
310
        if(markers && markers.length > 0)
311
        {
312
            while(markers.length > 0)
313
            {
314
                marker = markers.shift();
315
                marker.destroy();
316
            }
317
            this.set("markers", []);
318
        }
319
        //fix name differences between graphic layer
320
        border.opacity = border.alpha;
321
        cfg = {
322
            id: this._getChart().get("id") + "_" + styles.graphOrder,
323
            stroke: border,
324
            fill: styles.fill,
325
            dimensions: styles.dimensions,
326
            xvalues: styles.xvalues,
327
            yvalues: styles.yvalues
328
        };
329
        cfg.fill.opacity = styles.fill.alpha;
330
        shape = this._getGroupShape(styles.shape);
331
        if(shape)
332
        {
333
            cfg.type = shape;
334
        }
335
        if(styles.hasOwnProperty("radius") && !isNaN(styles.radius))
336
        {
337
            cfg.dimensions.radius = styles.radius;
338
        }
339
        if(this._groupMarker)
340
        {
341
            this._groupMarker.destroy();
342
        }
343
        graphic = this.get("graphic");
344
        this._groupMarker = graphic.addShape(cfg);
345
        graphic._redraw();
346
    },
347
 
348
    /**
349
     * Toggles visibility
350
     *
351
     * @method _toggleVisible
352
     * @param {Boolean} visible indicates visibilitye
353
     * @private
354
     */
355
    _toggleVisible: function(visible)
356
    {
357
        var marker,
358
            markers = this.get("markers"),
359
            i = 0,
360
            len;
361
        if(markers)
362
        {
363
            len = markers.length;
364
            for(; i < len; ++i)
365
            {
366
                marker = markers[i];
367
                if(marker)
368
                {
369
                    marker.set("visible", visible);
370
                }
371
            }
372
        }
373
    },
374
 
375
    /**
376
     * Removes unused markers from the marker cache
377
     *
378
     * @method _clearMarkerCache
379
     * @private
380
     */
381
    _clearMarkerCache: function()
382
    {
383
        var marker;
384
        while(this._markerCache.length > 0)
385
        {
386
            marker = this._markerCache.shift();
387
            if(marker)
388
            {
389
                marker.destroy();
390
            }
391
        }
392
    },
393
 
394
    /**
395
     * Resizes and positions markers based on a mouse interaction.
396
     *
397
     * @method updateMarkerState
398
     * @param {String} type state of the marker
399
     * @param {Number} i index of the marker
400
     * @protected
401
     */
402
    updateMarkerState: function(type, i)
403
    {
404
        if(this._markers && this._markers[i])
405
        {
406
            var w,
407
                h,
408
                styles = this._copyObject(this.get("styles").marker),
409
                state = this._getState(type),
410
                xcoords = this.get("xcoords"),
411
                ycoords = this.get("ycoords"),
412
                marker = this._markers[i],
413
                markerStyles = state === "off" || !styles[state] ? styles : styles[state];
414
                markerStyles.fill.color = this._getItemColor(markerStyles.fill.color, i);
415
                markerStyles.border.color = this._getItemColor(markerStyles.border.color, i);
416
                markerStyles.stroke = markerStyles.border;
417
                marker.set(markerStyles);
418
                w = markerStyles.width;
419
                h = markerStyles.height;
420
                marker.set("x", (xcoords[i] - w/2));
421
                marker.set("y",  (ycoords[i] - h/2));
422
                marker.set("visible", this.get("visible"));
423
        }
424
    },
425
 
426
    /**
427
     * Parses a color from an array.
428
     *
429
     * @method _getItemColor
430
     * @param {Array} val collection of colors
431
     * @param {Number} i index of the item
432
     * @return String
433
     * @protected
434
     */
435
    _getItemColor: function(val, i)
436
    {
437
        if(Y_Lang.isArray(val))
438
        {
439
            return val[i % val.length];
440
        }
441
        return val;
442
    },
443
 
444
    /**
445
     * Method used by `styles` setter. Overrides base implementation.
446
     *
447
     * @method _setStyles
448
     * @param {Object} newStyles Hash of properties to update.
449
     * @return Object
450
     * @protected
451
     */
452
    _setStyles: function(val)
453
    {
454
        val = this._parseMarkerStyles(val);
455
        return Y.Renderer.prototype._setStyles.apply(this, [val]);
456
    },
457
 
458
    /**
459
     * Combines new styles with existing styles.
460
     *
461
     * @method _parseMarkerStyles
462
     * @param {Object} Object containing style properties for the marker.
463
     * @return Object
464
     * @private
465
     */
466
    _parseMarkerStyles: function(val)
467
    {
468
        if(val.marker)
469
        {
470
            var defs = this._getPlotDefaults();
471
            val.marker = this._mergeStyles(val.marker, defs);
472
            if(val.marker.over)
473
            {
474
                val.marker.over = this._mergeStyles(val.marker.over, val.marker);
475
            }
476
            if(val.marker.down)
477
            {
478
                val.marker.down = this._mergeStyles(val.marker.down, val.marker);
479
            }
480
        }
481
        return val;
482
    },
483
 
484
    /**
485
     * Returns marker state based on event type
486
     *
487
     * @method _getState
488
     * @param {String} type event type
489
     * @return String
490
     * @protected
491
     */
492
    _getState: function(type)
493
    {
494
        var state;
495
        switch(type)
496
        {
497
            case "mouseout" :
498
                state = "off";
499
            break;
500
            case "mouseover" :
501
                state = "over";
502
            break;
503
            case "mouseup" :
504
                state = "over";
505
            break;
506
            case "mousedown" :
507
                state = "down";
508
            break;
509
        }
510
        return state;
511
    },
512
 
513
    /**
514
     * @property _statSyles
515
     * @type Object
516
     * @private
517
     */
518
    _stateSyles: null,
519
 
520
    /**
521
     * @protected
522
     *
523
     * Draws the series.
524
     *
525
     * @method drawSeries
526
     */
527
    drawSeries: function()
528
    {
529
        this.drawPlots();
530
    },
531
 
532
    /**
533
     * @protected
534
     *
535
     * Gets the default value for the `styles` attribute. Overrides
536
     * base implementation.
537
     *
538
     * @method _getDefaultStyles
539
     * @return Object
540
     */
541
    _getDefaultStyles: function()
542
    {
543
        var styles = this._mergeStyles({marker:this._getPlotDefaults()}, this.constructor.superclass._getDefaultStyles());
544
        return styles;
545
    }
546
};
547
 
548
Y.augment(Plots, Y.Attribute);
549
Y.Plots = Plots;
550
 
551
 
552
}, '3.18.1');