Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('charts-legend', function (Y, NAME) {
2
 
3
/**
4
 * Adds legend functionality to charts.
5
 *
6
 * @module charts
7
 * @submodule charts-legend
8
 */
9
var TOP = "top",
10
RIGHT = "right",
11
BOTTOM = "bottom",
12
LEFT = "left",
13
EXTERNAL = "external",
14
HORIZONTAL = "horizontal",
15
VERTICAL = "vertical",
16
WIDTH = "width",
17
HEIGHT = "height",
18
POSITION = "position",
19
_X = "x",
20
_Y = "y",
21
PX = "px",
22
PieChartLegend,
23
LEGEND = {
24
    setter: function(val)
25
    {
26
        var legend = this.get("legend");
27
        if(legend)
28
        {
29
            legend.destroy(true);
30
        }
31
        if(val instanceof Y.ChartLegend)
32
        {
33
            legend = val;
34
            legend.set("chart", this);
35
        }
36
        else
37
        {
38
            val.chart = this;
39
            if(!val.hasOwnProperty("render"))
40
            {
41
                val.render = this.get("contentBox");
42
                val.includeInChartLayout = true;
43
            }
44
            legend = new Y.ChartLegend(val);
45
        }
46
        return legend;
47
    }
48
},
49
 
50
/**
51
 * Contains methods for displaying items horizontally in a legend.
52
 *
53
 * @module charts
54
 * @submodule charts-legend
55
 * @class HorizontalLegendLayout
56
 */
57
HorizontalLegendLayout = {
58
    /**
59
     * Displays items horizontally in a legend.
60
     *
61
     * @method _positionLegendItems
62
     * @param {Array} items Array of items to display in the legend.
63
     * @param {Number} maxWidth The width of the largest item in the legend.
64
     * @param {Number} maxHeight The height of the largest item in the legend.
65
     * @param {Number} totalWidth The total width of all items in a legend.
66
     * @param {Number} totalHeight The total height of all items in a legend.
67
     * @param {Number} padding The left, top, right and bottom padding properties for the legend.
68
     * @param {Number} horizontalGap The horizontal distance between items in a legend.
69
     * @param {Number} verticalGap The vertical distance between items in a legend.
70
     * @param {String} hAlign The horizontal alignment of the legend.
71
     * @protected
72
     */
73
    _positionLegendItems: function(items, maxWidth, maxHeight, totalWidth, totalHeight, padding, horizontalGap, verticalGap, hAlign)
74
    {
75
        var i = 0,
76
            rowIterator = 0,
77
            item,
78
            node,
79
            itemWidth,
80
            itemHeight,
81
            len,
82
            width = this.get("width"),
83
            rows,
84
            rowsLen,
85
            row,
86
            totalWidthArray,
87
            legendWidth,
88
            topHeight = padding.top - verticalGap,
89
            limit = width - (padding.left + padding.right),
90
            left,
91
            top,
92
            right,
93
            bottom;
94
        HorizontalLegendLayout._setRowArrays(items, limit, horizontalGap);
95
        rows = HorizontalLegendLayout.rowArray;
96
        totalWidthArray = HorizontalLegendLayout.totalWidthArray;
97
        rowsLen = rows.length;
98
        for(; rowIterator < rowsLen; ++ rowIterator)
99
        {
100
            topHeight += verticalGap;
101
            row = rows[rowIterator];
102
            len = row.length;
103
            legendWidth =  HorizontalLegendLayout.getStartPoint(width, totalWidthArray[rowIterator], hAlign, padding);
104
            for(i = 0; i < len; ++i)
105
            {
106
                item = row[i];
107
                node = item.node;
108
                itemWidth = item.width;
109
                itemHeight = item.height;
110
                item.x = legendWidth;
111
                item.y = 0;
112
                left = !isNaN(left) ? Math.min(left, legendWidth) : legendWidth;
113
                top = !isNaN(top) ? Math.min(top, topHeight) : topHeight;
114
                right = !isNaN(right) ? Math.max(legendWidth + itemWidth, right) : legendWidth + itemWidth;
115
                bottom = !isNaN(bottom) ? Math.max(topHeight + itemHeight, bottom) : topHeight + itemHeight;
116
                node.setStyle("left", legendWidth + PX);
117
                node.setStyle("top", topHeight + PX);
118
                legendWidth += itemWidth + horizontalGap;
119
            }
120
            topHeight += item.height;
121
        }
122
        this._contentRect = {
123
            left: left,
124
            top: top,
125
            right: right,
126
            bottom: bottom
127
        };
128
        if(this.get("includeInChartLayout"))
129
        {
130
            this.set("height", topHeight + padding.bottom);
131
        }
132
    },
133
 
134
    /**
135
     * Creates row and total width arrays used for displaying multiple rows of
136
     * legend items based on the items, available width and horizontalGap for the legend.
137
     *
138
     * @method _setRowArrays
139
     * @param {Array} items Array of legend items to display in a legend.
140
     * @param {Number} limit Total available width for displaying items in a legend.
141
     * @param {Number} horizontalGap Horizontal distance between items in a legend.
142
     * @protected
143
     */
144
    _setRowArrays: function(items, limit, horizontalGap)
145
    {
146
        var item = items[0],
147
            rowArray = [[item]],
148
            i = 1,
149
            rowIterator = 0,
150
            len = items.length,
151
            totalWidth = item.width,
152
            itemWidth,
153
            totalWidthArray = [[totalWidth]];
154
        for(; i < len; ++i)
155
        {
156
            item = items[i];
157
            itemWidth = item.width;
158
            if((totalWidth + horizontalGap + itemWidth) <= limit)
159
            {
160
                totalWidth += horizontalGap + itemWidth;
161
                rowArray[rowIterator].push(item);
162
            }
163
            else
164
            {
165
                totalWidth = horizontalGap + itemWidth;
166
                if(rowArray[rowIterator])
167
                {
168
                    rowIterator += 1;
169
                }
170
                rowArray[rowIterator] = [item];
171
            }
172
            totalWidthArray[rowIterator] = totalWidth;
173
        }
174
        HorizontalLegendLayout.rowArray = rowArray;
175
        HorizontalLegendLayout.totalWidthArray = totalWidthArray;
176
    },
177
 
178
    /**
179
     * Returns the starting x-coordinate for a row of legend items.
180
     *
181
     * @method getStartPoint
182
     * @param {Number} w Width of the legend.
183
     * @param {Number} totalWidth Total width of all labels in the row.
184
     * @param {String} align Horizontal alignment of items for the legend.
185
     * @param {Object} padding Object contain left, top, right and bottom padding properties.
186
     * @return Number
187
     * @protected
188
     */
189
    getStartPoint: function(w, totalWidth, align, padding)
190
    {
191
        var startPoint;
192
        switch(align)
193
        {
194
            case LEFT :
195
                startPoint = padding.left;
196
            break;
197
            case "center" :
198
                startPoint = (w - totalWidth) * 0.5;
199
            break;
200
            case RIGHT :
201
                startPoint = w - totalWidth - padding.right;
202
            break;
203
        }
204
        return startPoint;
205
    }
206
},
207
 
208
/**
209
 * Contains methods for displaying items vertically in a legend.
210
 *
211
 * @module charts
212
 * @submodule charts-legend
213
 * @class VerticalLegendLayout
214
 */
215
VerticalLegendLayout = {
216
    /**
217
     * Displays items vertically in a legend.
218
     *
219
     * @method _positionLegendItems
220
     * @param {Array} items Array of items to display in the legend.
221
     * @param {Number} maxWidth The width of the largest item in the legend.
222
     * @param {Number} maxHeight The height of the largest item in the legend.
223
     * @param {Number} totalWidth The total width of all items in a legend.
224
     * @param {Number} totalHeight The total height of all items in a legend.
225
     * @param {Number} padding The left, top, right and bottom padding properties for the legend.
226
     * @param {Number} horizontalGap The horizontal distance between items in a legend.
227
     * @param {Number} verticalGap The vertical distance between items in a legend.
228
     * @param {String} vAlign The vertical alignment of the legend.
229
     * @protected
230
     */
231
    _positionLegendItems: function(items, maxWidth, maxHeight, totalWidth, totalHeight, padding, horizontalGap, verticalGap, vAlign)
232
    {
233
        var i = 0,
234
            columnIterator = 0,
235
            item,
236
            node,
237
            itemHeight,
238
            itemWidth,
239
            len,
240
            height = this.get("height"),
241
            columns,
242
            columnsLen,
243
            column,
244
            totalHeightArray,
245
            legendHeight,
246
            leftWidth = padding.left - horizontalGap,
247
            legendWidth,
248
            limit = height - (padding.top + padding.bottom),
249
            left,
250
            top,
251
            right,
252
            bottom;
253
        VerticalLegendLayout._setColumnArrays(items, limit, verticalGap);
254
        columns = VerticalLegendLayout.columnArray;
255
        totalHeightArray = VerticalLegendLayout.totalHeightArray;
256
        columnsLen = columns.length;
257
        for(; columnIterator < columnsLen; ++ columnIterator)
258
        {
259
            leftWidth += horizontalGap;
260
            column = columns[columnIterator];
261
            len = column.length;
262
            legendHeight =  VerticalLegendLayout.getStartPoint(height, totalHeightArray[columnIterator], vAlign, padding);
263
            legendWidth = 0;
264
            for(i = 0; i < len; ++i)
265
            {
266
                item = column[i];
267
                node = item.node;
268
                itemHeight = item.height;
269
                itemWidth = item.width;
270
                item.y = legendHeight;
271
                item.x = leftWidth;
272
                left = !isNaN(left) ? Math.min(left, leftWidth) : leftWidth;
273
                top = !isNaN(top) ? Math.min(top, legendHeight) : legendHeight;
274
                right = !isNaN(right) ? Math.max(leftWidth + itemWidth, right) : leftWidth + itemWidth;
275
                bottom = !isNaN(bottom) ? Math.max(legendHeight + itemHeight, bottom) : legendHeight + itemHeight;
276
                node.setStyle("left", leftWidth + PX);
277
                node.setStyle("top", legendHeight + PX);
278
                legendHeight += itemHeight + verticalGap;
279
                legendWidth = Math.max(legendWidth, item.width);
280
            }
281
            leftWidth += legendWidth;
282
        }
283
        this._contentRect = {
284
            left: left,
285
            top: top,
286
            right: right,
287
            bottom: bottom
288
        };
289
        if(this.get("includeInChartLayout"))
290
        {
291
            this.set("width", leftWidth + padding.right);
292
        }
293
    },
294
 
295
    /**
296
     * Creates column and total height arrays used for displaying multiple columns of
297
     * legend items based on the items, available height and verticalGap for the legend.
298
     *
299
     * @method _setColumnArrays
300
     * @param {Array} items Array of legend items to display in a legend.
301
     * @param {Number} limit Total available height for displaying items in a legend.
302
     * @param {Number} verticalGap Vertical distance between items in a legend.
303
     * @protected
304
     */
305
    _setColumnArrays: function(items, limit, verticalGap)
306
    {
307
        var item = items[0],
308
            columnArray = [[item]],
309
            i = 1,
310
            columnIterator = 0,
311
            len = items.length,
312
            totalHeight = item.height,
313
            itemHeight,
314
            totalHeightArray = [[totalHeight]];
315
        for(; i < len; ++i)
316
        {
317
            item = items[i];
318
            itemHeight = item.height;
319
            if((totalHeight + verticalGap + itemHeight) <= limit)
320
            {
321
                totalHeight += verticalGap + itemHeight;
322
                columnArray[columnIterator].push(item);
323
            }
324
            else
325
            {
326
                totalHeight = verticalGap + itemHeight;
327
                if(columnArray[columnIterator])
328
                {
329
                    columnIterator += 1;
330
                }
331
                columnArray[columnIterator] = [item];
332
            }
333
            totalHeightArray[columnIterator] = totalHeight;
334
        }
335
        VerticalLegendLayout.columnArray = columnArray;
336
        VerticalLegendLayout.totalHeightArray = totalHeightArray;
337
    },
338
 
339
    /**
340
     * Returns the starting y-coordinate for a column of legend items.
341
     *
342
     * @method getStartPoint
343
     * @param {Number} h Height of the legend.
344
     * @param {Number} totalHeight Total height of all labels in the column.
345
     * @param {String} align Vertical alignment of items for the legend.
346
     * @param {Object} padding Object contain left, top, right and bottom padding properties.
347
     * @return Number
348
     * @protected
349
     */
350
    getStartPoint: function(h, totalHeight, align, padding)
351
    {
352
        var startPoint;
353
        switch(align)
354
        {
355
            case TOP :
356
                startPoint = padding.top;
357
            break;
358
            case "middle" :
359
                startPoint = (h - totalHeight) * 0.5;
360
            break;
361
            case BOTTOM :
362
                startPoint = h - totalHeight - padding.bottom;
363
            break;
364
        }
365
        return startPoint;
366
    }
367
},
368
 
369
CartesianChartLegend = Y.Base.create("cartesianChartLegend", Y.CartesianChart, [], {
370
    /**
371
     * Redraws and position all the components of the chart instance.
372
     *
373
     * @method _redraw
374
     * @private
375
     */
376
    _redraw: function()
377
    {
378
        if(this._drawing)
379
        {
380
            this._callLater = true;
381
            return;
382
        }
383
        this._drawing = true;
384
        this._callLater = false;
385
        var w = this.get("width"),
386
            h = this.get("height"),
387
            layoutBoxDimensions = this._getLayoutBoxDimensions(),
388
            leftPaneWidth = layoutBoxDimensions.left,
389
            rightPaneWidth = layoutBoxDimensions.right,
390
            topPaneHeight = layoutBoxDimensions.top,
391
            bottomPaneHeight = layoutBoxDimensions.bottom,
392
            leftAxesCollection = this.get("leftAxesCollection"),
393
            rightAxesCollection = this.get("rightAxesCollection"),
394
            topAxesCollection = this.get("topAxesCollection"),
395
            bottomAxesCollection = this.get("bottomAxesCollection"),
396
            i = 0,
397
            l,
398
            axis,
399
            graphOverflow = "visible",
400
            graph = this.get("graph"),
401
            topOverflow,
402
            bottomOverflow,
403
            leftOverflow,
404
            rightOverflow,
405
            graphWidth,
406
            graphHeight,
407
            graphX,
408
            graphY,
409
            allowContentOverflow = this.get("allowContentOverflow"),
410
            diff,
411
            rightAxesXCoords,
412
            leftAxesXCoords,
413
            topAxesYCoords,
414
            bottomAxesYCoords,
415
            legend = this.get("legend"),
416
            graphRect = {};
417
 
418
        if(leftAxesCollection)
419
        {
420
            leftAxesXCoords = [];
421
            l = leftAxesCollection.length;
422
            for(i = l - 1; i > -1; --i)
423
            {
424
                leftAxesXCoords.unshift(leftPaneWidth);
425
                leftPaneWidth += leftAxesCollection[i].get("width");
426
            }
427
        }
428
        if(rightAxesCollection)
429
        {
430
            rightAxesXCoords = [];
431
            l = rightAxesCollection.length;
432
            i = 0;
433
            for(i = l - 1; i > -1; --i)
434
            {
435
                rightPaneWidth += rightAxesCollection[i].get("width");
436
                rightAxesXCoords.unshift(w - rightPaneWidth);
437
            }
438
        }
439
        if(topAxesCollection)
440
        {
441
            topAxesYCoords = [];
442
            l = topAxesCollection.length;
443
            for(i = l - 1; i > -1; --i)
444
            {
445
                topAxesYCoords.unshift(topPaneHeight);
446
                topPaneHeight += topAxesCollection[i].get("height");
447
            }
448
        }
449
        if(bottomAxesCollection)
450
        {
451
            bottomAxesYCoords = [];
452
            l = bottomAxesCollection.length;
453
            for(i = l - 1; i > -1; --i)
454
            {
455
                bottomPaneHeight += bottomAxesCollection[i].get("height");
456
                bottomAxesYCoords.unshift(h - bottomPaneHeight);
457
            }
458
        }
459
 
460
        graphWidth = w - (leftPaneWidth + rightPaneWidth);
461
        graphHeight = h - (bottomPaneHeight + topPaneHeight);
462
        graphRect.left = leftPaneWidth;
463
        graphRect.top = topPaneHeight;
464
        graphRect.bottom = h - bottomPaneHeight;
465
        graphRect.right = w - rightPaneWidth;
466
        if(!allowContentOverflow)
467
        {
468
            topOverflow = this._getTopOverflow(leftAxesCollection, rightAxesCollection);
469
            bottomOverflow = this._getBottomOverflow(leftAxesCollection, rightAxesCollection);
470
            leftOverflow = this._getLeftOverflow(bottomAxesCollection, topAxesCollection);
471
            rightOverflow = this._getRightOverflow(bottomAxesCollection, topAxesCollection);
472
 
473
            diff = topOverflow - topPaneHeight;
474
            if(diff > 0)
475
            {
476
                graphRect.top = topOverflow;
477
                if(topAxesYCoords)
478
                {
479
                    i = 0;
480
                    l = topAxesYCoords.length;
481
                    for(; i < l; ++i)
482
                    {
483
                        topAxesYCoords[i] += diff;
484
                    }
485
                }
486
            }
487
 
488
            diff = bottomOverflow - bottomPaneHeight;
489
            if(diff > 0)
490
            {
491
                graphRect.bottom = h - bottomOverflow;
492
                if(bottomAxesYCoords)
493
                {
494
                    i = 0;
495
                    l = bottomAxesYCoords.length;
496
                    for(; i < l; ++i)
497
                    {
498
                        bottomAxesYCoords[i] -= diff;
499
                    }
500
                }
501
            }
502
 
503
            diff = leftOverflow - leftPaneWidth;
504
            if(diff > 0)
505
            {
506
                graphRect.left = leftOverflow;
507
                if(leftAxesXCoords)
508
                {
509
                    i = 0;
510
                    l = leftAxesXCoords.length;
511
                    for(; i < l; ++i)
512
                    {
513
                        leftAxesXCoords[i] += diff;
514
                    }
515
                }
516
            }
517
 
518
            diff = rightOverflow - rightPaneWidth;
519
            if(diff > 0)
520
            {
521
                graphRect.right = w - rightOverflow;
522
                if(rightAxesXCoords)
523
                {
524
                    i = 0;
525
                    l = rightAxesXCoords.length;
526
                    for(; i < l; ++i)
527
                    {
528
                        rightAxesXCoords[i] -= diff;
529
                    }
530
                }
531
            }
532
        }
533
        graphWidth = graphRect.right - graphRect.left;
534
        graphHeight = graphRect.bottom - graphRect.top;
535
        graphX = graphRect.left;
536
        graphY = graphRect.top;
537
        if(legend)
538
        {
539
            if(legend.get("includeInChartLayout"))
540
            {
541
                switch(legend.get("position"))
542
                {
543
                    case "left" :
544
                        legend.set("y", graphY);
545
                        legend.set("height", graphHeight);
546
                    break;
547
                    case "top" :
548
                        legend.set("x", graphX);
549
                        legend.set("width", graphWidth);
550
                    break;
551
                    case "bottom" :
552
                        legend.set("x", graphX);
553
                        legend.set("width", graphWidth);
554
                    break;
555
                    case "right" :
556
                        legend.set("y", graphY);
557
                        legend.set("height", graphHeight);
558
                    break;
559
                }
560
            }
561
        }
562
        if(topAxesCollection)
563
        {
564
            l = topAxesCollection.length;
565
            i = 0;
566
            for(; i < l; i++)
567
            {
568
                axis = topAxesCollection[i];
569
                if(axis.get("width") !== graphWidth)
570
                {
571
                    axis.set("width", graphWidth);
572
                }
573
                axis.get("boundingBox").setStyle("left", graphX + PX);
574
                axis.get("boundingBox").setStyle("top", topAxesYCoords[i] + PX);
575
            }
576
            if(axis._hasDataOverflow())
577
            {
578
                graphOverflow = "hidden";
579
            }
580
        }
581
        if(bottomAxesCollection)
582
        {
583
            l = bottomAxesCollection.length;
584
            i = 0;
585
            for(; i < l; i++)
586
            {
587
                axis = bottomAxesCollection[i];
588
                if(axis.get("width") !== graphWidth)
589
                {
590
                    axis.set("width", graphWidth);
591
                }
592
                axis.get("boundingBox").setStyle("left", graphX + PX);
593
                axis.get("boundingBox").setStyle("top", bottomAxesYCoords[i] + PX);
594
            }
595
            if(axis._hasDataOverflow())
596
            {
597
                graphOverflow = "hidden";
598
            }
599
        }
600
        if(leftAxesCollection)
601
        {
602
            l = leftAxesCollection.length;
603
            i = 0;
604
            for(; i < l; ++i)
605
            {
606
                axis = leftAxesCollection[i];
607
                axis.get("boundingBox").setStyle("top", graphY + PX);
608
                axis.get("boundingBox").setStyle("left", leftAxesXCoords[i] + PX);
609
                if(axis.get("height") !== graphHeight)
610
                {
611
                    axis.set("height", graphHeight);
612
                }
613
            }
614
            if(axis._hasDataOverflow())
615
            {
616
                graphOverflow = "hidden";
617
            }
618
        }
619
        if(rightAxesCollection)
620
        {
621
            l = rightAxesCollection.length;
622
            i = 0;
623
            for(; i < l; ++i)
624
            {
625
                axis = rightAxesCollection[i];
626
                axis.get("boundingBox").setStyle("top", graphY + PX);
627
                axis.get("boundingBox").setStyle("left", rightAxesXCoords[i] + PX);
628
                if(axis.get("height") !== graphHeight)
629
                {
630
                    axis.set("height", graphHeight);
631
                }
632
            }
633
            if(axis._hasDataOverflow())
634
            {
635
                graphOverflow = "hidden";
636
            }
637
        }
638
        this._drawing = false;
639
        if(this._callLater)
640
        {
641
            this._redraw();
642
            return;
643
        }
644
        if(graph)
645
        {
646
            graph.get("boundingBox").setStyle("left", graphX + PX);
647
            graph.get("boundingBox").setStyle("top", graphY + PX);
648
            graph.set("width", graphWidth);
649
            graph.set("height", graphHeight);
650
            graph.get("boundingBox").setStyle("overflow", graphOverflow);
651
        }
652
 
653
        if(this._overlay)
654
        {
655
            this._overlay.setStyle("left", graphX + PX);
656
            this._overlay.setStyle("top", graphY + PX);
657
            this._overlay.setStyle("width", graphWidth + PX);
658
            this._overlay.setStyle("height", graphHeight + PX);
659
        }
660
    },
661
 
662
    /**
663
     * Positions the legend in a chart and returns the properties of the legend to be used in the
664
     * chart's layout algorithm.
665
     *
666
     * @method _getLayoutDimensions
667
     * @return {Object} The left, top, right and bottom values for the legend.
668
     * @protected
669
     */
670
    _getLayoutBoxDimensions: function()
671
    {
672
        var box = {
673
                top: 0,
674
                right: 0,
675
                bottom: 0,
676
                left: 0
677
            },
678
            legend = this.get("legend"),
679
            position,
680
            direction,
681
            dimension,
682
            size,
683
            w = this.get(WIDTH),
684
            h = this.get(HEIGHT),
685
            gap;
686
        if(legend && legend.get("includeInChartLayout"))
687
        {
688
            gap = legend.get("styles").gap;
689
            position = legend.get(POSITION);
690
            if(position !== EXTERNAL)
691
            {
692
                direction = legend.get("direction");
693
                dimension = direction === HORIZONTAL ? HEIGHT : WIDTH;
694
                size = legend.get(dimension);
695
                box[position] = size + gap;
696
                switch(position)
697
                {
698
                    case TOP :
699
                        legend.set(_Y, 0);
700
                    break;
701
                    case BOTTOM :
702
                        legend.set(_Y, h - size);
703
                    break;
704
                    case RIGHT :
705
                        legend.set(_X, w - size);
706
                    break;
707
                    case LEFT:
708
                        legend.set(_X, 0);
709
                    break;
710
                }
711
            }
712
        }
713
        return box;
714
    },
715
 
716
    /**
717
     * Destructor implementation for the CartesianChart class. Calls destroy on all axes, series, legend (if available) and the Graph instance.
718
     * Removes the tooltip and overlay HTML elements.
719
     *
720
     * @method destructor
721
     * @protected
722
     */
723
    destructor: function()
724
    {
725
        var legend = this.get("legend");
726
        if(legend)
727
        {
728
            legend.destroy(true);
729
        }
730
    }
731
}, {
732
    ATTRS: {
733
        legend: LEGEND
734
    }
735
});
736
 
737
Y.CartesianChart = CartesianChartLegend;
738
 
739
PieChartLegend = Y.Base.create("pieChartLegend", Y.PieChart, [], {
740
    /**
741
     * Redraws the chart instance.
742
     *
743
     * @method _redraw
744
     * @private
745
     */
746
    _redraw: function()
747
    {
748
        if(this._drawing)
749
        {
750
            this._callLater = true;
751
            return;
752
        }
753
        this._drawing = true;
754
        this._callLater = false;
755
        var graph = this.get("graph"),
756
            w = this.get("width"),
757
            h = this.get("height"),
758
            graphWidth,
759
            graphHeight,
760
            legend = this.get("legend"),
761
            x = 0,
762
            y = 0,
763
            legendX = 0,
764
            legendY = 0,
765
            legendWidth,
766
            legendHeight,
767
            dimension,
768
            gap,
769
            position,
770
            direction;
771
        if(graph)
772
        {
773
            if(legend)
774
            {
775
                position = legend.get("position");
776
                direction = legend.get("direction");
777
                graphWidth = graph.get("width");
778
                graphHeight = graph.get("height");
779
                legendWidth = legend.get("width");
780
                legendHeight = legend.get("height");
781
                gap = legend.get("styles").gap;
782
 
783
                if((direction === "vertical" && (graphWidth + legendWidth + gap !== w)) ||
784
                    (direction === "horizontal" &&  (graphHeight + legendHeight + gap !== h)))
785
                {
786
                    switch(legend.get("position"))
787
                    {
788
                        case LEFT :
789
                            dimension = Math.min(w - (legendWidth + gap), h);
790
                            legendHeight = h;
791
                            x = legendWidth + gap;
792
                            legend.set(HEIGHT, legendHeight);
793
                        break;
794
                        case TOP :
795
                            dimension = Math.min(h - (legendHeight + gap), w);
796
                            legendWidth = w;
797
                            y = legendHeight + gap;
798
                            legend.set(WIDTH, legendWidth);
799
                        break;
800
                        case RIGHT :
801
                            dimension = Math.min(w - (legendWidth + gap), h);
802
                            legendHeight = h;
803
                            legendX = dimension + gap;
804
                            legend.set(HEIGHT, legendHeight);
805
                        break;
806
                        case BOTTOM :
807
                            dimension = Math.min(h - (legendHeight + gap), w);
808
                            legendWidth = w;
809
                            legendY = dimension + gap;
810
                            legend.set(WIDTH, legendWidth);
811
                        break;
812
                    }
813
                    graph.set(WIDTH, dimension);
814
                    graph.set(HEIGHT, dimension);
815
                }
816
                else
817
                {
818
                    switch(legend.get("position"))
819
                    {
820
                        case LEFT :
821
                            x = legendWidth + gap;
822
                        break;
823
                        case TOP :
824
                            y = legendHeight + gap;
825
                        break;
826
                        case RIGHT :
827
                            legendX = graphWidth + gap;
828
                        break;
829
                        case BOTTOM :
830
                            legendY = graphHeight + gap;
831
                        break;
832
                    }
833
                }
834
            }
835
            else
836
            {
837
                graph.set(_X, 0);
838
                graph.set(_Y, 0);
839
                graph.set(WIDTH, w);
840
                graph.set(HEIGHT, h);
841
            }
842
        }
843
        this._drawing = false;
844
        if(this._callLater)
845
        {
846
            this._redraw();
847
            return;
848
        }
849
        if(graph)
850
        {
851
            graph.set(_X, x);
852
            graph.set(_Y, y);
853
        }
854
        if(legend)
855
        {
856
            legend.set(_X, legendX);
857
            legend.set(_Y, legendY);
858
        }
859
    }
860
}, {
861
    ATTRS: {
862
        /**
863
         * The legend for the chart.
864
         *
865
         * @attribute
866
         * @type Legend
867
         */
868
        legend: LEGEND
869
    }
870
});
871
Y.PieChart = PieChartLegend;
872
/**
873
 * ChartLegend provides a legend for a chart.
874
 *
875
 * @class ChartLegend
876
 * @module charts
877
 * @submodule charts-legend
878
 * @extends Widget
879
 */
880
Y.ChartLegend = Y.Base.create("chartlegend", Y.Widget, [Y.Renderer], {
881
    /**
882
     * Initializes the chart.
883
     *
884
     * @method initializer
885
     * @private
886
     */
887
    initializer: function()
888
    {
889
        this._items = [];
890
    },
891
 
892
    /**
893
     * @method renderUI
894
     * @private
895
     */
896
    renderUI: function()
897
    {
898
        var bb = this.get("boundingBox"),
899
            cb = this.get("contentBox"),
900
            styles = this.get("styles").background,
901
            background = new Y.Rect({
902
                graphic: cb,
903
                fill: styles.fill,
904
                stroke: styles.border
905
            });
906
        bb.setStyle("display", "block");
907
        bb.setStyle("position", "absolute");
908
        this.set("background", background);
909
    },
910
 
911
    /**
912
     * @method bindUI
913
     * @private
914
     */
915
    bindUI: function()
916
    {
917
        this.get("chart").after("seriesCollectionChange", Y.bind(this._updateHandler, this));
918
        this.get("chart").after("stylesChange", Y.bind(this._updateHandler, this));
919
        this.after("stylesChange", this._updateHandler);
920
        this.after("positionChange", this._positionChangeHandler);
921
        this.after("widthChange", this._handleSizeChange);
922
        this.after("heightChange", this._handleSizeChange);
923
    },
924
 
925
    /**
926
     * @method syncUI
927
     * @private
928
     */
929
    syncUI: function()
930
    {
931
        var w = this.get("width"),
932
            h = this.get("height");
933
        if(isFinite(w) && isFinite(h) && w > 0 && h > 0)
934
        {
935
            this._drawLegend();
936
        }
937
    },
938
 
939
    /**
940
     * Handles changes to legend.
941
     *
942
     * @method _updateHandler
943
     * @param {Object} e Event object
944
     * @private
945
     */
946
    _updateHandler: function()
947
    {
948
        if(this.get("rendered"))
949
        {
950
            this._drawLegend();
951
        }
952
    },
953
 
954
    /**
955
     * Handles position changes.
956
     *
957
     * @method _positionChangeHandler
958
     * @param {Object} e Event object
959
     * @private
960
     */
961
    _positionChangeHandler: function()
962
    {
963
        var chart = this.get("chart"),
964
            parentNode = this._parentNode;
965
        if(parentNode && ((chart && this.get("includeInChartLayout"))))
966
        {
967
            this.fire("legendRendered");
968
        }
969
        else if(this.get("rendered"))
970
        {
971
            this._drawLegend();
972
        }
973
    },
974
 
975
    /**
976
     * Updates the legend when the size changes.
977
     *
978
     * @method _handleSizeChange
979
     * @param {Object} e Event object.
980
     * @private
981
     */
982
    _handleSizeChange: function(e)
983
    {
984
        var attrName = e.attrName,
985
            pos = this.get(POSITION),
986
            vert = pos === LEFT || pos === RIGHT,
987
            hor = pos === BOTTOM || pos === TOP;
988
        if((hor && attrName === WIDTH) || (vert && attrName === HEIGHT))
989
        {
990
            this._drawLegend();
991
        }
992
    },
993
 
994
    /**
995
     * Draws the legend
996
     *
997
     * @method _drawLegend
998
     * @private
999
     */
1000
    _drawLegend: function()
1001
    {
1002
        if(this._drawing)
1003
        {
1004
            this._callLater = true;
1005
            return;
1006
        }
1007
        this._drawing = true;
1008
        this._callLater = false;
1009
        if(this.get("includeInChartLayout"))
1010
        {
1011
            this.get("chart")._itemRenderQueue.unshift(this);
1012
        }
1013
        var chart = this.get("chart"),
1014
            node = this.get("contentBox"),
1015
            seriesCollection = chart.get("seriesCollection"),
1016
            series,
1017
            styles = this.get("styles"),
1018
            padding = styles.padding,
1019
            itemStyles = styles.item,
1020
            seriesStyles,
1021
            hSpacing = itemStyles.hSpacing,
1022
            vSpacing = itemStyles.vSpacing,
1023
            direction = this.get("direction"),
1024
            align = direction === "vertical" ? styles.vAlign : styles.hAlign,
1025
            marker = styles.marker,
1026
            labelStyles = itemStyles.label,
1027
            displayName,
1028
            layout = this._layout[direction],
1029
            i,
1030
            len,
1031
            isArray,
1032
            legendShape,
1033
            shape,
1034
            shapeClass,
1035
            item,
1036
            fill,
1037
            border,
1038
            fillColors,
1039
            borderColors,
1040
            borderWeight,
1041
            items = [],
1042
            markerWidth = marker.width,
1043
            markerHeight = marker.height,
1044
            totalWidth = 0 - hSpacing,
1045
            totalHeight = 0 - vSpacing,
1046
            maxWidth = 0,
1047
            maxHeight = 0,
1048
            itemWidth,
1049
            itemHeight;
1050
        if(marker && marker.shape)
1051
        {
1052
            legendShape = marker.shape;
1053
        }
1054
        this._destroyLegendItems();
1055
        if(chart instanceof Y.PieChart)
1056
        {
1057
            series = seriesCollection[0];
1058
            displayName = series.get("categoryAxis").getDataByKey(series.get("categoryKey"));
1059
            seriesStyles = series.get("styles").marker;
1060
            fillColors = seriesStyles.fill.colors;
1061
            borderColors = seriesStyles.border.colors;
1062
            borderWeight = seriesStyles.border.weight;
1063
            i = 0;
1064
            len = displayName.length;
1065
            shape = legendShape || Y.Circle;
1066
            isArray = Y.Lang.isArray(shape);
1067
            for(; i < len; ++i)
1068
            {
1069
                shape = isArray ? shape[i] : shape;
1070
                fill = {
1071
                    color: fillColors[i]
1072
                };
1073
                border = {
1074
                    colors: borderColors[i],
1075
                    weight: borderWeight
1076
                };
1077
                displayName = chart.getSeriesItems(series, i).category.value;
1078
                item = this._getLegendItem(node, this._getShapeClass(shape), fill, border, labelStyles, markerWidth, markerHeight, displayName);
1079
                itemWidth = item.width;
1080
                itemHeight = item.height;
1081
                maxWidth = Math.max(maxWidth, itemWidth);
1082
                maxHeight = Math.max(maxHeight, itemHeight);
1083
                totalWidth += itemWidth + hSpacing;
1084
                totalHeight += itemHeight + vSpacing;
1085
                items.push(item);
1086
            }
1087
        }
1088
        else
1089
        {
1090
            i = 0;
1091
            len = seriesCollection.length;
1092
            for(; i < len; ++i)
1093
            {
1094
                series = seriesCollection[i];
1095
                seriesStyles = this._getStylesBySeriesType(series, shape);
1096
                if(!legendShape)
1097
                {
1098
                    shape = seriesStyles.shape;
1099
                    if(!shape)
1100
                    {
1101
                        shape = Y.Circle;
1102
                    }
1103
                }
1104
                shapeClass = Y.Lang.isArray(shape) ? shape[i] : shape;
1105
                item = this._getLegendItem(
1106
                    node,
1107
                    this._getShapeClass(shape),
1108
                    seriesStyles.fill,
1109
                    seriesStyles.border,
1110
                    labelStyles,
1111
                    markerWidth,
1112
                    markerHeight,
1113
                    series.get("valueDisplayName")
1114
                );
1115
                itemWidth = item.width;
1116
                itemHeight = item.height;
1117
                maxWidth = Math.max(maxWidth, itemWidth);
1118
                maxHeight = Math.max(maxHeight, itemHeight);
1119
                totalWidth += itemWidth + hSpacing;
1120
                totalHeight += itemHeight + vSpacing;
1121
                items.push(item);
1122
            }
1123
        }
1124
        this._drawing = false;
1125
        if(this._callLater)
1126
        {
1127
            this._drawLegend();
1128
        }
1129
        else
1130
        {
1131
            layout._positionLegendItems.apply(
1132
                this,
1133
                [items, maxWidth, maxHeight, totalWidth, totalHeight, padding, hSpacing, vSpacing, align]
1134
            );
1135
            this._updateBackground(styles);
1136
            this.fire("legendRendered");
1137
        }
1138
    },
1139
 
1140
    /**
1141
     * Updates the background for the legend.
1142
     *
1143
     * @method _updateBackground
1144
     * @param {Object} styles Reference to the legend's styles attribute
1145
     * @private
1146
     */
1147
    _updateBackground: function(styles)
1148
    {
1149
        var backgroundStyles = styles.background,
1150
            contentRect = this._contentRect,
1151
            padding = styles.padding,
1152
            x = contentRect.left - padding.left,
1153
            y = contentRect.top - padding.top,
1154
            w = contentRect.right - x + padding.right,
1155
            h = contentRect.bottom - y + padding.bottom;
1156
        this.get("background").set({
1157
            fill: backgroundStyles.fill,
1158
            stroke: backgroundStyles.border,
1159
            width: w,
1160
            height: h,
1161
            x: x,
1162
            y: y
1163
        });
1164
    },
1165
 
1166
    /**
1167
     * Retrieves the marker styles based on the type of series. For series that contain a marker, the marker styles are returned.
1168
     *
1169
     * @method _getStylesBySeriesType
1170
     * @param {CartesianSeries | PieSeries} The series in which the style properties will be received.
1171
     * @return Object An object containing fill, border and shape information.
1172
     * @private
1173
     */
1174
    _getStylesBySeriesType: function(series)
1175
    {
1176
        var styles = series.get("styles"),
1177
            color;
1178
        if(series instanceof Y.LineSeries || series instanceof Y.StackedLineSeries)
1179
        {
1180
            styles = series.get("styles").line;
1181
            color = styles.color || series._getDefaultColor(series.get("graphOrder"), "line");
1182
            return {
1183
                border: {
1184
                    weight: 1,
1185
                    color: color
1186
                },
1187
                fill: {
1188
                    color: color
1189
                }
1190
            };
1191
        }
1192
        else if(series instanceof Y.AreaSeries || series instanceof Y.StackedAreaSeries)
1193
        {
1194
            styles = series.get("styles").area;
1195
            color = styles.color || series._getDefaultColor(series.get("graphOrder"), "slice");
1196
            return {
1197
                border: {
1198
                    weight: 1,
1199
                    color: color
1200
                },
1201
                fill: {
1202
                    color: color
1203
                }
1204
            };
1205
        }
1206
        else
1207
        {
1208
            styles = series.get("styles").marker;
1209
            return {
1210
                fill: styles.fill,
1211
 
1212
                border: {
1213
                    weight: styles.border.weight,
1214
 
1215
                    color: styles.border.color,
1216
 
1217
                    shape: styles.shape
1218
                },
1219
                shape: styles.shape
1220
            };
1221
        }
1222
    },
1223
 
1224
    /**
1225
     * Returns a legend item consisting of the following properties:
1226
     *  <dl>
1227
     *    <dt>node</dt><dd>The `Node` containing the legend item elements.</dd>
1228
     *      <dt>shape</dt><dd>The `Shape` element for the legend item.</dd>
1229
     *      <dt>textNode</dt><dd>The `Node` containing the text></dd>
1230
     *      <dt>text</dt><dd></dd>
1231
     *  </dl>
1232
     *
1233
     * @method _getLegendItem
1234
     * @param {Node} shapeProps Reference to the `node` attribute.
1235
     * @param {String | Class} shapeClass The type of shape
1236
     * @param {Object} fill Properties for the shape's fill
1237
     * @param {Object} border Properties for the shape's border
1238
     * @param {String} labelStyles String to be rendered as the legend's text
1239
     * @param {Number} width Total width of the legend item
1240
     * @param {Number} height Total height of the legend item
1241
     * @param {String} text Text for the legendItem
1242
     * @return Object
1243
     * @private
1244
     */
1245
    _getLegendItem: function(node, shapeClass, fill, border, labelStyles, w, h, text)
1246
    {
1247
        var containerNode = Y.Node.create("<div>"),
1248
            textField = Y.Node.create("<span>"),
1249
            shape,
1250
            dimension,
1251
            padding,
1252
            left,
1253
            item,
1254
            ShapeClass = shapeClass;
1255
        containerNode.setStyle(POSITION, "absolute");
1256
        textField.setStyle(POSITION, "absolute");
1257
        textField.setStyles(labelStyles);
1258
        textField.set("text", text);
1259
        containerNode.appendChild(textField);
1260
        node.append(containerNode);
1261
        dimension = textField.get("offsetHeight");
1262
        padding = dimension - h;
1263
        left = w + padding + 2;
1264
        textField.setStyle("left", left + PX);
1265
        containerNode.setStyle("height", dimension + PX);
1266
        containerNode.setStyle("width", (left + textField.get("offsetWidth")) + PX);
1267
        shape = new ShapeClass({
1268
            fill: fill,
1269
            stroke: border,
1270
            width: w,
1271
            height: h,
1272
            x: padding * 0.5,
1273
            y: padding * 0.5,
1274
            w: w,
1275
            h: h,
1276
            graphic: containerNode
1277
        });
1278
        textField.setStyle("left", dimension + PX);
1279
        item = {
1280
            node: containerNode,
1281
            width: containerNode.get("offsetWidth"),
1282
            height: containerNode.get("offsetHeight"),
1283
            shape: shape,
1284
            textNode: textField,
1285
            text: text
1286
        };
1287
        this._items.push(item);
1288
        return item;
1289
    },
1290
 
1291
    /**
1292
     * Evaluates and returns correct class for drawing a shape.
1293
     *
1294
     * @method _getShapeClass
1295
     * @return Shape
1296
     * @private
1297
     */
1298
    _getShapeClass: function()
1299
    {
1300
        var graphic = this.get("background").get("graphic");
1301
        return graphic._getShapeClass.apply(graphic, arguments);
1302
    },
1303
 
1304
    /**
1305
     * Returns the default hash for the `styles` attribute.
1306
     *
1307
     * @method _getDefaultStyles
1308
     * @return Object
1309
     * @protected
1310
     */
1311
    _getDefaultStyles: function()
1312
    {
1313
        var styles = {
1314
            padding: {
1315
                top: 8,
1316
                right: 8,
1317
                bottom: 8,
1318
                left: 9
1319
            },
1320
            gap: 10,
1321
            hAlign: "center",
1322
            vAlign: "top",
1323
            marker: this._getPlotDefaults(),
1324
            item: {
1325
                hSpacing: 10,
1326
                vSpacing: 5,
1327
                label: {
1328
                    color:"#808080",
1329
                    fontSize:"85%",
1330
                    whiteSpace: "nowrap"
1331
                }
1332
            },
1333
            background: {
1334
                shape: "rect",
1335
                fill:{
1336
                    color:"#faf9f2"
1337
                },
1338
                border: {
1339
                    color:"#dad8c9",
1340
                    weight: 1
1341
                }
1342
            }
1343
        };
1344
        return styles;
1345
    },
1346
 
1347
    /**
1348
     * Gets the default values for series that use the utility. This method is used by
1349
     * the class' `styles` attribute's getter to get build default values.
1350
     *
1351
     * @method _getPlotDefaults
1352
     * @return Object
1353
     * @protected
1354
     */
1355
    _getPlotDefaults: function()
1356
    {
1357
        var defs = {
1358
            width: 10,
1359
            height: 10
1360
        };
1361
        return defs;
1362
    },
1363
 
1364
    /**
1365
     * Destroys legend items.
1366
     *
1367
     * @method _destroyLegendItems
1368
     * @private
1369
     */
1370
    _destroyLegendItems: function()
1371
    {
1372
        var item;
1373
        if(this._items)
1374
        {
1375
            while(this._items.length > 0)
1376
            {
1377
                item = this._items.shift();
1378
                item.shape.get("graphic").destroy();
1379
                item.node.empty();
1380
                item.node.destroy(true);
1381
                item.node = null;
1382
                item = null;
1383
            }
1384
        }
1385
        this._items = [];
1386
    },
1387
 
1388
    /**
1389
     * Maps layout classes.
1390
     *
1391
     * @property _layout
1392
     * @private
1393
     */
1394
    _layout: {
1395
        vertical: VerticalLegendLayout,
1396
        horizontal: HorizontalLegendLayout
1397
    },
1398
 
1399
    /**
1400
     * Destructor implementation ChartLegend class. Removes all items and the Graphic instance from the widget.
1401
     *
1402
     * @method destructor
1403
     * @protected
1404
     */
1405
    destructor: function()
1406
    {
1407
        var background = this.get("background"),
1408
            backgroundGraphic;
1409
        this._destroyLegendItems();
1410
        if(background)
1411
        {
1412
            backgroundGraphic = background.get("graphic");
1413
            if(backgroundGraphic)
1414
            {
1415
                backgroundGraphic.destroy();
1416
            }
1417
            else
1418
            {
1419
                background.destroy();
1420
            }
1421
        }
1422
 
1423
    }
1424
}, {
1425
    ATTRS: {
1426
        /**
1427
         * Indicates whether the chart's contentBox is the parentNode for the legend.
1428
         *
1429
         * @attribute includeInChartLayout
1430
         * @type Boolean
1431
         * @private
1432
         */
1433
        includeInChartLayout: {
1434
            value: false
1435
        },
1436
 
1437
        /**
1438
         * Reference to the `Chart` instance.
1439
         *
1440
         * @attribute chart
1441
         * @type Chart
1442
         */
1443
        chart: {
1444
            setter: function(val)
1445
            {
1446
                this.after("legendRendered", Y.bind(val._itemRendered, val));
1447
                return val;
1448
            }
1449
        },
1450
 
1451
        /**
1452
         * Indicates the direction in relation of the legend's layout. The `direction` of the legend is determined by its
1453
         * `position` value.
1454
         *
1455
         * @attribute direction
1456
         * @type String
1457
         */
1458
        direction: {
1459
            value: "vertical"
1460
        },
1461
 
1462
        /**
1463
         * Indicates the position and direction of the legend. Possible values are `left`, `top`, `right` and `bottom`.
1464
         * Values of `left` and `right` values have a `direction` of `vertical`. Values of `top` and `bottom` values have
1465
         * a `direction` of `horizontal`.
1466
         *
1467
         * @attribute position
1468
         * @type String
1469
         */
1470
        position: {
1471
            lazyAdd: false,
1472
 
1473
            value: "right",
1474
 
1475
            setter: function(val)
1476
            {
1477
                if(val === TOP || val === BOTTOM)
1478
                {
1479
                    this.set("direction", HORIZONTAL);
1480
                }
1481
                else if(val === LEFT || val === RIGHT)
1482
                {
1483
                    this.set("direction", VERTICAL);
1484
                }
1485
                return val;
1486
            }
1487
        },
1488
 
1489
        /**
1490
         * The width of the legend. Depending on the implementation of the ChartLegend, this value is `readOnly`.
1491
         * By default, the legend is included in the layout of the `Chart` that it references. Under this circumstance,
1492
         * `width` is always `readOnly`. When the legend is rendered in its own dom element, the `readOnly` status is
1493
         * determined by the direction of the legend. If the `position` is `left` or `right` or the `direction` is
1494
         * `vertical`, width is `readOnly`. If the position is `top` or `bottom` or the `direction` is `horizontal`,
1495
         * width can be explicitly set. If width is not explicitly set, the width will be determined by the width of the
1496
         * legend's parent element.
1497
         *
1498
         * @attribute width
1499
         * @type Number
1500
         */
1501
        width: {
1502
            getter: function()
1503
            {
1504
                var chart = this.get("chart"),
1505
                    parentNode = this._parentNode;
1506
                if(parentNode)
1507
                {
1508
                    if((chart && this.get("includeInChartLayout")) || this._width)
1509
                    {
1510
                        if(!this._width)
1511
                        {
1512
                            this._width = 0;
1513
                        }
1514
                        return this._width;
1515
                    }
1516
                    else
1517
                    {
1518
                        return parentNode.get("offsetWidth");
1519
                    }
1520
                }
1521
                return "";
1522
            },
1523
 
1524
            setter: function(val)
1525
            {
1526
                this._width = val;
1527
                return val;
1528
            }
1529
        },
1530
 
1531
        /**
1532
         * The height of the legend. Depending on the implementation of the ChartLegend, this value is `readOnly`.
1533
         * By default, the legend is included in the layout of the `Chart` that it references. Under this circumstance,
1534
         * `height` is always `readOnly`. When the legend is rendered in its own dom element, the `readOnly` status is
1535
         * determined by the direction of the legend. If the `position` is `top` or `bottom` or the `direction` is
1536
         * `horizontal`, height is `readOnly`. If the position is `left` or `right` or the `direction` is `vertical`,
1537
         * height can be explicitly set. If height is not explicitly set, the height will be determined by the width of the
1538
         * legend's parent element.
1539
         *
1540
         * @attribute height
1541
         * @type Number
1542
         */
1543
        height: {
1544
            valueFn: "_heightGetter",
1545
 
1546
            getter: function()
1547
            {
1548
                var chart = this.get("chart"),
1549
                    parentNode = this._parentNode;
1550
                if(parentNode)
1551
                {
1552
                    if((chart && this.get("includeInChartLayout")) || this._height)
1553
                    {
1554
                        if(!this._height)
1555
                        {
1556
                            this._height = 0;
1557
                        }
1558
                        return this._height;
1559
                    }
1560
                    else
1561
                    {
1562
                        return parentNode.get("offsetHeight");
1563
                    }
1564
                }
1565
                return "";
1566
            },
1567
 
1568
            setter: function(val)
1569
            {
1570
                this._height = val;
1571
                return val;
1572
            }
1573
        },
1574
 
1575
        /**
1576
         * Indicates the x position of legend.
1577
         *
1578
         * @attribute x
1579
         * @type Number
1580
         * @readOnly
1581
         */
1582
        x: {
1583
            lazyAdd: false,
1584
 
1585
            value: 0,
1586
 
1587
            setter: function(val)
1588
            {
1589
                var node = this.get("boundingBox");
1590
                if(node)
1591
                {
1592
                    node.setStyle(LEFT, val + PX);
1593
                }
1594
                return val;
1595
            }
1596
        },
1597
 
1598
        /**
1599
         * Indicates the y position of legend.
1600
         *
1601
         * @attribute y
1602
         * @type Number
1603
         * @readOnly
1604
         */
1605
        y: {
1606
            lazyAdd: false,
1607
 
1608
            value: 0,
1609
 
1610
            setter: function(val)
1611
            {
1612
                var node = this.get("boundingBox");
1613
                if(node)
1614
                {
1615
                    node.setStyle(TOP, val + PX);
1616
                }
1617
                return val;
1618
            }
1619
        },
1620
 
1621
        /**
1622
         * Array of items contained in the legend. Each item is an object containing the following properties:
1623
         *
1624
         * <dl>
1625
         *      <dt>node</dt><dd>Node containing text for the legend item.</dd>
1626
         *      <dt>marker</dt><dd>Shape for the legend item.</dd>
1627
         * </dl>
1628
         *
1629
         * @attribute items
1630
         * @type Array
1631
         * @readOnly
1632
         */
1633
        items: {
1634
            getter: function()
1635
            {
1636
                return this._items;
1637
            }
1638
        },
1639
 
1640
        /**
1641
         * Background for the legend.
1642
         *
1643
         * @attribute background
1644
         * @type Rect
1645
         */
1646
        background: {}
1647
 
1648
        /**
1649
         * Properties used to display and style the ChartLegend.  This attribute is inherited from `Renderer`.
1650
         * Below are the default values:
1651
         *
1652
         *  <dl>
1653
         *      <dt>gap</dt><dd>Distance, in pixels, between the `ChartLegend` instance and the chart's content. When `ChartLegend`
1654
         *      is rendered within a `Chart` instance this value is applied.</dd>
1655
         *      <dt>hAlign</dt><dd>Defines the horizontal alignment of the `items` in a `ChartLegend` rendered in a horizontal direction.
1656
         *      This value is applied when the instance's `position` is set to top or bottom. This attribute can be set to left, center
1657
         *      or right. The default value is center.</dd>
1658
         *      <dt>vAlign</dt><dd>Defines the vertical alignment of the `items` in a `ChartLegend` rendered in vertical direction. This
1659
         *      value is applied when the instance's `position` is set to left or right. The attribute can be set to top, middle or
1660
         *      bottom. The default value is middle.</dd>
1661
         *      <dt>item</dt><dd>Set of style properties applied to the `items` of the `ChartLegend`.
1662
         *          <dl>
1663
         *              <dt>hSpacing</dt><dd>Horizontal distance, in pixels, between legend `items`.</dd>
1664
         *              <dt>vSpacing</dt><dd>Vertical distance, in pixels, between legend `items`.</dd>
1665
         *              <dt>label</dt><dd>Properties for the text of an `item`.
1666
         *                  <dl>
1667
         *                      <dt>color</dt><dd>Color of the text. The default values is "#808080".</dd>
1668
         *                      <dt>fontSize</dt><dd>Font size for the text. The default value is "85%".</dd>
1669
         *                  </dl>
1670
         *              </dd>
1671
         *              <dt>marker</dt><dd>Properties for the `item` markers.
1672
         *                  <dl>
1673
         *                      <dt>width</dt><dd>Specifies the width of the markers.</dd>
1674
         *                      <dt>height</dt><dd>Specifies the height of the markers.</dd>
1675
         *                  </dl>
1676
         *              </dd>
1677
         *          </dl>
1678
         *      </dd>
1679
         *      <dt>background</dt><dd>Properties for the `ChartLegend` background.
1680
         *          <dl>
1681
         *              <dt>fill</dt><dd>Properties for the background fill.
1682
         *                  <dl>
1683
         *                      <dt>color</dt><dd>Color for the fill. The default value is "#faf9f2".</dd>
1684
         *                  </dl>
1685
         *              </dd>
1686
         *              <dt>border</dt><dd>Properties for the background border.
1687
         *                  <dl>
1688
         *                      <dt>color</dt><dd>Color for the border. The default value is "#dad8c9".</dd>
1689
         *                      <dt>weight</dt><dd>Weight of the border. The default values is 1.</dd>
1690
         *                  </dl>
1691
         *              </dd>
1692
         *          </dl>
1693
         *      </dd>
1694
         * </dl>
1695
         *
1696
         * @attribute styles
1697
         * @type Object
1698
         */
1699
    }
1700
});
1701
 
1702
 
1703
}, '3.18.1', {"requires": ["charts-base"]});