src/cm/media/js/lib/yui/yui3-3.15.0/build/series-fill-util/series-fill-util-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('series-fill-util', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4  * Provides functionality for drawing fills in a series.
       
     5  *
       
     6  * @module charts
       
     7  * @submodule series-fill-util
       
     8  */
       
     9 var Y_Lang = Y.Lang;
       
    10 
       
    11 /**
       
    12  * Utility class used for drawing area fills.
       
    13  *
       
    14  * @class Fills
       
    15  * @constructor
       
    16  * @submodule series-fill-util
       
    17  */
       
    18 function Fills() {}
       
    19 
       
    20 Fills.ATTRS = {
       
    21     area: {
       
    22         getter: function()
       
    23         {
       
    24             return this._defaults || this._getAreaDefaults();
       
    25         },
       
    26 
       
    27         setter: function(val)
       
    28         {
       
    29             var defaults = this._defaults || this._getAreaDefaults();
       
    30             this._defaults = Y.merge(defaults, val);
       
    31         }
       
    32     }
       
    33 };
       
    34 
       
    35 Fills.prototype = {
       
    36     /**
       
    37      * Returns a path shape used for drawing fills.
       
    38      *
       
    39      * @method _getPath
       
    40      * @return Path
       
    41      * @private
       
    42      */
       
    43     _getPath: function()
       
    44     {
       
    45         var path = this._path;
       
    46         if(!path)
       
    47         {
       
    48             path = this.get("graphic").addShape({type:"path"});
       
    49             this._path = path;
       
    50         }
       
    51         return path;
       
    52     },
       
    53 
       
    54     /**
       
    55      * Toggles visibility
       
    56      *
       
    57      * @method _toggleVisible
       
    58      * @param {Boolean} visible indicates visibilitye
       
    59      * @private
       
    60      */
       
    61     _toggleVisible: function(visible)
       
    62     {
       
    63         if(this._path)
       
    64         {
       
    65             this._path.set("visible", visible);
       
    66         }
       
    67     },
       
    68 
       
    69     /**
       
    70      * Draws fill
       
    71      *
       
    72      * @method drawFill
       
    73      * @param {Array} xcoords The x-coordinates for the series.
       
    74      * @param {Array} ycoords The y-coordinates for the series.
       
    75      * @protected
       
    76      */
       
    77     drawFill: function(xcoords, ycoords)
       
    78     {
       
    79         if(xcoords.length < 1)
       
    80         {
       
    81             return;
       
    82         }
       
    83         var isNumber = Y_Lang.isNumber,
       
    84             len = xcoords.length,
       
    85             firstX = xcoords[0],
       
    86             firstY = ycoords[0],
       
    87             lastValidX = firstX,
       
    88             lastValidY = firstY,
       
    89             nextX,
       
    90             nextY,
       
    91             pointValid,
       
    92             noPointsRendered = true,
       
    93             i = 0,
       
    94             styles = this.get("styles").area,
       
    95             path = this._getPath(),
       
    96             color = styles.color || this._getDefaultColor(this.get("graphOrder"), "slice");
       
    97         path.clear();
       
    98         path.set("fill", {
       
    99             color: color,
       
   100             opacity: styles.alpha
       
   101         });
       
   102         path.set("stroke", {weight: 0});
       
   103         for(; i < len; i = ++i)
       
   104         {
       
   105             nextX = xcoords[i];
       
   106             nextY = ycoords[i];
       
   107             pointValid = isNumber(nextX) && isNumber(nextY);
       
   108             if(!pointValid)
       
   109             {
       
   110                 continue;
       
   111             }
       
   112             if(noPointsRendered)
       
   113             {
       
   114                 this._firstValidX = nextX;
       
   115                 this._firstValidY = nextY;
       
   116                 noPointsRendered = false;
       
   117                 path.moveTo(nextX, nextY);
       
   118             }
       
   119             else
       
   120             {
       
   121                 path.lineTo(nextX, nextY);
       
   122             }
       
   123             lastValidX = nextX;
       
   124             lastValidY = nextY;
       
   125         }
       
   126         this._lastValidX = lastValidX;
       
   127         this._lastValidY = lastValidY;
       
   128         path.end();
       
   129     },
       
   130 
       
   131     /**
       
   132      * Draws a fill for a spline
       
   133      *
       
   134      * @method drawAreaSpline
       
   135      * @protected
       
   136      */
       
   137     drawAreaSpline: function()
       
   138     {
       
   139         if(this.get("xcoords").length < 1)
       
   140         {
       
   141             return;
       
   142         }
       
   143         var xcoords = this.get("xcoords"),
       
   144             ycoords = this.get("ycoords"),
       
   145             curvecoords = this.getCurveControlPoints(xcoords, ycoords),
       
   146             len = curvecoords.length,
       
   147             cx1,
       
   148             cx2,
       
   149             cy1,
       
   150             cy2,
       
   151             x,
       
   152             y,
       
   153             i = 0,
       
   154             firstX = xcoords[0],
       
   155             firstY = ycoords[0],
       
   156             styles = this.get("styles").area,
       
   157             path = this._getPath(),
       
   158             color = styles.color || this._getDefaultColor(this.get("graphOrder"), "slice");
       
   159         path.set("fill", {
       
   160             color: color,
       
   161             opacity: styles.alpha
       
   162         });
       
   163         path.set("stroke", {weight: 0});
       
   164         path.moveTo(firstX, firstY);
       
   165         for(; i < len; i = ++i)
       
   166         {
       
   167             x = curvecoords[i].endx;
       
   168             y = curvecoords[i].endy;
       
   169             cx1 = curvecoords[i].ctrlx1;
       
   170             cx2 = curvecoords[i].ctrlx2;
       
   171             cy1 = curvecoords[i].ctrly1;
       
   172             cy2 = curvecoords[i].ctrly2;
       
   173             path.curveTo(cx1, cy1, cx2, cy2, x, y);
       
   174         }
       
   175         if(this.get("direction") === "vertical")
       
   176         {
       
   177             path.lineTo(this._leftOrigin, y);
       
   178             path.lineTo(this._leftOrigin, firstY);
       
   179         }
       
   180         else
       
   181         {
       
   182             path.lineTo(x, this._bottomOrigin);
       
   183             path.lineTo(firstX, this._bottomOrigin);
       
   184         }
       
   185         path.lineTo(firstX, firstY);
       
   186         path.end();
       
   187     },
       
   188 
       
   189     /**
       
   190      * Draws a a stacked area spline
       
   191      *
       
   192      * @method drawStackedAreaSpline
       
   193      * @protected
       
   194      */
       
   195     drawStackedAreaSpline: function()
       
   196     {
       
   197         if(this.get("xcoords").length < 1)
       
   198         {
       
   199             return;
       
   200         }
       
   201         var xcoords = this.get("xcoords"),
       
   202             ycoords = this.get("ycoords"),
       
   203             curvecoords,
       
   204             order = this.get("order"),
       
   205             seriesCollection = this.get("seriesTypeCollection"),
       
   206             prevXCoords,
       
   207             prevYCoords,
       
   208             len,
       
   209             cx1,
       
   210             cx2,
       
   211             cy1,
       
   212             cy2,
       
   213             x,
       
   214             y,
       
   215             i = 0,
       
   216             firstX,
       
   217             firstY,
       
   218             styles = this.get("styles").area,
       
   219             path = this._getPath(),
       
   220             color = styles.color || this._getDefaultColor(this.get("graphOrder"), "slice");
       
   221         firstX = xcoords[0];
       
   222         firstY = ycoords[0];
       
   223         curvecoords = this.getCurveControlPoints(xcoords, ycoords);
       
   224         len = curvecoords.length;
       
   225         path.set("fill", {
       
   226             color: color,
       
   227             opacity: styles.alpha
       
   228         });
       
   229         path.set("stroke", {weight: 0});
       
   230         path.moveTo(firstX, firstY);
       
   231         for(; i < len; i = ++i)
       
   232         {
       
   233             x = curvecoords[i].endx;
       
   234             y = curvecoords[i].endy;
       
   235             cx1 = curvecoords[i].ctrlx1;
       
   236             cx2 = curvecoords[i].ctrlx2;
       
   237             cy1 = curvecoords[i].ctrly1;
       
   238             cy2 = curvecoords[i].ctrly2;
       
   239             path.curveTo(cx1, cy1, cx2, cy2, x, y);
       
   240         }
       
   241         if(order > 0)
       
   242         {
       
   243             prevXCoords = seriesCollection[order - 1].get("xcoords").concat().reverse();
       
   244             prevYCoords = seriesCollection[order - 1].get("ycoords").concat().reverse();
       
   245             curvecoords = this.getCurveControlPoints(prevXCoords, prevYCoords);
       
   246             i = 0;
       
   247             len = curvecoords.length;
       
   248             path.lineTo(prevXCoords[0], prevYCoords[0]);
       
   249             for(; i < len; i = ++i)
       
   250             {
       
   251                 x = curvecoords[i].endx;
       
   252                 y = curvecoords[i].endy;
       
   253                 cx1 = curvecoords[i].ctrlx1;
       
   254                 cx2 = curvecoords[i].ctrlx2;
       
   255                 cy1 = curvecoords[i].ctrly1;
       
   256                 cy2 = curvecoords[i].ctrly2;
       
   257                 path.curveTo(cx1, cy1, cx2, cy2, x, y);
       
   258             }
       
   259         }
       
   260         else
       
   261         {
       
   262             if(this.get("direction") === "vertical")
       
   263             {
       
   264                 path.lineTo(this._leftOrigin, ycoords[ycoords.length-1]);
       
   265                 path.lineTo(this._leftOrigin, firstY);
       
   266             }
       
   267             else
       
   268             {
       
   269                 path.lineTo(xcoords[xcoords.length-1], this._bottomOrigin);
       
   270                 path.lineTo(firstX, this._bottomOrigin);
       
   271             }
       
   272 
       
   273         }
       
   274         path.lineTo(firstX, firstY);
       
   275         path.end();
       
   276     },
       
   277 
       
   278     /**
       
   279      * Storage for default area styles.
       
   280      *
       
   281      * @property _defaults
       
   282      * @type Object
       
   283      * @private
       
   284      */
       
   285     _defaults: null,
       
   286 
       
   287     /**
       
   288      * Concatenates coordinate array with correct coordinates for closing an area fill.
       
   289      *
       
   290      * @method _getClosingPoints
       
   291      * @return Array
       
   292      * @protected
       
   293      */
       
   294     _getClosingPoints: function()
       
   295     {
       
   296         var xcoords = this.get("xcoords").concat(),
       
   297             ycoords = this.get("ycoords").concat(),
       
   298             firstValidIndex,
       
   299             lastValidIndex;
       
   300         if(this.get("direction") === "vertical")
       
   301         {
       
   302             lastValidIndex = this._getLastValidIndex(xcoords);
       
   303             firstValidIndex = this._getFirstValidIndex(xcoords);
       
   304             ycoords.push(ycoords[lastValidIndex]);
       
   305             ycoords.push(ycoords[firstValidIndex]);
       
   306             xcoords.push(this._leftOrigin);
       
   307             xcoords.push(this._leftOrigin);
       
   308         }
       
   309         else
       
   310         {
       
   311             lastValidIndex = this._getLastValidIndex(ycoords);
       
   312             firstValidIndex = this._getFirstValidIndex(ycoords);
       
   313             xcoords.push(xcoords[lastValidIndex]);
       
   314             xcoords.push(xcoords[firstValidIndex]);
       
   315             ycoords.push(this._bottomOrigin);
       
   316             ycoords.push(this._bottomOrigin);
       
   317         }
       
   318         xcoords.push(xcoords[0]);
       
   319         ycoords.push(ycoords[0]);
       
   320         return [xcoords, ycoords];
       
   321     },
       
   322 
       
   323     /**
       
   324      * Returns the order of the series closest to the current series that has a valid value for the current index.
       
   325      *
       
   326      * @method _getHighestValidOrder
       
   327      * @param {Array} seriesCollection Array of series of a given type.
       
   328      * @param {Number} index Index of the series item.
       
   329      * @param {Number} order Index of the the series in the seriesCollection
       
   330      * @param {String} direction Indicates the direction of the series
       
   331      * @return Number
       
   332      * @private
       
   333      */
       
   334     _getHighestValidOrder: function(seriesCollection, index, order, direction)
       
   335     {
       
   336         var coords = direction === "vertical" ? "stackedXCoords" : "stackedYCoords",
       
   337             coord;
       
   338         while(isNaN(coord) && order > -1)
       
   339         {
       
   340           order = order - 1;
       
   341           if(order > -1)
       
   342           {
       
   343             coord = seriesCollection[order].get(coords)[index];
       
   344           }
       
   345         }
       
   346         return order;
       
   347     },
       
   348 
       
   349     /**
       
   350      * Returns an array containing the x and y coordinates for a given series and index.
       
   351      *
       
   352      * @method _getCoordsByOrderAndIndex
       
   353      * @param {Array} seriesCollection Array of series of a given type.
       
   354      * @param {Number} index Index of the series item.
       
   355      * @param {Number} order Index of the the series in the seriesCollection
       
   356      * @param {String} direction Indicates the direction of the series
       
   357      * @return Array
       
   358      * @private
       
   359      */
       
   360     _getCoordsByOrderAndIndex: function(seriesCollection, index, order, direction)
       
   361     {
       
   362         var xcoord,
       
   363             ycoord;
       
   364         if(direction === "vertical")
       
   365         {
       
   366             xcoord = order < 0 ? this._leftOrigin : seriesCollection[order].get("stackedXCoords")[index];
       
   367             ycoord = this.get("stackedYCoords")[index];
       
   368         }
       
   369         else
       
   370         {
       
   371             xcoord = this.get("stackedXCoords")[index];
       
   372             ycoord = order < 0 ? this._bottomOrigin : seriesCollection[order].get("stackedYCoords")[index];
       
   373         }
       
   374         return [xcoord, ycoord];
       
   375     },
       
   376 
       
   377     /**
       
   378      * Concatenates coordinate array with the correct coordinates for closing an area stack.
       
   379      *
       
   380      * @method _getStackedClosingPoints
       
   381      * @return Array
       
   382      * @protected
       
   383      */
       
   384     _getStackedClosingPoints: function()
       
   385     {
       
   386         var order = this.get("order"),
       
   387             direction = this.get("direction"),
       
   388             seriesCollection = this.get("seriesTypeCollection"),
       
   389             firstValidIndex,
       
   390             lastValidIndex,
       
   391             xcoords = this.get("stackedXCoords"),
       
   392             ycoords = this.get("stackedYCoords"),
       
   393             limit,
       
   394             previousSeries,
       
   395             previousSeriesFirstValidIndex,
       
   396             previousSeriesLastValidIndex,
       
   397             previousXCoords,
       
   398             previousYCoords,
       
   399             coords,
       
   400             closingXCoords,
       
   401             closingYCoords,
       
   402             currentIndex,
       
   403             highestValidOrder,
       
   404             oldOrder;
       
   405         if(order < 1)
       
   406         {
       
   407           return this._getClosingPoints();
       
   408         }
       
   409 
       
   410         previousSeries = seriesCollection[order - 1];
       
   411         previousXCoords = previousSeries.get("stackedXCoords").concat();
       
   412         previousYCoords = previousSeries.get("stackedYCoords").concat();
       
   413         if(direction === "vertical")
       
   414         {
       
   415             firstValidIndex = this._getFirstValidIndex(xcoords);
       
   416             lastValidIndex = this._getLastValidIndex(xcoords);
       
   417             previousSeriesFirstValidIndex = previousSeries._getFirstValidIndex(previousXCoords);
       
   418             previousSeriesLastValidIndex = previousSeries._getLastValidIndex(previousXCoords);
       
   419         }
       
   420         else
       
   421         {
       
   422             firstValidIndex = this._getFirstValidIndex(ycoords);
       
   423             lastValidIndex = this._getLastValidIndex(ycoords);
       
   424             previousSeriesFirstValidIndex = previousSeries._getFirstValidIndex(previousYCoords);
       
   425             previousSeriesLastValidIndex = previousSeries._getLastValidIndex(previousYCoords);
       
   426         }
       
   427         if(previousSeriesLastValidIndex >= firstValidIndex && previousSeriesFirstValidIndex <= lastValidIndex)
       
   428         {
       
   429             previousSeriesFirstValidIndex = Math.max(firstValidIndex, previousSeriesFirstValidIndex);
       
   430             previousSeriesLastValidIndex = Math.min(lastValidIndex, previousSeriesLastValidIndex);
       
   431             previousXCoords = previousXCoords.slice(previousSeriesFirstValidIndex, previousSeriesLastValidIndex + 1);
       
   432             previousYCoords = previousYCoords.slice(previousSeriesFirstValidIndex, previousSeriesLastValidIndex + 1);
       
   433             limit = previousSeriesFirstValidIndex;
       
   434         }
       
   435         else
       
   436         {
       
   437             limit = lastValidIndex;
       
   438         }
       
   439 
       
   440         closingXCoords = [xcoords[firstValidIndex]];
       
   441         closingYCoords = [ycoords[firstValidIndex]];
       
   442         currentIndex = firstValidIndex;
       
   443         while((isNaN(highestValidOrder) || highestValidOrder < order - 1) && currentIndex <= limit)
       
   444         {
       
   445             oldOrder = highestValidOrder;
       
   446             highestValidOrder = this._getHighestValidOrder(seriesCollection, currentIndex, order, direction);
       
   447             if(!isNaN(oldOrder) && highestValidOrder > oldOrder)
       
   448             {
       
   449                 coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, oldOrder, direction);
       
   450                 closingXCoords.push(coords[0]);
       
   451                 closingYCoords.push(coords[1]);
       
   452             }
       
   453             coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, highestValidOrder, direction);
       
   454             closingXCoords.push(coords[0]);
       
   455             closingYCoords.push(coords[1]);
       
   456             currentIndex = currentIndex + 1;
       
   457         }
       
   458         if(previousXCoords &&
       
   459             previousXCoords.length > 0 &&
       
   460             previousSeriesLastValidIndex > firstValidIndex &&
       
   461             previousSeriesFirstValidIndex < lastValidIndex)
       
   462         {
       
   463             closingXCoords = closingXCoords.concat(previousXCoords);
       
   464             closingYCoords = closingYCoords.concat(previousYCoords);
       
   465             highestValidOrder = order -1;
       
   466         }
       
   467         currentIndex = Math.max(firstValidIndex, previousSeriesLastValidIndex);
       
   468         order = order - 1;
       
   469         highestValidOrder = NaN;
       
   470         while(currentIndex <= lastValidIndex)
       
   471         {
       
   472             oldOrder = highestValidOrder;
       
   473             highestValidOrder = this._getHighestValidOrder(seriesCollection, currentIndex, order, direction);
       
   474             if(!isNaN(oldOrder))
       
   475             {
       
   476                 if(highestValidOrder > oldOrder)
       
   477                 {
       
   478                     coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, oldOrder, direction);
       
   479                     closingXCoords.push(coords[0]);
       
   480                     closingYCoords.push(coords[1]);
       
   481                 }
       
   482                 else if(highestValidOrder < oldOrder)
       
   483                 {
       
   484                     coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex - 1, highestValidOrder, direction);
       
   485                     closingXCoords.push(coords[0]);
       
   486                     closingYCoords.push(coords[1]);
       
   487                 }
       
   488             }
       
   489             coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, highestValidOrder, direction);
       
   490             closingXCoords.push(coords[0]);
       
   491             closingYCoords.push(coords[1]);
       
   492             currentIndex = currentIndex + 1;
       
   493         }
       
   494 
       
   495         closingXCoords.reverse();
       
   496         closingYCoords.reverse();
       
   497         return [xcoords.concat(closingXCoords), ycoords.concat(closingYCoords)];
       
   498     },
       
   499 
       
   500     /**
       
   501      * Returns default values for area styles.
       
   502      *
       
   503      * @method _getAreaDefaults
       
   504      * @return Object
       
   505      * @private
       
   506      */
       
   507     _getAreaDefaults: function()
       
   508     {
       
   509         return {
       
   510         };
       
   511     }
       
   512 };
       
   513 Y.augment(Fills, Y.Attribute);
       
   514 Y.Fills = Fills;
       
   515 
       
   516 
       
   517 }, '@VERSION@');