highcharts-rails 3.0.3 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +13 -13
- data.tar.gz.asc +13 -13
- data/.gitignore +1 -0
- data/CHANGELOG.markdown +4 -0
- data/README.markdown +1 -0
- data/Rakefile +1 -29
- data/app/assets/javascripts/highcharts.js +280 -16676
- data/app/assets/javascripts/highcharts/adapters/mootools.js +13 -313
- data/app/assets/javascripts/highcharts/adapters/prototype.js +15 -316
- data/app/assets/javascripts/highcharts/adapters/standalone.js +17 -0
- data/app/assets/javascripts/highcharts/highcharts-more.js +50 -2426
- data/app/assets/javascripts/highcharts/modules/annotations.js +7 -401
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +133 -3113
- data/app/assets/javascripts/highcharts/modules/data.js +16 -581
- data/app/assets/javascripts/highcharts/modules/exporting.js +22 -704
- data/app/assets/javascripts/highcharts/modules/funnel.js +12 -284
- data/app/assets/javascripts/highcharts/modules/heatmap.js +1 -57
- data/app/assets/javascripts/highcharts/modules/map.js +21 -576
- data/highcharts-rails.gemspec +0 -1
- data/lib/highcharts/version.rb +1 -1
- metadata +4 -4
- metadata.gz.asc +13 -13
| @@ -1,582 +1,17 @@ | |
| 1 | 
            -
            /**
         | 
| 2 | 
            -
             * @license Data plugin for Highcharts
         | 
| 3 | 
            -
             *
         | 
| 4 | 
            -
             * (c) 2012-2013 Torstein Hønsi
         | 
| 5 | 
            -
             * Last revision 2013-06-07
         | 
| 6 | 
            -
             *
         | 
| 7 | 
            -
             * License: www.highcharts.com/license
         | 
| 8 | 
            -
             */
         | 
| 9 | 
            -
             | 
| 10 1 | 
             
            /*
         | 
| 11 | 
            -
              | 
| 12 | 
            -
             | 
| 13 | 
            -
              | 
| 14 | 
            -
              | 
| 15 | 
            -
             | 
| 16 | 
            -
              | 
| 17 | 
            -
             | 
| 18 | 
            -
              | 
| 19 | 
            -
              | 
| 20 | 
            -
             | 
| 21 | 
            -
              | 
| 22 | 
            -
             | 
| 23 | 
            -
              | 
| 24 | 
            -
              | 
| 25 | 
            -
              | 
| 26 | 
            -
              | 
| 27 | 
            -
             * external source, and parsed. The first argument passed is a finished chart options
         | 
| 28 | 
            -
             * object, containing series and an xAxis with categories if applicable. Thise options
         | 
| 29 | 
            -
             * can be extended with additional options and passed directly to the chart constructor.
         | 
| 30 | 
            -
             *
         | 
| 31 | 
            -
             * - csv : String
         | 
| 32 | 
            -
             * A comma delimited string to be parsed. Related options are startRow, endRow, startColumn
         | 
| 33 | 
            -
             * and endColumn to delimit what part of the table is used. The lineDelimiter and 
         | 
| 34 | 
            -
             * itemDelimiter options define the CSV delimiter formats.
         | 
| 35 | 
            -
             * 
         | 
| 36 | 
            -
             * - endColumn : Integer
         | 
| 37 | 
            -
             * In tabular input data, the first row (indexed by 0) to use. Defaults to the last 
         | 
| 38 | 
            -
             * column containing data.
         | 
| 39 | 
            -
             *
         | 
| 40 | 
            -
             * - endRow : Integer
         | 
| 41 | 
            -
             * In tabular input data, the last row (indexed by 0) to use. Defaults to the last row
         | 
| 42 | 
            -
             * containing data.
         | 
| 43 | 
            -
             *
         | 
| 44 | 
            -
             * - googleSpreadsheetKey : String 
         | 
| 45 | 
            -
             * A Google Spreadsheet key. See https://developers.google.com/gdata/samples/spreadsheet_sample
         | 
| 46 | 
            -
             * for general information on GS.
         | 
| 47 | 
            -
             *
         | 
| 48 | 
            -
             * - googleSpreadsheetWorksheet : String 
         | 
| 49 | 
            -
             * The Google Spreadsheet worksheet. The available id's can be read from 
         | 
| 50 | 
            -
             * https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic
         | 
| 51 | 
            -
             *
         | 
| 52 | 
            -
             * - itemDelimiter : String
         | 
| 53 | 
            -
             * Item or cell delimiter for parsing CSV. Defaults to ",".
         | 
| 54 | 
            -
             *
         | 
| 55 | 
            -
             * - lineDelimiter : String
         | 
| 56 | 
            -
             * Line delimiter for parsing CSV. Defaults to "\n".
         | 
| 57 | 
            -
             *
         | 
| 58 | 
            -
             * - parsed : Function
         | 
| 59 | 
            -
             * A callback function to access the parsed columns, the two-dimentional input data
         | 
| 60 | 
            -
             * array directly, before they are interpreted into series data and categories.
         | 
| 61 | 
            -
             *
         | 
| 62 | 
            -
             * - parseDate : Function
         | 
| 63 | 
            -
             * A callback function to parse string representations of dates into JavaScript timestamps.
         | 
| 64 | 
            -
             * Return an integer on success.
         | 
| 65 | 
            -
             *
         | 
| 66 | 
            -
             * - rows : Array<Array<Mixed>>
         | 
| 67 | 
            -
             * The same as the columns input option, but defining rows intead of columns.
         | 
| 68 | 
            -
             *
         | 
| 69 | 
            -
             * - startColumn : Integer
         | 
| 70 | 
            -
             * In tabular input data, the first column (indexed by 0) to use. 
         | 
| 71 | 
            -
             *
         | 
| 72 | 
            -
             * - startRow : Integer
         | 
| 73 | 
            -
             * In tabular input data, the first row (indexed by 0) to use.
         | 
| 74 | 
            -
             *
         | 
| 75 | 
            -
             * - table : String|HTMLElement
         | 
| 76 | 
            -
             * A HTML table or the id of such to be parsed as input data. Related options ara startRow,
         | 
| 77 | 
            -
             * endRow, startColumn and endColumn to delimit what part of the table is used.
         | 
| 78 | 
            -
             */
         | 
