Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

???

  • Loading branch information...
commit a9280d2e7499c0738006ef1c76e375e3b17a5e10 1 parent b7bc440
@gka authored
View
2  dist/LASTBUILD
@@ -1 +1 @@
-2012/05/23 11:14
+2012/06/19 02:22
View
239 dist/miso.ds.0.1.3.js
@@ -1,5 +1,5 @@
/**
-* Miso.Dataset - v0.1.3 - 5/23/2012
+* Miso.Dataset - v0.1.3 - 6/19/2012
* http://github.com/misoproject/dataset
* Copyright (c) 2012 Alex Graul, Irene Ros;
* Dual Licensed: MIT, GPL
@@ -96,11 +96,39 @@
}
},
- number : {
+ number : {
name : "number",
+ regexp : /^[\-]?[0-9]+$/,
+ coerce : function(v) {
+ if (_.isNull(v)) {
+ return null;
+ }
+ return _.isNaN(v) ? null : +v;
+ },
+ test : function(v, gracious) {
+ if (v === null || typeof v === "undefined" || typeof v === 'number' || this.regexp.test( v ) || (gracious && (Miso.types['number-decimal-point'].test(v) || Miso.types['number-decimal-comma'].test(v) ))) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ compare : function(n1, n2) {
+ if (n1 == null && n2 != null) { return -1; }
+ if (n1 != null && n2 == null) { return 1; }
+ if (n1 == null && n2 == null) { return 0; }
+ if (n1 === n2) { return 0; }
+ return (n1 < n2 ? -1 : 1);
+ },
+ numeric : function(value) {
+ return value;
+ }
+ },
+
+ 'number-decimal-point' : {
+ name : "number-decimal-point",
regexp : /^[\-\.]?[0-9]+([\.][0-9]+)?$/,
coerce : function(v) {
- if (_.isNull(v) || v === "") {
+ if (_.isNull(v)) {
return null;
}
return _.isNaN(v) ? null : +v;
@@ -124,6 +152,34 @@
}
},
+ 'number-decimal-comma' : {
+ name : "number-decimal-comma",
+ regexp : /^[\-,]?[0-9]+([,][0-9]+)?$/,
+ coerce : function(v) {
+ if (_.isNull(v)) {
+ return null;
+ }
+ return _.isNaN(v) ? null : +String(v).replace(',', '.');
+ },
+ test : function(v) {
+ if (v === null || typeof v === "undefined" || typeof v === 'number' || this.regexp.test( v ) ) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ compare : function(n1, n2) {
+ if (n1 == null && n2 != null) { return -1; }
+ if (n1 != null && n2 == null) { return 1; }
+ if (n1 == null && n2 == null) { return 0; }
+ if (n1 === n2) { return 0; }
+ return (n1 < n2 ? -1 : 1);
+ },
+ numeric : function(value) {
+ return value;
+ }
+ },
+
time : {
name : "time",
format : "DD/MM/YYYY",
@@ -401,8 +457,14 @@
if (type.length === 1) {
column.type = type[0];
} else {
- //empty column or mixed type
- column.type = 'mixed';
+ type.sort();
+ if (type.length === 2 && type[0] === 'number' && type[1].substr(0,6) === 'number') {
+ // number column in local format
+ column.type = type[1];
+ } else {
+ //empty column or mixed type
+ column.type = 'mixed';
+ }
}
return column;
@@ -889,7 +951,7 @@
* iterator - function that is passed each row
* iterator(rowObject, index, dataset)
* context - options object. Optional.
- */
+ */
each : function(iterator, context) {
for(var i = 0; i < this.length; i++) {
iterator.apply(context || this, [this.rowByPosition(i), i]);
@@ -897,6 +959,19 @@
},
/**
+ * Iterates over all rows in the dataset in reverse order
+ * Parameters:
+ * iterator - function that is passed each row
+ * iterator(rowObject, index, dataset)
+ * context - options object. Optional.
+ */
+ reverseEach : function(iterator, context) {
+ for(var i = this.length-1; i >= 0; i--) {
+ iterator.apply(context || this, [this.rowByPosition(i), i]);
+ }
+ },
+
+ /**
* Iterates over each column.
* Parameters:
* iterator - function that is passed:
@@ -968,7 +1043,7 @@
var Type = Miso.types[column.type];
// test if value matches column type
- if (column.force || Type.test(row[column.name], column)) {
+ if (column.force || Type.test(row[column.name], true)) {
// do we have a before filter? If so, pass it through that first
if (!_.isUndefined(column.before)) {
@@ -1061,8 +1136,15 @@
* Parameters:
* options - Optional
*/
- sort : function(options) {
- options = options || {};
+ sort : function(args) {
+ var options = {};
+
+ //If the first param is the comparator, set it as such.
+ if ( _.isFunction(args) ) {
+ options.comparator = args;
+ } else {
+ options = args || options;
+ }
if (options.comparator) {
this.comparator = options.comparator;
@@ -1594,13 +1676,14 @@ Version 0.0.1.2
// implementation, pass it as an option
if (options.deferred) {
this.deferred = options.deferred;
+ } else {
+ this.deferred = new _.Deferred();
}
//build any columns present in the constructor
if ( options.columns ) {
this.addColumns(options.columns);
}
-
},
/**
@@ -1631,7 +1714,7 @@ Version 0.0.1.2
fetch : function(options) {
options = options || {};
- var dfd = this.deferred || new _.Deferred();
+ var dfd = this.deferred;
if ( _.isNull(this.importer) ) {
throw "No importer defined";
@@ -1640,7 +1723,15 @@ Version 0.0.1.2
this.importer.fetch({
success: _.bind(function( data ) {
- this._apply( data );
+ try {
+ this._apply( data );
+ } catch (e) {
+ if (options.error) {
+ options.error.call(this, e);
+ } else {
+ throw e;
+ }
+ }
// if a comparator was defined, sort the data
if (this.comparator) {
@@ -1662,7 +1753,7 @@ Version 0.0.1.2
error : _.bind(function(e) {
if (options.error) {
- options.error.call(this);
+ options.error.call(this, e);
}
dfd.reject(e);
@@ -2436,7 +2527,8 @@ Version 0.0.1.2
this.params = {
type : "GET",
url : _.isFunction(this._url) ? _.bind(this._url, this) : this._url,
- dataType : options.dataType ? options.dataType : (options.jsonp ? "jsonp" : "json")
+ dataType : options.dataType ? options.dataType : (options.jsonp ? "jsonp" : "json"),
+ callback : options.callback
};
};
@@ -2491,7 +2583,8 @@ Version 0.0.1.2
url,
options.success,
options.dataType === "script",
- options.error
+ options.error,
+ options.callback
);
return;
@@ -2519,7 +2612,7 @@ Version 0.0.1.2
}
};
- Miso.Xhr.getJSONP = function(url, success, isScript, error) {
+ Miso.Xhr.getJSONP = function(url, success, isScript, error, callback) {
// If this is a script request, ensure that we do not
// call something that has already been loaded
if (isScript) {
@@ -2546,7 +2639,7 @@ Version 0.0.1.2
paramStr = url.split("?")[ 1 ],
isFired = false,
params = [],
- callback, parts, callparam;
+ parts;
// Extract params
if (paramStr && !isScript) {
@@ -2555,10 +2648,18 @@ Version 0.0.1.2
if (params.length) {
parts = params[params.length - 1].split("=");
}
- callback = params.length ? (parts[ 1 ] ? parts[ 1 ] : parts[ 0 ]) : "jsonp";
+ if (!callback) {
+ var fallback = _.uniqueId('callback');
+ callback = params.length ? (parts[ 1 ] ? parts[ 1 ] : fallback) : fallback;
+ }
if (!paramStr && !isScript) {
- url += "?callback=" + callback;
+ url += "?";
+ }
+
+ if ( !paramStr || !/callback/.test(paramStr) ) {
+ if (paramStr) { url += '&'; }
+ url += "callback=" + callback;
}
if (callback && !isScript) {
@@ -2577,7 +2678,9 @@ Version 0.0.1.2
};
// Replace callback param and callback name
- url = url.replace(parts.join("="), parts[0] + "=" + callback);
+ if (parts) {
+ url = url.replace(parts.join("="), parts[0] + "=" + callback);
+ }
}
script.onload = script.onreadystatechange = function() {
@@ -2610,7 +2713,7 @@ Version 0.0.1.2
script.onerror = function(e) {
if (error) {
- error.call(null);
+ error.call(null, e);
}
};
@@ -2773,19 +2876,16 @@ Version 0.0.1.2
options.url = "https://spreadsheets.google.com/tq?key=" + options.key;
- if (options.sheetName) {
- options.url += "&sheet=" + options.sheetName;
- } else {
- options.url += "&gid=" + (options.worksheet || 1);
- delete options.worksheet;
- }
+ if (typeof options.sheetName === "undefined") {
+ options.sheetName = "Sheet1";
+ }
+ options.url += "&sheet=" + options.sheetName;
this.callback = "misodsgs" + new Date().getTime();
options.url += "&tqx=version:0.6;responseHandler:" + this.callback;
options.url += ";reqId:0;out:json&tq&_=1335871249558#";
delete options.sheetName;
-
} else {
options.url = "https://spreadsheets.google.com/feeds/cells/" +
options.key + "/" +
@@ -2797,6 +2897,7 @@ Version 0.0.1.2
}
}
+
this.params = {
type : "GET",
url : options.url,
@@ -2854,8 +2955,12 @@ Version 0.0.1.2
var columnData = {}, columnNames = [];
_.each(data.columns, function(column) {
- columnNames.push( column.name );
- columnData[ column.name ] = column.data;
+ if (columnNames.indexOf(column.name) !== -1) {
+ throw new Error("You have more than one column named \"" + column.name + "\"");
+ } else {
+ columnNames.push( column.name );
+ columnData[ column.name ] = column.data;
+ }
});
return {
@@ -2931,11 +3036,32 @@ Version 0.0.1.2
keyedData = {},
i;
+ // the fast importer API is not available
+ if (typeof data.status !== "undefined" && data.status === "error") {
+ throw new Error("You can't use the fast importer for this url. Disable the fast flag");
+ }
+
if (this.fast) {
// init column names
columns = _.pluck(data.table.cols, "label");
+ // check that the column names don't have duplicates
+ if (_.unique(columns).length < columns.length) {
+ var dup = "";
+
+ _.inject(columns, function(memo, val) {
+
+ memo[val] = (memo[val] + 1) || 1;
+ if (memo[val] > 1) {
+ dup = val;
+ }
+ return memo;
+ }, {});
+
+ throw new Error("You have more than one column named \"" + dup + "\"");
+ }
+
// save data
_.each(data.table.rows, function(row) {
row = row.c;
@@ -2964,15 +3090,20 @@ Version 0.0.1.2
column = parts[1],
position = parseInt(parts[2], 10);
- if (_.isUndefined(columnPositions[column])) {
-
- // cache the column position
- columnPositions[column] = columnData.length;
+ // this is the first row, thus column names.
+ if (position === 1) {
- // we found a new column, so build a new column type.
- columns[columnPositions[column]] = cell.content.$t;
- columnData[columnPositions[column]] = [];
+ // if we've already seen this column name, throw an exception
+ if (columns.indexOf(cell.content.$t) !== -1) {
+ throw new Error("You have more than one column named \"" + cell.content.$t + "\"");
+ } else {
+ // cache the column position
+ columnPositions[column] = columnData.length;
+ // we found a new column, so build a new column type.
+ columns[columnPositions[column]] = cell.content.$t;
+ columnData[columnPositions[column]] = [];
+ }
} else {
@@ -3059,8 +3190,19 @@ Version 0.0.1.2
_.extend(Miso.Parsers.Delimited.prototype, Miso.Parsers.prototype, {
parse : function(data) {
- var columns = [];
- var columnData = {};
+ var columns = [],
+ columnData = {},
+ uniqueSequence = {};
+
+ var uniqueId = function(str) {
+ if ( !uniqueSequence[str] ) {
+ uniqueSequence[str] = 0;
+ }
+ var id = str + uniqueSequence[str];
+ uniqueSequence[str] += 1;
+ return id;
+ };
+
var parseCSV = function(delimiterPattern, strData, strDelimiter, skipRows, emptyValue) {
@@ -3182,6 +3324,25 @@ Version 0.0.1.2
columnData[columns[columnIndex]].push(strMatchedValue);
} else {
+
+ var createColumnName = function(start) {
+ var newName = uniqueId(start);
+ while ( columns.indexOf(newName) !== -1 ) {
+ newName = uniqueId(start);
+ }
+ return newName;
+ };
+
+ //No column name? Create one starting with X
+ if ( _.isUndefined(strMatchedValue) || strMatchedValue === '' ) {
+ strMatchedValue = 'X';
+ }
+
+ //Duplicate column name? Create a new one starting with the name
+ if (columns.indexOf(strMatchedValue) !== -1) {
+ strMatchedValue = createColumnName(strMatchedValue);
+ }
+
// we are building the column names here
columns.push(strMatchedValue);
columnData[strMatchedValue] = [];
View
5,151 dist/miso.ds.deps.0.1.3.js
4,058 additions, 1,093 deletions not shown
View
4 dist/miso.ds.deps.min.0.1.3.js
2 additions, 2 deletions not shown
View
BIN  dist/miso.ds.dev.0.1.3.zip
Binary file not shown
View
4 dist/miso.ds.min.0.1.3.js
@@ -1,9 +1,9 @@
/**
-* Miso.Dataset - v0.1.3 - 5/23/2012
+* Miso.Dataset - v0.1.3 - 6/19/2012
* http://github.com/misoproject/dataset
* Copyright (c) 2012 Alex Graul, Irene Ros;
* Dual Licensed: MIT, GPL
* https://github.com/misoproject/dataset/blob/master/LICENSE-MIT
* https://github.com/misoproject/dataset/blob/master/LICENSE-GPL
*/
-(function(a,_){var b=a.Miso={};b.typeOf=function(a,c){var d=_.keys(b.types),e;return d.push(d.splice(_.indexOf(d,"string"),1)[0]),d.push(d.splice(_.indexOf(d,"mixed"),1)[0]),e=_.find(d,function(d){return b.types[d].test(a,c)}),e=_.isUndefined(e)?"string":e,e},b.types={mixed:{name:"mixed",coerce:function(a){return a},test:function(a){return!0},compare:function(a,b){return a<b?-1:a>b?1:0},numeric:function(a){return _.isNaN(Number(a))?0:Number(a)}},string:{name:"string",coerce:function(a){return a==null?null:a.toString()},test:function(a){return a===null||typeof a=="undefined"||typeof a=="string"},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a<b?-1:a>b?1:0},numeric:function(a){return _.isNaN(+a)?0:+a}},"boolean":{name:"boolean",regexp:/^(true|false)$/,coerce:function(a){return a==="false"?!1:Boolean(a)},test:function(a){return a===null||typeof a=="undefined"||typeof a=="boolean"||this.regexp.test(a)?!0:!1},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a==null&&b==null?0:a===b?0:a<b?-1:1},numeric:function(a){return a?1:0}},number:{name:"number",regexp:/^[\-\.]?[0-9]+([\.][0-9]+)?$/,coerce:function(a){return _.isNull(a)||a===""?null:_.isNaN(a)?null:+a},test:function(a){return a===null||typeof a=="undefined"||typeof a=="number"||this.regexp.test(a)?!0:!1},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a==null&&b==null?0:a===b?0:a<b?-1:1},numeric:function(a){return a}},time:{name:"time",format:"DD/MM/YYYY",_formatLookup:[["DD","\\d{2}"],["D","\\d{1}|\\d{2}"],["MM","\\d{2}"],["M","\\d{1}|\\d{2}"],["YYYY","\\d{4}"],["YY","\\d{2}"],["A","[AM|PM]"],["hh","\\d{2}"],["h","\\d{1}|\\d{2}"],["mm","\\d{2}"],["m","\\d{1}|\\d{2}"],["ss","\\d{2}"],["s","\\d{1}|\\d{2}"],["ZZ","[-|+]\\d{4}"],["Z","[-|+]\\d{2}:\\d{2}"]],_regexpTable:{},_regexp:function(a){if(this._regexpTable[a])return new RegExp(this._regexpTable[a],"g");var b=a;return _.each(this._formatLookup,function(a){b=b.replace(a[0],a[1])},this),b=b.split("/").join("\\/"),this._regexpTable[a]=b,new RegExp(this._regexpTable[a],"g")},coerce:function(a,b){b=b||{};if(_.isString(a)){var c=b.format||this.format;return moment(a,b.format)}return _.isNumber(a)?moment(a):a},test:function(a,b){b=b||{};if(a===null||typeof a=="undefined")return!0;if(_.isString(a)){var c=b.format||this.format,d=this._regexp(c);return d.test(a)}return!0},compare:function(a,b){return a<b?-1:a>b?1:0},numeric:function(a){return a.valueOf()}}}})(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Event=function(a){_.isArray(a)||(a=[a]),this.deltas=a},_.extend(b.Event.prototype,{affectedColumns:function(){var a=[];return _.each(this.deltas,function(b){b.old=b.old||[],b.changed=b.changed||[],a=_.chain(a).union(_.keys(b.old),_.keys(b.changed)).reject(function(a){return a==="_id"}).value()}),a}}),_.extend(b.Event,{isRemove:function(a){return _.isUndefined(a.changed)||_.keys(a.changed).length===0?!0:!1},isAdd:function(a){return _.isUndefined(a.old)||_.keys(a.old).length===0?!0:!1},isUpdate:function(a){return!this.isRemove(a)&&!this.isAdd(a)?!0:!1}}),b.Events={},b.Events.bind=function(a,b,c){var d=this._callbacks||(this._callbacks={}),e=d[a]||(d[a]={}),f=e.tail||(e.tail=e.next={});return f.callback=b,f.context=c,e.tail=f.next={},this},b.Events.unbind=function(a,b){var c,d,e;if(!a)this._callbacks=null;else if(c=this._callbacks)if(!b)c[a]={};else if(d=c[a])while((e=d)&&(d=d.next)){if(d.callback!==b)continue;e.next=d.next,d.context=d.callback=null;break}return this},b.Events.trigger=function(a){var b,c,d,e,f,g=["all",a];if(!(c=this._callbacks))return this;while(f=g.pop()){if(!(b=c[f]))continue;e=f==="all"?arguments:Array.prototype.slice.call(arguments,1);while(b=b.next)(d=b.callback)&&d.apply(b.context||this,e)}return this},b.Events._buildEvent=function(a){return new b.Event(a)}}(this,_),function(a,_){var b=a.Miso||{};b.Builder={detectColumnType:function(a,c){var d=_.inject(c.slice(0,5),function(a,c){var d=b.typeOf(c);return c!==""&&a.indexOf(d)===-1&&!_.isNull(c)&&a.push(d),a},[]);return d.length===1?a.type=d[0]:a.type="mixed",a},detectColumnTypes:function(a,c){_.each(c,function(c,d){var e=a.column(d);if(e.type){e.force=!0;return}b.Builder.detectColumnType(e,c)},this)},cacheRows:function(a){b.Builder.clearRowCache(a),_.each(a._columns[a._columnPositionByName._id].data,function(b,c){a._rowPositionById[b]=c,a._rowIdByPosition.push(b)},a);var c=_.uniq(_.map(a._columns,function(a){return a.data.length}));if(c.length>1)throw new Error("Row lengths need to be the same. Empty values should be set to null."+_.map(a._columns,function(a){return a.data+"|||"}));a.length=c[0]},clearRowCache:function(a){a._rowPositionById={},a._rowIdByPosition=[]},cacheColumns:function(a){a._columnPositionByName={},_.each(a._columns,function(b,c){a._columnPositionByName[b.name]=c})}},Array.prototype.indexOf||(Array.prototype.indexOf=function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1})}(this,_),function(a,_){var b=a.Miso;b.Column=function(a){return _.extend(this,a),this._id=a.id||_.uniqueId(),this.data=a.data||[],this},_.extend(b.Column.prototype,{toNumeric:function(a){return b.types[this.type].numeric(a)},numericAt:function(a){return this.toNumeric(this.data[a])},coerce:function(){this.data=_.map(this.data,function(a){return b.types[this.type].coerce(a,this)},this)},_sum:function(){return _.sum(this.data)},_mean:function(){var a=0;for(var c=0;c<this.data.length;c++)a+=this.numericAt(c);return a/=this.data.length,b.types[this.type].coerce(a,this)},_median:function(){return b.types[this.type].coerce(_.median(this.data),this)},_max:function(){var a=-Infinity;for(var c=0;c<this.data.length;c++)b.types[this.type].compare(this.data[c],a)>0&&(a=this.numericAt(c));return b.types[this.type].coerce(a,this)},_min:function(){var a=Infinity;for(var c=0;c<this.data.length;c++)b.types[this.type].compare(this.data[c],a)<0&&(a=this.numericAt(c));return b.types[this.type].coerce(a,this)}}),b.DataView=function(a){if(typeof a!="undefined"){a=a||(a={});if(_.isUndefined(a.parent))throw new Error("A view must have a parent specified.");this.parent=a.parent,this._initialize(a)}},_.extend(b.DataView.prototype,{_initialize:function(a){this.parent.syncable===!0&&(_.extend(this,b.Events),this.syncable=!0),this.filter={columns:this._columnFilter(a.filter.columns||undefined),rows:this._rowFilter(a.filter.rows||undefined)},this._columns=this._selectData(),b.Builder.cacheColumns(this),b.Builder.cacheRows(this),this.syncable&&this.parent.bind("change",this._sync,this)},_sync:function(a){var c=a.deltas,d=null;_.each(c,function(c,e){var f=this._rowPositionById[c._id];if(typeof f=="undefined"&&b.Event.isAdd(c))this.filter.rows&&this.filter.rows(c.changed)&&(this._add(c.changed),d="add");else{if(f==="undefined")return;_.each(c.changed,function(a,b){var c=this._columnPositionByName[b];if(_.isUndefined(c))return;this._columns[c].data[f]=a,d="update"},this)}var g=this.rowByPosition(f);if(b.Event.isRemove(c)||this.filter.row&&!this.filter.row(g)){var h={_id:c._id,old:this.rowByPosition(f),changed:{}};a.deltas.splice(e,1,h),this._remove(f),d="delete"}},this),this.syncable&&(this.trigger(d,a),this.trigger("change",a))},where:function(a,c){return c=c||{},c.parent=this,c.filter=a||{},new b.DataView(c)},_selectData:function(){var a=[];return _.each(this.parent._columns,function(c){this.filter.columns(c)&&a.push(new b.Column({name:c.name,data:[],type:c.type,_id:c._id}))},this),this.parent.each(function(b){if(!this.filter.rows(b))return;for(var c=0;c<a.length;c++)a[c].data.push(b[a[c].name])},this),a},_columnFilter:function(a){var b;return _.isUndefined(a)?b=function(){return!0}:(_.isString(a)&&(a=[a]),a.push("_id"),b=function(b){return _.indexOf(a,b.name)===-1?!1:!0}),b},_rowFilter:function(a){var b;return _.isNumber(a)&&(a=[a]),_.isUndefined(a)?b=function(){return!0}:_.isFunction(a)?b=a:b=function(b){return _.indexOf(a,b._id)===-1?!1:!0},b},column:function(a){return this._column(a)},_column:function(a){if(_.isUndefined(this._columnPositionByName))return undefined;var b=this._columnPositionByName[a];return this._columns[b]},columns:function(a){return new b.DataView({filter:{columns:a},parent:this})},columnNames:function(){var a=_.pluck(this._columns,"name");return _.reject(a,function(a){return a==="_id"||a==="_oids"})},hasColumn:function(a){return!_.isUndefined(this._columnPositionByName[a])},each:function(a,b){for(var c=0;c<this.length;c++)a.apply(b||this,[this.rowByPosition(c),c])},eachColumn:function(a,b){var c=this.columnNames();for(var d=0;d<c.length;d++)a.apply(b||this,[c[d],this.column(c[d]),d])},rowByPosition:function(a){return this._row(a)},rowById:function(a){return this._row(this._rowPositionById[a])},_row:function(a){var b={};return _.each(this._columns,function(c){b[c.name]=c.data[a]}),b},_remove:function(a){var b=this._rowPositionById[a];return _.each(this._columns,function(a){a.data.splice(b,1)}),delete this._rowPositionById[a],this._rowIdByPosition.splice(b,1),this.length--,this},_add:function(a,c){_.each(a,function(c,d){var e=this.column(d);if(typeof e!="undefined"){var f=b.types[e.type];if(e.force||f.test(a[e.name],e))_.isUndefined(e.before)||(a[e.name]=e.before(a[e.name])),a[e.name]=f.coerce(a[e.name],e);else throw"incorrect value '"+a[e.name]+"' of type "+b.typeOf(a[e.name],e)+" passed to column with type "+e.type}},this);if(_.isUndefined(this.comparator))_.each(this._columns,function(b){b.data.push(!_.isUndefined(a[b.name])&&!_.isNull(a[b.name])?a[b.name]:null)}),this.length++,this._rowIdByPosition=this._rowIdByPosition||(this._rowIdByPosition=[]),this._rowPositionById=this._rowPositionById||(this._rowPositionById={}),this._rowIdByPosition.push(a._id),this._rowPositionById[a._id]=this._rowIdByPosition.length;else{var d=function(a,b,c){Array.prototype.splice.apply(c,[a,0].concat(b))},e;this.length++;for(e=0;e<this.length;e++){var f=this.rowByPosition(e);if(_.isUndefined(f._id)||this.comparator(a,f)<0){_.each(this._columns,function(b){d(e,a[b.name]?a[b.name]:null,b.data)});break}}this._rowIdByPosition=[],this._rowPositionById={},this.each(function(a,b){this._rowIdByPosition.push(a._id),this._rowPositionById[a._id]=b})}return this},rows:function(a){return new b.DataView({filter:{rows:a},parent:this})},sort:function(a){a=a||{},a.comparator&&(this.comparator=a.comparator);if(_.isUndefined(this.comparator))throw new Error("Cannot sort without this.comparator.");var b=this.length,c;if(b===1)return;var d=_.bind(function(a,b){var c=this.rowByPosition(b);_.each(c,function(c,d){var e=this._columnPositionByName[d],f=this._columns[e].data[a];this._columns[e].data.splice(a,1,c),this._columns[e].data.splice(b,1,f)},this)},this),e=_.bind(function(a,b){var c=a,e;while(c*2<=b){e=c*2;var f=this.rowByPosition(c);e+1<b&&this.comparator(this.rowByPosition(e),this.rowByPosition(e+1))<0&&e++;if(this.comparator(f,this.rowByPosition(e))<0)d(c,e),c=e;else return}},this),f=function(a){var b=Math.round((a-2)/2);while(b>=0)e(b,a-1),b--};if(b>2){f(b),c=b-1;while(c>1)d(c,0),c--,e(0,c)}else this.comparator(this.rowByPosition(0),this.rowByPosition(1))>0&&d(0,1);return this.comparator(this.rowByPosition(this.length-2),this.rowByPosition(this.length-1))>0&&d(this.length-1,this.length-2),this.syncable&&a.silent&&this.trigger("sort"),this},toJSON:function(){var a=[];for(var b=0;b<this.length;b++)a.push(this.rowByPosition(b));return a}})}(this,_),function(a,_){var b=a.Miso;b.Product=b.Product||function(a){a=a||{},this.func=a.func;if(a.columns){var b=a.columns;_.isArray(a.columns)&&(b=a.columns[0]),this.valuetype=b.type,this.numeric=function(){return b.toNumeric(this.value)}}return this.func({silent:!0}),this},_.extend(b.Product.prototype,b.Events,{val:function(){return this.value},type:function(){return this.valuetype},_sync:function(a){this.func()},_buildDelta:function(a,b){return{old:a,changed:b}}}),_.extend(b.DataView.prototype,{_findColumns:function(a){var b=[];return _.isUndefined(a)&&(a=this.columnNames()),a=_.isArray(a)?a:[a],_.each(a,function(a){a=this._columns[this._columnPositionByName[a]],b.push(a)},this),b},sum:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){return _.each(a,function(a){if(a.type===b.types.time.name)throw new Error("Can't sum up time")}),_.sum(_.map(a,function(a){return a._sum()}))}}(d);return this._calculated(d,e)},max:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){var c=_.max(_.map(a,function(a){return a._max()})),d=a[0].type,e=a[0].typeOptions;return b.types[d].coerce(c,e)}}(d);return this._calculated(d,e)},min:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){var c=_.min(_.map(a,function(a){return a._min()})),d=a[0].type,e=a[0].typeOptions;return b.types[d].coerce(c,e)}}(d);return this._calculated(d,e)},mean:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){var c=[];_.each(a,function(a){c.push(a.data)}),c=_.flatten(c);var d=a[0].type,e=a[0].typeOptions;return c=_.map(c,function(a){return b.types[d].numeric(a)}),b.types[d].coerce(_.mean(c),e)}}(d);return this._calculated(d,e)},_calculated:function(a,c){var d=this,e=new b.Product({columns:a,func:function(a){a=a||{};var b=this._buildDelta(this.value,c.apply(d));this.value=b.changed;if(d.syncable){var e=this._buildEvent(b);!_.isUndefined(b.old)&&!a.silent&&b.old!==b.changed&&this.trigger("change",e)}}});return this.syncable?(this.bind("change",e._sync,e),e):c()}})}(this,_),function(a,_,moment){var b=a.Miso;b.Dataset=function(a){this.length=0,this._columns=[],this._columnPositionByName={},typeof a!="undefined"&&(a=a||{},this._initialize(a))},b.Dataset.prototype=new b.DataView,_.extend(b.Dataset.prototype,{_initialize:function(a){a.sync===!0&&(_.extend(this,b.Events),this.syncable=!0),this.importer=a.importer||null,this.parser=a.parser||b.Parsers.Obj,_.isUndefined(a.parser)&&(a.strict?this.parser=b.Parsers.Strict:a.delimiter&&(this.parser=b.Parsers.Delimited)),this.importer===null&&(a.url?a.interval?(this.importer=b.Importers.Polling,this.interval=a.interval):this.importer=b.Importers.Remote:this.importer=b.Importers.Local),this.parser=new this.parser(a),this.parser instanceof b.Parsers.Delimited&&(a.dataType="text"),this.importer=new this.importer(a),a.comparator&&(this.comparator=a.comparator),a.ready&&(this.ready=a.ready),a.resetOnFetch&&(this.resetOnFetch=a.resetOnFetch),a.uniqueAgainst&&(this.uniqueAgainst=a.uniqueAgainst),_.isUndefined(a.data)&&_.isUndefined(a.url)&&this._addIdColumn(),a.deferred&&(this.deferred=a.deferred),a.columns&&this.addColumns(a.columns)},fetch:function(a){a=a||{};var b=this.deferred||new _.Deferred;if(_.isNull(this.importer))throw"No importer defined";return this.importer.fetch({success:_.bind(function(c){this._apply(c),this.comparator&&this.sort(),this.ready&&this.ready.call(this),a.success&&a.success.call(this),b.resolveWith(this,[this])},this),error:_.bind(function(c){a.error&&a.error.call(this),b.reject(c)},this)}),b.promise()},_applications:{againstColumn:function(a){var b=[],c=_.keys(a),d,e=this.column(this.uniqueAgainst),f=a[this._columns[1].name].length,g=_.max(_.map(c,function(b){return a[b].length},this)),h=[],i;for(i=0;i<f;i++){var j=a[this.uniqueAgainst][i];e.data.indexOf(j)!==-1&&h.push(i)}h.sort().reverse();for(i=0;i<g;i++)if(h.indexOf(i)===-1){d={};for(var k=0;k<c.length;k++)d[c[k]]=a[c[k]][i];b.push(d)}this.add(b)},blind:function(a){var b,c,d=[],e,f=_.keys(a),g=_.max(_.map(f,function(b){return a[b].length},this));for(var h=0;h<g;h++){e={};for(var i=0;i<f.length;i++)e[f[i]]=a[f[i]][h];d.push(e)}this.add(d)}},_apply:function(a){var c=this.parser.parse(a);if(!this.fetched)this._addIdColumn(),this.addColumns(_.map(c.columns,function(a){return{name:a}})),b.Builder.detectColumnTypes(this,c.data),this._applications.blind.call(this,c.data),this.fetched=!0;else if(this.resetOnFetch)this.reset(),this._applications.blind.call(this,c.data);else if(this.uniqueAgainst){if(!this.hasColumn(this.uniqueAgainst))throw new Error("You requested a unique add against a column that doesn't exist.");this._applications.againstColumn.call(this,c.data)}else this._applications.blind.call(this,c.data);b.Builder.cacheRows(this)},addColumns:function(a){_.each(a,function(a){this.addColumn(a)},this)},addColumn:function(a){return _.isUndefined(this.column(a.name))?(a=new b.Column(a),this._columns.push(a),this._columnPositionByName[a.name]=this._columns.length-1,a):!1},_addIdColumn:function(a){if(!_.isUndefined(this.column("_id")))return;var b=[];a&&a>0&&_.times(a,function(){b.push(_.uniqueId())}),this.addColumn({name:"_id",type:"number",data:b});if(this._columnPositionByName._id!==0){var c=this._columns[this._columnPositionByName._id],d=this._columnPositionByName._id;this._columns.splice(d,1),this._columns.unshift(c),this._columnPositionByName._id=0,_.each(this._columnPositionByName,function(a,b){b!=="_id"&&this._columnPositionByName[b]<d&&this._columnPositionByName[b]++},this)}},add:function(a,b){b=b||{},_.isArray(a)||(a=[a]);var c=[];_.each(a,function(a){a._id||(a._id=_.uniqueId()),this._add(a,b),this.syncable&&!b.silent&&c.push({changed:a})},this);if(this.syncable&&!b.silent){var d=this._buildEvent(c);this.trigger("add",d),this.trigger("change",d)}return this},remove:function(a,b){a=this._rowFilter(a);var c=[],d=[];this.each(function(b,e){a(b)&&(d.push(b._id),c.push({old:b}))}),_.each(d,function(a){this._remove(a)},this);if(this.syncable&&(!b||!b.silent)){var e=this._buildEvent(c);this.trigger("remove",e),this.trigger("change",e)}},update:function(a,c,d){var e,f=[],g=_.bind(function(a,d){var g,h;_.isFunction(c)?h=c.apply(this,[a]):h=c,e=_.keys(h),_.each(e,function(a){g=this.column(a);var c=b.types[g.type];if(c)if(c.test(h[g.name],g))_.isUndefined(g.before)||(h[g.name]=g.before(h[g.name])),h[g.name]=c.coerce(h[g.name],g);else throw"incorrect value '"+h[g.name]+"' of type "+b.typeOf(h[g.name],g)+" passed to column with type "+g.type;g.data[d]=h[g.name]},this),f.push({_id:a._id,old:a,changed:h})},this);_.isString(a)&&(a=[a]);if(_.isArray(a)){var h,i;_.each(a,function(a){h=this.rowById(a),i=this._rowPositionById[a],g(h,i)})}else a=this._rowFilter(a),this.each(function(b,c){a(b)&&g(b,c)},this);if(this.syncable&&(!d||!d.silent)){var j=this._buildEvent(f);this.trigger("update",j),this.trigger("change",j)}return this},reset:function(a){_.each(this._columns,function(a){a.data=[]}),this.length=0,this.syncable&&(!a||!a.silent)&&this.trigger("reset")}})}(this,_,moment),function(a,_){var b=a.Miso||(a.Miso={});b.Derived=function(a){a=a||{},b.Dataset.call(this),this.parent=a.parent,this.method=a.method,this._addIdColumn(),this.addColumn({name:"_oids",type:"mixed"}),this.parent.syncable&&(_.extend(this,b.Events),this.syncable=!0,this.parent.bind("change",this._sync,this))},b.Derived.prototype=new b.Dataset,_.extend(b.Derived.prototype,{_sync:function(a){this.func.call(this.args),this.trigger("change")}}),_.extend(b.DataView.prototype,{movingAverage:function(a,c,d){d=d||{};var e=new b.Derived({parent:this,method:d.method||_.mean,size:c,args:arguments});this.eachColumn(function(a){e.addColumn({name:a,type:this.column(a).type,data:[]})},this),b.Builder.cacheColumns(e);var f=function(){var d=[];typeof a=="string"&&(a=[a]),this.column("_id").data=this.parent.column("_id").data.slice(c-1,this.parent.length),this.eachColumn(function(b,d,e){a.indexOf(b)===-1&&b!=="_oids"?d.data=this.parent.column(b).data.slice(c-1,this.parent.length):d.data=_.movingAvg(this.parent.column(b).data,c,this.method)},this),this.length=this.parent.length-c+1;var e=this.column("_oids");e.data=[];for(var f=0;f<this.length;f++)e.data.push(this.parent.column("_id").data.slice(f,f+c));return b.Builder.cacheRows(this),this};return e.func=_.bind(f,e),e.func.call(e.args)},countBy:function(a,c){function j(a,c,d){var e;for(e=0;e<a.length;e++)if(b.types[d].compare(a[e],c)===0)return e;return-1}c=c||{};var d=new b.Derived({parent:this,method:_.sum,args:arguments}),e=this.column(a);d.addColumn({name:a,type:e.type}),d.addColumn({name:"count",type:"number"}),d.addColumn({name:"_oids",type:"mixed"}),b.Builder.cacheColumns(d);var f=d._column(a).data,g=d._column("count").data,h=d._column("_oids").data,i=d._column("_id").data;return this.each(function(b){var c=j(f,b[a],e.type);c===-1?(f.push(b[a]),i.push(_.uniqueId()),g.push(1),h.push([b._id])):(g[c]+=1,h[c].push(b._id))}),b.Builder.cacheRows(d),d},groupBy:function(a,c,d){d=d||{};var e=new b.Derived({parent:this,method:d.method||_.sum,args:arguments});d&&d.preprocess&&(e.preprocess=d.preprocess);var f=_.union([a],c);_.each(f,function(a){this.addColumn({name:a,type:this.parent.column(a).type})},e),b.Builder.cacheColumns(e);var g=function(){b.Builder.clearRowCache(this);var d={},e=0,f=this._columnPositionByName[a],g=this.parent.column(a);for(var h=0;h<this.parent.length;h++){var i=null;this.preprocess?i=this.preprocess(g.data[h]):i=g.data[h],_.isUndefined(d[i])&&(d[i]=e,_.each(c,function(a){var b=this.column(a),c=this.column("_id");b.data[e]=[],c.data[e]=_.uniqueId()},this),this.column(a).data[e]=i,e++),_.each(c,function(a){var b=this.column(a),c=this.parent.column(a).data[h],e=d[i];b.data[e].push(this.parent.rowByPosition(h))},this)}var j=this._columns[this._columnPositionByName._oids];return j.data=[],_.each(c,function(a){var b=this.column(a);_.each(b.data,function(c,d){_.isArray(c)&&(j.data[d]=j.data[d]||[],j.data[d].push(_.map(c,function(a){return a._id})),j.data[d]=_.flatten(j.data[d]),b.data[d]=this.method(_.map(c,function(b){return b[a]})),this.length++)},this)},this),b.Builder.cacheRows(this),this};return e.func=_.bind(g,e),e.func.call(e.args)}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers=function(a,b){},b.Importers.prototype.extract=function(a){return a=_.clone(a),a}}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.Local=function(a){a=a||{},this.data=a.data||null,this.extract=a.extract||this.extract},_.extend(b.Importers.Local.prototype,b.Importers.prototype,{fetch:function(a){var b=a.data?a.data:this.data;a.success(this.extract(b))}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.Remote=function(a){a=a||{},this._url=a.url,this.extract=a.extract||this.extract,this.params={type:"GET",url:_.isFunction(this._url)?_.bind(this._url,this):this._url,dataType:a.dataType?a.dataType:a.jsonp?"jsonp":"json"}},_.extend(b.Importers.Remote.prototype,b.Importers.prototype,{fetch:function(a){var c=_.bind(function(b){a.success(this.extract(b))},this);this.callback&&(window[this.callback]=c),b.Xhr(_.extend(this.params,{success:this.callback?this.callback:c,error:a.error}))}});var c={url:"",data:"",dataType:"",success:function(){},type:"GET",async:!0,xhr:function(){return new a.XMLHttpRequest}},d=/\?/;b.Xhr=function(a){a.dataType=a.dataType&&a.dataType.toLowerCase()||null;var e=_.isFunction(a.url)?a.url():a.url;if(!(!a.dataType||a.dataType!=="jsonp"&&a.dataType!=="script")){b.Xhr.getJSONP(e,a.success,a.dataType==="script",a.error);return}var f=_.extend({},c,a,{url:e});f.ajax=f.xhr();if(f.ajax)return f.type==="GET"&&f.data&&(f.url+=(d.test(f.url)?"&":"?")+f.data,f.data=null),f.ajax.open(f.type,f.url,f.async),f.ajax.send(f.data||null),b.Xhr.httpData(f)},b.Xhr.getJSONP=function(a,b,c,d){if(c){var e=document.querySelectorAll('script[src="'+a+'"]');if(e.length){b&&b(!0);return}}var f=document.head||document.getElementsByTagName("head")[0]||document.documentElement,g=document.createElement("script"),h=a.split("?")[1],i=!1,j=[],k,l,m;h&&!c&&(j=h.split("&")),j.length&&(l=j[j.length-1].split("=")),k=j.length?l[1]?l[1]:l[0]:"jsonp",!h&&!c&&(a+="?callback="+k),k&&!c&&(!window[k]||(k=k+ +(new Date)+_.uniqueId()),window[k]=function(a){b&&b(a),i=!0},a=a.replace(l.join("="),l[0]+"="+k)),g.onload=g.onreadystatechange=function(){if(!g.readyState||/loaded|complete/.test(g.readyState)){c&&b&&b();if(i){try{delete window[k]}catch(a){window[k]=void 0}f.removeChild(g)}}},g.onerror=function(a){d&&d.call(null)},g.src=a,f.insertBefore(g,f.firstChild);return},b.Xhr.httpData=function(a){var b,c=null;return a.ajax.onreadystatechange=function(){if(a.ajax.readyState===4){try{c=JSON.parse(a.ajax.responseText)}catch(d){}b={xml:a.ajax.responseXML,text:a.ajax.responseText,json:c},a.dataType&&(b=b[a.dataType]),/(2..)/.test(a.ajax.status)?a.success.call(a.ajax,b):a.error&&a.error.call(null,a.ajax.statusText)}},b}}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.Polling=function(a){a=a||{},this.interval=a.interval||1e3,this._def=null,b.Importers.Remote.apply(this,[a])},_.extend(b.Importers.Polling.prototype,b.Importers.Remote.prototype,{fetch:function(c){this._def===null&&(this._def=_.Deferred(),this.success_callback=_.bind(function(a){c.success(this.extract(a)),this._def.resolve(this)},this),this.error_callback=_.bind(function(a){c.error(a),this._def.reject(a)},this)),_.when(this._def.promise()).then(function(a){var b=_.bind(function(){this.fetch({success:this.success_callback,error:this.error_callback})},a);a._timeout=setTimeout(b,a.interval),a._def=_.Deferred()}),b.Xhr(_.extend(this.params,{success:this.success_callback,error:this.error_callback})),a.imp=this},stop:function(){this._def!==null&&this._def.reject(),typeof this._timeout!="undefined"&&clearTimeout(this._timeout)},start:function(){this._def!==null&&(this._def=_.Deferred(),this.fetch())}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.GoogleSpreadsheet=function(a){a=a||{};if(a.url)a.url=a.url;else{if(_.isUndefined(a.key))throw new Error("Set options 'key' properties to point to your google document.");a.fast?(a.url="https://spreadsheets.google.com/tq?key="+a.key,a.sheetName?a.url+="&sheet="+a.sheetName:(a.url+="&gid="+(a.worksheet||1),delete a.worksheet),this.callback="misodsgs"+(new Date).getTime(),a.url+="&tqx=version:0.6;responseHandler:"+this.callback,a.url+=";reqId:0;out:json&tq&_=1335871249558#",delete a.sheetName):a.url="https://spreadsheets.google.com/feeds/cells/"+a.key+"/"+a.worksheet+"/public/basic?alt=json-in-script&callback=",delete a.key}return this.params={type:"GET",url:a.url,dataType:"jsonp"},this},_.extend(b.Importers.GoogleSpreadsheet.prototype,b.Importers.Remote.prototype)}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers=function(a){this.options=a||{}},_.extend(b.Parsers.prototype,{parse:function(){}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.Strict=function(a){this.options=a||{}},_.extend(b.Parsers.Strict.prototype,b.Parsers.prototype,{parse:function(a){var b={},c=[];return _.each(a.columns,function(a){c.push(a.name),b[a.name]=a.data}),{columns:c,data:b}}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.Obj=b.Parsers,_.extend(b.Parsers.Obj.prototype,b.Parsers.prototype,{parse:function(a){var b=_.keys(a[0]),c={};return _.each(b,function(a){c[a]=[]}),_.each(b,function(b){_.times(a.length,function(d){c[b].push(a[d][b])})}),{columns:b,data:c}}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.GoogleSpreadsheet=function(a){this.fast=a.fast||!1},_.extend(b.Parsers.GoogleSpreadsheet.prototype,b.Parsers.prototype,{parse:function(a){var b=[],c=[],d={},e;if(this.fast)b=_.pluck(a.table.cols,"label"),_.each(a.table.rows,function(a){a=a.c;for(e=0;e<a.length;e++)c[e]=c[e]||[],a[e].v===""?c[e].push(null):c[e].push(a[e].v)}),_.each(b,function(a,b){d[a]=c[b]});else{var f=/([A-Z]+)(\d+)/,g={};_.each(a.feed.entry,function(a,d){var e=f.exec(a.title.$t),h=e[1],i=parseInt(e[2],10);if(_.isUndefined(g[h]))g[h]=c.length,b[g[h]]=a.content.$t,c[g[h]]=[];else{var j=g[h];c[j][i-1]=a.content.$t}},this),_.each(c,function(a,e){a.length=_.max(_.pluck(c,"length")),a.splice(0,1);for(var f=0;f<a.length;f++)if(_.isUndefined(a[f])||a[f]==="")a[f]=null;d[b[e]]=a})}return{columns:b,data:d}}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.Delimited=function(a){a=a||{},this.delimiter=a.delimiter||",",this.skipRows=a.skipRows||0,this.emptyValue=a.emptyValue||null,this.__delimiterPatterns=new RegExp("(\\"+this.delimiter+"|\\r?\\n|\\r|^)"+'(?:"([^"]*(?:""[^"]*)*)"|'+'([^"\\'+this.delimiter+"\\r\\n]*))","gi")},typeof String.prototype.trim!="function"&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),_.extend(b.Parsers.Delimited.prototype,b.Parsers.prototype,{parse:function(a){var b=[],c={},d=function(a,d,e,f,g){e=e||",";var h=null,i=0,j=!1,k=-1,l=0;try{d=d.trim();if(f>0){var m=0,n=0,o=d.length;while(m<f&&n<o)/\n|\r|\r\n/.test(d[n])&&m++,n++;d=d.slice(n,o)}while(h=a.exec(d)){var p=h[1];if(p.length&&p!==e){l++;if(k<i-1)throw l--,new Error("Not enough items in row");j=!0,k=0}else j||i++,k++;var q=null;h[2]?q=h[2].replace(new RegExp('""',"g"),'"'):q=h[3];if(j){q===""&&(q=g);if(typeof c[b[k]]=="undefined")throw new Error("Too many items in row");c[b[k]].push(q)}else b.push(q),c[q]=[]}}catch(r){throw new Error("Error while parsing delimited data on row "+l+". Message: "+r.message)}return{columns:b,data:c}};return d(this.__delimiterPatterns,a,this.delimiter,this.skipRows,this.emptyValue)}})}(this,_)
+(function(a,_){var b=a.Miso={};b.typeOf=function(a,c){var d=_.keys(b.types),e;return d.push(d.splice(_.indexOf(d,"string"),1)[0]),d.push(d.splice(_.indexOf(d,"mixed"),1)[0]),e=_.find(d,function(d){return b.types[d].test(a,c)}),e=_.isUndefined(e)?"string":e,e},b.types={mixed:{name:"mixed",coerce:function(a){return a},test:function(a){return!0},compare:function(a,b){return a<b?-1:a>b?1:0},numeric:function(a){return _.isNaN(Number(a))?0:Number(a)}},string:{name:"string",coerce:function(a){return a==null?null:a.toString()},test:function(a){return a===null||typeof a=="undefined"||typeof a=="string"},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a<b?-1:a>b?1:0},numeric:function(a){return _.isNaN(+a)?0:+a}},"boolean":{name:"boolean",regexp:/^(true|false)$/,coerce:function(a){return a==="false"?!1:Boolean(a)},test:function(a){return a===null||typeof a=="undefined"||typeof a=="boolean"||this.regexp.test(a)?!0:!1},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a==null&&b==null?0:a===b?0:a<b?-1:1},numeric:function(a){return a?1:0}},number:{name:"number",regexp:/^[\-]?[0-9]+$/,coerce:function(a){return _.isNull(a)?null:_.isNaN(a)?null:+a},test:function(a,c){return a===null||typeof a=="undefined"||typeof a=="number"||this.regexp.test(a)||c&&(b.types["number-decimal-point"].test(a)||b.types["number-decimal-comma"].test(a))?!0:!1},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a==null&&b==null?0:a===b?0:a<b?-1:1},numeric:function(a){return a}},"number-decimal-point":{name:"number-decimal-point",regexp:/^[\-\.]?[0-9]+([\.][0-9]+)?$/,coerce:function(a){return _.isNull(a)?null:_.isNaN(a)?null:+a},test:function(a){return a===null||typeof a=="undefined"||typeof a=="number"||this.regexp.test(a)?!0:!1},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a==null&&b==null?0:a===b?0:a<b?-1:1},numeric:function(a){return a}},"number-decimal-comma":{name:"number-decimal-comma",regexp:/^[\-,]?[0-9]+([,][0-9]+)?$/,coerce:function(a){return _.isNull(a)?null:_.isNaN(a)?null:+String(a).replace(",",".")},test:function(a){return a===null||typeof a=="undefined"||typeof a=="number"||this.regexp.test(a)?!0:!1},compare:function(a,b){return a==null&&b!=null?-1:a!=null&&b==null?1:a==null&&b==null?0:a===b?0:a<b?-1:1},numeric:function(a){return a}},time:{name:"time",format:"DD/MM/YYYY",_formatLookup:[["DD","\\d{2}"],["D","\\d{1}|\\d{2}"],["MM","\\d{2}"],["M","\\d{1}|\\d{2}"],["YYYY","\\d{4}"],["YY","\\d{2}"],["A","[AM|PM]"],["hh","\\d{2}"],["h","\\d{1}|\\d{2}"],["mm","\\d{2}"],["m","\\d{1}|\\d{2}"],["ss","\\d{2}"],["s","\\d{1}|\\d{2}"],["ZZ","[-|+]\\d{4}"],["Z","[-|+]\\d{2}:\\d{2}"]],_regexpTable:{},_regexp:function(a){if(this._regexpTable[a])return new RegExp(this._regexpTable[a],"g");var b=a;return _.each(this._formatLookup,function(a){b=b.replace(a[0],a[1])},this),b=b.split("/").join("\\/"),this._regexpTable[a]=b,new RegExp(this._regexpTable[a],"g")},coerce:function(a,b){b=b||{};if(_.isString(a)){var c=b.format||this.format;return moment(a,b.format)}return _.isNumber(a)?moment(a):a},test:function(a,b){b=b||{};if(a===null||typeof a=="undefined")return!0;if(_.isString(a)){var c=b.format||this.format,d=this._regexp(c);return d.test(a)}return!0},compare:function(a,b){return a<b?-1:a>b?1:0},numeric:function(a){return a.valueOf()}}}})(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Event=function(a){_.isArray(a)||(a=[a]),this.deltas=a},_.extend(b.Event.prototype,{affectedColumns:function(){var a=[];return _.each(this.deltas,function(b){b.old=b.old||[],b.changed=b.changed||[],a=_.chain(a).union(_.keys(b.old),_.keys(b.changed)).reject(function(a){return a==="_id"}).value()}),a}}),_.extend(b.Event,{isRemove:function(a){return _.isUndefined(a.changed)||_.keys(a.changed).length===0?!0:!1},isAdd:function(a){return _.isUndefined(a.old)||_.keys(a.old).length===0?!0:!1},isUpdate:function(a){return!this.isRemove(a)&&!this.isAdd(a)?!0:!1}}),b.Events={},b.Events.bind=function(a,b,c){var d=this._callbacks||(this._callbacks={}),e=d[a]||(d[a]={}),f=e.tail||(e.tail=e.next={});return f.callback=b,f.context=c,e.tail=f.next={},this},b.Events.unbind=function(a,b){var c,d,e;if(!a)this._callbacks=null;else if(c=this._callbacks)if(!b)c[a]={};else if(d=c[a])while((e=d)&&(d=d.next)){if(d.callback!==b)continue;e.next=d.next,d.context=d.callback=null;break}return this},b.Events.trigger=function(a){var b,c,d,e,f,g=["all",a];if(!(c=this._callbacks))return this;while(f=g.pop()){if(!(b=c[f]))continue;e=f==="all"?arguments:Array.prototype.slice.call(arguments,1);while(b=b.next)(d=b.callback)&&d.apply(b.context||this,e)}return this},b.Events._buildEvent=function(a){return new b.Event(a)}}(this,_),function(a,_){var b=a.Miso||{};b.Builder={detectColumnType:function(a,c){var d=_.inject(c.slice(0,5),function(a,c){var d=b.typeOf(c);return c!==""&&a.indexOf(d)===-1&&!_.isNull(c)&&a.push(d),a},[]);return d.length===1?a.type=d[0]:(d.sort(),d.length===2&&d[0]==="number"&&d[1].substr(0,6)==="number"?a.type=d[1]:a.type="mixed"),a},detectColumnTypes:function(a,c){_.each(c,function(c,d){var e=a.column(d);if(e.type){e.force=!0;return}b.Builder.detectColumnType(e,c)},this)},cacheRows:function(a){b.Builder.clearRowCache(a),_.each(a._columns[a._columnPositionByName._id].data,function(b,c){a._rowPositionById[b]=c,a._rowIdByPosition.push(b)},a);var c=_.uniq(_.map(a._columns,function(a){return a.data.length}));if(c.length>1)throw new Error("Row lengths need to be the same. Empty values should be set to null."+_.map(a._columns,function(a){return a.data+"|||"}));a.length=c[0]},clearRowCache:function(a){a._rowPositionById={},a._rowIdByPosition=[]},cacheColumns:function(a){a._columnPositionByName={},_.each(a._columns,function(b,c){a._columnPositionByName[b.name]=c})}},Array.prototype.indexOf||(Array.prototype.indexOf=function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1})}(this,_),function(a,_){var b=a.Miso;b.Column=function(a){return _.extend(this,a),this._id=a.id||_.uniqueId(),this.data=a.data||[],this},_.extend(b.Column.prototype,{toNumeric:function(a){return b.types[this.type].numeric(a)},numericAt:function(a){return this.toNumeric(this.data[a])},coerce:function(){this.data=_.map(this.data,function(a){return b.types[this.type].coerce(a,this)},this)},_sum:function(){return _.sum(this.data)},_mean:function(){var a=0;for(var c=0;c<this.data.length;c++)a+=this.numericAt(c);return a/=this.data.length,b.types[this.type].coerce(a,this)},_median:function(){return b.types[this.type].coerce(_.median(this.data),this)},_max:function(){var a=-Infinity;for(var c=0;c<this.data.length;c++)b.types[this.type].compare(this.data[c],a)>0&&(a=this.numericAt(c));return b.types[this.type].coerce(a,this)},_min:function(){var a=Infinity;for(var c=0;c<this.data.length;c++)b.types[this.type].compare(this.data[c],a)<0&&(a=this.numericAt(c));return b.types[this.type].coerce(a,this)}}),b.DataView=function(a){if(typeof a!="undefined"){a=a||(a={});if(_.isUndefined(a.parent))throw new Error("A view must have a parent specified.");this.parent=a.parent,this._initialize(a)}},_.extend(b.DataView.prototype,{_initialize:function(a){this.parent.syncable===!0&&(_.extend(this,b.Events),this.syncable=!0),this.filter={columns:this._columnFilter(a.filter.columns||undefined),rows:this._rowFilter(a.filter.rows||undefined)},this._columns=this._selectData(),b.Builder.cacheColumns(this),b.Builder.cacheRows(this),this.syncable&&this.parent.bind("change",this._sync,this)},_sync:function(a){var c=a.deltas,d=null;_.each(c,function(c,e){var f=this._rowPositionById[c._id];if(typeof f=="undefined"&&b.Event.isAdd(c))this.filter.rows&&this.filter.rows(c.changed)&&(this._add(c.changed),d="add");else{if(f==="undefined")return;_.each(c.changed,function(a,b){var c=this._columnPositionByName[b];if(_.isUndefined(c))return;this._columns[c].data[f]=a,d="update"},this)}var g=this.rowByPosition(f);if(b.Event.isRemove(c)||this.filter.row&&!this.filter.row(g)){var h={_id:c._id,old:this.rowByPosition(f),changed:{}};a.deltas.splice(e,1,h),this._remove(f),d="delete"}},this),this.syncable&&(this.trigger(d,a),this.trigger("change",a))},where:function(a,c){return c=c||{},c.parent=this,c.filter=a||{},new b.DataView(c)},_selectData:function(){var a=[];return _.each(this.parent._columns,function(c){this.filter.columns(c)&&a.push(new b.Column({name:c.name,data:[],type:c.type,_id:c._id}))},this),this.parent.each(function(b){if(!this.filter.rows(b))return;for(var c=0;c<a.length;c++)a[c].data.push(b[a[c].name])},this),a},_columnFilter:function(a){var b;return _.isUndefined(a)?b=function(){return!0}:(_.isString(a)&&(a=[a]),a.push("_id"),b=function(b){return _.indexOf(a,b.name)===-1?!1:!0}),b},_rowFilter:function(a){var b;return _.isNumber(a)&&(a=[a]),_.isUndefined(a)?b=function(){return!0}:_.isFunction(a)?b=a:b=function(b){return _.indexOf(a,b._id)===-1?!1:!0},b},column:function(a){return this._column(a)},_column:function(a){if(_.isUndefined(this._columnPositionByName))return undefined;var b=this._columnPositionByName[a];return this._columns[b]},columns:function(a){return new b.DataView({filter:{columns:a},parent:this})},columnNames:function(){var a=_.pluck(this._columns,"name");return _.reject(a,function(a){return a==="_id"||a==="_oids"})},hasColumn:function(a){return!_.isUndefined(this._columnPositionByName[a])},each:function(a,b){for(var c=0;c<this.length;c++)a.apply(b||this,[this.rowByPosition(c),c])},reverseEach:function(a,b){for(var c=this.length-1;c>=0;c--)a.apply(b||this,[this.rowByPosition(c),c])},eachColumn:function(a,b){var c=this.columnNames();for(var d=0;d<c.length;d++)a.apply(b||this,[c[d],this.column(c[d]),d])},rowByPosition:function(a){return this._row(a)},rowById:function(a){return this._row(this._rowPositionById[a])},_row:function(a){var b={};return _.each(this._columns,function(c){b[c.name]=c.data[a]}),b},_remove:function(a){var b=this._rowPositionById[a];return _.each(this._columns,function(a){a.data.splice(b,1)}),delete this._rowPositionById[a],this._rowIdByPosition.splice(b,1),this.length--,this},_add:function(a,c){_.each(a,function(c,d){var e=this.column(d);if(typeof e!="undefined"){var f=b.types[e.type];if(e.force||f.test(a[e.name],!0))_.isUndefined(e.before)||(a[e.name]=e.before(a[e.name])),a[e.name]=f.coerce(a[e.name],e);else throw"incorrect value '"+a[e.name]+"' of type "+b.typeOf(a[e.name],e)+" passed to column with type "+e.type}},this);if(_.isUndefined(this.comparator))_.each(this._columns,function(b){b.data.push(!_.isUndefined(a[b.name])&&!_.isNull(a[b.name])?a[b.name]:null)}),this.length++,this._rowIdByPosition=this._rowIdByPosition||(this._rowIdByPosition=[]),this._rowPositionById=this._rowPositionById||(this._rowPositionById={}),this._rowIdByPosition.push(a._id),this._rowPositionById[a._id]=this._rowIdByPosition.length;else{var d=function(a,b,c){Array.prototype.splice.apply(c,[a,0].concat(b))},e;this.length++;for(e=0;e<this.length;e++){var f=this.rowByPosition(e);if(_.isUndefined(f._id)||this.comparator(a,f)<0){_.each(this._columns,function(b){d(e,a[b.name]?a[b.name]:null,b.data)});break}}this._rowIdByPosition=[],this._rowPositionById={},this.each(function(a,b){this._rowIdByPosition.push(a._id),this._rowPositionById[a._id]=b})}return this},rows:function(a){return new b.DataView({filter:{rows:a},parent:this})},sort:function(a){var b={};_.isFunction(a)?b.comparator=a:b=a||b,b.comparator&&(this.comparator=b.comparator);if(_.isUndefined(this.comparator))throw new Error("Cannot sort without this.comparator.");var c=this.length,d;if(c===1)return;var e=_.bind(function(a,b){var c=this.rowByPosition(b);_.each(c,function(c,d){var e=this._columnPositionByName[d],f=this._columns[e].data[a];this._columns[e].data.splice(a,1,c),this._columns[e].data.splice(b,1,f)},this)},this),f=_.bind(function(a,b){var c=a,d;while(c*2<=b){d=c*2;var f=this.rowByPosition(c);d+1<b&&this.comparator(this.rowByPosition(d),this.rowByPosition(d+1))<0&&d++;if(this.comparator(f,this.rowByPosition(d))<0)e(c,d),c=d;else return}},this),g=function(a){var b=Math.round((a-2)/2);while(b>=0)f(b,a-1),b--};if(c>2){g(c),d=c-1;while(d>1)e(d,0),d--,f(0,d)}else this.comparator(this.rowByPosition(0),this.rowByPosition(1))>0&&e(0,1);return this.comparator(this.rowByPosition(this.length-2),this.rowByPosition(this.length-1))>0&&e(this.length-1,this.length-2),this.syncable&&b.silent&&this.trigger("sort"),this},toJSON:function(){var a=[];for(var b=0;b<this.length;b++)a.push(this.rowByPosition(b));return a}})}(this,_),function(a,_){var b=a.Miso;b.Product=b.Product||function(a){a=a||{},this.func=a.func;if(a.columns){var b=a.columns;_.isArray(a.columns)&&(b=a.columns[0]),this.valuetype=b.type,this.numeric=function(){return b.toNumeric(this.value)}}return this.func({silent:!0}),this},_.extend(b.Product.prototype,b.Events,{val:function(){return this.value},type:function(){return this.valuetype},_sync:function(a){this.func()},_buildDelta:function(a,b){return{old:a,changed:b}}}),_.extend(b.DataView.prototype,{_findColumns:function(a){var b=[];return _.isUndefined(a)&&(a=this.columnNames()),a=_.isArray(a)?a:[a],_.each(a,function(a){a=this._columns[this._columnPositionByName[a]],b.push(a)},this),b},sum:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){return _.each(a,function(a){if(a.type===b.types.time.name)throw new Error("Can't sum up time")}),_.sum(_.map(a,function(a){return a._sum()}))}}(d);return this._calculated(d,e)},max:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){var c=_.max(_.map(a,function(a){return a._max()})),d=a[0].type,e=a[0].typeOptions;return b.types[d].coerce(c,e)}}(d);return this._calculated(d,e)},min:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){var c=_.min(_.map(a,function(a){return a._min()})),d=a[0].type,e=a[0].typeOptions;return b.types[d].coerce(c,e)}}(d);return this._calculated(d,e)},mean:function(a,c){c=c||{};var d=this._findColumns(a),e=function(a){return function(){var c=[];_.each(a,function(a){c.push(a.data)}),c=_.flatten(c);var d=a[0].type,e=a[0].typeOptions;return c=_.map(c,function(a){return b.types[d].numeric(a)}),b.types[d].coerce(_.mean(c),e)}}(d);return this._calculated(d,e)},_calculated:function(a,c){var d=this,e=new b.Product({columns:a,func:function(a){a=a||{};var b=this._buildDelta(this.value,c.apply(d));this.value=b.changed;if(d.syncable){var e=this._buildEvent(b);!_.isUndefined(b.old)&&!a.silent&&b.old!==b.changed&&this.trigger("change",e)}}});return this.syncable?(this.bind("change",e._sync,e),e):c()}})}(this,_),function(a,_,moment){var b=a.Miso;b.Dataset=function(a){this.length=0,this._columns=[],this._columnPositionByName={},typeof a!="undefined"&&(a=a||{},this._initialize(a))},b.Dataset.prototype=new b.DataView,_.extend(b.Dataset.prototype,{_initialize:function(a){a.sync===!0&&(_.extend(this,b.Events),this.syncable=!0),this.importer=a.importer||null,this.parser=a.parser||b.Parsers.Obj,_.isUndefined(a.parser)&&(a.strict?this.parser=b.Parsers.Strict:a.delimiter&&(this.parser=b.Parsers.Delimited)),this.importer===null&&(a.url?a.interval?(this.importer=b.Importers.Polling,this.interval=a.interval):this.importer=b.Importers.Remote:this.importer=b.Importers.Local),this.parser=new this.parser(a),this.parser instanceof b.Parsers.Delimited&&(a.dataType="text"),this.importer=new this.importer(a),a.comparator&&(this.comparator=a.comparator),a.ready&&(this.ready=a.ready),a.resetOnFetch&&(this.resetOnFetch=a.resetOnFetch),a.uniqueAgainst&&(this.uniqueAgainst=a.uniqueAgainst),_.isUndefined(a.data)&&_.isUndefined(a.url)&&this._addIdColumn(),a.deferred?this.deferred=a.deferred:this.deferred=new _.Deferred,a.columns&&this.addColumns(a.columns)},fetch:function(a){a=a||{};var b=this.deferred;if(_.isNull(this.importer))throw"No importer defined";return this.importer.fetch({success:_.bind(function(c){try{this._apply(c)}catch(d){if(a.error)a.error.call(this,d);else throw d}this.comparator&&this.sort(),this.ready&&this.ready.call(this),a.success&&a.success.call(this),b.resolveWith(this,[this])},this),error:_.bind(function(c){a.error&&a.error.call(this,c),b.reject(c)},this)}),b.promise()},_applications:{againstColumn:function(a){var b=[],c=_.keys(a),d,e=this.column(this.uniqueAgainst),f=a[this._columns[1].name].length,g=_.max(_.map(c,function(b){return a[b].length},this)),h=[],i;for(i=0;i<f;i++){var j=a[this.uniqueAgainst][i];e.data.indexOf(j)!==-1&&h.push(i)}h.sort().reverse();for(i=0;i<g;i++)if(h.indexOf(i)===-1){d={};for(var k=0;k<c.length;k++)d[c[k]]=a[c[k]][i];b.push(d)}this.add(b)},blind:function(a){var b,c,d=[],e,f=_.keys(a),g=_.max(_.map(f,function(b){return a[b].length},this));for(var h=0;h<g;h++){e={};for(var i=0;i<f.length;i++)e[f[i]]=a[f[i]][h];d.push(e)}this.add(d)}},_apply:function(a){var c=this.parser.parse(a);if(!this.fetched)this._addIdColumn(),this.addColumns(_.map(c.columns,function(a){return{name:a}})),b.Builder.detectColumnTypes(this,c.data),this._applications.blind.call(this,c.data),this.fetched=!0;else if(this.resetOnFetch)this.reset(),this._applications.blind.call(this,c.data);else if(this.uniqueAgainst){if(!this.hasColumn(this.uniqueAgainst))throw new Error("You requested a unique add against a column that doesn't exist.");this._applications.againstColumn.call(this,c.data)}else this._applications.blind.call(this,c.data);b.Builder.cacheRows(this)},addColumns:function(a){_.each(a,function(a){this.addColumn(a)},this)},addColumn:function(a){return _.isUndefined(this.column(a.name))?(a=new b.Column(a),this._columns.push(a),this._columnPositionByName[a.name]=this._columns.length-1,a):!1},_addIdColumn:function(a){if(!_.isUndefined(this.column("_id")))return;var b=[];a&&a>0&&_.times(a,function(){b.push(_.uniqueId())}),this.addColumn({name:"_id",type:"number",data:b});if(this._columnPositionByName._id!==0){var c=this._columns[this._columnPositionByName._id],d=this._columnPositionByName._id;this._columns.splice(d,1),this._columns.unshift(c),this._columnPositionByName._id=0,_.each(this._columnPositionByName,function(a,b){b!=="_id"&&this._columnPositionByName[b]<d&&this._columnPositionByName[b]++},this)}},add:function(a,b){b=b||{},_.isArray(a)||(a=[a]);var c=[];_.each(a,function(a){a._id||(a._id=_.uniqueId()),this._add(a,b),this.syncable&&!b.silent&&c.push({changed:a})},this);if(this.syncable&&!b.silent){var d=this._buildEvent(c);this.trigger("add",d),this.trigger("change",d)}return this},remove:function(a,b){a=this._rowFilter(a);var c=[],d=[];this.each(function(b,e){a(b)&&(d.push(b._id),c.push({old:b}))}),_.each(d,function(a){this._remove(a)},this);if(this.syncable&&(!b||!b.silent)){var e=this._buildEvent(c);this.trigger("remove",e),this.trigger("change",e)}},update:function(a,c,d){var e,f=[],g=_.bind(function(a,d){var g,h;_.isFunction(c)?h=c.apply(this,[a]):h=c,e=_.keys(h),_.each(e,function(a){g=this.column(a);var c=b.types[g.type];if(c)if(c.test(h[g.name],g))_.isUndefined(g.before)||(h[g.name]=g.before(h[g.name])),h[g.name]=c.coerce(h[g.name],g);else throw"incorrect value '"+h[g.name]+"' of type "+b.typeOf(h[g.name],g)+" passed to column with type "+g.type;g.data[d]=h[g.name]},this),f.push({_id:a._id,old:a,changed:h})},this);_.isString(a)&&(a=[a]);if(_.isArray(a)){var h,i;_.each(a,function(a){h=this.rowById(a),i=this._rowPositionById[a],g(h,i)})}else a=this._rowFilter(a),this.each(function(b,c){a(b)&&g(b,c)},this);if(this.syncable&&(!d||!d.silent)){var j=this._buildEvent(f);this.trigger("update",j),this.trigger("change",j)}return this},reset:function(a){_.each(this._columns,function(a){a.data=[]}),this.length=0,this.syncable&&(!a||!a.silent)&&this.trigger("reset")}})}(this,_,moment),function(a,_){var b=a.Miso||(a.Miso={});b.Derived=function(a){a=a||{},b.Dataset.call(this),this.parent=a.parent,this.method=a.method,this._addIdColumn(),this.addColumn({name:"_oids",type:"mixed"}),this.parent.syncable&&(_.extend(this,b.Events),this.syncable=!0,this.parent.bind("change",this._sync,this))},b.Derived.prototype=new b.Dataset,_.extend(b.Derived.prototype,{_sync:function(a){this.func.call(this.args),this.trigger("change")}}),_.extend(b.DataView.prototype,{movingAverage:function(a,c,d){d=d||{};var e=new b.Derived({parent:this,method:d.method||_.mean,size:c,args:arguments});this.eachColumn(function(a){e.addColumn({name:a,type:this.column(a).type,data:[]})},this),b.Builder.cacheColumns(e);var f=function(){var d=[];typeof a=="string"&&(a=[a]),this.column("_id").data=this.parent.column("_id").data.slice(c-1,this.parent.length),this.eachColumn(function(b,d,e){a.indexOf(b)===-1&&b!=="_oids"?d.data=this.parent.column(b).data.slice(c-1,this.parent.length):d.data=_.movingAvg(this.parent.column(b).data,c,this.method)},this),this.length=this.parent.length-c+1;var e=this.column("_oids");e.data=[];for(var f=0;f<this.length;f++)e.data.push(this.parent.column("_id").data.slice(f,f+c));return b.Builder.cacheRows(this),this};return e.func=_.bind(f,e),e.func.call(e.args)},countBy:function(a,c){function j(a,c,d){var e;for(e=0;e<a.length;e++)if(b.types[d].compare(a[e],c)===0)return e;return-1}c=c||{};var d=new b.Derived({parent:this,method:_.sum,args:arguments}),e=this.column(a);d.addColumn({name:a,type:e.type}),d.addColumn({name:"count",type:"number"}),d.addColumn({name:"_oids",type:"mixed"}),b.Builder.cacheColumns(d);var f=d._column(a).data,g=d._column("count").data,h=d._column("_oids").data,i=d._column("_id").data;return this.each(function(b){var c=j(f,b[a],e.type);c===-1?(f.push(b[a]),i.push(_.uniqueId()),g.push(1),h.push([b._id])):(g[c]+=1,h[c].push(b._id))}),b.Builder.cacheRows(d),d},groupBy:function(a,c,d){d=d||{};var e=new b.Derived({parent:this,method:d.method||_.sum,args:arguments});d&&d.preprocess&&(e.preprocess=d.preprocess);var f=_.union([a],c);_.each(f,function(a){this.addColumn({name:a,type:this.parent.column(a).type})},e),b.Builder.cacheColumns(e);var g=function(){b.Builder.clearRowCache(this);var d={},e=0,f=this._columnPositionByName[a],g=this.parent.column(a);for(var h=0;h<this.parent.length;h++){var i=null;this.preprocess?i=this.preprocess(g.data[h]):i=g.data[h],_.isUndefined(d[i])&&(d[i]=e,_.each(c,function(a){var b=this.column(a),c=this.column("_id");b.data[e]=[],c.data[e]=_.uniqueId()},this),this.column(a).data[e]=i,e++),_.each(c,function(a){var b=this.column(a),c=this.parent.column(a).data[h],e=d[i];b.data[e].push(this.parent.rowByPosition(h))},this)}var j=this._columns[this._columnPositionByName._oids];return j.data=[],_.each(c,function(a){var b=this.column(a);_.each(b.data,function(c,d){_.isArray(c)&&(j.data[d]=j.data[d]||[],j.data[d].push(_.map(c,function(a){return a._id})),j.data[d]=_.flatten(j.data[d]),b.data[d]=this.method(_.map(c,function(b){return b[a]})),this.length++)},this)},this),b.Builder.cacheRows(this),this};return e.func=_.bind(g,e),e.func.call(e.args)}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers=function(a,b){},b.Importers.prototype.extract=function(a){return a=_.clone(a),a}}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.Local=function(a){a=a||{},this.data=a.data||null,this.extract=a.extract||this.extract},_.extend(b.Importers.Local.prototype,b.Importers.prototype,{fetch:function(a){var b=a.data?a.data:this.data;a.success(this.extract(b))}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.Remote=function(a){a=a||{},this._url=a.url,this.extract=a.extract||this.extract,this.params={type:"GET",url:_.isFunction(this._url)?_.bind(this._url,this):this._url,dataType:a.dataType?a.dataType:a.jsonp?"jsonp":"json",callback:a.callback}},_.extend(b.Importers.Remote.prototype,b.Importers.prototype,{fetch:function(a){var c=_.bind(function(b){a.success(this.extract(b))},this);this.callback&&(window[this.callback]=c),b.Xhr(_.extend(this.params,{success:this.callback?this.callback:c,error:a.error}))}});var c={url:"",data:"",dataType:"",success:function(){},type:"GET",async:!0,xhr:function(){return new a.XMLHttpRequest}},d=/\?/;b.Xhr=function(a){a.dataType=a.dataType&&a.dataType.toLowerCase()||null;var e=_.isFunction(a.url)?a.url():a.url;if(!(!a.dataType||a.dataType!=="jsonp"&&a.dataType!=="script")){b.Xhr.getJSONP(e,a.success,a.dataType==="script",a.error,a.callback);return}var f=_.extend({},c,a,{url:e});f.ajax=f.xhr();if(f.ajax)return f.type==="GET"&&f.data&&(f.url+=(d.test(f.url)?"&":"?")+f.data,f.data=null),f.ajax.open(f.type,f.url,f.async),f.ajax.send(f.data||null),b.Xhr.httpData(f)},b.Xhr.getJSONP=function(a,b,c,d,e){if(c){var f=document.querySelectorAll('script[src="'+a+'"]');if(f.length){b&&b(!0);return}}var g=document.head||document.getElementsByTagName("head")[0]||document.documentElement,h=document.createElement("script"),i=a.split("?")[1],j=!1,k=[],l;i&&!c&&(k=i.split("&")),k.length&&(l=k[k.length-1].split("="));if(!e){var m=_.uniqueId("callback");e=k.length?l[1]?l[1]:m:m}!i&&!c&&(a+="?");if(!i||!/callback/.test(i))i&&(a+="&"),a+="callback="+e;e&&!c&&(!window[e]||(e=e+ +(new Date)+_.uniqueId()),window[e]=function(a){b&&b(a),j=!0},l&&(a=a.replace(l.join("="),l[0]+"="+e))),h.onload=h.onreadystatechange=function(){if(!h.readyState||/loaded|complete/.test(h.readyState)){c&&b&&b();if(j){try{delete window[e]}catch(a){window[e]=void 0}g.removeChild(h)}}},h.onerror=function(a){d&&d.call(null,a)},h.src=a,g.insertBefore(h,g.firstChild);return},b.Xhr.httpData=function(a){var b,c=null;return a.ajax.onreadystatechange=function(){if(a.ajax.readyState===4){try{c=JSON.parse(a.ajax.responseText)}catch(d){}b={xml:a.ajax.responseXML,text:a.ajax.responseText,json:c},a.dataType&&(b=b[a.dataType]),/(2..)/.test(a.ajax.status)?a.success.call(a.ajax,b):a.error&&a.error.call(null,a.ajax.statusText)}},b}}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.Polling=function(a){a=a||{},this.interval=a.interval||1e3,this._def=null,b.Importers.Remote.apply(this,[a])},_.extend(b.Importers.Polling.prototype,b.Importers.Remote.prototype,{fetch:function(c){this._def===null&&(this._def=_.Deferred(),this.success_callback=_.bind(function(a){c.success(this.extract(a)),this._def.resolve(this)},this),this.error_callback=_.bind(function(a){c.error(a),this._def.reject(a)},this)),_.when(this._def.promise()).then(function(a){var b=_.bind(function(){this.fetch({success:this.success_callback,error:this.error_callback})},a);a._timeout=setTimeout(b,a.interval),a._def=_.Deferred()}),b.Xhr(_.extend(this.params,{success:this.success_callback,error:this.error_callback})),a.imp=this},stop:function(){this._def!==null&&this._def.reject(),typeof this._timeout!="undefined"&&clearTimeout(this._timeout)},start:function(){this._def!==null&&(this._def=_.Deferred(),this.fetch())}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Importers.GoogleSpreadsheet=function(a){a=a||{};if(a.url)a.url=a.url;else{if(_.isUndefined(a.key))throw new Error("Set options 'key' properties to point to your google document.");a.fast?(a.url="https://spreadsheets.google.com/tq?key="+a.key,typeof a.sheetName=="undefined"&&(a.sheetName="Sheet1"),a.url+="&sheet="+a.sheetName,this.callback="misodsgs"+(new Date).getTime(),a.url+="&tqx=version:0.6;responseHandler:"+this.callback,a.url+=";reqId:0;out:json&tq&_=1335871249558#",delete a.sheetName):a.url="https://spreadsheets.google.com/feeds/cells/"+a.key+"/"+a.worksheet+"/public/basic?alt=json-in-script&callback=",delete a.key}return this.params={type:"GET",url:a.url,dataType:"jsonp"},this},_.extend(b.Importers.GoogleSpreadsheet.prototype,b.Importers.Remote.prototype)}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers=function(a){this.options=a||{}},_.extend(b.Parsers.prototype,{parse:function(){}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.Strict=function(a){this.options=a||{}},_.extend(b.Parsers.Strict.prototype,b.Parsers.prototype,{parse:function(a){var b={},c=[];return _.each(a.columns,function(a){if(c.indexOf(a.name)!==-1)throw new Error('You have more than one column named "'+a.name+'"');c.push(a.name),b[a.name]=a.data}),{columns:c,data:b}}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.Obj=b.Parsers,_.extend(b.Parsers.Obj.prototype,b.Parsers.prototype,{parse:function(a){var b=_.keys(a[0]),c={};return _.each(b,function(a){c[a]=[]}),_.each(b,function(b){_.times(a.length,function(d){c[b].push(a[d][b])})}),{columns:b,data:c}}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.GoogleSpreadsheet=function(a){this.fast=a.fast||!1},_.extend(b.Parsers.GoogleSpreadsheet.prototype,b.Parsers.prototype,{parse:function(a){var b=[],c=[],d={},e;if(typeof a.status!="undefined"&&a.status==="error")throw new Error("You can't use the fast importer for this url. Disable the fast flag");if(this.fast){b=_.pluck(a.table.cols,"label");if(_.unique(b).length<b.length){var f="";throw _.inject(b,function(a,b){return a[b]=a[b]+1||1,a[b]>1&&(f=b),a},{}),new Error('You have more than one column named "'+f+'"')}_.each(a.table.rows,function(a){a=a.c;for(e=0;e<a.length;e++)c[e]=c[e]||[],a[e].v===""?c[e].push(null):c[e].push(a[e].v)}),_.each(b,function(a,b){d[a]=c[b]})}else{var g=/([A-Z]+)(\d+)/,h={};_.each(a.feed.entry,function(a,d){var e=g.exec(a.title.$t),f=e[1],i=parseInt(e[2],10);if(i===1){if(b.indexOf(a.content.$t)!==-1)throw new Error('You have more than one column named "'+a.content.$t+'"');h[f]=c.length,b[h[f]]=a.content.$t,c[h[f]]=[]}else{var j=h[f];c[j][i-1]=a.content.$t}},this),_.each(c,function(a,e){a.length=_.max(_.pluck(c,"length")),a.splice(0,1);for(var f=0;f<a.length;f++)if(_.isUndefined(a[f])||a[f]==="")a[f]=null;d[b[e]]=a})}return{columns:b,data:d}}})}(this,_),function(a,_){var b=a.Miso||(a.Miso={});b.Parsers.Delimited=function(a){a=a||{},this.delimiter=a.delimiter||",",this.skipRows=a.skipRows||0,this.emptyValue=a.emptyValue||null,this.__delimiterPatterns=new RegExp("(\\"+this.delimiter+"|\\r?\\n|\\r|^)"+'(?:"([^"]*(?:""[^"]*)*)"|'+'([^"\\'+this.delimiter+"\\r\\n]*))","gi")},typeof String.prototype.trim!="function"&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),_.extend(b.Parsers.Delimited.prototype,b.Parsers.prototype,{parse:function(a){var b=[],c={},d={},e=function(a){d[a]||(d[a]=0);var b=a+d[a];return d[a]+=1,b},f=function(a,d,f,g,h){f=f||",";var i=null,j=0,k=!1,l=-1,m=0;try{d=d.trim();if(g>0){var n=0,o=0,p=d.length;while(n<g&&o<p)/\n|\r|\r\n/.test(d[o])&&n++,o++;d=d.slice(o,p)}while(i=a.exec(d)){var q=i[1];if(q.length&&q!==f){m++;if(l<j-1)throw m--,new Error("Not enough items in row");k=!0,l=0}else k||j++,l++;var r=null;i[2]?r=i[2].replace(new RegExp('""',"g"),'"'):r=i[3];if(k){r===""&&(r=h);if(typeof c[b[l]]=="undefined")throw new Error("Too many items in row");c[b[l]].push(r)}else{var s=function(a){var c=e(a);while(b.indexOf(c)!==-1)c=e(a);return c};if(_.isUndefined(r)||r==="")r="X";b.indexOf(r)!==-1&&(r=s(r)),b.push(r),c[r]=[]}}}catch(t){throw new Error("Error while parsing delimited data on row "+m+". Message: "+t.message)}return{columns:b,data:c}};return f(this.__delimiterPatterns,a,this.delimiter,this.skipRows,this.emptyValue)}})}(this,_);
View
241 dist/node/miso.ds.deps.0.1.3.js
@@ -1,5 +1,5 @@
var path = require("path");
-var _ = require("underscore");
+var _ = require("lodash");
var moment = require("moment");
_.mixin(require("underscore.deferred"));
var request = require("request");
@@ -112,7 +112,7 @@ var request = require("request");
// Include Miso Dataset lib
/**
-* Miso.Dataset - v0.1.3 - 5/23/2012
+* Miso.Dataset - v0.1.3 - 6/19/2012
* http://github.com/misoproject/dataset
* Copyright (c) 2012 Alex Graul, Irene Ros;
* Dual Licensed: MIT, GPL
@@ -209,11 +209,39 @@ var request = require("request");
}
},
- number : {
+ number : {
name : "number",
+ regexp : /^[\-]?[0-9]+$/,
+ coerce : function(v) {
+ if (_.isNull(v)) {
+ return null;
+ }
+ return _.isNaN(v) ? null : +v;
+ },
+ test : function(v, gracious) {
+ if (v === null || typeof v === "undefined" || typeof v === 'number' || this.regexp.test( v ) || (gracious && (Miso.types['number-decimal-point'].test(v) || Miso.types['number-decimal-comma'].test(v) ))) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ compare : function(n1, n2) {
+ if (n1 == null && n2 != null) { return -1; }
+ if (n1 != null && n2 == null) { return 1; }
+ if (n1 == null && n2 == null) { return 0; }
+ if (n1 === n2) { return 0; }
+ return (n1 < n2 ? -1 : 1);
+ },
+ numeric : function(value) {
+ return value;
+ }
+ },
+
+ 'number-decimal-point' : {
+ name : "number-decimal-point",
regexp : /^[\-\.]?[0-9]+([\.][0-9]+)?$/,
coerce : function(v) {
- if (_.isNull(v) || v === "") {
+ if (_.isNull(v)) {
return null;
}
return _.isNaN(v) ? null : +v;
@@ -237,6 +265,34 @@ var request = require("request");
}
},
+ 'number-decimal-comma' : {
+ name : "number-decimal-comma",
+ regexp : /^[\-,]?[0-9]+([,][0-9]+)?$/,
+ coerce : function(v) {
+ if (_.isNull(v)) {
+ return null;
+ }
+ return _.isNaN(v) ? null : +String(v).replace(',', '.');
+ },
+ test : function(v) {
+ if (v === null || typeof v === "undefined" || typeof v === 'number' || this.regexp.test( v ) ) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ compare : function(n1, n2) {
+ if (n1 == null && n2 != null) { return -1; }
+ if (n1 != null && n2 == null) { return 1; }
+ if (n1 == null && n2 == null) { return 0; }
+ if (n1 === n2) { return 0; }
+ return (n1 < n2 ? -1 : 1);
+ },
+ numeric : function(value) {
+ return value;
+ }
+ },
+
time : {
name : "time",
format : "DD/MM/YYYY",
@@ -514,8 +570,14 @@ var request = require("request");
if (type.length === 1) {
column.type = type[0];
} else {
- //empty column or mixed type
- column.type = 'mixed';
+ type.sort();
+ if (type.length === 2 && type[0] === 'number' && type[1].substr(0,6) === 'number') {
+ // number column in local format
+ column.type = type[1];
+ } else {
+ //empty column or mixed type
+ column.type = 'mixed';
+ }
}
return column;
@@ -1002,7 +1064,7 @@ var request = require("request");
* iterator - function that is passed each row
* iterator(rowObject, index, dataset)
* context - options object. Optional.
- */
+ */
each : function(iterator, context) {
for(var i = 0; i < this.length; i++) {
iterator.apply(context || this, [this.rowByPosition(i), i]);
@@ -1010,6 +1072,19 @@ var request = require("request");
},
/**
+ * Iterates over all rows in the dataset in reverse order
+ * Parameters:
+ * iterator - function that is passed each row
+ * iterator(rowObject, index, dataset)
+ * context - options object. Optional.
+ */
+ reverseEach : function(iterator, context) {
+ for(var i = this.length-1; i >= 0; i--) {
+ iterator.apply(context || this, [this.rowByPosition(i), i]);
+ }
+ },
+
+ /**
* Iterates over each column.
* Parameters:
* iterator - function that is passed:
@@ -1081,7 +1156,7 @@ var request = require("request");
var Type = Miso.types[column.type];
// test if value matches column type
- if (column.force || Type.test(row[column.name], column)) {
+ if (column.force || Type.test(row[column.name], true)) {
// do we have a before filter? If so, pass it through that first
if (!_.isUndefined(column.before)) {
@@ -1174,8 +1249,15 @@ var request = require("request");
* Parameters:
* options - Optional
*/
- sort : function(options) {
- options = options || {};
+ sort : function(args) {
+ var options = {};
+
+ //If the first param is the comparator, set it as such.
+ if ( _.isFunction(args) ) {
+ options.comparator = args;
+ } else {
+ options = args || options;
+ }
if (options.comparator) {
this.comparator = options.comparator;
@@ -1707,13 +1789,14 @@ Version 0.0.1.2
// implementation, pass it as an option
if (options.deferred) {
this.deferred = options.deferred;
+ } else {
+ this.deferred = new _.Deferred();
}
//build any columns present in the constructor
if ( options.columns ) {
this.addColumns(options.columns);
}
-
},
/**
@@ -1744,7 +1827,7 @@ Version 0.0.1.2
fetch : function(options) {
options = options || {};
- var dfd = this.deferred || new _.Deferred();
+ var dfd = this.deferred;
if ( _.isNull(this.importer) ) {
throw "No importer defined";
@@ -1753,7 +1836,15 @@ Version 0.0.1.2
this.importer.fetch({
success: _.bind(function( data ) {
- this._apply( data );
+ try {
+ this._apply( data );
+ } catch (e) {
+ if (options.error) {
+ options.error.call(this, e);
+ } else {
+ throw e;
+ }
+ }
// if a comparator was defined, sort the data
if (this.comparator) {
@@ -1775,7 +1866,7 @@ Version 0.0.1.2
error : _.bind(function(e) {
if (options.error) {
- options.error.call(this);
+ options.error.call(this, e);
}
dfd.reject(e);
@@ -2549,7 +2640,8 @@ Version 0.0.1.2
this.params = {
type : "GET",
url : _.isFunction(this._url) ? _.bind(this._url, this) : this._url,
- dataType : options.dataType ? options.dataType : (options.jsonp ? "jsonp" : "json")
+ dataType : options.dataType ? options.dataType : (options.jsonp ? "jsonp" : "json"),
+ callback : options.callback
};
};
@@ -2604,7 +2696,8 @@ Version 0.0.1.2
url,
options.success,
options.dataType === "script",
- options.error
+ options.error,
+ options.callback
);
return;
@@ -2632,7 +2725,7 @@ Version 0.0.1.2
}
};
- Miso.Xhr.getJSONP = function(url, success, isScript, error) {
+ Miso.Xhr.getJSONP = function(url, success, isScript, error, callback) {
// If this is a script request, ensure that we do not
// call something that has already been loaded
if (isScript) {
@@ -2659,7 +2752,7 @@ Version 0.0.1.2
paramStr = url.split("?")[ 1 ],
isFired = false,
params = [],
- callback, parts, callparam;
+ parts;
// Extract params
if (paramStr && !isScript) {
@@ -2668,10 +2761,18 @@ Version 0.0.1.2
if (params.length) {
parts = params[params.length - 1].split("=");
}
- callback = params.length ? (parts[ 1 ] ? parts[ 1 ] : parts[ 0 ]) : "jsonp";
+ if (!callback) {
+ var fallback = _.uniqueId('callback');
+ callback = params.length ? (parts[ 1 ] ? parts[ 1 ] : fallback) : fallback;
+ }
if (!paramStr && !isScript) {
- url += "?callback=" + callback;
+ url += "?";
+ }
+
+ if ( !paramStr || !/callback/.test(paramStr) ) {
+ if (paramStr) { url += '&'; }
+ url += "callback=" + callback;
}
if (callback && !isScript) {
@@ -2690,7 +2791,9 @@ Version 0.0.1.2
};
// Replace callback param and callback name
- url = url.replace(parts.join("="), parts[0] + "=" + callback);
+ if (parts) {
+ url = url.replace(parts.join("="), parts[0] + "=" + callback);
+ }
}
script.onload = script.onreadystatechange = function() {
@@ -2723,7 +2826,7 @@ Version 0.0.1.2
script.onerror = function(e) {
if (error) {
- error.call(null);
+ error.call(null, e);
}
};
@@ -2886,19 +2989,16 @@ Version 0.0.1.2
options.url = "https://spreadsheets.google.com/tq?key=" + options.key;
- if (options.sheetName) {
- options.url += "&sheet=" + options.sheetName;
- } else {
- options.url += "&gid=" + (options.worksheet || 1);
- delete options.worksheet;
- }
+ if (typeof options.sheetName === "undefined") {
+ options.sheetName = "Sheet1";
+ }
+ options.url += "&sheet=" + options.sheetName;
this.callback = "misodsgs" + new Date().getTime();
options.url += "&tqx=version:0.6;responseHandler:" + this.callback;
options.url += ";reqId:0;out:json&tq&_=1335871249558#";
delete options.sheetName;
-
} else {
options.url = "https://spreadsheets.google.com/feeds/cells/" +
options.key + "/" +
@@ -2910,6 +3010,7 @@ Version 0.0.1.2
}
}
+
this.params = {
type : "GET",
url : options.url,
@@ -2967,8 +3068,12 @@ Version 0.0.1.2
var columnData = {}, columnNames = [];
_.each(data.columns, function(column) {
- columnNames.push( column.name );
- columnData[ column.name ] = column.data;
+ if (columnNames.indexOf(column.name) !== -1) {
+ throw new Error("You have more than one column named \"" + column.name + "\"");
+ } else {
+ columnNames.push( column.name );
+ columnData[ column.name ] = column.data;
+ }
});
return {
@@ -3044,11 +3149,32 @@ Version 0.0.1.2
keyedData = {},
i;
+ // the fast importer API is not available
+ if (typeof data.status !== "undefined" && data.status === "error") {
+ throw new Error("You can't use the fast importer for this url. Disable the fast flag");
+ }
+
if (this.fast) {
// init column names
columns = _.pluck(data.table.cols, "label");
+ // check that the column names don't have duplicates
+ if (_.unique(columns).length < columns.length) {
+ var dup = "";
+
+ _.inject(columns, function(memo, val) {
+
+ memo[val] = (memo[val] + 1) || 1;
+ if (memo[val] > 1) {
+ dup = val;
+ }
+ return memo;
+ }, {});
+
+ throw new Error("You have more than one column named \"" + dup + "\"");
+ }
+
// save data
_.each(data.table.rows, function(row) {
row = row.c;
@@ -3077,15 +3203,20 @@ Version 0.0.1.2
column = parts[1],
position = parseInt(parts[2], 10);
- if (_.isUndefined(columnPositions[column])) {
-
- // cache the column position
- columnPositions[column] = columnData.length;
+ // this is the first row, thus column names.
+ if (position === 1) {
- // we found a new column, so build a new column type.
- columns[columnPositions[column]] = cell.content.$t;
- columnData[columnPositions[column]] = [];
+ // if we've already seen this column name, throw an exception
+ if (columns.indexOf(cell.content.$t) !== -1) {
+ throw new Error("You have more than one column named \"" + cell.content.$t + "\"");
+ } else {
+ // cache the column position
+ columnPositions[column] = columnData.length;
+ // we found a new column, so build a new column type.
+ columns[columnPositions[column]] = cell.content.$t;
+ columnData[columnPositions[column]] = [];
+ }
} else {
@@ -3172,8 +3303,19 @@ Version 0.0.1.2
_.extend(Miso.Parsers.Delimited.prototype, Miso.Parsers.prototype, {
parse : function(data) {
- var columns = [];
- var columnData = {};
+ var columns = [],
+ columnData = {},
+ uniqueSequence = {};
+
+ var uniqueId = function(str) {
+ if ( !uniqueSequence[str] ) {
+ uniqueSequence[str] = 0;
+ }
+ var id = str + uniqueSequence[str];
+ uniqueSequence[str] += 1;
+ return id;
+ };
+
var parseCSV = function(delimiterPattern, strData, strDelimiter, skipRows, emptyValue) {
@@ -3295,6 +3437,25 @@ Version 0.0.1.2
columnData[columns[columnIndex]].push(strMatchedValue);
} else {
+
+ var createColumnName = function(start) {
+ var newName = uniqueId(start);
+ while ( columns.indexOf(newName) !== -1 ) {
+ newName = uniqueId(start);
+ }
+ return newName;
+ };
+
+ //No column name? Create one starting with X
+ if ( _.isUndefined(strMatchedValue) || strMatchedValue === '' ) {
+ strMatchedValue = 'X';
+ }
+
+ //Duplicate column name? Create a new one starting with the name
+ if (columns.indexOf(strMatchedValue) !== -1) {
+ strMatchedValue = createColumnName(strMatchedValue);
+ }
+
// we are building the column names here
columns.push(strMatchedValue);
columnData[strMatchedValue] = [];
View
2  src/view.js
@@ -483,7 +483,7 @@
var Type = Miso.types[column.type];
// test if value matches column type
- if (column.force || Type.test(row[column.name], column)) {
+ if (column.force || Type.test(row[column.name], column, true)) {
// do we have a before filter? If so, pass it through that first
if (!_.isUndefined(column.before)) {
Please sign in to comment.
Something went wrong with that request. Please try again.