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