| 79 | 
            -
             | 
| 80 | 
            -
            // JSLint options:
         | 
| 81 | 
            -
            /*global jQuery */
         | 
| 82 | 
            -
             | 
| 83 | 
            -
            (function (Highcharts) {	
         | 
| 84 | 
            -
            	
         | 
| 85 | 
            -
            	// Utilities
         | 
| 86 | 
            -
            	var each = Highcharts.each;
         | 
| 87 | 
            -
            	
         | 
| 88 | 
            -
            	
         | 
| 89 | 
            -
            	// The Data constructor
         | 
| 90 | 
            -
            	var Data = function (dataOptions, chartOptions) {
         | 
| 91 | 
            -
            		this.init(dataOptions, chartOptions);
         | 
| 92 | 
            -
            	};
         | 
| 93 | 
            -
            	
         | 
| 94 | 
            -
            	// Set the prototype properties
         | 
| 95 | 
            -
            	Highcharts.extend(Data.prototype, {
         | 
| 96 | 
            -
            		
         | 
| 97 | 
            -
            	/**
         | 
| 98 | 
            -
            	 * Initialize the Data object with the given options
         | 
| 99 | 
            -
            	 */
         | 
| 100 | 
            -
            	init: function (options, chartOptions) {
         | 
| 101 | 
            -
            		this.options = options;
         | 
| 102 | 
            -
            		this.chartOptions = chartOptions;
         | 
| 103 | 
            -
            		this.columns = options.columns || this.rowsToColumns(options.rows) || [];
         | 
| 104 | 
            -
             | 
| 105 | 
            -
            		// No need to parse or interpret anything
         | 
| 106 | 
            -
            		if (this.columns.length) {
         | 
| 107 | 
            -
            			this.dataFound();
         | 
| 108 | 
            -
             | 
| 109 | 
            -
            		// Parse and interpret
         | 
| 110 | 
            -
            		} else {
         | 
| 111 | 
            -
             | 
| 112 | 
            -
            			// Parse a CSV string if options.csv is given
         | 
| 113 | 
            -
            			this.parseCSV();
         | 
| 114 | 
            -
            			
         | 
| 115 | 
            -
            			// Parse a HTML table if options.table is given
         | 
| 116 | 
            -
            			this.parseTable();
         | 
| 117 | 
            -
             | 
| 118 | 
            -
            			// Parse a Google Spreadsheet 
         | 
| 119 | 
            -
            			this.parseGoogleSpreadsheet();	
         | 
| 120 | 
            -
            		}
         | 
| 121 | 
            -
             | 
| 122 | 
            -
            	},
         | 
| 123 | 
            -
             | 
| 124 | 
            -
            	/**
         | 
| 125 | 
            -
            	 * Get the column distribution. For example, a line series takes a single column for 
         | 
| 126 | 
            -
            	 * Y values. A range series takes two columns for low and high values respectively,
         | 
| 127 | 
            -
            	 * and an OHLC series takes four columns.
         | 
| 128 | 
            -
            	 */
         | 
| 129 | 
            -
            	getColumnDistribution: function () {
         | 
| 130 | 
            -
            		var chartOptions = this.chartOptions,
         | 
| 131 | 
            -
            			getValueCount = function (type) {
         | 
| 132 | 
            -
            				return (Highcharts.seriesTypes[type || 'line'].prototype.pointArrayMap || [0]).length;
         | 
| 133 | 
            -
            			},
         | 
| 134 | 
            -
            			globalType = chartOptions && chartOptions.chart && chartOptions.chart.type,
         | 
| 135 | 
            -
            			individualCounts = [];
         | 
| 136 | 
            -
             | 
| 137 | 
            -
            		each((chartOptions && chartOptions.series) || [], function (series) {
         | 
| 138 | 
            -
            			individualCounts.push(getValueCount(series.type || globalType));
         | 
| 139 | 
            -
            		});
         | 
| 140 | 
            -
             | 
| 141 | 
            -
            		this.valueCount = {
         | 
| 142 | 
            -
            			global: getValueCount(globalType),
         | 
| 143 | 
            -
            			individual: individualCounts
         | 
| 144 | 
            -
            		};
         | 
| 145 | 
            -
            	},
         | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
            	dataFound: function () {
         | 
| 149 | 
            -
            		// Interpret the values into right types
         | 
| 150 | 
            -
            		this.parseTypes();
         | 
| 151 | 
            -
            		
         | 
| 152 | 
            -
            		// Use first row for series names?
         | 
| 153 | 
            -
            		this.findHeaderRow();
         | 
| 154 | 
            -
            		
         | 
| 155 | 
            -
            		// Handle columns if a handleColumns callback is given
         | 
| 156 | 
            -
            		this.parsed();
         | 
| 157 | 
            -
            		
         | 
| 158 | 
            -
            		// Complete if a complete callback is given
         | 
| 159 | 
            -
            		this.complete();
         | 
| 160 | 
            -
            		
         | 
| 161 | 
            -
            	},
         | 
| 162 | 
            -
            	
         | 
| 163 | 
            -
            	/**
         | 
| 164 | 
            -
            	 * Parse a CSV input string
         | 
| 165 | 
            -
            	 */
         | 
| 166 | 
            -
            	parseCSV: function () {
         | 
| 167 | 
            -
            		var self = this,
         | 
| 168 | 
            -
            			options = this.options,
         | 
| 169 | 
            -
            			csv = options.csv,
         | 
| 170 | 
            -
            			columns = this.columns,
         | 
| 171 | 
            -
            			startRow = options.startRow || 0,
         | 
| 172 | 
            -
            			endRow = options.endRow || Number.MAX_VALUE,
         | 
| 173 | 
            -
            			startColumn = options.startColumn || 0,
         | 
| 174 | 
            -
            			endColumn = options.endColumn || Number.MAX_VALUE,
         | 
| 175 | 
            -
            			lines,
         | 
| 176 | 
            -
            			activeRowNo = 0;
         | 
| 177 | 
            -
            			
         | 
| 178 | 
            -
            		if (csv) {
         | 
| 179 | 
            -
            			
         | 
| 180 | 
            -
            			lines = csv
         | 
| 181 | 
            -
            				.replace(/\r\n/g, "\n") // Unix
         | 
| 182 | 
            -
            				.replace(/\r/g, "\n") // Mac
         | 
| 183 | 
            -
            				.split(options.lineDelimiter || "\n");
         | 
| 184 | 
            -
            			
         | 
| 185 | 
            -
            			each(lines, function (line, rowNo) {
         | 
| 186 | 
            -
            				var trimmed = self.trim(line),
         | 
| 187 | 
            -
            					isComment = trimmed.indexOf('#') === 0,
         | 
| 188 | 
            -
            					isBlank = trimmed === '',
         | 
| 189 | 
            -
            					items;
         | 
| 190 | 
            -
            				
         | 
| 191 | 
            -
            				if (rowNo >= startRow && rowNo <= endRow && !isComment && !isBlank) {
         | 
| 192 | 
            -
            					items = line.split(options.itemDelimiter || ',');
         | 
| 193 | 
            -
            					each(items, function (item, colNo) {
         | 
| 194 | 
            -
            						if (colNo >= startColumn && colNo <= endColumn) {
         | 
| 195 | 
            -
            							if (!columns[colNo - startColumn]) {
         | 
| 196 | 
            -
            								columns[colNo - startColumn] = [];					
         | 
| 197 | 
            -
            							}
         | 
| 198 | 
            -
            							
         | 
| 199 | 
            -
            							columns[colNo - startColumn][activeRowNo] = item;
         | 
| 200 | 
            -
            						}
         | 
| 201 | 
            -
            					});
         | 
| 202 | 
            -
            					activeRowNo += 1;
         | 
| 203 | 
            -
            				}
         | 
| 204 | 
            -
            			});
         | 
| 205 | 
            -
             | 
| 206 | 
            -
            			this.dataFound();
         | 
| 207 | 
            -
            		}
         | 
| 208 | 
            -
            	},
         | 
| 209 | 
            -
            	
         | 
| 210 | 
            -
            	/**
         | 
| 211 | 
            -
            	 * Parse a HTML table
         | 
| 212 | 
            -
            	 */
         | 
| 213 | 
            -
            	parseTable: function () {
         | 
| 214 | 
            -
            		var options = this.options,
         | 
| 215 | 
            -
            			table = options.table,
         | 
| 216 | 
            -
            			columns = this.columns,
         | 
| 217 | 
            -
            			startRow = options.startRow || 0,
         | 
| 218 | 
            -
            			endRow = options.endRow || Number.MAX_VALUE,
         | 
| 219 | 
            -
            			startColumn = options.startColumn || 0,
         | 
| 220 | 
            -
            			endColumn = options.endColumn || Number.MAX_VALUE,
         | 
| 221 | 
            -
            			colNo;
         | 
| 222 | 
            -
            			
         | 
| 223 | 
            -
            		if (table) {
         | 
| 224 | 
            -
            			
         | 
| 225 | 
            -
            			if (typeof table === 'string') {
         | 
| 226 | 
            -
            				table = document.getElementById(table);
         | 
| 227 | 
            -
            			}
         | 
| 228 | 
            -
            			
         | 
| 229 | 
            -
            			each(table.getElementsByTagName('tr'), function (tr, rowNo) {
         | 
| 230 | 
            -
            				colNo = 0; 
         | 
| 231 | 
            -
            				if (rowNo >= startRow && rowNo <= endRow) {
         | 
| 232 | 
            -
            					each(tr.childNodes, function (item) {
         | 
| 233 | 
            -
            						if ((item.tagName === 'TD' || item.tagName === 'TH') && colNo >= startColumn && colNo <= endColumn) {
         | 
| 234 | 
            -
            							if (!columns[colNo]) {
         | 
| 235 | 
            -
            								columns[colNo] = [];					
         | 
| 236 | 
            -
            							}
         | 
| 237 | 
            -
            							columns[colNo][rowNo - startRow] = item.innerHTML;
         | 
| 238 | 
            -
            							
         | 
| 239 | 
            -
            							colNo += 1;
         | 
| 240 | 
            -
            						}
         | 
| 241 | 
            -
            					});
         | 
| 242 | 
            -
            				}
         | 
| 243 | 
            -
            			});
         | 
| 244 | 
            -
             | 
| 245 | 
            -
            			this.dataFound(); // continue
         | 
| 246 | 
            -
            		}
         | 
| 247 | 
            -
            	},
         | 
| 248 | 
            -
             | 
| 249 | 
            -
            	/**
         | 
| 250 | 
            -
            	 * TODO: 
         | 
| 251 | 
            -
            	 * - switchRowsAndColumns
         | 
| 252 | 
            -
            	 */
         | 
| 253 | 
            -
            	parseGoogleSpreadsheet: function () {
         | 
| 254 | 
            -
            		var self = this,
         | 
| 255 | 
            -
            			options = this.options,
         | 
| 256 | 
            -
            			googleSpreadsheetKey = options.googleSpreadsheetKey,
         | 
| 257 | 
            -
            			columns = this.columns,
         | 
| 258 | 
            -
            			startRow = options.startRow || 0,
         | 
| 259 | 
            -
            			endRow = options.endRow || Number.MAX_VALUE,
         | 
| 260 | 
            -
            			startColumn = options.startColumn || 0,
         | 
| 261 | 
            -
            			endColumn = options.endColumn || Number.MAX_VALUE,
         | 
| 262 | 
            -
            			gr, // google row
         | 
| 263 | 
            -
            			gc; // google column
         | 
| 264 | 
            -
             | 
| 265 | 
            -
            		if (googleSpreadsheetKey) {
         | 
| 266 | 
            -
            			jQuery.getJSON('https://spreadsheets.google.com/feeds/cells/' + 
         | 
| 267 | 
            -
            				  googleSpreadsheetKey + '/' + (options.googleSpreadsheetWorksheet || 'od6') +
         | 
| 268 | 
            -
            					  '/public/values?alt=json-in-script&callback=?',
         | 
| 269 | 
            -
            					  function (json) {
         | 
| 270 | 
            -
            					
         | 
| 271 | 
            -
            				// Prepare the data from the spreadsheat
         | 
| 272 | 
            -
            				var cells = json.feed.entry,
         | 
| 273 | 
            -
            					cell,
         | 
| 274 | 
            -
            					cellCount = cells.length,
         | 
| 275 | 
            -
            					colCount = 0,
         | 
| 276 | 
            -
            					rowCount = 0,
         | 
| 277 | 
            -
            					i;
         | 
| 278 | 
            -
            			
         | 
| 279 | 
            -
            				// First, find the total number of columns and rows that 
         | 
| 280 | 
            -
            				// are actually filled with data
         | 
| 281 | 
            -
            				for (i = 0; i < cellCount; i++) {
         | 
| 282 | 
            -
            					cell = cells[i];
         | 
| 283 | 
            -
            					colCount = Math.max(colCount, cell.gs$cell.col);
         | 
| 284 | 
            -
            					rowCount = Math.max(rowCount, cell.gs$cell.row);			
         | 
| 285 | 
            -
            				}
         | 
| 286 | 
            -
            			
         | 
| 287 | 
            -
            				// Set up arrays containing the column data
         | 
| 288 | 
            -
            				for (i = 0; i < colCount; i++) {
         | 
| 289 | 
            -
            					if (i >= startColumn && i <= endColumn) {
         | 
| 290 | 
            -
            						// Create new columns with the length of either end-start or rowCount
         | 
| 291 | 
            -
            						columns[i - startColumn] = [];
         | 
| 292 | 
            -
             | 
| 293 | 
            -
            						// Setting the length to avoid jslint warning
         | 
| 294 | 
            -
            						columns[i - startColumn].length = Math.min(rowCount, endRow - startRow);
         | 
| 295 | 
            -
            					}
         | 
| 296 | 
            -
            				}
         | 
| 297 | 
            -
            				
         | 
| 298 | 
            -
            				// Loop over the cells and assign the value to the right
         | 
| 299 | 
            -
            				// place in the column arrays
         | 
| 300 | 
            -
            				for (i = 0; i < cellCount; i++) {
         | 
| 301 | 
            -
            					cell = cells[i];
         | 
| 302 | 
            -
            					gr = cell.gs$cell.row - 1; // rows start at 1
         | 
| 303 | 
            -
            					gc = cell.gs$cell.col - 1; // columns start at 1
         | 
| 304 | 
            -
             | 
| 305 | 
            -
            					// If both row and col falls inside start and end
         | 
| 306 | 
            -
            					// set the transposed cell value in the newly created columns
         | 
| 307 | 
            -
            					if (gc >= startColumn && gc <= endColumn &&
         | 
| 308 | 
            -
            						gr >= startRow && gr <= endRow) {
         | 
| 309 | 
            -
            						columns[gc - startColumn][gr - startRow] = cell.content.$t;
         | 
| 310 | 
            -
            					}
         | 
| 311 | 
            -
            				}
         | 
| 312 | 
            -
            				self.dataFound();
         | 
| 313 | 
            -
            			});
         | 
| 314 | 
            -
            		}
         | 
| 315 | 
            -
            	},
         | 
| 316 | 
            -
            	
         | 
| 317 | 
            -
            	/**
         | 
| 318 | 
            -
            	 * Find the header row. For now, we just check whether the first row contains
         | 
| 319 | 
            -
            	 * numbers or strings. Later we could loop down and find the first row with 
         | 
| 320 | 
            -
            	 * numbers.
         | 
| 321 | 
            -
            	 */
         | 
| 322 | 
            -
            	findHeaderRow: function () {
         | 
| 323 | 
            -
            		var headerRow = 0;
         | 
| 324 | 
            -
            		each(this.columns, function (column) {
         | 
| 325 | 
            -
            			if (typeof column[0] !== 'string') {
         | 
| 326 | 
            -
            				headerRow = null;
         | 
| 327 | 
            -
            			}
         | 
| 328 | 
            -
            		});
         | 
| 329 | 
            -
            		this.headerRow = 0;			
         | 
| 330 | 
            -
            	},
         | 
| 331 | 
            -
            	
         | 
| 332 | 
            -
            	/**
         | 
| 333 | 
            -
            	 * Trim a string from whitespace
         | 
| 334 | 
            -
            	 */
         | 
| 335 | 
            -
            	trim: function (str) {
         | 
| 336 | 
            -
            		return typeof str === 'string' ? str.replace(/^\s+|\s+$/g, '') : str;
         | 
| 337 | 
            -
            	},
         | 
| 338 | 
            -
            	
         | 
| 339 | 
            -
            	/**
         | 
| 340 | 
            -
            	 * Parse numeric cells in to number types and date types in to true dates.
         | 
| 341 | 
            -
            	 * @param {Object} columns
         | 
| 342 | 
            -
            	 */
         | 
| 343 | 
            -
            	parseTypes: function () {
         | 
| 344 | 
            -
            		var columns = this.columns,
         | 
| 345 | 
            -
            			col = columns.length, 
         | 
| 346 | 
            -
            			row,
         | 
| 347 | 
            -
            			val,
         | 
| 348 | 
            -
            			floatVal,
         | 
| 349 | 
            -
            			trimVal,
         | 
| 350 | 
            -
            			dateVal;
         | 
| 351 | 
            -
            			
         | 
| 352 | 
            -
            		while (col--) {
         | 
| 353 | 
            -
            			row = columns[col].length;
         | 
| 354 | 
            -
            			while (row--) {
         | 
| 355 | 
            -
            				val = columns[col][row];
         | 
| 356 | 
            -
            				floatVal = parseFloat(val);
         | 
| 357 | 
            -
            				trimVal = this.trim(val);
         | 
| 358 | 
            -
             | 
| 359 | 
            -
            				/*jslint eqeq: true*/
         | 
| 360 | 
            -
            				if (trimVal == floatVal) { // is numeric
         | 
| 361 | 
            -
            				/*jslint eqeq: false*/
         | 
| 362 | 
            -
            					columns[col][row] = floatVal;
         | 
| 363 | 
            -
            					
         | 
| 364 | 
            -
            					// If the number is greater than milliseconds in a year, assume datetime
         | 
| 365 | 
            -
            					if (floatVal > 365 * 24 * 3600 * 1000) {
         | 
| 366 | 
            -
            						columns[col].isDatetime = true;
         | 
| 367 | 
            -
            					} else {
         | 
| 368 | 
            -
            						columns[col].isNumeric = true;
         | 
| 369 | 
            -
            					}					
         | 
| 370 | 
            -
            				
         | 
| 371 | 
            -
            				} else { // string, continue to determine if it is a date string or really a string
         | 
| 372 | 
            -
            					dateVal = this.parseDate(val);
         | 
| 373 | 
            -
            					
         | 
| 374 | 
            -
            					if (col === 0 && typeof dateVal === 'number' && !isNaN(dateVal)) { // is date
         | 
| 375 | 
            -
            						columns[col][row] = dateVal;
         | 
| 376 | 
            -
            						columns[col].isDatetime = true;
         | 
| 377 | 
            -
            					
         | 
| 378 | 
            -
            					} else { // string
         | 
| 379 | 
            -
            						columns[col][row] = trimVal === '' ? null : trimVal;
         | 
| 380 | 
            -
            					}
         | 
| 381 | 
            -
            				}
         | 
| 382 | 
            -
            				
         | 
| 383 | 
            -
            			}
         | 
| 384 | 
            -
            		}
         | 
| 385 | 
            -
            	},
         | 
| 386 | 
            -
            	//*
         | 
| 387 | 
            -
            	dateFormats: {
         | 
| 388 | 
            -
            		'YYYY-mm-dd': {
         | 
| 389 | 
            -
            			regex: '^([0-9]{4})-([0-9]{2})-([0-9]{2})$',
         | 
| 390 | 
            -
            			parser: function (match) {
         | 
| 391 | 
            -
            				return Date.UTC(+match[1], match[2] - 1, +match[3]);
         | 
| 392 | 
            -
            			}
         | 
| 393 | 
            -
            		}
         | 
| 394 | 
            -
            	},
         | 
| 395 | 
            -
            	// */
         | 
| 396 | 
            -
            	/**
         | 
| 397 | 
            -
            	 * Parse a date and return it as a number. Overridable through options.parseDate.
         | 
| 398 | 
            -
            	 */
         | 
| 399 | 
            -
            	parseDate: function (val) {
         | 
| 400 | 
            -
            		var parseDate = this.options.parseDate,
         | 
| 401 | 
            -
            			ret,
         | 
| 402 | 
            -
            			key,
         | 
| 403 | 
            -
            			format,
         | 
| 404 | 
            -
            			match;
         | 
| 405 | 
            -
             | 
| 406 | 
            -
            		if (parseDate) {
         | 
| 407 | 
            -
            			ret = parseDate(val);
         | 
| 408 | 
            -
            		}
         | 
| 409 | 
            -
            			
         | 
| 410 | 
            -
            		if (typeof val === 'string') {
         | 
| 411 | 
            -
            			for (key in this.dateFormats) {
         | 
| 412 | 
            -
            				format = this.dateFormats[key];
         | 
| 413 | 
            -
            				match = val.match(format.regex);
         | 
| 414 | 
            -
            				if (match) {
         | 
| 415 | 
            -
            					ret = format.parser(match);
         | 
| 416 | 
            -
            				}
         | 
| 417 | 
            -
            			}
         | 
| 418 | 
            -
            		}
         | 
| 419 | 
            -
            		return ret;
         | 
| 420 | 
            -
            	},
         | 
| 421 | 
            -
            	
         | 
| 422 | 
            -
            	/**
         | 
| 423 | 
            -
            	 * Reorganize rows into columns
         | 
| 424 | 
            -
            	 */
         | 
| 425 | 
            -
            	rowsToColumns: function (rows) {
         | 
| 426 | 
            -
            		var row,
         | 
| 427 | 
            -
            			rowsLength,
         | 
| 428 | 
            -
            			col,
         | 
| 429 | 
            -
            			colsLength,
         | 
| 430 | 
            -
            			columns;
         | 
| 431 | 
            -
             | 
| 432 | 
            -
            		if (rows) {
         | 
| 433 | 
            -
            			columns = [];
         | 
| 434 | 
            -
            			rowsLength = rows.length;
         | 
| 435 | 
            -
            			for (row = 0; row < rowsLength; row++) {
         | 
| 436 | 
            -
            				colsLength = rows[row].length;
         | 
| 437 | 
            -
            				for (col = 0; col < colsLength; col++) {
         | 
| 438 | 
            -
            					if (!columns[col]) {
         | 
| 439 | 
            -
            						columns[col] = [];
         | 
| 440 | 
            -
            					}
         | 
| 441 | 
            -
            					columns[col][row] = rows[row][col];
         | 
| 442 | 
            -
            				}
         | 
| 443 | 
            -
            			}
         | 
| 444 | 
            -
            		}
         | 
| 445 | 
            -
            		return columns;
         | 
| 446 | 
            -
            	},
         | 
| 447 | 
            -
            	
         | 
| 448 | 
            -
            	/**
         | 
| 449 | 
            -
            	 * A hook for working directly on the parsed columns
         | 
| 450 | 
            -
            	 */
         | 
| 451 | 
            -
            	parsed: function () {
         | 
| 452 | 
            -
            		if (this.options.parsed) {
         | 
| 453 | 
            -
            			this.options.parsed.call(this, this.columns);
         | 
| 454 | 
            -
            		}
         | 
| 455 | 
            -
            	},
         | 
| 456 | 
            -
            	
         | 
| 457 | 
            -
            	/**
         | 
| 458 | 
            -
            	 * If a complete callback function is provided in the options, interpret the 
         | 
| 459 | 
            -
            	 * columns into a Highcharts options object.
         | 
| 460 | 
            -
            	 */
         | 
| 461 | 
            -
            	complete: function () {
         | 
| 462 | 
            -
            		
         | 
| 463 | 
            -
            		var columns = this.columns,
         | 
| 464 | 
            -
            			firstCol,
         | 
| 465 | 
            -
            			type,
         | 
| 466 | 
            -
            			options = this.options,
         | 
| 467 | 
            -
            			valueCount,
         | 
| 468 | 
            -
            			series,
         | 
| 469 | 
            -
            			data,
         | 
| 470 | 
            -
            			i,
         | 
| 471 | 
            -
            			j,
         | 
| 472 | 
            -
            			seriesIndex;
         | 
| 473 | 
            -
            			
         | 
| 474 | 
            -
            		
         | 
| 475 | 
            -
            		if (options.complete) {
         | 
| 476 | 
            -
             | 
| 477 | 
            -
            			this.getColumnDistribution();
         | 
| 478 | 
            -
            			
         | 
| 479 | 
            -
            			// Use first column for X data or categories?
         | 
| 480 | 
            -
            			if (columns.length > 1) {
         | 
| 481 | 
            -
            				firstCol = columns.shift();
         | 
| 482 | 
            -
            				if (this.headerRow === 0) {
         | 
| 483 | 
            -
            					firstCol.shift(); // remove the first cell
         | 
| 484 | 
            -
            				}
         | 
| 485 | 
            -
            				
         | 
| 486 | 
            -
            				
         | 
| 487 | 
            -
            				if (firstCol.isDatetime) {
         | 
| 488 | 
            -
            					type = 'datetime';
         | 
| 489 | 
            -
            				} else if (!firstCol.isNumeric) {
         | 
| 490 | 
            -
            					type = 'category';
         | 
| 491 | 
            -
            				}
         | 
| 492 | 
            -
            			}
         | 
| 493 | 
            -
             | 
| 494 | 
            -
            			// Get the names and shift the top row
         | 
| 495 | 
            -
            			for (i = 0; i < columns.length; i++) {
         | 
| 496 | 
            -
            				if (this.headerRow === 0) {
         | 
| 497 | 
            -
            					columns[i].name = columns[i].shift();
         | 
| 498 | 
            -
            				}
         | 
| 499 | 
            -
            			}
         | 
| 500 | 
            -
            			
         | 
| 501 | 
            -
            			// Use the next columns for series
         | 
| 502 | 
            -
            			series = [];
         | 
| 503 | 
            -
            			for (i = 0, seriesIndex = 0; i < columns.length; seriesIndex++) {
         | 
| 504 | 
            -
             | 
| 505 | 
            -
            				// This series' value count
         | 
| 506 | 
            -
            				valueCount = Highcharts.pick(this.valueCount.individual[seriesIndex], this.valueCount.global);
         | 
| 507 | 
            -
            				
         | 
| 508 | 
            -
            				// Iterate down the cells of each column and add data to the series
         | 
| 509 | 
            -
            				data = [];
         | 
| 510 | 
            -
            				for (j = 0; j < columns[i].length; j++) {
         | 
| 511 | 
            -
            					data[j] = [
         | 
| 512 | 
            -
            						firstCol[j], 
         | 
| 513 | 
            -
            						columns[i][j] !== undefined ? columns[i][j] : null
         | 
| 514 | 
            -
            					];
         | 
| 515 | 
            -
            					if (valueCount > 1) {
         | 
| 516 | 
            -
            						data[j].push(columns[i + 1][j] !== undefined ? columns[i + 1][j] : null);
         | 
| 517 | 
            -
            					}
         | 
| 518 | 
            -
            					if (valueCount > 2) {
         | 
| 519 | 
            -
            						data[j].push(columns[i + 2][j] !== undefined ? columns[i + 2][j] : null);
         | 
| 520 | 
            -
            					}
         | 
| 521 | 
            -
            					if (valueCount > 3) {
         | 
| 522 | 
            -
            						data[j].push(columns[i + 3][j] !== undefined ? columns[i + 3][j] : null);
         | 
| 523 | 
            -
            					}
         | 
| 524 | 
            -
            					if (valueCount > 4) {
         | 
| 525 | 
            -
            						data[j].push(columns[i + 4][j] !== undefined ? columns[i + 4][j] : null);
         | 
| 526 | 
            -
            					}
         | 
| 527 | 
            -
            				}
         | 
| 528 | 
            -
             | 
| 529 | 
            -
            				// Add the series
         | 
| 530 | 
            -
            				series[seriesIndex] = {
         | 
| 531 | 
            -
            					name: columns[i].name,
         | 
| 532 | 
            -
            					data: data
         | 
| 533 | 
            -
            				};
         | 
| 534 | 
            -
             | 
| 535 | 
            -
            				i += valueCount;
         | 
| 536 | 
            -
            			}
         | 
| 537 | 
            -
            			
         | 
| 538 | 
            -
            			// Do the callback
         | 
| 539 | 
            -
            			options.complete({
         | 
| 540 | 
            -
            				xAxis: {
         | 
| 541 | 
            -
            					type: type
         | 
| 542 | 
            -
            				},
         | 
| 543 | 
            -
            				series: series
         | 
| 544 | 
            -
            			});
         | 
| 545 | 
            -
            		}
         | 
| 546 | 
            -
            	}
         | 
| 547 | 
            -
            	});
         | 
| 548 | 
            -
            	
         | 
| 549 | 
            -
            	// Register the Data prototype and data function on Highcharts
         | 
| 550 | 
            -
            	Highcharts.Data = Data;
         | 
| 551 | 
            -
            	Highcharts.data = function (options, chartOptions) {
         | 
| 552 | 
            -
            		return new Data(options, chartOptions);
         | 
| 553 | 
            -
            	};
         | 
| 554 | 
            -
             | 
| 555 | 
            -
            	// Extend Chart.init so that the Chart constructor accepts a new configuration
         | 
| 556 | 
            -
            	// option group, data.
         | 
| 557 | 
            -
            	Highcharts.wrap(Highcharts.Chart.prototype, 'init', function (proceed, userOptions, callback) {
         | 
| 558 | 
            -
            		var chart = this;
         | 
| 559 | 
            -
             | 
| 560 | 
            -
            		if (userOptions && userOptions.data) {
         | 
| 561 | 
            -
            			Highcharts.data(Highcharts.extend(userOptions.data, {
         | 
| 562 | 
            -
            				complete: function (dataOptions) {
         | 
| 563 | 
            -
            					
         | 
| 564 | 
            -
            					// Merge series configs
         | 
| 565 | 
            -
            					if (userOptions.series) {
         | 
| 566 | 
            -
            						each(userOptions.series, function (series, i) {
         | 
| 567 | 
            -
            							userOptions.series[i] = Highcharts.merge(series, dataOptions.series[i]);
         | 
| 568 | 
            -
            						});
         | 
| 569 | 
            -
            					}
         | 
| 570 | 
            -
             | 
| 571 | 
            -
            					// Do the merge
         | 
| 572 | 
            -
            					userOptions = Highcharts.merge(dataOptions, userOptions);
         | 
| 573 | 
            -
             | 
| 574 | 
            -
            					proceed.call(chart, userOptions, callback);
         | 
| 575 | 
            -
            				}
         | 
| 576 | 
            -
            			}), userOptions);
         | 
| 577 | 
            -
            		} else {
         | 
| 578 | 
            -
            			proceed.call(chart, userOptions, callback);
         | 
| 579 | 
            -
            		}
         | 
| 580 | 
            -
            	});
         | 
| 581 | 
            -
             | 
| 582 | 
            -
            }(Highcharts));
         | 
