Ico

Ico is a JavaScript graph library that uses Raphael to draw. This means it can draw charts in multiple browsers (including IE).

Get it at GitHub: alexyoung / ico or view examples.

The API uses a data parameter then an additional option for customisation:

 new Ico.BarGraph(dom_element, data, options);

An array or object can be passed as data:

 new Ico.BarGraph(dom_element, [1, 2, 3, 4], { grid: true });

 new Ico.BarGraph($('dom_element'), {
     shoe_size: [1, 1, 1, 0, 2, 4, 6, 8, 3, 9, 6]
   },
   { colours: {shoe_size: '#990000' },
     grid: true });

base

src/base.js

The Ico.Base object which contains useful generic functions.

Ico.Base = {

Runs this.normalise on each value.

  • param: Array data Values to normalise

  • returns: Array Normalised values

normaliseData: function(data) {
    var values = [],
        i      = 0;
    for (i = 0; i < data.length; i++) {
      values.push(this.normalise(data[i]));
    }
    return values;
  },

Flattens objects into an array.

  • param: Object data Values to flatten

  • returns: Array Flattened values

flatten: function(data) {
    var flat_data = [];

    if (typeof data.length === 'undefined') {
      if (typeof data === 'object') {
        for (var key in data) {
          if (data.hasOwnProperty(key))
            flat_data = flat_data.concat(this.flatten(data[key]));
        }
      } else {
        return [];
      }
    }

    for (var i = 0; i < data.length; i++) {
      if (typeof data[i].length === 'number') {
        flat_data = flat_data.concat(this.flatten(data[i]));
      } else {
        flat_data.push(data[i]);
      }
    }
    return flat_data;
  },

Handy method to produce an array of numbers.

  • param: Integer start A number to start at

  • param: Integer end A number to end at

  • returns: Array An array of values

makeRange: function(start, end) {
    var values = [], i;
    for (i = start; i < end; i++) {
      values.push(i);
    }
    return values;
  }
};

helpers

src/helpers.js

Determines if a value is valid as a 'step' value. Steps are the increments between each bar or line.

  • param: Integer value A number to test

  • returns: Integer A valid step value

function validStepDivider(value) {
  return value > 1 ? value - 1 : 1;
}

Gets a CSS style property.

  • param: Object el A DOM element

  • param: String styleProp The name of a style property

  • returns: Object The style value

function getStyle(el, styleProp) {
  if (typeof window === 'undefined') return;

  var style;
  if (el.currentStyle) {
    style = el.currentStyle[styleProp];
  } else if (window.getComputedStyle) {
    style = document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
  }
  if (style && style.length === 0) {
    style = null;
  }
  return style;
}

var Helpers = {};

Helpers.sum = function(a) {
  for (var i = 0, sum = 0; i < a.length; sum += a[i++]) {}
  return sum;
};

if (typeof Array.prototype.max === 'undefined') {
  Helpers.max = function(a) {
    return Math.max.apply({}, a);
  };
} else {
  Helpers.max = function(a) {
    return a.max();
  };
}

if (typeof Array.prototype.min === 'undefined') {
  Helpers.min = function(a) {
    return Math.min.apply({}, a);
  };
} else {
  Helpers.min = function(a) {
    return a.min();
  };
}

Helpers.mean = function(a) {
  return Helpers.sum(a) / a.length;
};

Helpers.variance = function(a) {
  var mean = Helpers.mean(a),
      variance = 0;
  for (var i = 0; i < a.length; i++) {
    variance += Math.pow(a[i] - mean, 2);
  }
  return variance / (a.length - 1);
};

Helpers.standard_deviation = function(a) {
  return Math.sqrt(Helpers.variance(a));
};

if (typeof Object.extend === 'undefined') {
  Helpers.extend = function(destination, source) {
    for (var property in source) {
      if (source.hasOwnProperty(property)) {
        destination[property] = source[property];
      }
    }
    return destination;
  };
} else {
  Helpers.extend = Object.extend;
}

end

src/end.js

Assign the Ico object as a global property.

global.Ico = Ico;

  if (typeof exports !== 'undefined') {
    module.exports = Ico;
  }
})(typeof window === 'undefined' ? this : window);

normaliser

src/normaliser.js

Normalises lists of values to fit inside a graph.

  • param: Array data A list of values

  • param: Object options Can be used to set the start_value

Ico.Normaliser = function(data, options) {
  this.options = {
    start_value: null
  };

  if (typeof options !== 'undefined') {
    this.options = options;
  }

  this.min = Helpers.min(data);
  this.max = Helpers.max(data);
  this.standard_deviation = Helpers.standard_deviation(data);
  this.range = 0;
  this.step = this.labelStep(this.max - this.min);
  this.start_value = this.calculateStart();
  this.process();
};

Ico.Normaliser.prototype = {

Calculates the start value. This is often 0. ##

  • returns: Float The start value

calculateStart: function() {
    var min = typeof this.options.start_value !== 'undefined' && this.min >= 0 ? this.options.start_value : this.min,
        start_value = this.round(min, 1);

This is a boundary condition

if (this.min > 0 && start_value > this.min) {
      return 0;
    }

    if (this.min === this.max) {
      return 0;
    }

    return start_value;
  },

Given a value, this method rounds it to the nearest good value for an origin

round: function(value, offset) {
    offset = offset || 1;
    var roundedValue = value;

    if (this.standard_deviation > 0.1) {
      var multiplier = Math.pow(10, -offset);
      roundedValue = Math.round(value * multiplier) / multiplier;

      if (roundedValue > this.min) {
        return this.round(value - this.step);
      }
    }
    return roundedValue;
  },

Calculates the range and step values.

process: function() {
    this.range = this.max - this.start_value;
    this.step = this.labelStep(this.range);
  },

Calculates the label step value.

  • param: Float value A value to convert to a label position

  • returns: Float The rounded label step result

labelStep: function(value) {
    return Math.pow(10, Math.round((Math.log(value) / Math.LN10)) - 1);
  }
};


start

src/start.js

The Ico object.

(function(global) {
  var Ico = {
    VERSION: '0.3.2',

Rounds a float to the specified number of decimal places.

  • param: Float num A number to round

  • param: Integer dec The number of decimal places

  • returns: Float The rounded result

round: function(num, dec) {
      var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
      return result;
    }
  };