text: /*
  This file is part of Ext JS 4.2
  
  Copyright (c) 2011-2013 Sencha Inc
  
  Contact:  http://www.sencha.com/contact
  
  Commercial Usage
  Licensees holding valid commercial licenses may use this file in accordance with the Commercial
  Software License Agreement provided with the Software or, alternatively, in accordance with the
  terms contained in a written agreement between you and Sencha.
  
  If you are unsure which license is appropriate for your use, please contact the sales department
  at http://www.sencha.com/contact.
  
  Build date: 2013-09-18 17:18:59 (940c324ac822b840618a3a8b2b4b873f83a1a9b1)
  */
  /**
   * @class Ext.chart.series.Cartesian
   *
   * Common base class for series implementations which plot values using x/y coordinates.
   */
  Ext.define('Ext.chart.series.Cartesian', {
  
      /* Begin Definitions */
  
      extend: 'Ext.chart.series.Series',
  
      alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'],
  
      /* End Definitions */
  
      /**
       * @cfg {String} xField
       * The name of the data Model field corresponding to the x-axis value.
       */
      xField: null,
  
      /**
       * @cfg {String/String[]} yField
       * The name(s) of the data Model field(s) corresponding to the y-axis value(s).
       */
      yField: null,
  
      /**
       * @cfg {String/String[]} axis
       * The position of the axis to bind the values to. Possible values are 'left', 'bottom', 'top' and 'right'.
       * You must explicitly set this value to bind the values of the line series to the ones in the axis, otherwise a
       * relative scale will be used. For example, if you're using a Scatter or Line series and you'd like to have the
       * values in the chart relative to the bottom and left axes then `axis` should be `['left', 'bottom']`.
       */
      axis: 'left',
  
      getLegendLabels: function() {
          var me = this,
              labels = [],
              fields, i, ln,
              combinations = me.combinations,
              title,
              combo, label0, label1;
  
          fields = [].concat(me.yField);
          for (i = 0, ln = fields.length; i < ln; i++) {
              title = me.title;
              // Use the 'title' config if present, otherwise use the raw yField name
              labels.push((Ext.isArray(title) ? title[i] : title) || fields[i]);
          }
  
          // Handle yFields combined via legend drag-drop
          // TODO need to check to see if this is supported in extjs 4 branch
          if (combinations) {
              combinations = Ext.Array.from(combinations);
              for (i = 0, ln = combinations.length; i < ln; i++) {
                  combo = combinations[i];
                  label0 = labels[combo[0]];
                  label1 = labels[combo[1]];
                  labels[combo[1]] = label0 + ' & ' + label1;
                  labels.splice(combo[0], 1);
              }
          }
  
          return labels;
      },
  
      /**
       * @protected Iterates over a given record's values for each of this series's yFields,
       * executing a given function for each value. Any yFields that have been combined
       * via legend drag-drop will be treated as a single value.
       * @param {Ext.data.Model} record
       * @param {Function} fn
       * @param {Object} scope
       */
      eachYValue: function(record, fn, scope) {
          var me = this,
              yValueAccessors = me.getYValueAccessors(),
              i, ln, accessor;
          
          for (i = 0, ln = yValueAccessors.length; i < ln; i++) {
              accessor = yValueAccessors[i];
              fn.call(scope, accessor(record), i);
          }
      },
  
      /**
       * @protected Returns the number of yField values, taking into account fields combined
       * via legend drag-drop.
       * @return {Number}
       */
      getYValueCount: function() {
          return this.getYValueAccessors().length;
      },
  
      combine: function(index1, index2) {
          var me = this,
              accessors = me.getYValueAccessors(),
              accessor1 = accessors[index1],
              accessor2 = accessors[index2];
  
          // Combine the yValue accessors for the two indexes into a single accessor that returns their sum
          accessors[index2] = function(record) {
              return accessor1(record) + accessor2(record);
          };
          accessors.splice(index1, 1);
  
          me.callParent([index1, index2]);
      },
  
      clearCombinations: function() {
          // Clear combined accessors, they'll get regenerated on next call to getYValueAccessors
          delete this.yValueAccessors;
          this.callParent();
      },
  
      /**
       * @protected Returns an array of functions, each of which returns the value of the yField
       * corresponding to function's index in the array, for a given record (each function takes the
       * record as its only argument.) If yFields have been combined by the user via legend drag-drop,
       * this list of accessors will be kept in sync with those combinations.
       * @return {Array} array of accessor functions
       */
      getYValueAccessors: function() {
          var me = this,
              accessors = me.yValueAccessors,
              yFields, i, ln;
  
          function getFieldAccessor(field) {
              return function(record) {
                  return record.get(field);
              }
          }
  
          if (!accessors) {
              accessors = me.yValueAccessors = [];
              yFields = [].concat(me.yField);
              for (i = 0, ln = yFields.length; i < ln; i++) {
                  accessors.push(getFieldAccessor(yFields[i]));
              }
          }
          return accessors;
      },
  
      /**
       * Calculate the min and max values for this series's xField.
       * @return {Array} [min, max]
       */
      getMinMaxXValues: function() {
          var me = this,
              chart = me.chart,
              store = chart.getChartStore(),
              data = store.data.items,
              count = me.getRecordCount(),
              i, ln, record,
              min, max,
              xField = me.xField,
              xValue;
  
          if (count > 0) {
              min = Infinity;
              max = -min;
                  
              for (i = 0, ln = data.length; i < ln; i++) {
                  record = data[i];
                  xValue = record.get(xField);
                  if (xValue > max) {
                      max = xValue;
                  }
                  if (xValue < min) {
                      min = xValue;
                  }
              }
              
              // If we made no progress, treat it like a category axis
              if (min == Infinity) {
                  min = 0;
              }
              
              if (max == -Infinity) {
                  max = count - 1;
              }
          } else {
              min = max = 0;
          }
          return [min, max];
      },
  
      /**
       * Calculate the min and max values for this series's yField(s). Takes into account yField
       * combinations, exclusions, and stacking.
       * @return {Array} [min, max]
       */
      getMinMaxYValues: function() {
          var me = this,
              chart = me.chart,
              store = chart.getChartStore(),
              data = store.data.items,
              count = me.getRecordCount(),
              i, ln, record,
              stacked = me.stacked,
              min, max,
              positiveTotal, negativeTotal;
  
          function eachYValueStacked(yValue, i) {
              if (!me.isExcluded(i)) {
                  if (yValue < 0) {
                      negativeTotal += yValue;
                  } else {
                      positiveTotal += yValue;
                  }
              }
          }
  
          function eachYValue(yValue, i) {
              if (!me.isExcluded(i)) {
                  if (yValue > max) {
                      max = yValue;
                  }
                  if (yValue < min) {
                      min = yValue;
                  }
              }
          }
  
          if (count > 0) {
              min = Infinity;
              max = -min;
              
              for (i = 0, ln = data.length; i < ln; i++) {
                  record = data[i];
                  if (stacked) {
                      positiveTotal = 0;
                      negativeTotal = 0;
                      me.eachYValue(record, eachYValueStacked);
                      if (positiveTotal > max) {
                          max = positiveTotal;
                      }
                      if (negativeTotal < min) {
                          min = negativeTotal;
                      }
                  } else {
                      me.eachYValue(record, eachYValue);
                  }
              }
              
              // If we made no progress, treat it like a category axis
              if (min == Infinity) {
                  min = 0;
              }
              
              if (max == -Infinity) {
                  max = count - 1;
              }
          } else {
              min = max = 0;
          }
          return [min, max];
      },
  
      getAxesForXAndYFields: function() {
          var me = this,
              axes = me.chart.axes,
              reverse = me.reverse,
              axis = [].concat(me.axis),
              yFields = {}, yFieldList = [].concat(me.yField),
              xFields = {}, xFieldList = [].concat(me.xField),
              fields, xAxis, yAxis, i, ln, flipXY;
  
          
          flipXY = me.type === 'bar' && me.column === false;
          if(flipXY) {
              fields = yFieldList;
              yFieldList = xFieldList;
              xFieldList = fields;
          }
          if (Ext.Array.indexOf(axis, 'top') > -1) {
              xAxis = 'top';
          } else if (Ext.Array.indexOf(axis, 'bottom') > -1) {
              xAxis = 'bottom';
          } else {
              if (axes.get('top') && axes.get('bottom')) {
                  for (i = 0, ln = xFieldList.length; i < ln; i++) {
                      xFields[xFieldList[i]] = true;
                  }
                  fields = [].concat(axes.get('bottom').fields);
                  for (i = 0, ln = fields.length; i < ln; i++) {
                      if (xFields[fields[i]]) {
                          xAxis = 'bottom';
                          break;
                      }
                  }
                  fields = [].concat(axes.get('top').fields);
                  for (i = 0, ln = fields.length; i < ln; i++) {
                      if (xFields[fields[i]]) {
                          xAxis = 'top';
                          break;
                      }
                  }
              } else if (axes.get('top')) {
                  xAxis = 'top';
              } else if (axes.get('bottom')) {
                  xAxis = 'bottom';
              }
          }
          
          if (Ext.Array.indexOf(axis, 'left') > -1) {
              yAxis = flipXY ? 'right' : 'left';
          } else if (Ext.Array.indexOf(axis, 'right') > -1) {
              yAxis = flipXY ? 'left' : 'right';
          } else {
              if (axes.get('left') && axes.get('right')) {
                  for (i = 0, ln = yFieldList.length; i < ln; i++) {
                      yFields[yFieldList[i]] = true;
                  }
                  fields = [].concat(axes.get('right').fields);
                  for (i = 0, ln = fields.length; i < ln; i++) {
                      if (yFields[fields[i]]) {
                          break;
                      }
                  }
                  fields = [].concat(axes.get('left').fields);
                  for (i = 0, ln = fields.length; i < ln; i++) {
                      if (yFields[fields[i]]) {
                          yAxis = 'left';
                          break;
                      }
                  }
              } else if (axes.get('left')) {
                  yAxis = 'left';
              } else if (axes.get('right')) {
                  yAxis = 'right';
              }
          }
  
          return flipXY ? {
              xAxis: yAxis,
              yAxis: xAxis
          }: {
              xAxis: xAxis,
              yAxis: yAxis
          };
      }
  
  
  });
  