| 2 | 
            +
             Data plugin for Highcharts
         | 
| 3 | 
            +
             | 
| 4 | 
            +
             (c) 2012-2013 Torstein Hønsi
         | 
| 5 | 
            +
             Last revision 2013-06-07
         | 
| 6 | 
            +
             | 
| 7 | 
            +
             License: www.highcharts.com/license
         | 
| 8 | 
            +
            */
         | 
| 9 | 
            +
            (function(h){var k=h.each,m=function(b,a){this.init(b,a)};h.extend(m.prototype,{init:function(b,a){this.options=b;this.chartOptions=a;this.columns=b.columns||this.rowsToColumns(b.rows)||[];this.columns.length?this.dataFound():(this.parseCSV(),this.parseTable(),this.parseGoogleSpreadsheet())},getColumnDistribution:function(){var b=this.chartOptions,a=b&&b.chart&&b.chart.type,c=[];k(b&&b.series||[],function(b){c.push((h.seriesTypes[b.type||a||"line"].prototype.pointArrayMap||[0]).length)});this.valueCount=
         | 
| 10 | 
            +
            {global:(h.seriesTypes[a||"line"].prototype.pointArrayMap||[0]).length,individual:c}},dataFound:function(){this.parseTypes();this.findHeaderRow();this.parsed();this.complete()},parseCSV:function(){var b=this,a=this.options,c=a.csv,d=this.columns,f=a.startRow||0,i=a.endRow||Number.MAX_VALUE,j=a.startColumn||0,e=a.endColumn||Number.MAX_VALUE,g=0;c&&(c=c.replace(/\r\n/g,"\n").replace(/\r/g,"\n").split(a.lineDelimiter||"\n"),k(c,function(c,h){var n=b.trim(c),p=n.indexOf("#")===0;h>=f&&h<=i&&!p&&n!==""&&
         | 
| 11 | 
            +
            (n=c.split(a.itemDelimiter||","),k(n,function(b,a){a>=j&&a<=e&&(d[a-j]||(d[a-j]=[]),d[a-j][g]=b)}),g+=1)}),this.dataFound())},parseTable:function(){var b=this.options,a=b.table,c=this.columns,d=b.startRow||0,f=b.endRow||Number.MAX_VALUE,i=b.startColumn||0,j=b.endColumn||Number.MAX_VALUE,e;a&&(typeof a==="string"&&(a=document.getElementById(a)),k(a.getElementsByTagName("tr"),function(a,b){e=0;b>=d&&b<=f&&k(a.childNodes,function(a){if((a.tagName==="TD"||a.tagName==="TH")&&e>=i&&e<=j)c[e]||(c[e]=[]),
         | 
| 12 | 
            +
            c[e][b-d]=a.innerHTML,e+=1})}),this.dataFound())},parseGoogleSpreadsheet:function(){var b=this,a=this.options,c=a.googleSpreadsheetKey,d=this.columns,f=a.startRow||0,i=a.endRow||Number.MAX_VALUE,j=a.startColumn||0,e=a.endColumn||Number.MAX_VALUE,g,h;c&&jQuery.getJSON("https://spreadsheets.google.com/feeds/cells/"+c+"/"+(a.googleSpreadsheetWorksheet||"od6")+"/public/values?alt=json-in-script&callback=?",function(a){var a=a.feed.entry,c,k=a.length,m=0,o=0,l;for(l=0;l<k;l++)c=a[l],m=Math.max(m,c.gs$cell.col),
         | 
| 13 | 
            +
            o=Math.max(o,c.gs$cell.row);for(l=0;l<m;l++)if(l>=j&&l<=e)d[l-j]=[],d[l-j].length=Math.min(o,i-f);for(l=0;l<k;l++)if(c=a[l],g=c.gs$cell.row-1,h=c.gs$cell.col-1,h>=j&&h<=e&&g>=f&&g<=i)d[h-j][g-f]=c.content.$t;b.dataFound()})},findHeaderRow:function(){k(this.columns,function(){});this.headerRow=0},trim:function(b){return typeof b==="string"?b.replace(/^\s+|\s+$/g,""):b},parseTypes:function(){for(var b=this.columns,a=b.length,c,d,f,i;a--;)for(c=b[a].length;c--;)d=b[a][c],f=parseFloat(d),i=this.trim(d),
         | 
| 14 | 
            +
            i==f?(b[a][c]=f,f>31536E6?b[a].isDatetime=!0:b[a].isNumeric=!0):(d=this.parseDate(d),a===0&&typeof d==="number"&&!isNaN(d)?(b[a][c]=d,b[a].isDatetime=!0):b[a][c]=i===""?null:i)},dateFormats:{"YYYY-mm-dd":{regex:"^([0-9]{4})-([0-9]{2})-([0-9]{2})$",parser:function(b){return Date.UTC(+b[1],b[2]-1,+b[3])}}},parseDate:function(b){var a=this.options.parseDate,c,d,f;a&&(c=a(b));if(typeof b==="string")for(d in this.dateFormats)a=this.dateFormats[d],(f=b.match(a.regex))&&(c=a.parser(f));return c},rowsToColumns:function(b){var a,
         | 
| 15 | 
            +
            c,d,f,i;if(b){i=[];c=b.length;for(a=0;a<c;a++){f=b[a].length;for(d=0;d<f;d++)i[d]||(i[d]=[]),i[d][a]=b[a][d]}}return i},parsed:function(){this.options.parsed&&this.options.parsed.call(this,this.columns)},complete:function(){var b=this.columns,a,c,d=this.options,f,i,j,e,g,k;if(d.complete){this.getColumnDistribution();b.length>1&&(a=b.shift(),this.headerRow===0&&a.shift(),a.isDatetime?c="datetime":a.isNumeric||(c="category"));for(e=0;e<b.length;e++)if(this.headerRow===0)b[e].name=b[e].shift();i=[];
         | 
| 16 | 
            +
            for(e=0,k=0;e<b.length;k++){f=h.pick(this.valueCount.individual[k],this.valueCount.global);j=[];for(g=0;g<b[e].length;g++)j[g]=[a[g],b[e][g]!==void 0?b[e][g]:null],f>1&&j[g].push(b[e+1][g]!==void 0?b[e+1][g]:null),f>2&&j[g].push(b[e+2][g]!==void 0?b[e+2][g]:null),f>3&&j[g].push(b[e+3][g]!==void 0?b[e+3][g]:null),f>4&&j[g].push(b[e+4][g]!==void 0?b[e+4][g]:null);i[k]={name:b[e].name,data:j};e+=f}d.complete({xAxis:{type:c},series:i})}}});h.Data=m;h.data=function(b,a){return new m(b,a)};h.wrap(h.Chart.prototype,
         | 
| 17 | 
            +
            "init",function(b,a,c){var d=this;a&&a.data?h.data(h.extend(a.data,{complete:function(f){a.series&&k(a.series,function(b,c){a.series[c]=h.merge(b,f.series[c])});a=h.merge(f,a);b.call(d,a,c)}}),a):b.call(d,a,c)})})(Highcharts);
         |