src/cm/media/js/lib/yui/yui_3.10.3/build/charts-legend/charts-legend.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     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.10.3', {"requires": ["charts-base"]});