~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/yuilib/3.13.0/charts-legend/charts-legend-debug.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

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