Daniel@0
|
1 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.vg = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
Daniel@0
|
2 module.exports = {
|
Daniel@0
|
3 version: '2.2.6',
|
Daniel@0
|
4 dataflow: require('vega-dataflow'),
|
Daniel@0
|
5 parse: require('./src/parse/'),
|
Daniel@0
|
6 scene: {
|
Daniel@0
|
7 Bounder: require('./src/scene/Bounder'),
|
Daniel@0
|
8 Builder: require('./src/scene/Builder'),
|
Daniel@0
|
9 Encoder: require('./src/scene/Encoder'),
|
Daniel@0
|
10 GroupBuilder: require('./src/scene/GroupBuilder'),
|
Daniel@0
|
11 },
|
Daniel@0
|
12 transforms: require('./src/transforms'),
|
Daniel@0
|
13 schema: require('./src/core/schema'),
|
Daniel@0
|
14 config: require('./src/core/config'),
|
Daniel@0
|
15 util: require('datalib'),
|
Daniel@0
|
16 debug: require('vega-logging').debug
|
Daniel@0
|
17 };
|
Daniel@0
|
18 },{"./src/core/config":88,"./src/core/schema":89,"./src/parse/":95,"./src/scene/Bounder":107,"./src/scene/Builder":108,"./src/scene/Encoder":109,"./src/scene/GroupBuilder":110,"./src/transforms":139,"datalib":24,"vega-dataflow":39,"vega-logging":45}],2:[function(require,module,exports){
|
Daniel@0
|
19
|
Daniel@0
|
20 },{}],3:[function(require,module,exports){
|
Daniel@0
|
21 (function (global, factory) {
|
Daniel@0
|
22 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
Daniel@0
|
23 typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
Daniel@0
|
24 factory((global.dsv = {}));
|
Daniel@0
|
25 }(this, function (exports) { 'use strict';
|
Daniel@0
|
26
|
Daniel@0
|
27 var dsv = function(delimiter) {
|
Daniel@0
|
28 var reFormat = new RegExp("[\"" + delimiter + "\n]"),
|
Daniel@0
|
29 delimiterCode = delimiter.charCodeAt(0);
|
Daniel@0
|
30
|
Daniel@0
|
31 function parse(text, f) {
|
Daniel@0
|
32 var o;
|
Daniel@0
|
33 return parseRows(text, function(row, i) {
|
Daniel@0
|
34 if (o) return o(row, i - 1);
|
Daniel@0
|
35 var a = new Function("d", "return {" + row.map(function(name, i) {
|
Daniel@0
|
36 return JSON.stringify(name) + ": d[" + i + "]";
|
Daniel@0
|
37 }).join(",") + "}");
|
Daniel@0
|
38 o = f ? function(row, i) { return f(a(row), i); } : a;
|
Daniel@0
|
39 });
|
Daniel@0
|
40 }
|
Daniel@0
|
41
|
Daniel@0
|
42 function parseRows(text, f) {
|
Daniel@0
|
43 var EOL = {}, // sentinel value for end-of-line
|
Daniel@0
|
44 EOF = {}, // sentinel value for end-of-file
|
Daniel@0
|
45 rows = [], // output rows
|
Daniel@0
|
46 N = text.length,
|
Daniel@0
|
47 I = 0, // current character index
|
Daniel@0
|
48 n = 0, // the current line number
|
Daniel@0
|
49 t, // the current token
|
Daniel@0
|
50 eol; // is the current token followed by EOL?
|
Daniel@0
|
51
|
Daniel@0
|
52 function token() {
|
Daniel@0
|
53 if (I >= N) return EOF; // special case: end of file
|
Daniel@0
|
54 if (eol) return eol = false, EOL; // special case: end of line
|
Daniel@0
|
55
|
Daniel@0
|
56 // special case: quotes
|
Daniel@0
|
57 var j = I;
|
Daniel@0
|
58 if (text.charCodeAt(j) === 34) {
|
Daniel@0
|
59 var i = j;
|
Daniel@0
|
60 while (i++ < N) {
|
Daniel@0
|
61 if (text.charCodeAt(i) === 34) {
|
Daniel@0
|
62 if (text.charCodeAt(i + 1) !== 34) break;
|
Daniel@0
|
63 ++i;
|
Daniel@0
|
64 }
|
Daniel@0
|
65 }
|
Daniel@0
|
66 I = i + 2;
|
Daniel@0
|
67 var c = text.charCodeAt(i + 1);
|
Daniel@0
|
68 if (c === 13) {
|
Daniel@0
|
69 eol = true;
|
Daniel@0
|
70 if (text.charCodeAt(i + 2) === 10) ++I;
|
Daniel@0
|
71 } else if (c === 10) {
|
Daniel@0
|
72 eol = true;
|
Daniel@0
|
73 }
|
Daniel@0
|
74 return text.slice(j + 1, i).replace(/""/g, "\"");
|
Daniel@0
|
75 }
|
Daniel@0
|
76
|
Daniel@0
|
77 // common case: find next delimiter or newline
|
Daniel@0
|
78 while (I < N) {
|
Daniel@0
|
79 var c = text.charCodeAt(I++), k = 1;
|
Daniel@0
|
80 if (c === 10) eol = true; // \n
|
Daniel@0
|
81 else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
|
Daniel@0
|
82 else if (c !== delimiterCode) continue;
|
Daniel@0
|
83 return text.slice(j, I - k);
|
Daniel@0
|
84 }
|
Daniel@0
|
85
|
Daniel@0
|
86 // special case: last token before EOF
|
Daniel@0
|
87 return text.slice(j);
|
Daniel@0
|
88 }
|
Daniel@0
|
89
|
Daniel@0
|
90 while ((t = token()) !== EOF) {
|
Daniel@0
|
91 var a = [];
|
Daniel@0
|
92 while (t !== EOL && t !== EOF) {
|
Daniel@0
|
93 a.push(t);
|
Daniel@0
|
94 t = token();
|
Daniel@0
|
95 }
|
Daniel@0
|
96 if (f && (a = f(a, n++)) == null) continue;
|
Daniel@0
|
97 rows.push(a);
|
Daniel@0
|
98 }
|
Daniel@0
|
99
|
Daniel@0
|
100 return rows;
|
Daniel@0
|
101 }
|
Daniel@0
|
102
|
Daniel@0
|
103 function format(rows) {
|
Daniel@0
|
104 if (Array.isArray(rows[0])) return formatRows(rows); // deprecated; use formatRows
|
Daniel@0
|
105 var fieldSet = Object.create(null), fields = [];
|
Daniel@0
|
106
|
Daniel@0
|
107 // Compute unique fields in order of discovery.
|
Daniel@0
|
108 rows.forEach(function(row) {
|
Daniel@0
|
109 for (var field in row) {
|
Daniel@0
|
110 if (!((field += "") in fieldSet)) {
|
Daniel@0
|
111 fields.push(fieldSet[field] = field);
|
Daniel@0
|
112 }
|
Daniel@0
|
113 }
|
Daniel@0
|
114 });
|
Daniel@0
|
115
|
Daniel@0
|
116 return [fields.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
|
Daniel@0
|
117 return fields.map(function(field) {
|
Daniel@0
|
118 return formatValue(row[field]);
|
Daniel@0
|
119 }).join(delimiter);
|
Daniel@0
|
120 })).join("\n");
|
Daniel@0
|
121 }
|
Daniel@0
|
122
|
Daniel@0
|
123 function formatRows(rows) {
|
Daniel@0
|
124 return rows.map(formatRow).join("\n");
|
Daniel@0
|
125 }
|
Daniel@0
|
126
|
Daniel@0
|
127 function formatRow(row) {
|
Daniel@0
|
128 return row.map(formatValue).join(delimiter);
|
Daniel@0
|
129 }
|
Daniel@0
|
130
|
Daniel@0
|
131 function formatValue(text) {
|
Daniel@0
|
132 return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text;
|
Daniel@0
|
133 }
|
Daniel@0
|
134
|
Daniel@0
|
135 return {
|
Daniel@0
|
136 parse: parse,
|
Daniel@0
|
137 parseRows: parseRows,
|
Daniel@0
|
138 format: format,
|
Daniel@0
|
139 formatRows: formatRows
|
Daniel@0
|
140 };
|
Daniel@0
|
141 }
|
Daniel@0
|
142
|
Daniel@0
|
143 exports.csv = dsv(",");
|
Daniel@0
|
144 exports.tsv = dsv("\t");
|
Daniel@0
|
145
|
Daniel@0
|
146 exports.dsv = dsv;
|
Daniel@0
|
147
|
Daniel@0
|
148 }));
|
Daniel@0
|
149 },{}],4:[function(require,module,exports){
|
Daniel@0
|
150 if (typeof Map === "undefined") {
|
Daniel@0
|
151 Map = function() { this.clear(); };
|
Daniel@0
|
152 Map.prototype = {
|
Daniel@0
|
153 set: function(k, v) { this._[k] = v; return this; },
|
Daniel@0
|
154 get: function(k) { return this._[k]; },
|
Daniel@0
|
155 has: function(k) { return k in this._; },
|
Daniel@0
|
156 delete: function(k) { return k in this._ && delete this._[k]; },
|
Daniel@0
|
157 clear: function() { this._ = Object.create(null); },
|
Daniel@0
|
158 get size() { var n = 0; for (var k in this._) ++n; return n; },
|
Daniel@0
|
159 forEach: function(c) { for (var k in this._) c(this._[k], k, this); }
|
Daniel@0
|
160 };
|
Daniel@0
|
161 } else (function() {
|
Daniel@0
|
162 var m = new Map;
|
Daniel@0
|
163 if (m.set(0, 0) !== m) {
|
Daniel@0
|
164 m = m.set;
|
Daniel@0
|
165 Map.prototype.set = function() { m.apply(this, arguments); return this; };
|
Daniel@0
|
166 }
|
Daniel@0
|
167 })();
|
Daniel@0
|
168
|
Daniel@0
|
169 (function (global, factory) {
|
Daniel@0
|
170 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
Daniel@0
|
171 typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
Daniel@0
|
172 factory((global.format = {}));
|
Daniel@0
|
173 }(this, function (exports) { 'use strict';
|
Daniel@0
|
174
|
Daniel@0
|
175 var zhCn = {
|
Daniel@0
|
176 decimal: ".",
|
Daniel@0
|
177 thousands: ",",
|
Daniel@0
|
178 grouping: [3],
|
Daniel@0
|
179 currency: ["¥", ""]
|
Daniel@0
|
180 };
|
Daniel@0
|
181
|
Daniel@0
|
182 var ruRu = {
|
Daniel@0
|
183 decimal: ",",
|
Daniel@0
|
184 thousands: "\xa0",
|
Daniel@0
|
185 grouping: [3],
|
Daniel@0
|
186 currency: ["", "\xa0руб."]
|
Daniel@0
|
187 };
|
Daniel@0
|
188
|
Daniel@0
|
189 var ptBr = {
|
Daniel@0
|
190 decimal: ",",
|
Daniel@0
|
191 thousands: ".",
|
Daniel@0
|
192 grouping: [3],
|
Daniel@0
|
193 currency: ["R$", ""]
|
Daniel@0
|
194 };
|
Daniel@0
|
195
|
Daniel@0
|
196 var plPl = {
|
Daniel@0
|
197 decimal: ",",
|
Daniel@0
|
198 thousands: ".",
|
Daniel@0
|
199 grouping: [3],
|
Daniel@0
|
200 currency: ["", "zł"]
|
Daniel@0
|
201 };
|
Daniel@0
|
202
|
Daniel@0
|
203 var nlNl = {
|
Daniel@0
|
204 decimal: ",",
|
Daniel@0
|
205 thousands: ".",
|
Daniel@0
|
206 grouping: [3],
|
Daniel@0
|
207 currency: ["€\xa0", ""]
|
Daniel@0
|
208 };
|
Daniel@0
|
209
|
Daniel@0
|
210 var mkMk = {
|
Daniel@0
|
211 decimal: ",",
|
Daniel@0
|
212 thousands: ".",
|
Daniel@0
|
213 grouping: [3],
|
Daniel@0
|
214 currency: ["", "\xa0ден."]
|
Daniel@0
|
215 };
|
Daniel@0
|
216
|
Daniel@0
|
217 var jaJp = {
|
Daniel@0
|
218 decimal: ".",
|
Daniel@0
|
219 thousands: ",",
|
Daniel@0
|
220 grouping: [3],
|
Daniel@0
|
221 currency: ["", "円"]
|
Daniel@0
|
222 };
|
Daniel@0
|
223
|
Daniel@0
|
224 var itIt = {
|
Daniel@0
|
225 decimal: ",",
|
Daniel@0
|
226 thousands: ".",
|
Daniel@0
|
227 grouping: [3],
|
Daniel@0
|
228 currency: ["€", ""]
|
Daniel@0
|
229 };
|
Daniel@0
|
230
|
Daniel@0
|
231 var heIl = {
|
Daniel@0
|
232 decimal: ".",
|
Daniel@0
|
233 thousands: ",",
|
Daniel@0
|
234 grouping: [3],
|
Daniel@0
|
235 currency: ["₪", ""]
|
Daniel@0
|
236 };
|
Daniel@0
|
237
|
Daniel@0
|
238 var frFr = {
|
Daniel@0
|
239 decimal: ",",
|
Daniel@0
|
240 thousands: ".",
|
Daniel@0
|
241 grouping: [3],
|
Daniel@0
|
242 currency: ["", "\xa0€"]
|
Daniel@0
|
243 };
|
Daniel@0
|
244
|
Daniel@0
|
245 var frCa = {
|
Daniel@0
|
246 decimal: ",",
|
Daniel@0
|
247 thousands: "\xa0",
|
Daniel@0
|
248 grouping: [3],
|
Daniel@0
|
249 currency: ["", "$"]
|
Daniel@0
|
250 };
|
Daniel@0
|
251
|
Daniel@0
|
252 var fiFi = {
|
Daniel@0
|
253 decimal: ",",
|
Daniel@0
|
254 thousands: "\xa0",
|
Daniel@0
|
255 grouping: [3],
|
Daniel@0
|
256 currency: ["", "\xa0€"]
|
Daniel@0
|
257 };
|
Daniel@0
|
258
|
Daniel@0
|
259 var esEs = {
|
Daniel@0
|
260 decimal: ",",
|
Daniel@0
|
261 thousands: ".",
|
Daniel@0
|
262 grouping: [3],
|
Daniel@0
|
263 currency: ["", "\xa0€"]
|
Daniel@0
|
264 };
|
Daniel@0
|
265
|
Daniel@0
|
266 var enUs = {
|
Daniel@0
|
267 decimal: ".",
|
Daniel@0
|
268 thousands: ",",
|
Daniel@0
|
269 grouping: [3],
|
Daniel@0
|
270 currency: ["$", ""]
|
Daniel@0
|
271 };
|
Daniel@0
|
272
|
Daniel@0
|
273 var enGb = {
|
Daniel@0
|
274 decimal: ".",
|
Daniel@0
|
275 thousands: ",",
|
Daniel@0
|
276 grouping: [3],
|
Daniel@0
|
277 currency: ["£", ""]
|
Daniel@0
|
278 };
|
Daniel@0
|
279
|
Daniel@0
|
280 var enCa = {
|
Daniel@0
|
281 decimal: ".",
|
Daniel@0
|
282 thousands: ",",
|
Daniel@0
|
283 grouping: [3],
|
Daniel@0
|
284 currency: ["$", ""]
|
Daniel@0
|
285 };
|
Daniel@0
|
286
|
Daniel@0
|
287 var deDe = {
|
Daniel@0
|
288 decimal: ",",
|
Daniel@0
|
289 thousands: ".",
|
Daniel@0
|
290 grouping: [3],
|
Daniel@0
|
291 currency: ["", "\xa0€"]
|
Daniel@0
|
292 };
|
Daniel@0
|
293
|
Daniel@0
|
294 var caEs = {
|
Daniel@0
|
295 decimal: ",",
|
Daniel@0
|
296 thousands: ".",
|
Daniel@0
|
297 grouping: [3],
|
Daniel@0
|
298 currency: ["", "\xa0€"]
|
Daniel@0
|
299 };
|
Daniel@0
|
300
|
Daniel@0
|
301
|
Daniel@0
|
302 // Computes the decimal coefficient and exponent of the specified number x with
|
Daniel@0
|
303 // significant digits p, where x is positive and p is in [1, 21] or undefined.
|
Daniel@0
|
304 // For example, formatDecimal(1.23) returns ["123", 0].
|
Daniel@0
|
305 function formatDecimal(x, p) {
|
Daniel@0
|
306 if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
|
Daniel@0
|
307 var i, coefficient = x.slice(0, i);
|
Daniel@0
|
308
|
Daniel@0
|
309 // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
|
Daniel@0
|
310 // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
|
Daniel@0
|
311 return [
|
Daniel@0
|
312 coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
|
Daniel@0
|
313 +x.slice(i + 1)
|
Daniel@0
|
314 ];
|
Daniel@0
|
315 }
|
Daniel@0
|
316
|
Daniel@0
|
317 function exponent(x) {
|
Daniel@0
|
318 return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
|
Daniel@0
|
319 }
|
Daniel@0
|
320
|
Daniel@0
|
321 var prefixExponent;
|
Daniel@0
|
322
|
Daniel@0
|
323 function formatPrefixAuto(x, p) {
|
Daniel@0
|
324 var d = formatDecimal(x, p);
|
Daniel@0
|
325 if (!d) return x + "";
|
Daniel@0
|
326 var coefficient = d[0],
|
Daniel@0
|
327 exponent = d[1],
|
Daniel@0
|
328 i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
|
Daniel@0
|
329 n = coefficient.length;
|
Daniel@0
|
330 return i === n ? coefficient
|
Daniel@0
|
331 : i > n ? coefficient + new Array(i - n + 1).join("0")
|
Daniel@0
|
332 : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
|
Daniel@0
|
333 : "0." + new Array(1 - i).join("0") + formatDecimal(x, p + i - 1)[0]; // less than 1y!
|
Daniel@0
|
334 }
|
Daniel@0
|
335
|
Daniel@0
|
336 function formatRounded(x, p) {
|
Daniel@0
|
337 var d = formatDecimal(x, p);
|
Daniel@0
|
338 if (!d) return x + "";
|
Daniel@0
|
339 var coefficient = d[0],
|
Daniel@0
|
340 exponent = d[1];
|
Daniel@0
|
341 return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
|
Daniel@0
|
342 : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
|
Daniel@0
|
343 : coefficient + new Array(exponent - coefficient.length + 2).join("0");
|
Daniel@0
|
344 }
|
Daniel@0
|
345
|
Daniel@0
|
346 function formatDefault(x, p) {
|
Daniel@0
|
347 x = x.toPrecision(p);
|
Daniel@0
|
348
|
Daniel@0
|
349 out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
|
Daniel@0
|
350 switch (x[i]) {
|
Daniel@0
|
351 case ".": i0 = i1 = i; break;
|
Daniel@0
|
352 case "0": if (i0 === 0) i0 = i; i1 = i; break;
|
Daniel@0
|
353 case "e": break out;
|
Daniel@0
|
354 default: if (i0 > 0) i0 = 0; break;
|
Daniel@0
|
355 }
|
Daniel@0
|
356 }
|
Daniel@0
|
357
|
Daniel@0
|
358 return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
|
Daniel@0
|
359 }
|
Daniel@0
|
360
|
Daniel@0
|
361 var formatTypes = {
|
Daniel@0
|
362 "": formatDefault,
|
Daniel@0
|
363 "%": function(x, p) { return (x * 100).toFixed(p); },
|
Daniel@0
|
364 "b": function(x) { return Math.round(x).toString(2); },
|
Daniel@0
|
365 "c": function(x) { return x + ""; },
|
Daniel@0
|
366 "d": function(x) { return Math.round(x).toString(10); },
|
Daniel@0
|
367 "e": function(x, p) { return x.toExponential(p); },
|
Daniel@0
|
368 "f": function(x, p) { return x.toFixed(p); },
|
Daniel@0
|
369 "g": function(x, p) { return x.toPrecision(p); },
|
Daniel@0
|
370 "o": function(x) { return Math.round(x).toString(8); },
|
Daniel@0
|
371 "p": function(x, p) { return formatRounded(x * 100, p); },
|
Daniel@0
|
372 "r": formatRounded,
|
Daniel@0
|
373 "s": formatPrefixAuto,
|
Daniel@0
|
374 "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
|
Daniel@0
|
375 "x": function(x) { return Math.round(x).toString(16); }
|
Daniel@0
|
376 };
|
Daniel@0
|
377
|
Daniel@0
|
378
|
Daniel@0
|
379 // [[fill]align][sign][symbol][0][width][,][.precision][type]
|
Daniel@0
|
380 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
|
Daniel@0
|
381
|
Daniel@0
|
382 function formatSpecifier(specifier) {
|
Daniel@0
|
383 return new FormatSpecifier(specifier);
|
Daniel@0
|
384 }
|
Daniel@0
|
385
|
Daniel@0
|
386 function FormatSpecifier(specifier) {
|
Daniel@0
|
387 if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
|
Daniel@0
|
388
|
Daniel@0
|
389 var match,
|
Daniel@0
|
390 fill = match[1] || " ",
|
Daniel@0
|
391 align = match[2] || ">",
|
Daniel@0
|
392 sign = match[3] || "-",
|
Daniel@0
|
393 symbol = match[4] || "",
|
Daniel@0
|
394 zero = !!match[5],
|
Daniel@0
|
395 width = match[6] && +match[6],
|
Daniel@0
|
396 comma = !!match[7],
|
Daniel@0
|
397 precision = match[8] && +match[8].slice(1),
|
Daniel@0
|
398 type = match[9] || "";
|
Daniel@0
|
399
|
Daniel@0
|
400 // The "n" type is an alias for ",g".
|
Daniel@0
|
401 if (type === "n") comma = true, type = "g";
|
Daniel@0
|
402
|
Daniel@0
|
403 // Map invalid types to the default format.
|
Daniel@0
|
404 else if (!formatTypes[type]) type = "";
|
Daniel@0
|
405
|
Daniel@0
|
406 // If zero fill is specified, padding goes after sign and before digits.
|
Daniel@0
|
407 if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
|
Daniel@0
|
408
|
Daniel@0
|
409 this.fill = fill;
|
Daniel@0
|
410 this.align = align;
|
Daniel@0
|
411 this.sign = sign;
|
Daniel@0
|
412 this.symbol = symbol;
|
Daniel@0
|
413 this.zero = zero;
|
Daniel@0
|
414 this.width = width;
|
Daniel@0
|
415 this.comma = comma;
|
Daniel@0
|
416 this.precision = precision;
|
Daniel@0
|
417 this.type = type;
|
Daniel@0
|
418 }
|
Daniel@0
|
419
|
Daniel@0
|
420 FormatSpecifier.prototype.toString = function() {
|
Daniel@0
|
421 return this.fill
|
Daniel@0
|
422 + this.align
|
Daniel@0
|
423 + this.sign
|
Daniel@0
|
424 + this.symbol
|
Daniel@0
|
425 + (this.zero ? "0" : "")
|
Daniel@0
|
426 + (this.width == null ? "" : Math.max(1, this.width | 0))
|
Daniel@0
|
427 + (this.comma ? "," : "")
|
Daniel@0
|
428 + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
|
Daniel@0
|
429 + this.type;
|
Daniel@0
|
430 };
|
Daniel@0
|
431
|
Daniel@0
|
432 function formatGroup(grouping, thousands) {
|
Daniel@0
|
433 return function(value, width) {
|
Daniel@0
|
434 var i = value.length,
|
Daniel@0
|
435 t = [],
|
Daniel@0
|
436 j = 0,
|
Daniel@0
|
437 g = grouping[0],
|
Daniel@0
|
438 length = 0;
|
Daniel@0
|
439
|
Daniel@0
|
440 while (i > 0 && g > 0) {
|
Daniel@0
|
441 if (length + g + 1 > width) g = Math.max(1, width - length);
|
Daniel@0
|
442 t.push(value.substring(i -= g, i + g));
|
Daniel@0
|
443 if ((length += g + 1) > width) break;
|
Daniel@0
|
444 g = grouping[j = (j + 1) % grouping.length];
|
Daniel@0
|
445 }
|
Daniel@0
|
446
|
Daniel@0
|
447 return t.reverse().join(thousands);
|
Daniel@0
|
448 };
|
Daniel@0
|
449 }
|
Daniel@0
|
450
|
Daniel@0
|
451 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
|
Daniel@0
|
452
|
Daniel@0
|
453 function identity(x) {
|
Daniel@0
|
454 return x;
|
Daniel@0
|
455 }
|
Daniel@0
|
456
|
Daniel@0
|
457 function locale(locale) {
|
Daniel@0
|
458 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
|
Daniel@0
|
459 currency = locale.currency,
|
Daniel@0
|
460 decimal = locale.decimal;
|
Daniel@0
|
461
|
Daniel@0
|
462 function format(specifier) {
|
Daniel@0
|
463 specifier = formatSpecifier(specifier);
|
Daniel@0
|
464
|
Daniel@0
|
465 var fill = specifier.fill,
|
Daniel@0
|
466 align = specifier.align,
|
Daniel@0
|
467 sign = specifier.sign,
|
Daniel@0
|
468 symbol = specifier.symbol,
|
Daniel@0
|
469 zero = specifier.zero,
|
Daniel@0
|
470 width = specifier.width,
|
Daniel@0
|
471 comma = specifier.comma,
|
Daniel@0
|
472 precision = specifier.precision,
|
Daniel@0
|
473 type = specifier.type;
|
Daniel@0
|
474
|
Daniel@0
|
475 // Compute the prefix and suffix.
|
Daniel@0
|
476 // For SI-prefix, the suffix is lazily computed.
|
Daniel@0
|
477 var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
|
Daniel@0
|
478 suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
|
Daniel@0
|
479
|
Daniel@0
|
480 // What format function should we use?
|
Daniel@0
|
481 // Is this an integer type?
|
Daniel@0
|
482 // Can this type generate exponential notation?
|
Daniel@0
|
483 var formatType = formatTypes[type],
|
Daniel@0
|
484 maybeSuffix = !type || /[defgprs%]/.test(type);
|
Daniel@0
|
485
|
Daniel@0
|
486 // Set the default precision if not specified,
|
Daniel@0
|
487 // or clamp the specified precision to the supported range.
|
Daniel@0
|
488 // For significant precision, it must be in [1, 21].
|
Daniel@0
|
489 // For fixed precision, it must be in [0, 20].
|
Daniel@0
|
490 precision = precision == null ? (type ? 6 : 12)
|
Daniel@0
|
491 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
|
Daniel@0
|
492 : Math.max(0, Math.min(20, precision));
|
Daniel@0
|
493
|
Daniel@0
|
494 return function(value) {
|
Daniel@0
|
495 var valuePrefix = prefix,
|
Daniel@0
|
496 valueSuffix = suffix;
|
Daniel@0
|
497
|
Daniel@0
|
498 if (type === "c") {
|
Daniel@0
|
499 valueSuffix = formatType(value) + valueSuffix;
|
Daniel@0
|
500 value = "";
|
Daniel@0
|
501 } else {
|
Daniel@0
|
502 value = +value;
|
Daniel@0
|
503
|
Daniel@0
|
504 // Convert negative to positive, and compute the prefix.
|
Daniel@0
|
505 // Note that -0 is not less than 0, but 1 / -0 is!
|
Daniel@0
|
506 var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
|
Daniel@0
|
507
|
Daniel@0
|
508 // Perform the initial formatting.
|
Daniel@0
|
509 value = formatType(value, precision);
|
Daniel@0
|
510
|
Daniel@0
|
511 // Compute the prefix and suffix.
|
Daniel@0
|
512 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
|
Daniel@0
|
513 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
|
Daniel@0
|
514
|
Daniel@0
|
515 // Break the formatted value into the integer “value” part that can be
|
Daniel@0
|
516 // grouped, and fractional or exponential “suffix” part that is not.
|
Daniel@0
|
517 if (maybeSuffix) {
|
Daniel@0
|
518 var i = -1, n = value.length, c;
|
Daniel@0
|
519 while (++i < n) {
|
Daniel@0
|
520 if (c = value.charCodeAt(i), 48 > c || c > 57) {
|
Daniel@0
|
521 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
|
Daniel@0
|
522 value = value.slice(0, i);
|
Daniel@0
|
523 break;
|
Daniel@0
|
524 }
|
Daniel@0
|
525 }
|
Daniel@0
|
526 }
|
Daniel@0
|
527 }
|
Daniel@0
|
528
|
Daniel@0
|
529 // If the fill character is not "0", grouping is applied before padding.
|
Daniel@0
|
530 if (comma && !zero) value = group(value, Infinity);
|
Daniel@0
|
531
|
Daniel@0
|
532 // Compute the padding.
|
Daniel@0
|
533 var length = valuePrefix.length + value.length + valueSuffix.length,
|
Daniel@0
|
534 padding = length < width ? new Array(width - length + 1).join(fill) : "";
|
Daniel@0
|
535
|
Daniel@0
|
536 // If the fill character is "0", grouping is applied after padding.
|
Daniel@0
|
537 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
|
Daniel@0
|
538
|
Daniel@0
|
539 // Reconstruct the final output based on the desired alignment.
|
Daniel@0
|
540 switch (align) {
|
Daniel@0
|
541 case "<": return valuePrefix + value + valueSuffix + padding;
|
Daniel@0
|
542 case "=": return valuePrefix + padding + value + valueSuffix;
|
Daniel@0
|
543 case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
|
Daniel@0
|
544 }
|
Daniel@0
|
545 return padding + valuePrefix + value + valueSuffix;
|
Daniel@0
|
546 };
|
Daniel@0
|
547 }
|
Daniel@0
|
548
|
Daniel@0
|
549 function formatPrefix(specifier, value) {
|
Daniel@0
|
550 var f = format((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
|
Daniel@0
|
551 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
|
Daniel@0
|
552 k = Math.pow(10, -e),
|
Daniel@0
|
553 prefix = prefixes[8 + e / 3];
|
Daniel@0
|
554 return function(value) {
|
Daniel@0
|
555 return f(k * value) + prefix;
|
Daniel@0
|
556 };
|
Daniel@0
|
557 }
|
Daniel@0
|
558
|
Daniel@0
|
559 return {
|
Daniel@0
|
560 format: format,
|
Daniel@0
|
561 formatPrefix: formatPrefix
|
Daniel@0
|
562 };
|
Daniel@0
|
563 }
|
Daniel@0
|
564
|
Daniel@0
|
565 function precisionRound(step, max) {
|
Daniel@0
|
566 return Math.max(0, exponent(Math.abs(max)) - exponent(Math.abs(step))) + 1;
|
Daniel@0
|
567 }
|
Daniel@0
|
568
|
Daniel@0
|
569 function precisionPrefix(step, value) {
|
Daniel@0
|
570 return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
|
Daniel@0
|
571 }
|
Daniel@0
|
572
|
Daniel@0
|
573 function precisionFixed(step) {
|
Daniel@0
|
574 return Math.max(0, -exponent(Math.abs(step)));
|
Daniel@0
|
575 }
|
Daniel@0
|
576
|
Daniel@0
|
577 var localeDefinitions = (new Map)
|
Daniel@0
|
578 .set("ca-ES", caEs)
|
Daniel@0
|
579 .set("de-DE", deDe)
|
Daniel@0
|
580 .set("en-CA", enCa)
|
Daniel@0
|
581 .set("en-GB", enGb)
|
Daniel@0
|
582 .set("en-US", enUs)
|
Daniel@0
|
583 .set("es-ES", esEs)
|
Daniel@0
|
584 .set("fi-FI", fiFi)
|
Daniel@0
|
585 .set("fr-CA", frCa)
|
Daniel@0
|
586 .set("fr-FR", frFr)
|
Daniel@0
|
587 .set("he-IL", heIl)
|
Daniel@0
|
588 .set("it-IT", itIt)
|
Daniel@0
|
589 .set("ja-JP", jaJp)
|
Daniel@0
|
590 .set("mk-MK", mkMk)
|
Daniel@0
|
591 .set("nl-NL", nlNl)
|
Daniel@0
|
592 .set("pl-PL", plPl)
|
Daniel@0
|
593 .set("pt-BR", ptBr)
|
Daniel@0
|
594 .set("ru-RU", ruRu)
|
Daniel@0
|
595 .set("zh-CN", zhCn);
|
Daniel@0
|
596
|
Daniel@0
|
597 var defaultLocale = locale(enUs);
|
Daniel@0
|
598 exports.format = defaultLocale.format;
|
Daniel@0
|
599 exports.formatPrefix = defaultLocale.formatPrefix;
|
Daniel@0
|
600
|
Daniel@0
|
601 function localeFormat(definition) {
|
Daniel@0
|
602 if (typeof definition === "string") {
|
Daniel@0
|
603 definition = localeDefinitions.get(definition);
|
Daniel@0
|
604 if (!definition) return null;
|
Daniel@0
|
605 }
|
Daniel@0
|
606 return locale(definition);
|
Daniel@0
|
607 }
|
Daniel@0
|
608 ;
|
Daniel@0
|
609
|
Daniel@0
|
610 exports.localeFormat = localeFormat;
|
Daniel@0
|
611 exports.formatSpecifier = formatSpecifier;
|
Daniel@0
|
612 exports.precisionFixed = precisionFixed;
|
Daniel@0
|
613 exports.precisionPrefix = precisionPrefix;
|
Daniel@0
|
614 exports.precisionRound = precisionRound;
|
Daniel@0
|
615
|
Daniel@0
|
616 }));
|
Daniel@0
|
617 },{}],5:[function(require,module,exports){
|
Daniel@0
|
618 if (typeof Map === "undefined") {
|
Daniel@0
|
619 Map = function() { this.clear(); };
|
Daniel@0
|
620 Map.prototype = {
|
Daniel@0
|
621 set: function(k, v) { this._[k] = v; return this; },
|
Daniel@0
|
622 get: function(k) { return this._[k]; },
|
Daniel@0
|
623 has: function(k) { return k in this._; },
|
Daniel@0
|
624 delete: function(k) { return k in this._ && delete this._[k]; },
|
Daniel@0
|
625 clear: function() { this._ = Object.create(null); },
|
Daniel@0
|
626 get size() { var n = 0; for (var k in this._) ++n; return n; },
|
Daniel@0
|
627 forEach: function(c) { for (var k in this._) c(this._[k], k, this); }
|
Daniel@0
|
628 };
|
Daniel@0
|
629 } else (function() {
|
Daniel@0
|
630 var m = new Map;
|
Daniel@0
|
631 if (m.set(0, 0) !== m) {
|
Daniel@0
|
632 m = m.set;
|
Daniel@0
|
633 Map.prototype.set = function() { m.apply(this, arguments); return this; };
|
Daniel@0
|
634 }
|
Daniel@0
|
635 })();
|
Daniel@0
|
636
|
Daniel@0
|
637 (function (global, factory) {
|
Daniel@0
|
638 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
Daniel@0
|
639 typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
Daniel@0
|
640 factory((global.timeFormat = {}));
|
Daniel@0
|
641 }(this, function (exports) { 'use strict';
|
Daniel@0
|
642
|
Daniel@0
|
643 var zhCn = {
|
Daniel@0
|
644 dateTime: "%a %b %e %X %Y",
|
Daniel@0
|
645 date: "%Y/%-m/%-d",
|
Daniel@0
|
646 time: "%H:%M:%S",
|
Daniel@0
|
647 periods: ["上午", "下午"],
|
Daniel@0
|
648 days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
|
Daniel@0
|
649 shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
|
Daniel@0
|
650 months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
|
Daniel@0
|
651 shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
|
Daniel@0
|
652 };
|
Daniel@0
|
653
|
Daniel@0
|
654 var ruRu = {
|
Daniel@0
|
655 dateTime: "%A, %e %B %Y г. %X",
|
Daniel@0
|
656 date: "%d.%m.%Y",
|
Daniel@0
|
657 time: "%H:%M:%S",
|
Daniel@0
|
658 periods: ["AM", "PM"],
|
Daniel@0
|
659 days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
|
Daniel@0
|
660 shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
|
Daniel@0
|
661 months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
|
Daniel@0
|
662 shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
|
Daniel@0
|
663 };
|
Daniel@0
|
664
|
Daniel@0
|
665 var ptBr = {
|
Daniel@0
|
666 dateTime: "%A, %e de %B de %Y. %X",
|
Daniel@0
|
667 date: "%d/%m/%Y",
|
Daniel@0
|
668 time: "%H:%M:%S",
|
Daniel@0
|
669 periods: ["AM", "PM"],
|
Daniel@0
|
670 days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
|
Daniel@0
|
671 shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
|
Daniel@0
|
672 months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
|
Daniel@0
|
673 shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
|
Daniel@0
|
674 };
|
Daniel@0
|
675
|
Daniel@0
|
676 var plPl = {
|
Daniel@0
|
677 dateTime: "%A, %e %B %Y, %X",
|
Daniel@0
|
678 date: "%d/%m/%Y",
|
Daniel@0
|
679 time: "%H:%M:%S",
|
Daniel@0
|
680 periods: ["AM", "PM"], // unused
|
Daniel@0
|
681 days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
|
Daniel@0
|
682 shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."],
|
Daniel@0
|
683 months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
|
Daniel@0
|
684 shortMonths: ["Stycz.", "Luty", "Marz.", "Kwie.", "Maj", "Czerw.", "Lipc.", "Sierp.", "Wrz.", "Paźdz.", "Listop.", "Grudz."]/* In Polish language abbraviated months are not commonly used so there is a dispute about the proper abbraviations. */
|
Daniel@0
|
685 };
|
Daniel@0
|
686
|
Daniel@0
|
687 var nlNl = {
|
Daniel@0
|
688 dateTime: "%a %e %B %Y %T",
|
Daniel@0
|
689 date: "%d-%m-%Y",
|
Daniel@0
|
690 time: "%H:%M:%S",
|
Daniel@0
|
691 periods: ["AM", "PM"], // unused
|
Daniel@0
|
692 days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
|
Daniel@0
|
693 shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"],
|
Daniel@0
|
694 months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
|
Daniel@0
|
695 shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"]
|
Daniel@0
|
696 };
|
Daniel@0
|
697
|
Daniel@0
|
698 var mkMk = {
|
Daniel@0
|
699 dateTime: "%A, %e %B %Y г. %X",
|
Daniel@0
|
700 date: "%d.%m.%Y",
|
Daniel@0
|
701 time: "%H:%M:%S",
|
Daniel@0
|
702 periods: ["AM", "PM"],
|
Daniel@0
|
703 days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"],
|
Daniel@0
|
704 shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"],
|
Daniel@0
|
705 months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"],
|
Daniel@0
|
706 shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"]
|
Daniel@0
|
707 };
|
Daniel@0
|
708
|
Daniel@0
|
709 var jaJp = {
|
Daniel@0
|
710 dateTime: "%Y %b %e %a %X",
|
Daniel@0
|
711 date: "%Y/%m/%d",
|
Daniel@0
|
712 time: "%H:%M:%S",
|
Daniel@0
|
713 periods: ["AM", "PM"],
|
Daniel@0
|
714 days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
|
Daniel@0
|
715 shortDays: ["日", "月", "火", "水", "木", "金", "土"],
|
Daniel@0
|
716 months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"],
|
Daniel@0
|
717 shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
|
Daniel@0
|
718 };
|
Daniel@0
|
719
|
Daniel@0
|
720 var itIt = {
|
Daniel@0
|
721 dateTime: "%A %e %B %Y, %X",
|
Daniel@0
|
722 date: "%d/%m/%Y",
|
Daniel@0
|
723 time: "%H:%M:%S",
|
Daniel@0
|
724 periods: ["AM", "PM"], // unused
|
Daniel@0
|
725 days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
|
Daniel@0
|
726 shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
|
Daniel@0
|
727 months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
|
Daniel@0
|
728 shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"]
|
Daniel@0
|
729 };
|
Daniel@0
|
730
|
Daniel@0
|
731 var heIl = {
|
Daniel@0
|
732 dateTime: "%A, %e ב%B %Y %X",
|
Daniel@0
|
733 date: "%d.%m.%Y",
|
Daniel@0
|
734 time: "%H:%M:%S",
|
Daniel@0
|
735 periods: ["AM", "PM"],
|
Daniel@0
|
736 days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"],
|
Daniel@0
|
737 shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"],
|
Daniel@0
|
738 months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
|
Daniel@0
|
739 shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"]
|
Daniel@0
|
740 };
|
Daniel@0
|
741
|
Daniel@0
|
742 var frFr = {
|
Daniel@0
|
743 dateTime: "%A, le %e %B %Y, %X",
|
Daniel@0
|
744 date: "%d/%m/%Y",
|
Daniel@0
|
745 time: "%H:%M:%S",
|
Daniel@0
|
746 periods: ["AM", "PM"], // unused
|
Daniel@0
|
747 days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
|
Daniel@0
|
748 shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
|
Daniel@0
|
749 months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
|
Daniel@0
|
750 shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
|
Daniel@0
|
751 };
|
Daniel@0
|
752
|
Daniel@0
|
753 var frCa = {
|
Daniel@0
|
754 dateTime: "%a %e %b %Y %X",
|
Daniel@0
|
755 date: "%Y-%m-%d",
|
Daniel@0
|
756 time: "%H:%M:%S",
|
Daniel@0
|
757 periods: ["", ""],
|
Daniel@0
|
758 days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
|
Daniel@0
|
759 shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"],
|
Daniel@0
|
760 months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
|
Daniel@0
|
761 shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"]
|
Daniel@0
|
762 };
|
Daniel@0
|
763
|
Daniel@0
|
764 var fiFi = {
|
Daniel@0
|
765 dateTime: "%A, %-d. %Bta %Y klo %X",
|
Daniel@0
|
766 date: "%-d.%-m.%Y",
|
Daniel@0
|
767 time: "%H:%M:%S",
|
Daniel@0
|
768 periods: ["a.m.", "p.m."],
|
Daniel@0
|
769 days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
|
Daniel@0
|
770 shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"],
|
Daniel@0
|
771 months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
|
Daniel@0
|
772 shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"]
|
Daniel@0
|
773 };
|
Daniel@0
|
774
|
Daniel@0
|
775 var esEs = {
|
Daniel@0
|
776 dateTime: "%A, %e de %B de %Y, %X",
|
Daniel@0
|
777 date: "%d/%m/%Y",
|
Daniel@0
|
778 time: "%H:%M:%S",
|
Daniel@0
|
779 periods: ["AM", "PM"],
|
Daniel@0
|
780 days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
|
Daniel@0
|
781 shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
|
Daniel@0
|
782 months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
|
Daniel@0
|
783 shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
|
Daniel@0
|
784 };
|
Daniel@0
|
785
|
Daniel@0
|
786 var enUs = {
|
Daniel@0
|
787 dateTime: "%a %b %e %X %Y",
|
Daniel@0
|
788 date: "%m/%d/%Y",
|
Daniel@0
|
789 time: "%H:%M:%S",
|
Daniel@0
|
790 periods: ["AM", "PM"],
|
Daniel@0
|
791 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
Daniel@0
|
792 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
Daniel@0
|
793 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
Daniel@0
|
794 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
Daniel@0
|
795 };
|
Daniel@0
|
796
|
Daniel@0
|
797 var enGb = {
|
Daniel@0
|
798 dateTime: "%a %e %b %X %Y",
|
Daniel@0
|
799 date: "%d/%m/%Y",
|
Daniel@0
|
800 time: "%H:%M:%S",
|
Daniel@0
|
801 periods: ["AM", "PM"],
|
Daniel@0
|
802 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
Daniel@0
|
803 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
Daniel@0
|
804 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
Daniel@0
|
805 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
Daniel@0
|
806 };
|
Daniel@0
|
807
|
Daniel@0
|
808 var enCa = {
|
Daniel@0
|
809 dateTime: "%a %b %e %X %Y",
|
Daniel@0
|
810 date: "%Y-%m-%d",
|
Daniel@0
|
811 time: "%H:%M:%S",
|
Daniel@0
|
812 periods: ["AM", "PM"],
|
Daniel@0
|
813 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
Daniel@0
|
814 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
Daniel@0
|
815 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
Daniel@0
|
816 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
Daniel@0
|
817 };
|
Daniel@0
|
818
|
Daniel@0
|
819 var deDe = {
|
Daniel@0
|
820 dateTime: "%A, der %e. %B %Y, %X",
|
Daniel@0
|
821 date: "%d.%m.%Y",
|
Daniel@0
|
822 time: "%H:%M:%S",
|
Daniel@0
|
823 periods: ["AM", "PM"], // unused
|
Daniel@0
|
824 days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
|
Daniel@0
|
825 shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
|
Daniel@0
|
826 months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
|
Daniel@0
|
827 shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
|
Daniel@0
|
828 };
|
Daniel@0
|
829
|
Daniel@0
|
830 var caEs = {
|
Daniel@0
|
831 dateTime: "%A, %e de %B de %Y, %X",
|
Daniel@0
|
832 date: "%d/%m/%Y",
|
Daniel@0
|
833 time: "%H:%M:%S",
|
Daniel@0
|
834 periods: ["AM", "PM"],
|
Daniel@0
|
835 days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
|
Daniel@0
|
836 shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."],
|
Daniel@0
|
837 months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
|
Daniel@0
|
838 shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."]
|
Daniel@0
|
839 };
|
Daniel@0
|
840
|
Daniel@0
|
841 var t0 = new Date;
|
Daniel@0
|
842 var t1 = new Date;
|
Daniel@0
|
843
|
Daniel@0
|
844 function newInterval(floori, offseti, count) {
|
Daniel@0
|
845
|
Daniel@0
|
846 function interval(date) {
|
Daniel@0
|
847 return floori(date = new Date(+date)), date;
|
Daniel@0
|
848 }
|
Daniel@0
|
849
|
Daniel@0
|
850 interval.floor = interval;
|
Daniel@0
|
851
|
Daniel@0
|
852 interval.round = function(date) {
|
Daniel@0
|
853 var d0 = new Date(+date),
|
Daniel@0
|
854 d1 = new Date(date - 1);
|
Daniel@0
|
855 floori(d0), floori(d1), offseti(d1, 1);
|
Daniel@0
|
856 return date - d0 < d1 - date ? d0 : d1;
|
Daniel@0
|
857 };
|
Daniel@0
|
858
|
Daniel@0
|
859 interval.ceil = function(date) {
|
Daniel@0
|
860 return floori(date = new Date(date - 1)), offseti(date, 1), date;
|
Daniel@0
|
861 };
|
Daniel@0
|
862
|
Daniel@0
|
863 interval.offset = function(date, step) {
|
Daniel@0
|
864 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
|
Daniel@0
|
865 };
|
Daniel@0
|
866
|
Daniel@0
|
867 interval.range = function(start, stop, step) {
|
Daniel@0
|
868 var range = [];
|
Daniel@0
|
869 start = new Date(start - 1);
|
Daniel@0
|
870 stop = new Date(+stop);
|
Daniel@0
|
871 step = step == null ? 1 : Math.floor(step);
|
Daniel@0
|
872 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
|
Daniel@0
|
873 offseti(start, 1), floori(start);
|
Daniel@0
|
874 if (start < stop) range.push(new Date(+start));
|
Daniel@0
|
875 while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));
|
Daniel@0
|
876 return range;
|
Daniel@0
|
877 };
|
Daniel@0
|
878
|
Daniel@0
|
879 interval.filter = function(test) {
|
Daniel@0
|
880 return newInterval(function(date) {
|
Daniel@0
|
881 while (floori(date), !test(date)) date.setTime(date - 1);
|
Daniel@0
|
882 }, function(date, step) {
|
Daniel@0
|
883 while (--step >= 0) while (offseti(date, 1), !test(date));
|
Daniel@0
|
884 });
|
Daniel@0
|
885 };
|
Daniel@0
|
886
|
Daniel@0
|
887 if (count) interval.count = function(start, end) {
|
Daniel@0
|
888 t0.setTime(+start), t1.setTime(+end);
|
Daniel@0
|
889 floori(t0), floori(t1);
|
Daniel@0
|
890 return Math.floor(count(t0, t1));
|
Daniel@0
|
891 };
|
Daniel@0
|
892
|
Daniel@0
|
893 return interval;
|
Daniel@0
|
894 }
|
Daniel@0
|
895
|
Daniel@0
|
896 var day = newInterval(function(date) {
|
Daniel@0
|
897 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
898 }, function(date, step) {
|
Daniel@0
|
899 date.setDate(date.getDate() + step);
|
Daniel@0
|
900 }, function(start, end) {
|
Daniel@0
|
901 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;
|
Daniel@0
|
902 });
|
Daniel@0
|
903
|
Daniel@0
|
904 function weekday(i) {
|
Daniel@0
|
905 return newInterval(function(date) {
|
Daniel@0
|
906 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
907 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
|
Daniel@0
|
908 }, function(date, step) {
|
Daniel@0
|
909 date.setDate(date.getDate() + step * 7);
|
Daniel@0
|
910 }, function(start, end) {
|
Daniel@0
|
911 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;
|
Daniel@0
|
912 });
|
Daniel@0
|
913 }
|
Daniel@0
|
914
|
Daniel@0
|
915 var sunday = weekday(0);
|
Daniel@0
|
916 var monday = weekday(1);
|
Daniel@0
|
917
|
Daniel@0
|
918 var year = newInterval(function(date) {
|
Daniel@0
|
919 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
920 date.setMonth(0, 1);
|
Daniel@0
|
921 }, function(date, step) {
|
Daniel@0
|
922 date.setFullYear(date.getFullYear() + step);
|
Daniel@0
|
923 }, function(start, end) {
|
Daniel@0
|
924 return end.getFullYear() - start.getFullYear();
|
Daniel@0
|
925 });
|
Daniel@0
|
926
|
Daniel@0
|
927 var utcDay = newInterval(function(date) {
|
Daniel@0
|
928 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
929 }, function(date, step) {
|
Daniel@0
|
930 date.setUTCDate(date.getUTCDate() + step);
|
Daniel@0
|
931 }, function(start, end) {
|
Daniel@0
|
932 return (end - start) / 864e5;
|
Daniel@0
|
933 });
|
Daniel@0
|
934
|
Daniel@0
|
935 function utcWeekday(i) {
|
Daniel@0
|
936 return newInterval(function(date) {
|
Daniel@0
|
937 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
938 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
|
Daniel@0
|
939 }, function(date, step) {
|
Daniel@0
|
940 date.setUTCDate(date.getUTCDate() + step * 7);
|
Daniel@0
|
941 }, function(start, end) {
|
Daniel@0
|
942 return (end - start) / 6048e5;
|
Daniel@0
|
943 });
|
Daniel@0
|
944 }
|
Daniel@0
|
945
|
Daniel@0
|
946 var utcSunday = utcWeekday(0);
|
Daniel@0
|
947 var utcMonday = utcWeekday(1);
|
Daniel@0
|
948
|
Daniel@0
|
949 var utcYear = newInterval(function(date) {
|
Daniel@0
|
950 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
951 date.setUTCMonth(0, 1);
|
Daniel@0
|
952 }, function(date, step) {
|
Daniel@0
|
953 date.setUTCFullYear(date.getUTCFullYear() + step);
|
Daniel@0
|
954 }, function(start, end) {
|
Daniel@0
|
955 return end.getUTCFullYear() - start.getUTCFullYear();
|
Daniel@0
|
956 });
|
Daniel@0
|
957
|
Daniel@0
|
958 function localDate(d) {
|
Daniel@0
|
959 if (0 <= d.y && d.y < 100) {
|
Daniel@0
|
960 var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
|
Daniel@0
|
961 date.setFullYear(d.y);
|
Daniel@0
|
962 return date;
|
Daniel@0
|
963 }
|
Daniel@0
|
964 return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
|
Daniel@0
|
965 }
|
Daniel@0
|
966
|
Daniel@0
|
967 function utcDate(d) {
|
Daniel@0
|
968 if (0 <= d.y && d.y < 100) {
|
Daniel@0
|
969 var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
|
Daniel@0
|
970 date.setUTCFullYear(d.y);
|
Daniel@0
|
971 return date;
|
Daniel@0
|
972 }
|
Daniel@0
|
973 return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
|
Daniel@0
|
974 }
|
Daniel@0
|
975
|
Daniel@0
|
976 function newYear(y) {
|
Daniel@0
|
977 return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
|
Daniel@0
|
978 }
|
Daniel@0
|
979
|
Daniel@0
|
980 function locale(locale) {
|
Daniel@0
|
981 var locale_dateTime = locale.dateTime,
|
Daniel@0
|
982 locale_date = locale.date,
|
Daniel@0
|
983 locale_time = locale.time,
|
Daniel@0
|
984 locale_periods = locale.periods,
|
Daniel@0
|
985 locale_weekdays = locale.days,
|
Daniel@0
|
986 locale_shortWeekdays = locale.shortDays,
|
Daniel@0
|
987 locale_months = locale.months,
|
Daniel@0
|
988 locale_shortMonths = locale.shortMonths;
|
Daniel@0
|
989
|
Daniel@0
|
990 var periodLookup = formatLookup(locale_periods),
|
Daniel@0
|
991 weekdayRe = formatRe(locale_weekdays),
|
Daniel@0
|
992 weekdayLookup = formatLookup(locale_weekdays),
|
Daniel@0
|
993 shortWeekdayRe = formatRe(locale_shortWeekdays),
|
Daniel@0
|
994 shortWeekdayLookup = formatLookup(locale_shortWeekdays),
|
Daniel@0
|
995 monthRe = formatRe(locale_months),
|
Daniel@0
|
996 monthLookup = formatLookup(locale_months),
|
Daniel@0
|
997 shortMonthRe = formatRe(locale_shortMonths),
|
Daniel@0
|
998 shortMonthLookup = formatLookup(locale_shortMonths);
|
Daniel@0
|
999
|
Daniel@0
|
1000 var formats = {
|
Daniel@0
|
1001 "a": formatShortWeekday,
|
Daniel@0
|
1002 "A": formatWeekday,
|
Daniel@0
|
1003 "b": formatShortMonth,
|
Daniel@0
|
1004 "B": formatMonth,
|
Daniel@0
|
1005 "c": null,
|
Daniel@0
|
1006 "d": formatDayOfMonth,
|
Daniel@0
|
1007 "e": formatDayOfMonth,
|
Daniel@0
|
1008 "H": formatHour24,
|
Daniel@0
|
1009 "I": formatHour12,
|
Daniel@0
|
1010 "j": formatDayOfYear,
|
Daniel@0
|
1011 "L": formatMilliseconds,
|
Daniel@0
|
1012 "m": formatMonthNumber,
|
Daniel@0
|
1013 "M": formatMinutes,
|
Daniel@0
|
1014 "p": formatPeriod,
|
Daniel@0
|
1015 "S": formatSeconds,
|
Daniel@0
|
1016 "U": formatWeekNumberSunday,
|
Daniel@0
|
1017 "w": formatWeekdayNumber,
|
Daniel@0
|
1018 "W": formatWeekNumberMonday,
|
Daniel@0
|
1019 "x": null,
|
Daniel@0
|
1020 "X": null,
|
Daniel@0
|
1021 "y": formatYear,
|
Daniel@0
|
1022 "Y": formatFullYear,
|
Daniel@0
|
1023 "Z": formatZone,
|
Daniel@0
|
1024 "%": formatLiteralPercent
|
Daniel@0
|
1025 };
|
Daniel@0
|
1026
|
Daniel@0
|
1027 var utcFormats = {
|
Daniel@0
|
1028 "a": formatUTCShortWeekday,
|
Daniel@0
|
1029 "A": formatUTCWeekday,
|
Daniel@0
|
1030 "b": formatUTCShortMonth,
|
Daniel@0
|
1031 "B": formatUTCMonth,
|
Daniel@0
|
1032 "c": null,
|
Daniel@0
|
1033 "d": formatUTCDayOfMonth,
|
Daniel@0
|
1034 "e": formatUTCDayOfMonth,
|
Daniel@0
|
1035 "H": formatUTCHour24,
|
Daniel@0
|
1036 "I": formatUTCHour12,
|
Daniel@0
|
1037 "j": formatUTCDayOfYear,
|
Daniel@0
|
1038 "L": formatUTCMilliseconds,
|
Daniel@0
|
1039 "m": formatUTCMonthNumber,
|
Daniel@0
|
1040 "M": formatUTCMinutes,
|
Daniel@0
|
1041 "p": formatUTCPeriod,
|
Daniel@0
|
1042 "S": formatUTCSeconds,
|
Daniel@0
|
1043 "U": formatUTCWeekNumberSunday,
|
Daniel@0
|
1044 "w": formatUTCWeekdayNumber,
|
Daniel@0
|
1045 "W": formatUTCWeekNumberMonday,
|
Daniel@0
|
1046 "x": null,
|
Daniel@0
|
1047 "X": null,
|
Daniel@0
|
1048 "y": formatUTCYear,
|
Daniel@0
|
1049 "Y": formatUTCFullYear,
|
Daniel@0
|
1050 "Z": formatUTCZone,
|
Daniel@0
|
1051 "%": formatLiteralPercent
|
Daniel@0
|
1052 };
|
Daniel@0
|
1053
|
Daniel@0
|
1054 var parses = {
|
Daniel@0
|
1055 "a": parseShortWeekday,
|
Daniel@0
|
1056 "A": parseWeekday,
|
Daniel@0
|
1057 "b": parseShortMonth,
|
Daniel@0
|
1058 "B": parseMonth,
|
Daniel@0
|
1059 "c": parseLocaleDateTime,
|
Daniel@0
|
1060 "d": parseDayOfMonth,
|
Daniel@0
|
1061 "e": parseDayOfMonth,
|
Daniel@0
|
1062 "H": parseHour24,
|
Daniel@0
|
1063 "I": parseHour24,
|
Daniel@0
|
1064 "j": parseDayOfYear,
|
Daniel@0
|
1065 "L": parseMilliseconds,
|
Daniel@0
|
1066 "m": parseMonthNumber,
|
Daniel@0
|
1067 "M": parseMinutes,
|
Daniel@0
|
1068 "p": parsePeriod,
|
Daniel@0
|
1069 "S": parseSeconds,
|
Daniel@0
|
1070 "U": parseWeekNumberSunday,
|
Daniel@0
|
1071 "w": parseWeekdayNumber,
|
Daniel@0
|
1072 "W": parseWeekNumberMonday,
|
Daniel@0
|
1073 "x": parseLocaleDate,
|
Daniel@0
|
1074 "X": parseLocaleTime,
|
Daniel@0
|
1075 "y": parseYear,
|
Daniel@0
|
1076 "Y": parseFullYear,
|
Daniel@0
|
1077 "Z": parseZone,
|
Daniel@0
|
1078 "%": parseLiteralPercent
|
Daniel@0
|
1079 };
|
Daniel@0
|
1080
|
Daniel@0
|
1081 // These recursive directive definitions must be deferred.
|
Daniel@0
|
1082 formats.x = newFormat(locale_date, formats);
|
Daniel@0
|
1083 formats.X = newFormat(locale_time, formats);
|
Daniel@0
|
1084 formats.c = newFormat(locale_dateTime, formats);
|
Daniel@0
|
1085 utcFormats.x = newFormat(locale_date, utcFormats);
|
Daniel@0
|
1086 utcFormats.X = newFormat(locale_time, utcFormats);
|
Daniel@0
|
1087 utcFormats.c = newFormat(locale_dateTime, utcFormats);
|
Daniel@0
|
1088
|
Daniel@0
|
1089 function newFormat(specifier, formats) {
|
Daniel@0
|
1090 return function(date) {
|
Daniel@0
|
1091 var string = [],
|
Daniel@0
|
1092 i = -1,
|
Daniel@0
|
1093 j = 0,
|
Daniel@0
|
1094 n = specifier.length,
|
Daniel@0
|
1095 c,
|
Daniel@0
|
1096 pad,
|
Daniel@0
|
1097 format;
|
Daniel@0
|
1098
|
Daniel@0
|
1099 while (++i < n) {
|
Daniel@0
|
1100 if (specifier.charCodeAt(i) === 37) {
|
Daniel@0
|
1101 string.push(specifier.slice(j, i));
|
Daniel@0
|
1102 if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
|
Daniel@0
|
1103 if (format = formats[c]) c = format(date, pad == null ? (c === "e" ? " " : "0") : pad);
|
Daniel@0
|
1104 string.push(c);
|
Daniel@0
|
1105 j = i + 1;
|
Daniel@0
|
1106 }
|
Daniel@0
|
1107 }
|
Daniel@0
|
1108
|
Daniel@0
|
1109 string.push(specifier.slice(j, i));
|
Daniel@0
|
1110 return string.join("");
|
Daniel@0
|
1111 };
|
Daniel@0
|
1112 }
|
Daniel@0
|
1113
|
Daniel@0
|
1114 function newParse(specifier, newDate) {
|
Daniel@0
|
1115 return function(string) {
|
Daniel@0
|
1116 var d = newYear(1900),
|
Daniel@0
|
1117 i = parseSpecifier(d, specifier, string, 0);
|
Daniel@0
|
1118 if (i != string.length) return null;
|
Daniel@0
|
1119
|
Daniel@0
|
1120 // The am-pm flag is 0 for AM, and 1 for PM.
|
Daniel@0
|
1121 if ("p" in d) d.H = d.H % 12 + d.p * 12;
|
Daniel@0
|
1122
|
Daniel@0
|
1123 // If a time zone is specified, all fields are interpreted as UTC and then
|
Daniel@0
|
1124 // offset according to the specified time zone.
|
Daniel@0
|
1125 if ("Z" in d) {
|
Daniel@0
|
1126 if ("w" in d && ("W" in d || "U" in d)) {
|
Daniel@0
|
1127 var day = utcDate(newYear(d.y)).getUTCDay();
|
Daniel@0
|
1128 if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day;
|
Daniel@0
|
1129 d.m = 0;
|
Daniel@0
|
1130 d.d = d.w + d.U * 7 - (day + 6) % 7;
|
Daniel@0
|
1131 }
|
Daniel@0
|
1132 d.H += d.Z / 100 | 0;
|
Daniel@0
|
1133 d.M += d.Z % 100;
|
Daniel@0
|
1134 return utcDate(d);
|
Daniel@0
|
1135 }
|
Daniel@0
|
1136
|
Daniel@0
|
1137 // Otherwise, all fields are in local time.
|
Daniel@0
|
1138 if ("w" in d && ("W" in d || "U" in d)) {
|
Daniel@0
|
1139 var day = newDate(newYear(d.y)).getDay();
|
Daniel@0
|
1140 if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day;
|
Daniel@0
|
1141 d.m = 0;
|
Daniel@0
|
1142 d.d = d.w + d.U * 7 - (day + 6) % 7;
|
Daniel@0
|
1143 }
|
Daniel@0
|
1144 return newDate(d);
|
Daniel@0
|
1145 };
|
Daniel@0
|
1146 }
|
Daniel@0
|
1147
|
Daniel@0
|
1148 function parseSpecifier(d, specifier, string, j) {
|
Daniel@0
|
1149 var i = 0,
|
Daniel@0
|
1150 n = specifier.length,
|
Daniel@0
|
1151 m = string.length,
|
Daniel@0
|
1152 c,
|
Daniel@0
|
1153 parse;
|
Daniel@0
|
1154
|
Daniel@0
|
1155 while (i < n) {
|
Daniel@0
|
1156 if (j >= m) return -1;
|
Daniel@0
|
1157 c = specifier.charCodeAt(i++);
|
Daniel@0
|
1158 if (c === 37) {
|
Daniel@0
|
1159 c = specifier.charAt(i++);
|
Daniel@0
|
1160 parse = parses[c in pads ? specifier.charAt(i++) : c];
|
Daniel@0
|
1161 if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
|
Daniel@0
|
1162 } else if (c != string.charCodeAt(j++)) {
|
Daniel@0
|
1163 return -1;
|
Daniel@0
|
1164 }
|
Daniel@0
|
1165 }
|
Daniel@0
|
1166
|
Daniel@0
|
1167 return j;
|
Daniel@0
|
1168 }
|
Daniel@0
|
1169
|
Daniel@0
|
1170 function parseShortWeekday(d, string, i) {
|
Daniel@0
|
1171 var n = shortWeekdayRe.exec(string.slice(i));
|
Daniel@0
|
1172 return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
Daniel@0
|
1173 }
|
Daniel@0
|
1174
|
Daniel@0
|
1175 function parseWeekday(d, string, i) {
|
Daniel@0
|
1176 var n = weekdayRe.exec(string.slice(i));
|
Daniel@0
|
1177 return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
Daniel@0
|
1178 }
|
Daniel@0
|
1179
|
Daniel@0
|
1180 function parseShortMonth(d, string, i) {
|
Daniel@0
|
1181 var n = shortMonthRe.exec(string.slice(i));
|
Daniel@0
|
1182 return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
Daniel@0
|
1183 }
|
Daniel@0
|
1184
|
Daniel@0
|
1185 function parseMonth(d, string, i) {
|
Daniel@0
|
1186 var n = monthRe.exec(string.slice(i));
|
Daniel@0
|
1187 return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
Daniel@0
|
1188 }
|
Daniel@0
|
1189
|
Daniel@0
|
1190 function parseLocaleDateTime(d, string, i) {
|
Daniel@0
|
1191 return parseSpecifier(d, locale_dateTime, string, i);
|
Daniel@0
|
1192 }
|
Daniel@0
|
1193
|
Daniel@0
|
1194 function parseLocaleDate(d, string, i) {
|
Daniel@0
|
1195 return parseSpecifier(d, locale_date, string, i);
|
Daniel@0
|
1196 }
|
Daniel@0
|
1197
|
Daniel@0
|
1198 function parseLocaleTime(d, string, i) {
|
Daniel@0
|
1199 return parseSpecifier(d, locale_time, string, i);
|
Daniel@0
|
1200 }
|
Daniel@0
|
1201
|
Daniel@0
|
1202 function parsePeriod(d, string, i) {
|
Daniel@0
|
1203 var n = periodLookup.get(string.slice(i, i += 2).toLowerCase());
|
Daniel@0
|
1204 return n == null ? -1 : (d.p = n, i);
|
Daniel@0
|
1205 }
|
Daniel@0
|
1206
|
Daniel@0
|
1207 function formatShortWeekday(d) {
|
Daniel@0
|
1208 return locale_shortWeekdays[d.getDay()];
|
Daniel@0
|
1209 }
|
Daniel@0
|
1210
|
Daniel@0
|
1211 function formatWeekday(d) {
|
Daniel@0
|
1212 return locale_weekdays[d.getDay()];
|
Daniel@0
|
1213 }
|
Daniel@0
|
1214
|
Daniel@0
|
1215 function formatShortMonth(d) {
|
Daniel@0
|
1216 return locale_shortMonths[d.getMonth()];
|
Daniel@0
|
1217 }
|
Daniel@0
|
1218
|
Daniel@0
|
1219 function formatMonth(d) {
|
Daniel@0
|
1220 return locale_months[d.getMonth()];
|
Daniel@0
|
1221 }
|
Daniel@0
|
1222
|
Daniel@0
|
1223 function formatPeriod(d) {
|
Daniel@0
|
1224 return locale_periods[+(d.getHours() >= 12)];
|
Daniel@0
|
1225 }
|
Daniel@0
|
1226
|
Daniel@0
|
1227 function formatUTCShortWeekday(d) {
|
Daniel@0
|
1228 return locale_shortWeekdays[d.getUTCDay()];
|
Daniel@0
|
1229 }
|
Daniel@0
|
1230
|
Daniel@0
|
1231 function formatUTCWeekday(d) {
|
Daniel@0
|
1232 return locale_weekdays[d.getUTCDay()];
|
Daniel@0
|
1233 }
|
Daniel@0
|
1234
|
Daniel@0
|
1235 function formatUTCShortMonth(d) {
|
Daniel@0
|
1236 return locale_shortMonths[d.getUTCMonth()];
|
Daniel@0
|
1237 }
|
Daniel@0
|
1238
|
Daniel@0
|
1239 function formatUTCMonth(d) {
|
Daniel@0
|
1240 return locale_months[d.getUTCMonth()];
|
Daniel@0
|
1241 }
|
Daniel@0
|
1242
|
Daniel@0
|
1243 function formatUTCPeriod(d) {
|
Daniel@0
|
1244 return locale_periods[+(d.getUTCHours() >= 12)];
|
Daniel@0
|
1245 }
|
Daniel@0
|
1246
|
Daniel@0
|
1247 return {
|
Daniel@0
|
1248 format: function(specifier) {
|
Daniel@0
|
1249 var f = newFormat(specifier += "", formats);
|
Daniel@0
|
1250 f.parse = newParse(specifier, localDate);
|
Daniel@0
|
1251 f.toString = function() { return specifier; };
|
Daniel@0
|
1252 return f;
|
Daniel@0
|
1253 },
|
Daniel@0
|
1254 utcFormat: function(specifier) {
|
Daniel@0
|
1255 var f = newFormat(specifier += "", utcFormats);
|
Daniel@0
|
1256 f.parse = newParse(specifier, utcDate);
|
Daniel@0
|
1257 f.toString = function() { return specifier; };
|
Daniel@0
|
1258 return f;
|
Daniel@0
|
1259 }
|
Daniel@0
|
1260 };
|
Daniel@0
|
1261 }
|
Daniel@0
|
1262
|
Daniel@0
|
1263 var pads = {"-": "", "_": " ", "0": "0"};
|
Daniel@0
|
1264 var numberRe = /^\s*\d+/;
|
Daniel@0
|
1265 var percentRe = /^%/;
|
Daniel@0
|
1266 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
|
Daniel@0
|
1267
|
Daniel@0
|
1268 function pad(value, fill, width) {
|
Daniel@0
|
1269 var sign = value < 0 ? "-" : "",
|
Daniel@0
|
1270 string = (sign ? -value : value) + "",
|
Daniel@0
|
1271 length = string.length;
|
Daniel@0
|
1272 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
|
Daniel@0
|
1273 }
|
Daniel@0
|
1274
|
Daniel@0
|
1275 function requote(s) {
|
Daniel@0
|
1276 return s.replace(requoteRe, "\\$&");
|
Daniel@0
|
1277 }
|
Daniel@0
|
1278
|
Daniel@0
|
1279 function formatRe(names) {
|
Daniel@0
|
1280 return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
|
Daniel@0
|
1281 }
|
Daniel@0
|
1282
|
Daniel@0
|
1283 function formatLookup(names) {
|
Daniel@0
|
1284 var map = new Map, i = -1, n = names.length;
|
Daniel@0
|
1285 while (++i < n) map.set(names[i].toLowerCase(), i);
|
Daniel@0
|
1286 return map;
|
Daniel@0
|
1287 }
|
Daniel@0
|
1288
|
Daniel@0
|
1289 function parseWeekdayNumber(d, string, i) {
|
Daniel@0
|
1290 var n = numberRe.exec(string.slice(i, i + 1));
|
Daniel@0
|
1291 return n ? (d.w = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1292 }
|
Daniel@0
|
1293
|
Daniel@0
|
1294 function parseWeekNumberSunday(d, string, i) {
|
Daniel@0
|
1295 var n = numberRe.exec(string.slice(i));
|
Daniel@0
|
1296 return n ? (d.U = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1297 }
|
Daniel@0
|
1298
|
Daniel@0
|
1299 function parseWeekNumberMonday(d, string, i) {
|
Daniel@0
|
1300 var n = numberRe.exec(string.slice(i));
|
Daniel@0
|
1301 return n ? (d.W = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1302 }
|
Daniel@0
|
1303
|
Daniel@0
|
1304 function parseFullYear(d, string, i) {
|
Daniel@0
|
1305 var n = numberRe.exec(string.slice(i, i + 4));
|
Daniel@0
|
1306 return n ? (d.y = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1307 }
|
Daniel@0
|
1308
|
Daniel@0
|
1309 function parseYear(d, string, i) {
|
Daniel@0
|
1310 var n = numberRe.exec(string.slice(i, i + 2));
|
Daniel@0
|
1311 return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
|
Daniel@0
|
1312 }
|
Daniel@0
|
1313
|
Daniel@0
|
1314 function parseZone(d, string, i) {
|
Daniel@0
|
1315 return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5))
|
Daniel@0
|
1316 ? (d.Z = -string, i + 5) // sign differs from getTimezoneOffset!
|
Daniel@0
|
1317 : -1;
|
Daniel@0
|
1318 }
|
Daniel@0
|
1319
|
Daniel@0
|
1320 function parseMonthNumber(d, string, i) {
|
Daniel@0
|
1321 var n = numberRe.exec(string.slice(i, i + 2));
|
Daniel@0
|
1322 return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
|
Daniel@0
|
1323 }
|
Daniel@0
|
1324
|
Daniel@0
|
1325 function parseDayOfMonth(d, string, i) {
|
Daniel@0
|
1326 var n = numberRe.exec(string.slice(i, i + 2));
|
Daniel@0
|
1327 return n ? (d.d = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1328 }
|
Daniel@0
|
1329
|
Daniel@0
|
1330 function parseDayOfYear(d, string, i) {
|
Daniel@0
|
1331 var n = numberRe.exec(string.slice(i, i + 3));
|
Daniel@0
|
1332 return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1333 }
|
Daniel@0
|
1334
|
Daniel@0
|
1335 function parseHour24(d, string, i) {
|
Daniel@0
|
1336 var n = numberRe.exec(string.slice(i, i + 2));
|
Daniel@0
|
1337 return n ? (d.H = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1338 }
|
Daniel@0
|
1339
|
Daniel@0
|
1340 function parseMinutes(d, string, i) {
|
Daniel@0
|
1341 var n = numberRe.exec(string.slice(i, i + 2));
|
Daniel@0
|
1342 return n ? (d.M = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1343 }
|
Daniel@0
|
1344
|
Daniel@0
|
1345 function parseSeconds(d, string, i) {
|
Daniel@0
|
1346 var n = numberRe.exec(string.slice(i, i + 2));
|
Daniel@0
|
1347 return n ? (d.S = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1348 }
|
Daniel@0
|
1349
|
Daniel@0
|
1350 function parseMilliseconds(d, string, i) {
|
Daniel@0
|
1351 var n = numberRe.exec(string.slice(i, i + 3));
|
Daniel@0
|
1352 return n ? (d.L = +n[0], i + n[0].length) : -1;
|
Daniel@0
|
1353 }
|
Daniel@0
|
1354
|
Daniel@0
|
1355 function parseLiteralPercent(d, string, i) {
|
Daniel@0
|
1356 var n = percentRe.exec(string.slice(i, i + 1));
|
Daniel@0
|
1357 return n ? i + n[0].length : -1;
|
Daniel@0
|
1358 }
|
Daniel@0
|
1359
|
Daniel@0
|
1360 function formatDayOfMonth(d, p) {
|
Daniel@0
|
1361 return pad(d.getDate(), p, 2);
|
Daniel@0
|
1362 }
|
Daniel@0
|
1363
|
Daniel@0
|
1364 function formatHour24(d, p) {
|
Daniel@0
|
1365 return pad(d.getHours(), p, 2);
|
Daniel@0
|
1366 }
|
Daniel@0
|
1367
|
Daniel@0
|
1368 function formatHour12(d, p) {
|
Daniel@0
|
1369 return pad(d.getHours() % 12 || 12, p, 2);
|
Daniel@0
|
1370 }
|
Daniel@0
|
1371
|
Daniel@0
|
1372 function formatDayOfYear(d, p) {
|
Daniel@0
|
1373 return pad(1 + day.count(year(d), d), p, 3);
|
Daniel@0
|
1374 }
|
Daniel@0
|
1375
|
Daniel@0
|
1376 function formatMilliseconds(d, p) {
|
Daniel@0
|
1377 return pad(d.getMilliseconds(), p, 3);
|
Daniel@0
|
1378 }
|
Daniel@0
|
1379
|
Daniel@0
|
1380 function formatMonthNumber(d, p) {
|
Daniel@0
|
1381 return pad(d.getMonth() + 1, p, 2);
|
Daniel@0
|
1382 }
|
Daniel@0
|
1383
|
Daniel@0
|
1384 function formatMinutes(d, p) {
|
Daniel@0
|
1385 return pad(d.getMinutes(), p, 2);
|
Daniel@0
|
1386 }
|
Daniel@0
|
1387
|
Daniel@0
|
1388 function formatSeconds(d, p) {
|
Daniel@0
|
1389 return pad(d.getSeconds(), p, 2);
|
Daniel@0
|
1390 }
|
Daniel@0
|
1391
|
Daniel@0
|
1392 function formatWeekNumberSunday(d, p) {
|
Daniel@0
|
1393 return pad(sunday.count(year(d), d), p, 2);
|
Daniel@0
|
1394 }
|
Daniel@0
|
1395
|
Daniel@0
|
1396 function formatWeekdayNumber(d) {
|
Daniel@0
|
1397 return d.getDay();
|
Daniel@0
|
1398 }
|
Daniel@0
|
1399
|
Daniel@0
|
1400 function formatWeekNumberMonday(d, p) {
|
Daniel@0
|
1401 return pad(monday.count(year(d), d), p, 2);
|
Daniel@0
|
1402 }
|
Daniel@0
|
1403
|
Daniel@0
|
1404 function formatYear(d, p) {
|
Daniel@0
|
1405 return pad(d.getFullYear() % 100, p, 2);
|
Daniel@0
|
1406 }
|
Daniel@0
|
1407
|
Daniel@0
|
1408 function formatFullYear(d, p) {
|
Daniel@0
|
1409 return pad(d.getFullYear() % 10000, p, 4);
|
Daniel@0
|
1410 }
|
Daniel@0
|
1411
|
Daniel@0
|
1412 function formatZone(d) {
|
Daniel@0
|
1413 var z = d.getTimezoneOffset();
|
Daniel@0
|
1414 return (z > 0 ? "-" : (z *= -1, "+"))
|
Daniel@0
|
1415 + pad(z / 60 | 0, "0", 2)
|
Daniel@0
|
1416 + pad(z % 60, "0", 2);
|
Daniel@0
|
1417 }
|
Daniel@0
|
1418
|
Daniel@0
|
1419 function formatUTCDayOfMonth(d, p) {
|
Daniel@0
|
1420 return pad(d.getUTCDate(), p, 2);
|
Daniel@0
|
1421 }
|
Daniel@0
|
1422
|
Daniel@0
|
1423 function formatUTCHour24(d, p) {
|
Daniel@0
|
1424 return pad(d.getUTCHours(), p, 2);
|
Daniel@0
|
1425 }
|
Daniel@0
|
1426
|
Daniel@0
|
1427 function formatUTCHour12(d, p) {
|
Daniel@0
|
1428 return pad(d.getUTCHours() % 12 || 12, p, 2);
|
Daniel@0
|
1429 }
|
Daniel@0
|
1430
|
Daniel@0
|
1431 function formatUTCDayOfYear(d, p) {
|
Daniel@0
|
1432 return pad(1 + utcDay.count(utcYear(d), d), p, 3);
|
Daniel@0
|
1433 }
|
Daniel@0
|
1434
|
Daniel@0
|
1435 function formatUTCMilliseconds(d, p) {
|
Daniel@0
|
1436 return pad(d.getUTCMilliseconds(), p, 3);
|
Daniel@0
|
1437 }
|
Daniel@0
|
1438
|
Daniel@0
|
1439 function formatUTCMonthNumber(d, p) {
|
Daniel@0
|
1440 return pad(d.getUTCMonth() + 1, p, 2);
|
Daniel@0
|
1441 }
|
Daniel@0
|
1442
|
Daniel@0
|
1443 function formatUTCMinutes(d, p) {
|
Daniel@0
|
1444 return pad(d.getUTCMinutes(), p, 2);
|
Daniel@0
|
1445 }
|
Daniel@0
|
1446
|
Daniel@0
|
1447 function formatUTCSeconds(d, p) {
|
Daniel@0
|
1448 return pad(d.getUTCSeconds(), p, 2);
|
Daniel@0
|
1449 }
|
Daniel@0
|
1450
|
Daniel@0
|
1451 function formatUTCWeekNumberSunday(d, p) {
|
Daniel@0
|
1452 return pad(utcSunday.count(utcYear(d), d), p, 2);
|
Daniel@0
|
1453 }
|
Daniel@0
|
1454
|
Daniel@0
|
1455 function formatUTCWeekdayNumber(d) {
|
Daniel@0
|
1456 return d.getUTCDay();
|
Daniel@0
|
1457 }
|
Daniel@0
|
1458
|
Daniel@0
|
1459 function formatUTCWeekNumberMonday(d, p) {
|
Daniel@0
|
1460 return pad(utcMonday.count(utcYear(d), d), p, 2);
|
Daniel@0
|
1461 }
|
Daniel@0
|
1462
|
Daniel@0
|
1463 function formatUTCYear(d, p) {
|
Daniel@0
|
1464 return pad(d.getUTCFullYear() % 100, p, 2);
|
Daniel@0
|
1465 }
|
Daniel@0
|
1466
|
Daniel@0
|
1467 function formatUTCFullYear(d, p) {
|
Daniel@0
|
1468 return pad(d.getUTCFullYear() % 10000, p, 4);
|
Daniel@0
|
1469 }
|
Daniel@0
|
1470
|
Daniel@0
|
1471 function formatUTCZone() {
|
Daniel@0
|
1472 return "+0000";
|
Daniel@0
|
1473 }
|
Daniel@0
|
1474
|
Daniel@0
|
1475 function formatLiteralPercent() {
|
Daniel@0
|
1476 return "%";
|
Daniel@0
|
1477 }
|
Daniel@0
|
1478
|
Daniel@0
|
1479 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
|
Daniel@0
|
1480
|
Daniel@0
|
1481 function formatIsoNative(date) {
|
Daniel@0
|
1482 return date.toISOString();
|
Daniel@0
|
1483 }
|
Daniel@0
|
1484
|
Daniel@0
|
1485 formatIsoNative.parse = function(string) {
|
Daniel@0
|
1486 var date = new Date(string);
|
Daniel@0
|
1487 return isNaN(date) ? null : date;
|
Daniel@0
|
1488 };
|
Daniel@0
|
1489
|
Daniel@0
|
1490 formatIsoNative.toString = function() {
|
Daniel@0
|
1491 return isoSpecifier;
|
Daniel@0
|
1492 };
|
Daniel@0
|
1493
|
Daniel@0
|
1494 var formatIso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z")
|
Daniel@0
|
1495 ? formatIsoNative
|
Daniel@0
|
1496 : enUs.utcFormat(isoSpecifier);
|
Daniel@0
|
1497
|
Daniel@0
|
1498 var isoFormat = formatIso;
|
Daniel@0
|
1499
|
Daniel@0
|
1500 var localeDefinitions = (new Map)
|
Daniel@0
|
1501 .set("ca-ES", caEs)
|
Daniel@0
|
1502 .set("de-DE", deDe)
|
Daniel@0
|
1503 .set("en-CA", enCa)
|
Daniel@0
|
1504 .set("en-GB", enGb)
|
Daniel@0
|
1505 .set("en-US", enUs)
|
Daniel@0
|
1506 .set("es-ES", esEs)
|
Daniel@0
|
1507 .set("fi-FI", fiFi)
|
Daniel@0
|
1508 .set("fr-CA", frCa)
|
Daniel@0
|
1509 .set("fr-FR", frFr)
|
Daniel@0
|
1510 .set("he-IL", heIl)
|
Daniel@0
|
1511 .set("it-IT", itIt)
|
Daniel@0
|
1512 .set("ja-JP", jaJp)
|
Daniel@0
|
1513 .set("mk-MK", mkMk)
|
Daniel@0
|
1514 .set("nl-NL", nlNl)
|
Daniel@0
|
1515 .set("pl-PL", plPl)
|
Daniel@0
|
1516 .set("pt-BR", ptBr)
|
Daniel@0
|
1517 .set("ru-RU", ruRu)
|
Daniel@0
|
1518 .set("zh-CN", zhCn);
|
Daniel@0
|
1519
|
Daniel@0
|
1520 var defaultLocale = locale(enUs);
|
Daniel@0
|
1521 exports.format = defaultLocale.format;
|
Daniel@0
|
1522 exports.utcFormat = defaultLocale.utcFormat;
|
Daniel@0
|
1523
|
Daniel@0
|
1524 function localeFormat(definition) {
|
Daniel@0
|
1525 if (typeof definition === "string") {
|
Daniel@0
|
1526 definition = localeDefinitions.get(definition);
|
Daniel@0
|
1527 if (!definition) return null;
|
Daniel@0
|
1528 }
|
Daniel@0
|
1529 return locale(definition);
|
Daniel@0
|
1530 }
|
Daniel@0
|
1531 ;
|
Daniel@0
|
1532
|
Daniel@0
|
1533 exports.localeFormat = localeFormat;
|
Daniel@0
|
1534 exports.isoFormat = isoFormat;
|
Daniel@0
|
1535
|
Daniel@0
|
1536 }));
|
Daniel@0
|
1537 },{}],6:[function(require,module,exports){
|
Daniel@0
|
1538 (function (global, factory) {
|
Daniel@0
|
1539 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
Daniel@0
|
1540 typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
Daniel@0
|
1541 factory((global.time = {}));
|
Daniel@0
|
1542 }(this, function (exports) { 'use strict';
|
Daniel@0
|
1543
|
Daniel@0
|
1544 var t1 = new Date;
|
Daniel@0
|
1545
|
Daniel@0
|
1546 var t0 = new Date;
|
Daniel@0
|
1547
|
Daniel@0
|
1548 function newInterval(floori, offseti, count) {
|
Daniel@0
|
1549
|
Daniel@0
|
1550 function interval(date) {
|
Daniel@0
|
1551 return floori(date = new Date(+date)), date;
|
Daniel@0
|
1552 }
|
Daniel@0
|
1553
|
Daniel@0
|
1554 interval.floor = interval;
|
Daniel@0
|
1555
|
Daniel@0
|
1556 interval.round = function(date) {
|
Daniel@0
|
1557 var d0 = new Date(+date),
|
Daniel@0
|
1558 d1 = new Date(date - 1);
|
Daniel@0
|
1559 floori(d0), floori(d1), offseti(d1, 1);
|
Daniel@0
|
1560 return date - d0 < d1 - date ? d0 : d1;
|
Daniel@0
|
1561 };
|
Daniel@0
|
1562
|
Daniel@0
|
1563 interval.ceil = function(date) {
|
Daniel@0
|
1564 return floori(date = new Date(date - 1)), offseti(date, 1), date;
|
Daniel@0
|
1565 };
|
Daniel@0
|
1566
|
Daniel@0
|
1567 interval.offset = function(date, step) {
|
Daniel@0
|
1568 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
|
Daniel@0
|
1569 };
|
Daniel@0
|
1570
|
Daniel@0
|
1571 interval.range = function(start, stop, step) {
|
Daniel@0
|
1572 var range = [];
|
Daniel@0
|
1573 start = new Date(start - 1);
|
Daniel@0
|
1574 stop = new Date(+stop);
|
Daniel@0
|
1575 step = step == null ? 1 : Math.floor(step);
|
Daniel@0
|
1576 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
|
Daniel@0
|
1577 offseti(start, 1), floori(start);
|
Daniel@0
|
1578 if (start < stop) range.push(new Date(+start));
|
Daniel@0
|
1579 while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));
|
Daniel@0
|
1580 return range;
|
Daniel@0
|
1581 };
|
Daniel@0
|
1582
|
Daniel@0
|
1583 interval.filter = function(test) {
|
Daniel@0
|
1584 return newInterval(function(date) {
|
Daniel@0
|
1585 while (floori(date), !test(date)) date.setTime(date - 1);
|
Daniel@0
|
1586 }, function(date, step) {
|
Daniel@0
|
1587 while (--step >= 0) while (offseti(date, 1), !test(date));
|
Daniel@0
|
1588 });
|
Daniel@0
|
1589 };
|
Daniel@0
|
1590
|
Daniel@0
|
1591 if (count) interval.count = function(start, end) {
|
Daniel@0
|
1592 t0.setTime(+start), t1.setTime(+end);
|
Daniel@0
|
1593 floori(t0), floori(t1);
|
Daniel@0
|
1594 return Math.floor(count(t0, t1));
|
Daniel@0
|
1595 };
|
Daniel@0
|
1596
|
Daniel@0
|
1597 return interval;
|
Daniel@0
|
1598 }
|
Daniel@0
|
1599
|
Daniel@0
|
1600 var second = newInterval(function(date) {
|
Daniel@0
|
1601 date.setMilliseconds(0);
|
Daniel@0
|
1602 }, function(date, step) {
|
Daniel@0
|
1603 date.setTime(+date + step * 1e3);
|
Daniel@0
|
1604 }, function(start, end) {
|
Daniel@0
|
1605 return (end - start) / 1e3;
|
Daniel@0
|
1606 });
|
Daniel@0
|
1607
|
Daniel@0
|
1608 exports.seconds = second.range;
|
Daniel@0
|
1609
|
Daniel@0
|
1610 var minute = newInterval(function(date) {
|
Daniel@0
|
1611 date.setSeconds(0, 0);
|
Daniel@0
|
1612 }, function(date, step) {
|
Daniel@0
|
1613 date.setTime(+date + step * 6e4);
|
Daniel@0
|
1614 }, function(start, end) {
|
Daniel@0
|
1615 return (end - start) / 6e4;
|
Daniel@0
|
1616 });
|
Daniel@0
|
1617
|
Daniel@0
|
1618 exports.minutes = minute.range;
|
Daniel@0
|
1619
|
Daniel@0
|
1620 var hour = newInterval(function(date) {
|
Daniel@0
|
1621 date.setMinutes(0, 0, 0);
|
Daniel@0
|
1622 }, function(date, step) {
|
Daniel@0
|
1623 date.setTime(+date + step * 36e5);
|
Daniel@0
|
1624 }, function(start, end) {
|
Daniel@0
|
1625 return (end - start) / 36e5;
|
Daniel@0
|
1626 });
|
Daniel@0
|
1627
|
Daniel@0
|
1628 exports.hours = hour.range;
|
Daniel@0
|
1629
|
Daniel@0
|
1630 var day = newInterval(function(date) {
|
Daniel@0
|
1631 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
1632 }, function(date, step) {
|
Daniel@0
|
1633 date.setDate(date.getDate() + step);
|
Daniel@0
|
1634 }, function(start, end) {
|
Daniel@0
|
1635 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;
|
Daniel@0
|
1636 });
|
Daniel@0
|
1637
|
Daniel@0
|
1638 exports.days = day.range;
|
Daniel@0
|
1639
|
Daniel@0
|
1640 function weekday(i) {
|
Daniel@0
|
1641 return newInterval(function(date) {
|
Daniel@0
|
1642 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
1643 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
|
Daniel@0
|
1644 }, function(date, step) {
|
Daniel@0
|
1645 date.setDate(date.getDate() + step * 7);
|
Daniel@0
|
1646 }, function(start, end) {
|
Daniel@0
|
1647 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;
|
Daniel@0
|
1648 });
|
Daniel@0
|
1649 }
|
Daniel@0
|
1650
|
Daniel@0
|
1651 exports.sunday = weekday(0);
|
Daniel@0
|
1652
|
Daniel@0
|
1653 exports.sundays = exports.sunday.range;
|
Daniel@0
|
1654
|
Daniel@0
|
1655 exports.monday = weekday(1);
|
Daniel@0
|
1656
|
Daniel@0
|
1657 exports.mondays = exports.monday.range;
|
Daniel@0
|
1658
|
Daniel@0
|
1659 exports.tuesday = weekday(2);
|
Daniel@0
|
1660
|
Daniel@0
|
1661 exports.tuesdays = exports.tuesday.range;
|
Daniel@0
|
1662
|
Daniel@0
|
1663 exports.wednesday = weekday(3);
|
Daniel@0
|
1664
|
Daniel@0
|
1665 exports.wednesdays = exports.wednesday.range;
|
Daniel@0
|
1666
|
Daniel@0
|
1667 exports.thursday = weekday(4);
|
Daniel@0
|
1668
|
Daniel@0
|
1669 exports.thursdays = exports.thursday.range;
|
Daniel@0
|
1670
|
Daniel@0
|
1671 exports.friday = weekday(5);
|
Daniel@0
|
1672
|
Daniel@0
|
1673 exports.fridays = exports.friday.range;
|
Daniel@0
|
1674
|
Daniel@0
|
1675 exports.saturday = weekday(6);
|
Daniel@0
|
1676
|
Daniel@0
|
1677 exports.saturdays = exports.saturday.range;
|
Daniel@0
|
1678
|
Daniel@0
|
1679 var week = exports.sunday;
|
Daniel@0
|
1680
|
Daniel@0
|
1681 exports.weeks = week.range;
|
Daniel@0
|
1682
|
Daniel@0
|
1683 var month = newInterval(function(date) {
|
Daniel@0
|
1684 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
1685 date.setDate(1);
|
Daniel@0
|
1686 }, function(date, step) {
|
Daniel@0
|
1687 date.setMonth(date.getMonth() + step);
|
Daniel@0
|
1688 }, function(start, end) {
|
Daniel@0
|
1689 return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
|
Daniel@0
|
1690 });
|
Daniel@0
|
1691
|
Daniel@0
|
1692 exports.months = month.range;
|
Daniel@0
|
1693
|
Daniel@0
|
1694 var year = newInterval(function(date) {
|
Daniel@0
|
1695 date.setHours(0, 0, 0, 0);
|
Daniel@0
|
1696 date.setMonth(0, 1);
|
Daniel@0
|
1697 }, function(date, step) {
|
Daniel@0
|
1698 date.setFullYear(date.getFullYear() + step);
|
Daniel@0
|
1699 }, function(start, end) {
|
Daniel@0
|
1700 return end.getFullYear() - start.getFullYear();
|
Daniel@0
|
1701 });
|
Daniel@0
|
1702
|
Daniel@0
|
1703 exports.years = year.range;
|
Daniel@0
|
1704
|
Daniel@0
|
1705 var utcSecond = newInterval(function(date) {
|
Daniel@0
|
1706 date.setUTCMilliseconds(0);
|
Daniel@0
|
1707 }, function(date, step) {
|
Daniel@0
|
1708 date.setTime(+date + step * 1e3);
|
Daniel@0
|
1709 }, function(start, end) {
|
Daniel@0
|
1710 return (end - start) / 1e3;
|
Daniel@0
|
1711 });
|
Daniel@0
|
1712
|
Daniel@0
|
1713 exports.utcSeconds = utcSecond.range;
|
Daniel@0
|
1714
|
Daniel@0
|
1715 var utcMinute = newInterval(function(date) {
|
Daniel@0
|
1716 date.setUTCSeconds(0, 0);
|
Daniel@0
|
1717 }, function(date, step) {
|
Daniel@0
|
1718 date.setTime(+date + step * 6e4);
|
Daniel@0
|
1719 }, function(start, end) {
|
Daniel@0
|
1720 return (end - start) / 6e4;
|
Daniel@0
|
1721 });
|
Daniel@0
|
1722
|
Daniel@0
|
1723 exports.utcMinutes = utcMinute.range;
|
Daniel@0
|
1724
|
Daniel@0
|
1725 var utcHour = newInterval(function(date) {
|
Daniel@0
|
1726 date.setUTCMinutes(0, 0, 0);
|
Daniel@0
|
1727 }, function(date, step) {
|
Daniel@0
|
1728 date.setTime(+date + step * 36e5);
|
Daniel@0
|
1729 }, function(start, end) {
|
Daniel@0
|
1730 return (end - start) / 36e5;
|
Daniel@0
|
1731 });
|
Daniel@0
|
1732
|
Daniel@0
|
1733 exports.utcHours = utcHour.range;
|
Daniel@0
|
1734
|
Daniel@0
|
1735 var utcDay = newInterval(function(date) {
|
Daniel@0
|
1736 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
1737 }, function(date, step) {
|
Daniel@0
|
1738 date.setUTCDate(date.getUTCDate() + step);
|
Daniel@0
|
1739 }, function(start, end) {
|
Daniel@0
|
1740 return (end - start) / 864e5;
|
Daniel@0
|
1741 });
|
Daniel@0
|
1742
|
Daniel@0
|
1743 exports.utcDays = utcDay.range;
|
Daniel@0
|
1744
|
Daniel@0
|
1745 function utcWeekday(i) {
|
Daniel@0
|
1746 return newInterval(function(date) {
|
Daniel@0
|
1747 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
1748 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
|
Daniel@0
|
1749 }, function(date, step) {
|
Daniel@0
|
1750 date.setUTCDate(date.getUTCDate() + step * 7);
|
Daniel@0
|
1751 }, function(start, end) {
|
Daniel@0
|
1752 return (end - start) / 6048e5;
|
Daniel@0
|
1753 });
|
Daniel@0
|
1754 }
|
Daniel@0
|
1755
|
Daniel@0
|
1756 exports.utcSunday = utcWeekday(0);
|
Daniel@0
|
1757
|
Daniel@0
|
1758 exports.utcSundays = exports.utcSunday.range;
|
Daniel@0
|
1759
|
Daniel@0
|
1760 exports.utcMonday = utcWeekday(1);
|
Daniel@0
|
1761
|
Daniel@0
|
1762 exports.utcMondays = exports.utcMonday.range;
|
Daniel@0
|
1763
|
Daniel@0
|
1764 exports.utcTuesday = utcWeekday(2);
|
Daniel@0
|
1765
|
Daniel@0
|
1766 exports.utcTuesdays = exports.utcTuesday.range;
|
Daniel@0
|
1767
|
Daniel@0
|
1768 exports.utcWednesday = utcWeekday(3);
|
Daniel@0
|
1769
|
Daniel@0
|
1770 exports.utcWednesdays = exports.utcWednesday.range;
|
Daniel@0
|
1771
|
Daniel@0
|
1772 exports.utcThursday = utcWeekday(4);
|
Daniel@0
|
1773
|
Daniel@0
|
1774 exports.utcThursdays = exports.utcThursday.range;
|
Daniel@0
|
1775
|
Daniel@0
|
1776 exports.utcFriday = utcWeekday(5);
|
Daniel@0
|
1777
|
Daniel@0
|
1778 exports.utcFridays = exports.utcFriday.range;
|
Daniel@0
|
1779
|
Daniel@0
|
1780 exports.utcSaturday = utcWeekday(6);
|
Daniel@0
|
1781
|
Daniel@0
|
1782 exports.utcSaturdays = exports.utcSaturday.range;
|
Daniel@0
|
1783
|
Daniel@0
|
1784 var utcWeek = exports.utcSunday;
|
Daniel@0
|
1785
|
Daniel@0
|
1786 exports.utcWeeks = utcWeek.range;
|
Daniel@0
|
1787
|
Daniel@0
|
1788 var utcMonth = newInterval(function(date) {
|
Daniel@0
|
1789 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
1790 date.setUTCDate(1);
|
Daniel@0
|
1791 }, function(date, step) {
|
Daniel@0
|
1792 date.setUTCMonth(date.getUTCMonth() + step);
|
Daniel@0
|
1793 }, function(start, end) {
|
Daniel@0
|
1794 return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
|
Daniel@0
|
1795 });
|
Daniel@0
|
1796
|
Daniel@0
|
1797 exports.utcMonths = utcMonth.range;
|
Daniel@0
|
1798
|
Daniel@0
|
1799 var utcYear = newInterval(function(date) {
|
Daniel@0
|
1800 date.setUTCHours(0, 0, 0, 0);
|
Daniel@0
|
1801 date.setUTCMonth(0, 1);
|
Daniel@0
|
1802 }, function(date, step) {
|
Daniel@0
|
1803 date.setUTCFullYear(date.getUTCFullYear() + step);
|
Daniel@0
|
1804 }, function(start, end) {
|
Daniel@0
|
1805 return end.getUTCFullYear() - start.getUTCFullYear();
|
Daniel@0
|
1806 });
|
Daniel@0
|
1807
|
Daniel@0
|
1808 exports.utcYears = utcYear.range;
|
Daniel@0
|
1809
|
Daniel@0
|
1810 exports.interval = newInterval;
|
Daniel@0
|
1811 exports.second = second;
|
Daniel@0
|
1812 exports.minute = minute;
|
Daniel@0
|
1813 exports.hour = hour;
|
Daniel@0
|
1814 exports.day = day;
|
Daniel@0
|
1815 exports.week = week;
|
Daniel@0
|
1816 exports.month = month;
|
Daniel@0
|
1817 exports.year = year;
|
Daniel@0
|
1818 exports.utcSecond = utcSecond;
|
Daniel@0
|
1819 exports.utcMinute = utcMinute;
|
Daniel@0
|
1820 exports.utcHour = utcHour;
|
Daniel@0
|
1821 exports.utcDay = utcDay;
|
Daniel@0
|
1822 exports.utcWeek = utcWeek;
|
Daniel@0
|
1823 exports.utcMonth = utcMonth;
|
Daniel@0
|
1824 exports.utcYear = utcYear;
|
Daniel@0
|
1825
|
Daniel@0
|
1826 }));
|
Daniel@0
|
1827 },{}],7:[function(require,module,exports){
|
Daniel@0
|
1828 var util = require('../util'),
|
Daniel@0
|
1829 Measures = require('./measures'),
|
Daniel@0
|
1830 Collector = require('./collector');
|
Daniel@0
|
1831
|
Daniel@0
|
1832 function Aggregator() {
|
Daniel@0
|
1833 this._cells = {};
|
Daniel@0
|
1834 this._aggr = [];
|
Daniel@0
|
1835 this._stream = false;
|
Daniel@0
|
1836 }
|
Daniel@0
|
1837
|
Daniel@0
|
1838 var Flags = Aggregator.Flags = {
|
Daniel@0
|
1839 ADD_CELL: 1,
|
Daniel@0
|
1840 MOD_CELL: 2
|
Daniel@0
|
1841 };
|
Daniel@0
|
1842
|
Daniel@0
|
1843 var proto = Aggregator.prototype;
|
Daniel@0
|
1844
|
Daniel@0
|
1845 // Parameters
|
Daniel@0
|
1846
|
Daniel@0
|
1847 proto.stream = function(v) {
|
Daniel@0
|
1848 if (v == null) return this._stream;
|
Daniel@0
|
1849 this._stream = !!v;
|
Daniel@0
|
1850 this._aggr = [];
|
Daniel@0
|
1851 return this;
|
Daniel@0
|
1852 };
|
Daniel@0
|
1853
|
Daniel@0
|
1854 // key accessor to use for streaming removes
|
Daniel@0
|
1855 proto.key = function(key) {
|
Daniel@0
|
1856 if (key == null) return this._key;
|
Daniel@0
|
1857 this._key = util.$(key);
|
Daniel@0
|
1858 return this;
|
Daniel@0
|
1859 };
|
Daniel@0
|
1860
|
Daniel@0
|
1861 // Input: array of objects of the form
|
Daniel@0
|
1862 // {name: string, get: function}
|
Daniel@0
|
1863 proto.groupby = function(dims) {
|
Daniel@0
|
1864 this._dims = util.array(dims).map(function(d, i) {
|
Daniel@0
|
1865 d = util.isString(d) ? {name: d, get: util.$(d)}
|
Daniel@0
|
1866 : util.isFunction(d) ? {name: util.name(d) || d.name || ('_' + i), get: d}
|
Daniel@0
|
1867 : (d.name && util.isFunction(d.get)) ? d : null;
|
Daniel@0
|
1868 if (d == null) throw 'Invalid groupby argument: ' + d;
|
Daniel@0
|
1869 return d;
|
Daniel@0
|
1870 });
|
Daniel@0
|
1871 return this.clear();
|
Daniel@0
|
1872 };
|
Daniel@0
|
1873
|
Daniel@0
|
1874 // Input: array of objects of the form
|
Daniel@0
|
1875 // {name: string, ops: [string, ...]}
|
Daniel@0
|
1876 proto.summarize = function(fields) {
|
Daniel@0
|
1877 fields = summarize_args(fields);
|
Daniel@0
|
1878 this._count = true;
|
Daniel@0
|
1879 var aggr = (this._aggr = []),
|
Daniel@0
|
1880 m, f, i, j, op, as, get;
|
Daniel@0
|
1881
|
Daniel@0
|
1882 for (i=0; i<fields.length; ++i) {
|
Daniel@0
|
1883 for (j=0, m=[], f=fields[i]; j<f.ops.length; ++j) {
|
Daniel@0
|
1884 op = f.ops[j];
|
Daniel@0
|
1885 if (op !== 'count') this._count = false;
|
Daniel@0
|
1886 as = (f.as && f.as[j]) || (op + (f.name==='*' ? '' : '_'+f.name));
|
Daniel@0
|
1887 m.push(Measures[op](as));
|
Daniel@0
|
1888 }
|
Daniel@0
|
1889 get = f.get && util.$(f.get) ||
|
Daniel@0
|
1890 (f.name === '*' ? util.identity : util.$(f.name));
|
Daniel@0
|
1891 aggr.push({
|
Daniel@0
|
1892 name: f.name,
|
Daniel@0
|
1893 measures: Measures.create(
|
Daniel@0
|
1894 m,
|
Daniel@0
|
1895 this._stream, // streaming remove flag
|
Daniel@0
|
1896 get, // input tuple getter
|
Daniel@0
|
1897 this._assign) // output tuple setter
|
Daniel@0
|
1898 });
|
Daniel@0
|
1899 }
|
Daniel@0
|
1900 return this.clear();
|
Daniel@0
|
1901 };
|
Daniel@0
|
1902
|
Daniel@0
|
1903 // Convenience method to summarize by count
|
Daniel@0
|
1904 proto.count = function() {
|
Daniel@0
|
1905 return this.summarize({'*':'count'});
|
Daniel@0
|
1906 };
|
Daniel@0
|
1907
|
Daniel@0
|
1908 // Override to perform custom tuple value assignment
|
Daniel@0
|
1909 proto._assign = function(object, name, value) {
|
Daniel@0
|
1910 object[name] = value;
|
Daniel@0
|
1911 };
|
Daniel@0
|
1912
|
Daniel@0
|
1913 function summarize_args(fields) {
|
Daniel@0
|
1914 if (util.isArray(fields)) { return fields; }
|
Daniel@0
|
1915 if (fields == null) { return []; }
|
Daniel@0
|
1916 var a = [], name, ops;
|
Daniel@0
|
1917 for (name in fields) {
|
Daniel@0
|
1918 ops = util.array(fields[name]);
|
Daniel@0
|
1919 a.push({name: name, ops: ops});
|
Daniel@0
|
1920 }
|
Daniel@0
|
1921 return a;
|
Daniel@0
|
1922 }
|
Daniel@0
|
1923
|
Daniel@0
|
1924 // Cell Management
|
Daniel@0
|
1925
|
Daniel@0
|
1926 proto.clear = function() {
|
Daniel@0
|
1927 return (this._cells = {}, this);
|
Daniel@0
|
1928 };
|
Daniel@0
|
1929
|
Daniel@0
|
1930 proto._cellkey = function(x) {
|
Daniel@0
|
1931 var d = this._dims,
|
Daniel@0
|
1932 n = d.length, i,
|
Daniel@0
|
1933 k = String(d[0].get(x));
|
Daniel@0
|
1934 for (i=1; i<n; ++i) {
|
Daniel@0
|
1935 k += '|' + d[i].get(x);
|
Daniel@0
|
1936 }
|
Daniel@0
|
1937 return k;
|
Daniel@0
|
1938 };
|
Daniel@0
|
1939
|
Daniel@0
|
1940 proto._cell = function(x) {
|
Daniel@0
|
1941 var key = this._dims.length ? this._cellkey(x) : '';
|
Daniel@0
|
1942 return this._cells[key] || (this._cells[key] = this._newcell(x, key));
|
Daniel@0
|
1943 };
|
Daniel@0
|
1944
|
Daniel@0
|
1945 proto._newcell = function(x, key) {
|
Daniel@0
|
1946 var cell = {
|
Daniel@0
|
1947 num: 0,
|
Daniel@0
|
1948 tuple: this._newtuple(x, key),
|
Daniel@0
|
1949 flag: Flags.ADD_CELL,
|
Daniel@0
|
1950 aggs: {}
|
Daniel@0
|
1951 };
|
Daniel@0
|
1952
|
Daniel@0
|
1953 var aggr = this._aggr, i;
|
Daniel@0
|
1954 for (i=0; i<aggr.length; ++i) {
|
Daniel@0
|
1955 cell.aggs[aggr[i].name] = new aggr[i].measures(cell, cell.tuple);
|
Daniel@0
|
1956 }
|
Daniel@0
|
1957 if (cell.collect) {
|
Daniel@0
|
1958 cell.data = new Collector(this._key);
|
Daniel@0
|
1959 }
|
Daniel@0
|
1960 return cell;
|
Daniel@0
|
1961 };
|
Daniel@0
|
1962
|
Daniel@0
|
1963 proto._newtuple = function(x) {
|
Daniel@0
|
1964 var dims = this._dims,
|
Daniel@0
|
1965 t = {}, i, n;
|
Daniel@0
|
1966 for (i=0, n=dims.length; i<n; ++i) {
|
Daniel@0
|
1967 t[dims[i].name] = dims[i].get(x);
|
Daniel@0
|
1968 }
|
Daniel@0
|
1969 return this._ingest(t);
|
Daniel@0
|
1970 };
|
Daniel@0
|
1971
|
Daniel@0
|
1972 // Override to perform custom tuple ingestion
|
Daniel@0
|
1973 proto._ingest = util.identity;
|
Daniel@0
|
1974
|
Daniel@0
|
1975 // Process Tuples
|
Daniel@0
|
1976
|
Daniel@0
|
1977 proto._add = function(x) {
|
Daniel@0
|
1978 var cell = this._cell(x),
|
Daniel@0
|
1979 aggr = this._aggr, i;
|
Daniel@0
|
1980
|
Daniel@0
|
1981 cell.num += 1;
|
Daniel@0
|
1982 if (!this._count) { // skip if count-only
|
Daniel@0
|
1983 if (cell.collect) cell.data.add(x);
|
Daniel@0
|
1984 for (i=0; i<aggr.length; ++i) {
|
Daniel@0
|
1985 cell.aggs[aggr[i].name].add(x);
|
Daniel@0
|
1986 }
|
Daniel@0
|
1987 }
|
Daniel@0
|
1988 cell.flag |= Flags.MOD_CELL;
|
Daniel@0
|
1989 if (this._on_add) this._on_add(x, cell);
|
Daniel@0
|
1990 };
|
Daniel@0
|
1991
|
Daniel@0
|
1992 proto._rem = function(x) {
|
Daniel@0
|
1993 var cell = this._cell(x),
|
Daniel@0
|
1994 aggr = this._aggr, i;
|
Daniel@0
|
1995
|
Daniel@0
|
1996 cell.num -= 1;
|
Daniel@0
|
1997 if (!this._count) { // skip if count-only
|
Daniel@0
|
1998 if (cell.collect) cell.data.rem(x);
|
Daniel@0
|
1999 for (i=0; i<aggr.length; ++i) {
|
Daniel@0
|
2000 cell.aggs[aggr[i].name].rem(x);
|
Daniel@0
|
2001 }
|
Daniel@0
|
2002 }
|
Daniel@0
|
2003 cell.flag |= Flags.MOD_CELL;
|
Daniel@0
|
2004 if (this._on_rem) this._on_rem(x, cell);
|
Daniel@0
|
2005 };
|
Daniel@0
|
2006
|
Daniel@0
|
2007 proto._mod = function(curr, prev) {
|
Daniel@0
|
2008 var cell0 = this._cell(prev),
|
Daniel@0
|
2009 cell1 = this._cell(curr),
|
Daniel@0
|
2010 aggr = this._aggr, i;
|
Daniel@0
|
2011
|
Daniel@0
|
2012 if (cell0 !== cell1) {
|
Daniel@0
|
2013 cell0.num -= 1;
|
Daniel@0
|
2014 cell1.num += 1;
|
Daniel@0
|
2015 if (cell0.collect) cell0.data.rem(prev);
|
Daniel@0
|
2016 if (cell1.collect) cell1.data.add(curr);
|
Daniel@0
|
2017 } else if (cell0.collect && !util.isObject(curr)) {
|
Daniel@0
|
2018 cell0.data.rem(prev);
|
Daniel@0
|
2019 cell0.data.add(curr);
|
Daniel@0
|
2020 }
|
Daniel@0
|
2021
|
Daniel@0
|
2022 for (i=0; i<aggr.length; ++i) {
|
Daniel@0
|
2023 cell0.aggs[aggr[i].name].rem(prev);
|
Daniel@0
|
2024 cell1.aggs[aggr[i].name].add(curr);
|
Daniel@0
|
2025 }
|
Daniel@0
|
2026 cell0.flag |= Flags.MOD_CELL;
|
Daniel@0
|
2027 cell1.flag |= Flags.MOD_CELL;
|
Daniel@0
|
2028 if (this._on_mod) this._on_mod(curr, prev, cell0, cell1);
|
Daniel@0
|
2029 };
|
Daniel@0
|
2030
|
Daniel@0
|
2031 proto.result = function() {
|
Daniel@0
|
2032 var result = [],
|
Daniel@0
|
2033 aggr = this._aggr,
|
Daniel@0
|
2034 cell, i, k;
|
Daniel@0
|
2035
|
Daniel@0
|
2036 for (k in this._cells) {
|
Daniel@0
|
2037 cell = this._cells[k];
|
Daniel@0
|
2038 if (cell.num > 0) {
|
Daniel@0
|
2039 // consolidate collector values
|
Daniel@0
|
2040 if (cell.collect) {
|
Daniel@0
|
2041 cell.data.values();
|
Daniel@0
|
2042 }
|
Daniel@0
|
2043 // update tuple properties
|
Daniel@0
|
2044 for (i=0; i<aggr.length; ++i) {
|
Daniel@0
|
2045 cell.aggs[aggr[i].name].set();
|
Daniel@0
|
2046 }
|
Daniel@0
|
2047 // add output tuple
|
Daniel@0
|
2048 result.push(cell.tuple);
|
Daniel@0
|
2049 } else {
|
Daniel@0
|
2050 delete this._cells[k];
|
Daniel@0
|
2051 }
|
Daniel@0
|
2052 cell.flag = 0;
|
Daniel@0
|
2053 }
|
Daniel@0
|
2054
|
Daniel@0
|
2055 this._rems = false;
|
Daniel@0
|
2056 return result;
|
Daniel@0
|
2057 };
|
Daniel@0
|
2058
|
Daniel@0
|
2059 proto.changes = function(output) {
|
Daniel@0
|
2060 var changes = output || {add:[], rem:[], mod:[]},
|
Daniel@0
|
2061 aggr = this._aggr,
|
Daniel@0
|
2062 cell, flag, i, k;
|
Daniel@0
|
2063
|
Daniel@0
|
2064 for (k in this._cells) {
|
Daniel@0
|
2065 cell = this._cells[k];
|
Daniel@0
|
2066 flag = cell.flag;
|
Daniel@0
|
2067
|
Daniel@0
|
2068 // consolidate collector values
|
Daniel@0
|
2069 if (cell.collect) {
|
Daniel@0
|
2070 cell.data.values();
|
Daniel@0
|
2071 }
|
Daniel@0
|
2072
|
Daniel@0
|
2073 // update tuple properties
|
Daniel@0
|
2074 for (i=0; i<aggr.length; ++i) {
|
Daniel@0
|
2075 cell.aggs[aggr[i].name].set();
|
Daniel@0
|
2076 }
|
Daniel@0
|
2077
|
Daniel@0
|
2078 // organize output tuples
|
Daniel@0
|
2079 if (cell.num <= 0) {
|
Daniel@0
|
2080 changes.rem.push(cell.tuple); // if (flag === Flags.MOD_CELL) { ??
|
Daniel@0
|
2081 delete this._cells[k];
|
Daniel@0
|
2082 if (this._on_drop) this._on_drop(cell);
|
Daniel@0
|
2083 } else {
|
Daniel@0
|
2084 if (this._on_keep) this._on_keep(cell);
|
Daniel@0
|
2085 if (flag & Flags.ADD_CELL) {
|
Daniel@0
|
2086 changes.add.push(cell.tuple);
|
Daniel@0
|
2087 } else if (flag & Flags.MOD_CELL) {
|
Daniel@0
|
2088 changes.mod.push(cell.tuple);
|
Daniel@0
|
2089 }
|
Daniel@0
|
2090 }
|
Daniel@0
|
2091
|
Daniel@0
|
2092 cell.flag = 0;
|
Daniel@0
|
2093 }
|
Daniel@0
|
2094
|
Daniel@0
|
2095 this._rems = false;
|
Daniel@0
|
2096 return changes;
|
Daniel@0
|
2097 };
|
Daniel@0
|
2098
|
Daniel@0
|
2099 proto.execute = function(input) {
|
Daniel@0
|
2100 return this.clear().insert(input).result();
|
Daniel@0
|
2101 };
|
Daniel@0
|
2102
|
Daniel@0
|
2103 proto.insert = function(input) {
|
Daniel@0
|
2104 this._consolidate();
|
Daniel@0
|
2105 for (var i=0; i<input.length; ++i) {
|
Daniel@0
|
2106 this._add(input[i]);
|
Daniel@0
|
2107 }
|
Daniel@0
|
2108 return this;
|
Daniel@0
|
2109 };
|
Daniel@0
|
2110
|
Daniel@0
|
2111 proto.remove = function(input) {
|
Daniel@0
|
2112 if (!this._stream) {
|
Daniel@0
|
2113 throw 'Aggregator not configured for streaming removes.' +
|
Daniel@0
|
2114 ' Call stream(true) prior to calling summarize.';
|
Daniel@0
|
2115 }
|
Daniel@0
|
2116 for (var i=0; i<input.length; ++i) {
|
Daniel@0
|
2117 this._rem(input[i]);
|
Daniel@0
|
2118 }
|
Daniel@0
|
2119 this._rems = true;
|
Daniel@0
|
2120 return this;
|
Daniel@0
|
2121 };
|
Daniel@0
|
2122
|
Daniel@0
|
2123 // consolidate removals
|
Daniel@0
|
2124 proto._consolidate = function() {
|
Daniel@0
|
2125 if (!this._rems) return;
|
Daniel@0
|
2126 for (var k in this._cells) {
|
Daniel@0
|
2127 if (this._cells[k].collect) {
|
Daniel@0
|
2128 this._cells[k].data.values();
|
Daniel@0
|
2129 }
|
Daniel@0
|
2130 }
|
Daniel@0
|
2131 this._rems = false;
|
Daniel@0
|
2132 };
|
Daniel@0
|
2133
|
Daniel@0
|
2134 module.exports = Aggregator;
|
Daniel@0
|
2135 },{"../util":29,"./collector":8,"./measures":10}],8:[function(require,module,exports){
|
Daniel@0
|
2136 var util = require('../util');
|
Daniel@0
|
2137 var stats = require('../stats');
|
Daniel@0
|
2138
|
Daniel@0
|
2139 var REM = '__dl_rem__';
|
Daniel@0
|
2140
|
Daniel@0
|
2141 function Collector(key) {
|
Daniel@0
|
2142 this._add = [];
|
Daniel@0
|
2143 this._rem = [];
|
Daniel@0
|
2144 this._key = key || null;
|
Daniel@0
|
2145 this._last = null;
|
Daniel@0
|
2146 }
|
Daniel@0
|
2147
|
Daniel@0
|
2148 var proto = Collector.prototype;
|
Daniel@0
|
2149
|
Daniel@0
|
2150 proto.add = function(v) {
|
Daniel@0
|
2151 this._add.push(v);
|
Daniel@0
|
2152 };
|
Daniel@0
|
2153
|
Daniel@0
|
2154 proto.rem = function(v) {
|
Daniel@0
|
2155 this._rem.push(v);
|
Daniel@0
|
2156 };
|
Daniel@0
|
2157
|
Daniel@0
|
2158 proto.values = function() {
|
Daniel@0
|
2159 this._get = null;
|
Daniel@0
|
2160 if (this._rem.length === 0) return this._add;
|
Daniel@0
|
2161
|
Daniel@0
|
2162 var a = this._add,
|
Daniel@0
|
2163 r = this._rem,
|
Daniel@0
|
2164 k = this._key,
|
Daniel@0
|
2165 x = Array(a.length - r.length),
|
Daniel@0
|
2166 i, j, n, m;
|
Daniel@0
|
2167
|
Daniel@0
|
2168 if (!util.isObject(r[0])) {
|
Daniel@0
|
2169 // processing raw values
|
Daniel@0
|
2170 m = stats.count.map(r);
|
Daniel@0
|
2171 for (i=0, j=0, n=a.length; i<n; ++i) {
|
Daniel@0
|
2172 if (m[a[i]] > 0) {
|
Daniel@0
|
2173 m[a[i]] -= 1;
|
Daniel@0
|
2174 } else {
|
Daniel@0
|
2175 x[j++] = a[i];
|
Daniel@0
|
2176 }
|
Daniel@0
|
2177 }
|
Daniel@0
|
2178 } else if (k) {
|
Daniel@0
|
2179 // has unique key field, so use that
|
Daniel@0
|
2180 m = util.toMap(r, k);
|
Daniel@0
|
2181 for (i=0, j=0, n=a.length; i<n; ++i) {
|
Daniel@0
|
2182 if (!m.hasOwnProperty(k(a[i]))) { x[j++] = a[i]; }
|
Daniel@0
|
2183 }
|
Daniel@0
|
2184 } else {
|
Daniel@0
|
2185 // no unique key, mark tuples directly
|
Daniel@0
|
2186 for (i=0, n=r.length; i<n; ++i) {
|
Daniel@0
|
2187 r[i][REM] = 1;
|
Daniel@0
|
2188 }
|
Daniel@0
|
2189 for (i=0, j=0, n=a.length; i<n; ++i) {
|
Daniel@0
|
2190 if (!a[i][REM]) { x[j++] = a[i]; }
|
Daniel@0
|
2191 }
|
Daniel@0
|
2192 for (i=0, n=r.length; i<n; ++i) {
|
Daniel@0
|
2193 delete r[i][REM];
|
Daniel@0
|
2194 }
|
Daniel@0
|
2195 }
|
Daniel@0
|
2196
|
Daniel@0
|
2197 this._rem = [];
|
Daniel@0
|
2198 return (this._add = x);
|
Daniel@0
|
2199 };
|
Daniel@0
|
2200
|
Daniel@0
|
2201 // memoizing statistics methods
|
Daniel@0
|
2202
|
Daniel@0
|
2203 proto.extent = function(get) {
|
Daniel@0
|
2204 if (this._get !== get || !this._ext) {
|
Daniel@0
|
2205 var v = this.values(),
|
Daniel@0
|
2206 i = stats.extent.index(v, get);
|
Daniel@0
|
2207 this._ext = [v[i[0]], v[i[1]]];
|
Daniel@0
|
2208 this._get = get;
|
Daniel@0
|
2209 }
|
Daniel@0
|
2210 return this._ext;
|
Daniel@0
|
2211 };
|
Daniel@0
|
2212
|
Daniel@0
|
2213 proto.argmin = function(get) {
|
Daniel@0
|
2214 return this.extent(get)[0];
|
Daniel@0
|
2215 };
|
Daniel@0
|
2216
|
Daniel@0
|
2217 proto.argmax = function(get) {
|
Daniel@0
|
2218 return this.extent(get)[1];
|
Daniel@0
|
2219 };
|
Daniel@0
|
2220
|
Daniel@0
|
2221 proto.min = function(get) {
|
Daniel@0
|
2222 var m = this.extent(get)[0];
|
Daniel@0
|
2223 return m ? get(m) : +Infinity;
|
Daniel@0
|
2224 };
|
Daniel@0
|
2225
|
Daniel@0
|
2226 proto.max = function(get) {
|
Daniel@0
|
2227 var m = this.extent(get)[1];
|
Daniel@0
|
2228 return m ? get(m) : -Infinity;
|
Daniel@0
|
2229 };
|
Daniel@0
|
2230
|
Daniel@0
|
2231 proto.quartile = function(get) {
|
Daniel@0
|
2232 if (this._get !== get || !this._q) {
|
Daniel@0
|
2233 this._q = stats.quartile(this.values(), get);
|
Daniel@0
|
2234 this._get = get;
|
Daniel@0
|
2235 }
|
Daniel@0
|
2236 return this._q;
|
Daniel@0
|
2237 };
|
Daniel@0
|
2238
|
Daniel@0
|
2239 proto.q1 = function(get) {
|
Daniel@0
|
2240 return this.quartile(get)[0];
|
Daniel@0
|
2241 };
|
Daniel@0
|
2242
|
Daniel@0
|
2243 proto.q2 = function(get) {
|
Daniel@0
|
2244 return this.quartile(get)[1];
|
Daniel@0
|
2245 };
|
Daniel@0
|
2246
|
Daniel@0
|
2247 proto.q3 = function(get) {
|
Daniel@0
|
2248 return this.quartile(get)[2];
|
Daniel@0
|
2249 };
|
Daniel@0
|
2250
|
Daniel@0
|
2251 module.exports = Collector;
|
Daniel@0
|
2252
|
Daniel@0
|
2253 },{"../stats":26,"../util":29}],9:[function(require,module,exports){
|
Daniel@0
|
2254 var util = require('../util');
|
Daniel@0
|
2255 var Aggregator = require('./aggregator');
|
Daniel@0
|
2256
|
Daniel@0
|
2257 module.exports = function() {
|
Daniel@0
|
2258 // flatten arguments into a single array
|
Daniel@0
|
2259 var args = [].reduce.call(arguments, function(a, x) {
|
Daniel@0
|
2260 return a.concat(util.array(x));
|
Daniel@0
|
2261 }, []);
|
Daniel@0
|
2262 // create and return an aggregator
|
Daniel@0
|
2263 return new Aggregator()
|
Daniel@0
|
2264 .groupby(args)
|
Daniel@0
|
2265 .summarize({'*':'values'});
|
Daniel@0
|
2266 };
|
Daniel@0
|
2267
|
Daniel@0
|
2268 },{"../util":29,"./aggregator":7}],10:[function(require,module,exports){
|
Daniel@0
|
2269 var util = require('../util');
|
Daniel@0
|
2270
|
Daniel@0
|
2271 var types = {
|
Daniel@0
|
2272 'values': measure({
|
Daniel@0
|
2273 name: 'values',
|
Daniel@0
|
2274 init: 'cell.collect = true;',
|
Daniel@0
|
2275 set: 'cell.data.values()', idx: -1
|
Daniel@0
|
2276 }),
|
Daniel@0
|
2277 'count': measure({
|
Daniel@0
|
2278 name: 'count',
|
Daniel@0
|
2279 set: 'cell.num'
|
Daniel@0
|
2280 }),
|
Daniel@0
|
2281 'missing': measure({
|
Daniel@0
|
2282 name: 'missing',
|
Daniel@0
|
2283 set: 'this.missing'
|
Daniel@0
|
2284 }),
|
Daniel@0
|
2285 'valid': measure({
|
Daniel@0
|
2286 name: 'valid',
|
Daniel@0
|
2287 set: 'this.valid'
|
Daniel@0
|
2288 }),
|
Daniel@0
|
2289 'sum': measure({
|
Daniel@0
|
2290 name: 'sum',
|
Daniel@0
|
2291 init: 'this.sum = 0;',
|
Daniel@0
|
2292 add: 'this.sum += v;',
|
Daniel@0
|
2293 rem: 'this.sum -= v;',
|
Daniel@0
|
2294 set: 'this.sum'
|
Daniel@0
|
2295 }),
|
Daniel@0
|
2296 'mean': measure({
|
Daniel@0
|
2297 name: 'mean',
|
Daniel@0
|
2298 init: 'this.mean = 0;',
|
Daniel@0
|
2299 add: 'var d = v - this.mean; this.mean += d / this.valid;',
|
Daniel@0
|
2300 rem: 'var d = v - this.mean; this.mean -= this.valid ? d / this.valid : this.mean;',
|
Daniel@0
|
2301 set: 'this.mean'
|
Daniel@0
|
2302 }),
|
Daniel@0
|
2303 'average': measure({
|
Daniel@0
|
2304 name: 'average',
|
Daniel@0
|
2305 set: 'this.mean',
|
Daniel@0
|
2306 req: ['mean'], idx: 1
|
Daniel@0
|
2307 }),
|
Daniel@0
|
2308 'variance': measure({
|
Daniel@0
|
2309 name: 'variance',
|
Daniel@0
|
2310 init: 'this.dev = 0;',
|
Daniel@0
|
2311 add: 'this.dev += d * (v - this.mean);',
|
Daniel@0
|
2312 rem: 'this.dev -= d * (v - this.mean);',
|
Daniel@0
|
2313 set: 'this.valid > 1 ? this.dev / (this.valid-1) : 0',
|
Daniel@0
|
2314 req: ['mean'], idx: 1
|
Daniel@0
|
2315 }),
|
Daniel@0
|
2316 'variancep': measure({
|
Daniel@0
|
2317 name: 'variancep',
|
Daniel@0
|
2318 set: 'this.valid > 1 ? this.dev / this.valid : 0',
|
Daniel@0
|
2319 req: ['variance'], idx: 2
|
Daniel@0
|
2320 }),
|
Daniel@0
|
2321 'stdev': measure({
|
Daniel@0
|
2322 name: 'stdev',
|
Daniel@0
|
2323 set: 'this.valid > 1 ? Math.sqrt(this.dev / (this.valid-1)) : 0',
|
Daniel@0
|
2324 req: ['variance'], idx: 2
|
Daniel@0
|
2325 }),
|
Daniel@0
|
2326 'stdevp': measure({
|
Daniel@0
|
2327 name: 'stdevp',
|
Daniel@0
|
2328 set: 'this.valid > 1 ? Math.sqrt(this.dev / this.valid) : 0',
|
Daniel@0
|
2329 req: ['variance'], idx: 2
|
Daniel@0
|
2330 }),
|
Daniel@0
|
2331 'median': measure({
|
Daniel@0
|
2332 name: 'median',
|
Daniel@0
|
2333 set: 'cell.data.q2(this.get)',
|
Daniel@0
|
2334 req: ['values'], idx: 3
|
Daniel@0
|
2335 }),
|
Daniel@0
|
2336 'q1': measure({
|
Daniel@0
|
2337 name: 'q1',
|
Daniel@0
|
2338 set: 'cell.data.q1(this.get)',
|
Daniel@0
|
2339 req: ['values'], idx: 3
|
Daniel@0
|
2340 }),
|
Daniel@0
|
2341 'q3': measure({
|
Daniel@0
|
2342 name: 'q3',
|
Daniel@0
|
2343 set: 'cell.data.q3(this.get)',
|
Daniel@0
|
2344 req: ['values'], idx: 3
|
Daniel@0
|
2345 }),
|
Daniel@0
|
2346 'distinct': measure({
|
Daniel@0
|
2347 name: 'distinct',
|
Daniel@0
|
2348 set: 'this.distinct(cell.data.values(), this.get)',
|
Daniel@0
|
2349 req: ['values'], idx: 3
|
Daniel@0
|
2350 }),
|
Daniel@0
|
2351 'argmin': measure({
|
Daniel@0
|
2352 name: 'argmin',
|
Daniel@0
|
2353 add: 'if (v < this.min) this.argmin = t;',
|
Daniel@0
|
2354 rem: 'if (v <= this.min) this.argmin = null;',
|
Daniel@0
|
2355 set: 'this.argmin = this.argmin || cell.data.argmin(this.get)',
|
Daniel@0
|
2356 req: ['min'], str: ['values'], idx: 3
|
Daniel@0
|
2357 }),
|
Daniel@0
|
2358 'argmax': measure({
|
Daniel@0
|
2359 name: 'argmax',
|
Daniel@0
|
2360 add: 'if (v > this.max) this.argmax = t;',
|
Daniel@0
|
2361 rem: 'if (v >= this.max) this.argmax = null;',
|
Daniel@0
|
2362 set: 'this.argmax = this.argmax || cell.data.argmax(this.get)',
|
Daniel@0
|
2363 req: ['max'], str: ['values'], idx: 3
|
Daniel@0
|
2364 }),
|
Daniel@0
|
2365 'min': measure({
|
Daniel@0
|
2366 name: 'min',
|
Daniel@0
|
2367 init: 'this.min = +Infinity;',
|
Daniel@0
|
2368 add: 'if (v < this.min) this.min = v;',
|
Daniel@0
|
2369 rem: 'if (v <= this.min) this.min = NaN;',
|
Daniel@0
|
2370 set: 'this.min = (isNaN(this.min) ? cell.data.min(this.get) : this.min)',
|
Daniel@0
|
2371 str: ['values'], idx: 4
|
Daniel@0
|
2372 }),
|
Daniel@0
|
2373 'max': measure({
|
Daniel@0
|
2374 name: 'max',
|
Daniel@0
|
2375 init: 'this.max = -Infinity;',
|
Daniel@0
|
2376 add: 'if (v > this.max) this.max = v;',
|
Daniel@0
|
2377 rem: 'if (v >= this.max) this.max = NaN;',
|
Daniel@0
|
2378 set: 'this.max = (isNaN(this.max) ? cell.data.max(this.get) : this.max)',
|
Daniel@0
|
2379 str: ['values'], idx: 4
|
Daniel@0
|
2380 }),
|
Daniel@0
|
2381 'modeskew': measure({
|
Daniel@0
|
2382 name: 'modeskew',
|
Daniel@0
|
2383 set: 'this.dev===0 ? 0 : (this.mean - cell.data.q2(this.get)) / Math.sqrt(this.dev/(this.valid-1))',
|
Daniel@0
|
2384 req: ['mean', 'stdev', 'median'], idx: 5
|
Daniel@0
|
2385 })
|
Daniel@0
|
2386 };
|
Daniel@0
|
2387
|
Daniel@0
|
2388 function measure(base) {
|
Daniel@0
|
2389 return function(out) {
|
Daniel@0
|
2390 var m = util.extend({init:'', add:'', rem:'', idx:0}, base);
|
Daniel@0
|
2391 m.out = out || base.name;
|
Daniel@0
|
2392 return m;
|
Daniel@0
|
2393 };
|
Daniel@0
|
2394 }
|
Daniel@0
|
2395
|
Daniel@0
|
2396 function resolve(agg, stream) {
|
Daniel@0
|
2397 function collect(m, a) {
|
Daniel@0
|
2398 function helper(r) { if (!m[r]) collect(m, m[r] = types[r]()); }
|
Daniel@0
|
2399 if (a.req) a.req.forEach(helper);
|
Daniel@0
|
2400 if (stream && a.str) a.str.forEach(helper);
|
Daniel@0
|
2401 return m;
|
Daniel@0
|
2402 }
|
Daniel@0
|
2403 var map = agg.reduce(
|
Daniel@0
|
2404 collect,
|
Daniel@0
|
2405 agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {})
|
Daniel@0
|
2406 );
|
Daniel@0
|
2407 return util.vals(map).sort(function(a, b) { return a.idx - b.idx; });
|
Daniel@0
|
2408 }
|
Daniel@0
|
2409
|
Daniel@0
|
2410 function create(agg, stream, accessor, mutator) {
|
Daniel@0
|
2411 var all = resolve(agg, stream),
|
Daniel@0
|
2412 ctr = 'this.cell = cell; this.tuple = t; this.valid = 0; this.missing = 0;',
|
Daniel@0
|
2413 add = 'if (v==null) this.missing++; if (!this.isValid(v)) return; ++this.valid;',
|
Daniel@0
|
2414 rem = 'if (v==null) this.missing--; if (!this.isValid(v)) return; --this.valid;',
|
Daniel@0
|
2415 set = 'var t = this.tuple; var cell = this.cell;';
|
Daniel@0
|
2416
|
Daniel@0
|
2417 all.forEach(function(a) {
|
Daniel@0
|
2418 if (a.idx < 0) {
|
Daniel@0
|
2419 ctr = a.init + ctr;
|
Daniel@0
|
2420 add = a.add + add;
|
Daniel@0
|
2421 rem = a.rem + rem;
|
Daniel@0
|
2422 } else {
|
Daniel@0
|
2423 ctr += a.init;
|
Daniel@0
|
2424 add += a.add;
|
Daniel@0
|
2425 rem += a.rem;
|
Daniel@0
|
2426 }
|
Daniel@0
|
2427 });
|
Daniel@0
|
2428 agg.slice()
|
Daniel@0
|
2429 .sort(function(a, b) { return a.idx - b.idx; })
|
Daniel@0
|
2430 .forEach(function(a) {
|
Daniel@0
|
2431 set += 'this.assign(t,\''+a.out+'\','+a.set+');';
|
Daniel@0
|
2432 });
|
Daniel@0
|
2433 set += 'return t;';
|
Daniel@0
|
2434
|
Daniel@0
|
2435 /* jshint evil: true */
|
Daniel@0
|
2436 ctr = Function('cell', 't', ctr);
|
Daniel@0
|
2437 ctr.prototype.assign = mutator;
|
Daniel@0
|
2438 ctr.prototype.add = Function('t', 'var v = this.get(t);' + add);
|
Daniel@0
|
2439 ctr.prototype.rem = Function('t', 'var v = this.get(t);' + rem);
|
Daniel@0
|
2440 ctr.prototype.set = Function(set);
|
Daniel@0
|
2441 ctr.prototype.get = accessor;
|
Daniel@0
|
2442 ctr.prototype.distinct = require('../stats').count.distinct;
|
Daniel@0
|
2443 ctr.prototype.isValid = util.isValid;
|
Daniel@0
|
2444 ctr.fields = agg.map(util.$('out'));
|
Daniel@0
|
2445 return ctr;
|
Daniel@0
|
2446 }
|
Daniel@0
|
2447
|
Daniel@0
|
2448 types.create = create;
|
Daniel@0
|
2449 module.exports = types;
|
Daniel@0
|
2450 },{"../stats":26,"../util":29}],11:[function(require,module,exports){
|
Daniel@0
|
2451 var util = require('../util'),
|
Daniel@0
|
2452 time = require('../time'),
|
Daniel@0
|
2453 EPSILON = 1e-15;
|
Daniel@0
|
2454
|
Daniel@0
|
2455 function bins(opt) {
|
Daniel@0
|
2456 if (!opt) { throw Error("Missing binning options."); }
|
Daniel@0
|
2457
|
Daniel@0
|
2458 // determine range
|
Daniel@0
|
2459 var maxb = opt.maxbins || 15,
|
Daniel@0
|
2460 base = opt.base || 10,
|
Daniel@0
|
2461 logb = Math.log(base),
|
Daniel@0
|
2462 div = opt.div || [5, 2],
|
Daniel@0
|
2463 min = opt.min,
|
Daniel@0
|
2464 max = opt.max,
|
Daniel@0
|
2465 span = max - min,
|
Daniel@0
|
2466 step, level, minstep, precision, v, i, eps;
|
Daniel@0
|
2467
|
Daniel@0
|
2468 if (opt.step) {
|
Daniel@0
|
2469 // if step size is explicitly given, use that
|
Daniel@0
|
2470 step = opt.step;
|
Daniel@0
|
2471 } else if (opt.steps) {
|
Daniel@0
|
2472 // if provided, limit choice to acceptable step sizes
|
Daniel@0
|
2473 step = opt.steps[Math.min(
|
Daniel@0
|
2474 opt.steps.length - 1,
|
Daniel@0
|
2475 bisect(opt.steps, span/maxb, 0, opt.steps.length)
|
Daniel@0
|
2476 )];
|
Daniel@0
|
2477 } else {
|
Daniel@0
|
2478 // else use span to determine step size
|
Daniel@0
|
2479 level = Math.ceil(Math.log(maxb) / logb);
|
Daniel@0
|
2480 minstep = opt.minstep || 0;
|
Daniel@0
|
2481 step = Math.max(
|
Daniel@0
|
2482 minstep,
|
Daniel@0
|
2483 Math.pow(base, Math.round(Math.log(span) / logb) - level)
|
Daniel@0
|
2484 );
|
Daniel@0
|
2485
|
Daniel@0
|
2486 // increase step size if too many bins
|
Daniel@0
|
2487 do { step *= base; } while (Math.ceil(span/step) > maxb);
|
Daniel@0
|
2488
|
Daniel@0
|
2489 // decrease step size if allowed
|
Daniel@0
|
2490 for (i=0; i<div.length; ++i) {
|
Daniel@0
|
2491 v = step / div[i];
|
Daniel@0
|
2492 if (v >= minstep && span / v <= maxb) step = v;
|
Daniel@0
|
2493 }
|
Daniel@0
|
2494 }
|
Daniel@0
|
2495
|
Daniel@0
|
2496 // update precision, min and max
|
Daniel@0
|
2497 v = Math.log(step);
|
Daniel@0
|
2498 precision = v >= 0 ? 0 : ~~(-v / logb) + 1;
|
Daniel@0
|
2499 eps = Math.pow(base, -precision - 1);
|
Daniel@0
|
2500 min = Math.min(min, Math.floor(min / step + eps) * step);
|
Daniel@0
|
2501 max = Math.ceil(max / step) * step;
|
Daniel@0
|
2502
|
Daniel@0
|
2503 return {
|
Daniel@0
|
2504 start: min,
|
Daniel@0
|
2505 stop: max,
|
Daniel@0
|
2506 step: step,
|
Daniel@0
|
2507 unit: {precision: precision},
|
Daniel@0
|
2508 value: value,
|
Daniel@0
|
2509 index: index
|
Daniel@0
|
2510 };
|
Daniel@0
|
2511 }
|
Daniel@0
|
2512
|
Daniel@0
|
2513 function bisect(a, x, lo, hi) {
|
Daniel@0
|
2514 while (lo < hi) {
|
Daniel@0
|
2515 var mid = lo + hi >>> 1;
|
Daniel@0
|
2516 if (util.cmp(a[mid], x) < 0) { lo = mid + 1; }
|
Daniel@0
|
2517 else { hi = mid; }
|
Daniel@0
|
2518 }
|
Daniel@0
|
2519 return lo;
|
Daniel@0
|
2520 }
|
Daniel@0
|
2521
|
Daniel@0
|
2522 function value(v) {
|
Daniel@0
|
2523 return this.step * Math.floor(v / this.step + EPSILON);
|
Daniel@0
|
2524 }
|
Daniel@0
|
2525
|
Daniel@0
|
2526 function index(v) {
|
Daniel@0
|
2527 return Math.floor((v - this.start) / this.step + EPSILON);
|
Daniel@0
|
2528 }
|
Daniel@0
|
2529
|
Daniel@0
|
2530 function date_value(v) {
|
Daniel@0
|
2531 return this.unit.date(value.call(this, v));
|
Daniel@0
|
2532 }
|
Daniel@0
|
2533
|
Daniel@0
|
2534 function date_index(v) {
|
Daniel@0
|
2535 return index.call(this, this.unit.unit(v));
|
Daniel@0
|
2536 }
|
Daniel@0
|
2537
|
Daniel@0
|
2538 bins.date = function(opt) {
|
Daniel@0
|
2539 if (!opt) { throw Error("Missing date binning options."); }
|
Daniel@0
|
2540
|
Daniel@0
|
2541 // find time step, then bin
|
Daniel@0
|
2542 var units = opt.utc ? time.utc : time,
|
Daniel@0
|
2543 dmin = opt.min,
|
Daniel@0
|
2544 dmax = opt.max,
|
Daniel@0
|
2545 maxb = opt.maxbins || 20,
|
Daniel@0
|
2546 minb = opt.minbins || 4,
|
Daniel@0
|
2547 span = (+dmax) - (+dmin),
|
Daniel@0
|
2548 unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb),
|
Daniel@0
|
2549 spec = bins({
|
Daniel@0
|
2550 min: unit.min != null ? unit.min : unit.unit(dmin),
|
Daniel@0
|
2551 max: unit.max != null ? unit.max : unit.unit(dmax),
|
Daniel@0
|
2552 maxbins: maxb,
|
Daniel@0
|
2553 minstep: unit.minstep,
|
Daniel@0
|
2554 steps: unit.step
|
Daniel@0
|
2555 });
|
Daniel@0
|
2556
|
Daniel@0
|
2557 spec.unit = unit;
|
Daniel@0
|
2558 spec.index = date_index;
|
Daniel@0
|
2559 if (!opt.raw) spec.value = date_value;
|
Daniel@0
|
2560 return spec;
|
Daniel@0
|
2561 };
|
Daniel@0
|
2562
|
Daniel@0
|
2563 module.exports = bins;
|
Daniel@0
|
2564
|
Daniel@0
|
2565 },{"../time":28,"../util":29}],12:[function(require,module,exports){
|
Daniel@0
|
2566 var bins = require('./bins'),
|
Daniel@0
|
2567 gen = require('../generate'),
|
Daniel@0
|
2568 type = require('../import/type'),
|
Daniel@0
|
2569 util = require('../util'),
|
Daniel@0
|
2570 stats = require('../stats');
|
Daniel@0
|
2571
|
Daniel@0
|
2572 var qtype = {
|
Daniel@0
|
2573 'integer': 1,
|
Daniel@0
|
2574 'number': 1,
|
Daniel@0
|
2575 'date': 1
|
Daniel@0
|
2576 };
|
Daniel@0
|
2577
|
Daniel@0
|
2578 function $bin(values, f, opt) {
|
Daniel@0
|
2579 opt = options(values, f, opt);
|
Daniel@0
|
2580 var b = spec(opt);
|
Daniel@0
|
2581 return !b ? (opt.accessor || util.identity) :
|
Daniel@0
|
2582 util.$func('bin', b.unit.unit ?
|
Daniel@0
|
2583 function(x) { return b.value(b.unit.unit(x)); } :
|
Daniel@0
|
2584 function(x) { return b.value(x); }
|
Daniel@0
|
2585 )(opt.accessor);
|
Daniel@0
|
2586 }
|
Daniel@0
|
2587
|
Daniel@0
|
2588 function histogram(values, f, opt) {
|
Daniel@0
|
2589 opt = options(values, f, opt);
|
Daniel@0
|
2590 var b = spec(opt);
|
Daniel@0
|
2591 return b ?
|
Daniel@0
|
2592 numerical(values, opt.accessor, b) :
|
Daniel@0
|
2593 categorical(values, opt.accessor, opt && opt.sort);
|
Daniel@0
|
2594 }
|
Daniel@0
|
2595
|
Daniel@0
|
2596 function spec(opt) {
|
Daniel@0
|
2597 var t = opt.type, b = null;
|
Daniel@0
|
2598 if (t == null || qtype[t]) {
|
Daniel@0
|
2599 if (t === 'integer' && opt.minstep == null) opt.minstep = 1;
|
Daniel@0
|
2600 b = (t === 'date') ? bins.date(opt) : bins(opt);
|
Daniel@0
|
2601 }
|
Daniel@0
|
2602 return b;
|
Daniel@0
|
2603 }
|
Daniel@0
|
2604
|
Daniel@0
|
2605 function options() {
|
Daniel@0
|
2606 var a = arguments,
|
Daniel@0
|
2607 i = 0,
|
Daniel@0
|
2608 values = util.isArray(a[i]) ? a[i++] : null,
|
Daniel@0
|
2609 f = util.isFunction(a[i]) || util.isString(a[i]) ? util.$(a[i++]) : null,
|
Daniel@0
|
2610 opt = util.extend({}, a[i]);
|
Daniel@0
|
2611
|
Daniel@0
|
2612 if (values) {
|
Daniel@0
|
2613 opt.type = opt.type || type(values, f);
|
Daniel@0
|
2614 if (qtype[opt.type]) {
|
Daniel@0
|
2615 var ext = stats.extent(values, f);
|
Daniel@0
|
2616 opt = util.extend({min: ext[0], max: ext[1]}, opt);
|
Daniel@0
|
2617 }
|
Daniel@0
|
2618 }
|
Daniel@0
|
2619 if (f) { opt.accessor = f; }
|
Daniel@0
|
2620 return opt;
|
Daniel@0
|
2621 }
|
Daniel@0
|
2622
|
Daniel@0
|
2623 function numerical(values, f, b) {
|
Daniel@0
|
2624 var h = gen.range(b.start, b.stop + b.step/2, b.step)
|
Daniel@0
|
2625 .map(function(v) { return {value: b.value(v), count: 0}; });
|
Daniel@0
|
2626
|
Daniel@0
|
2627 for (var i=0, v, j; i<values.length; ++i) {
|
Daniel@0
|
2628 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
2629 if (util.isValid(v)) {
|
Daniel@0
|
2630 j = b.index(v);
|
Daniel@0
|
2631 if (j < 0 || j >= h.length || !isFinite(j)) continue;
|
Daniel@0
|
2632 h[j].count += 1;
|
Daniel@0
|
2633 }
|
Daniel@0
|
2634 }
|
Daniel@0
|
2635 h.bins = b;
|
Daniel@0
|
2636 return h;
|
Daniel@0
|
2637 }
|
Daniel@0
|
2638
|
Daniel@0
|
2639 function categorical(values, f, sort) {
|
Daniel@0
|
2640 var u = stats.unique(values, f),
|
Daniel@0
|
2641 c = stats.count.map(values, f);
|
Daniel@0
|
2642 return u.map(function(k) { return {value: k, count: c[k]}; })
|
Daniel@0
|
2643 .sort(util.comparator(sort ? '-count' : '+value'));
|
Daniel@0
|
2644 }
|
Daniel@0
|
2645
|
Daniel@0
|
2646 module.exports = {
|
Daniel@0
|
2647 $bin: $bin,
|
Daniel@0
|
2648 histogram: histogram
|
Daniel@0
|
2649 };
|
Daniel@0
|
2650 },{"../generate":14,"../import/type":23,"../stats":26,"../util":29,"./bins":11}],13:[function(require,module,exports){
|
Daniel@0
|
2651 var d3_time = require('d3-time'),
|
Daniel@0
|
2652 d3_timeF = require('d3-time-format'),
|
Daniel@0
|
2653 d3_numberF = require('d3-format'),
|
Daniel@0
|
2654 numberF = d3_numberF, // defaults to EN-US
|
Daniel@0
|
2655 timeF = d3_timeF; // defaults to EN-US
|
Daniel@0
|
2656
|
Daniel@0
|
2657 function numberLocale(l) {
|
Daniel@0
|
2658 var f = d3_numberF.localeFormat(l);
|
Daniel@0
|
2659 if (f == null) throw Error('Unrecognized locale: ' + l);
|
Daniel@0
|
2660 numberF = f;
|
Daniel@0
|
2661 }
|
Daniel@0
|
2662
|
Daniel@0
|
2663 function timeLocale(l) {
|
Daniel@0
|
2664 var f = d3_timeF.localeFormat(l);
|
Daniel@0
|
2665 if (f == null) throw Error('Unrecognized locale: ' + l);
|
Daniel@0
|
2666 timeF = f;
|
Daniel@0
|
2667 }
|
Daniel@0
|
2668
|
Daniel@0
|
2669 module.exports = {
|
Daniel@0
|
2670 // Update number formatter to use provided locale configuration.
|
Daniel@0
|
2671 // For more see https://github.com/d3/d3-format
|
Daniel@0
|
2672 numberLocale: numberLocale,
|
Daniel@0
|
2673 number: function(f) { return numberF.format(f); },
|
Daniel@0
|
2674 numberPrefix: function(f, v) { return numberF.formatPrefix(f, v); },
|
Daniel@0
|
2675
|
Daniel@0
|
2676 // Update time formatter to use provided locale configuration.
|
Daniel@0
|
2677 // For more see https://github.com/d3/d3-time-format
|
Daniel@0
|
2678 timeLocale: timeLocale,
|
Daniel@0
|
2679 time: function(f) { return timeF.format(f); },
|
Daniel@0
|
2680 utc: function(f) { return timeF.utcFormat(f); },
|
Daniel@0
|
2681
|
Daniel@0
|
2682 // Set number and time locale simultaneously.
|
Daniel@0
|
2683 locale: function(l) { numberLocale(l); timeLocale(l); },
|
Daniel@0
|
2684
|
Daniel@0
|
2685 // automatic formatting functions
|
Daniel@0
|
2686 auto: {
|
Daniel@0
|
2687 number: numberAutoFormat,
|
Daniel@0
|
2688 time: function() { return timeAutoFormat(); },
|
Daniel@0
|
2689 utc: function() { return utcAutoFormat(); }
|
Daniel@0
|
2690 }
|
Daniel@0
|
2691 };
|
Daniel@0
|
2692
|
Daniel@0
|
2693 var e10 = Math.sqrt(50),
|
Daniel@0
|
2694 e5 = Math.sqrt(10),
|
Daniel@0
|
2695 e2 = Math.sqrt(2);
|
Daniel@0
|
2696
|
Daniel@0
|
2697 function intervals(domain, count) {
|
Daniel@0
|
2698 if (!domain.length) domain = [0];
|
Daniel@0
|
2699 if (count == null) count = 10;
|
Daniel@0
|
2700
|
Daniel@0
|
2701 var start = domain[0],
|
Daniel@0
|
2702 stop = domain[domain.length - 1];
|
Daniel@0
|
2703
|
Daniel@0
|
2704 if (stop < start) { error = stop; stop = start; start = error; }
|
Daniel@0
|
2705
|
Daniel@0
|
2706 var span = (stop - start) || (count = 1, start || stop || 1),
|
Daniel@0
|
2707 step = Math.pow(10, Math.floor(Math.log(span / count) / Math.LN10)),
|
Daniel@0
|
2708 error = span / count / step;
|
Daniel@0
|
2709
|
Daniel@0
|
2710 // Filter ticks to get closer to the desired count.
|
Daniel@0
|
2711 if (error >= e10) step *= 10;
|
Daniel@0
|
2712 else if (error >= e5) step *= 5;
|
Daniel@0
|
2713 else if (error >= e2) step *= 2;
|
Daniel@0
|
2714
|
Daniel@0
|
2715 // Round start and stop values to step interval.
|
Daniel@0
|
2716 return [
|
Daniel@0
|
2717 Math.ceil(start / step) * step,
|
Daniel@0
|
2718 Math.floor(stop / step) * step + step / 2, // inclusive
|
Daniel@0
|
2719 step
|
Daniel@0
|
2720 ];
|
Daniel@0
|
2721 }
|
Daniel@0
|
2722
|
Daniel@0
|
2723 function numberAutoFormat(domain, count, f) {
|
Daniel@0
|
2724 var range = intervals(domain, count);
|
Daniel@0
|
2725 if (f == null) {
|
Daniel@0
|
2726 f = ',.' + d3_numberF.precisionFixed(range[2]) + 'f';
|
Daniel@0
|
2727 } else {
|
Daniel@0
|
2728 switch (f = d3_numberF.formatSpecifier(f), f.type) {
|
Daniel@0
|
2729 case 's': {
|
Daniel@0
|
2730 var value = Math.max(Math.abs(range[0]), Math.abs(range[1]));
|
Daniel@0
|
2731 if (f.precision == null) f.precision = d3_numberF.precisionPrefix(range[2], value);
|
Daniel@0
|
2732 return numberF.formatPrefix(f, value);
|
Daniel@0
|
2733 }
|
Daniel@0
|
2734 case '':
|
Daniel@0
|
2735 case 'e':
|
Daniel@0
|
2736 case 'g':
|
Daniel@0
|
2737 case 'p':
|
Daniel@0
|
2738 case 'r': {
|
Daniel@0
|
2739 if (f.precision == null) f.precision = d3_numberF.precisionRound(range[2], Math.max(Math.abs(range[0]), Math.abs(range[1]))) - (f.type === 'e');
|
Daniel@0
|
2740 break;
|
Daniel@0
|
2741 }
|
Daniel@0
|
2742 case 'f':
|
Daniel@0
|
2743 case '%': {
|
Daniel@0
|
2744 if (f.precision == null) f.precision = d3_numberF.precisionFixed(range[2]) - (f.type === '%') * 2;
|
Daniel@0
|
2745 break;
|
Daniel@0
|
2746 }
|
Daniel@0
|
2747 }
|
Daniel@0
|
2748 }
|
Daniel@0
|
2749 return numberF.format(f);
|
Daniel@0
|
2750 }
|
Daniel@0
|
2751
|
Daniel@0
|
2752 function timeAutoFormat() {
|
Daniel@0
|
2753 var f = timeF.format,
|
Daniel@0
|
2754 formatMillisecond = f('.%L'),
|
Daniel@0
|
2755 formatSecond = f(':%S'),
|
Daniel@0
|
2756 formatMinute = f('%I:%M'),
|
Daniel@0
|
2757 formatHour = f('%I %p'),
|
Daniel@0
|
2758 formatDay = f('%a %d'),
|
Daniel@0
|
2759 formatWeek = f('%b %d'),
|
Daniel@0
|
2760 formatMonth = f('%B'),
|
Daniel@0
|
2761 formatYear = f('%Y');
|
Daniel@0
|
2762
|
Daniel@0
|
2763 return function(date) {
|
Daniel@0
|
2764 var d = +date;
|
Daniel@0
|
2765 return (d3_time.second(date) < d ? formatMillisecond
|
Daniel@0
|
2766 : d3_time.minute(date) < d ? formatSecond
|
Daniel@0
|
2767 : d3_time.hour(date) < d ? formatMinute
|
Daniel@0
|
2768 : d3_time.day(date) < d ? formatHour
|
Daniel@0
|
2769 : d3_time.month(date) < d ?
|
Daniel@0
|
2770 (d3_time.week(date) < d ? formatDay : formatWeek)
|
Daniel@0
|
2771 : d3_time.year(date) < d ? formatMonth
|
Daniel@0
|
2772 : formatYear)(date);
|
Daniel@0
|
2773 };
|
Daniel@0
|
2774 }
|
Daniel@0
|
2775
|
Daniel@0
|
2776 function utcAutoFormat() {
|
Daniel@0
|
2777 var f = timeF.utcFormat,
|
Daniel@0
|
2778 formatMillisecond = f('.%L'),
|
Daniel@0
|
2779 formatSecond = f(':%S'),
|
Daniel@0
|
2780 formatMinute = f('%I:%M'),
|
Daniel@0
|
2781 formatHour = f('%I %p'),
|
Daniel@0
|
2782 formatDay = f('%a %d'),
|
Daniel@0
|
2783 formatWeek = f('%b %d'),
|
Daniel@0
|
2784 formatMonth = f('%B'),
|
Daniel@0
|
2785 formatYear = f('%Y');
|
Daniel@0
|
2786
|
Daniel@0
|
2787 return function(date) {
|
Daniel@0
|
2788 var d = +date;
|
Daniel@0
|
2789 return (d3_time.utcSecond(date) < d ? formatMillisecond
|
Daniel@0
|
2790 : d3_time.utcMinute(date) < d ? formatSecond
|
Daniel@0
|
2791 : d3_time.utcHour(date) < d ? formatMinute
|
Daniel@0
|
2792 : d3_time.utcDay(date) < d ? formatHour
|
Daniel@0
|
2793 : d3_time.utcMonth(date) < d ?
|
Daniel@0
|
2794 (d3_time.utcWeek(date) < d ? formatDay : formatWeek)
|
Daniel@0
|
2795 : d3_time.utcYear(date) < d ? formatMonth
|
Daniel@0
|
2796 : formatYear)(date);
|
Daniel@0
|
2797 };
|
Daniel@0
|
2798 }
|
Daniel@0
|
2799
|
Daniel@0
|
2800 },{"d3-format":4,"d3-time":6,"d3-time-format":5}],14:[function(require,module,exports){
|
Daniel@0
|
2801 var gen = module.exports = {};
|
Daniel@0
|
2802
|
Daniel@0
|
2803 gen.repeat = function(val, n) {
|
Daniel@0
|
2804 var a = Array(n), i;
|
Daniel@0
|
2805 for (i=0; i<n; ++i) a[i] = val;
|
Daniel@0
|
2806 return a;
|
Daniel@0
|
2807 };
|
Daniel@0
|
2808
|
Daniel@0
|
2809 gen.zeros = function(n) {
|
Daniel@0
|
2810 return gen.repeat(0, n);
|
Daniel@0
|
2811 };
|
Daniel@0
|
2812
|
Daniel@0
|
2813 gen.range = function(start, stop, step) {
|
Daniel@0
|
2814 if (arguments.length < 3) {
|
Daniel@0
|
2815 step = 1;
|
Daniel@0
|
2816 if (arguments.length < 2) {
|
Daniel@0
|
2817 stop = start;
|
Daniel@0
|
2818 start = 0;
|
Daniel@0
|
2819 }
|
Daniel@0
|
2820 }
|
Daniel@0
|
2821 if ((stop - start) / step == Infinity) throw new Error('Infinite range');
|
Daniel@0
|
2822 var range = [], i = -1, j;
|
Daniel@0
|
2823 if (step < 0) while ((j = start + step * ++i) > stop) range.push(j);
|
Daniel@0
|
2824 else while ((j = start + step * ++i) < stop) range.push(j);
|
Daniel@0
|
2825 return range;
|
Daniel@0
|
2826 };
|
Daniel@0
|
2827
|
Daniel@0
|
2828 gen.random = {};
|
Daniel@0
|
2829
|
Daniel@0
|
2830 gen.random.uniform = function(min, max) {
|
Daniel@0
|
2831 if (max === undefined) {
|
Daniel@0
|
2832 max = min === undefined ? 1 : min;
|
Daniel@0
|
2833 min = 0;
|
Daniel@0
|
2834 }
|
Daniel@0
|
2835 var d = max - min;
|
Daniel@0
|
2836 var f = function() {
|
Daniel@0
|
2837 return min + d * Math.random();
|
Daniel@0
|
2838 };
|
Daniel@0
|
2839 f.samples = function(n) { return gen.zeros(n).map(f); };
|
Daniel@0
|
2840 return f;
|
Daniel@0
|
2841 };
|
Daniel@0
|
2842
|
Daniel@0
|
2843 gen.random.integer = function(a, b) {
|
Daniel@0
|
2844 if (b === undefined) {
|
Daniel@0
|
2845 b = a;
|
Daniel@0
|
2846 a = 0;
|
Daniel@0
|
2847 }
|
Daniel@0
|
2848 var d = b - a;
|
Daniel@0
|
2849 var f = function() {
|
Daniel@0
|
2850 return a + Math.floor(d * Math.random());
|
Daniel@0
|
2851 };
|
Daniel@0
|
2852 f.samples = function(n) { return gen.zeros(n).map(f); };
|
Daniel@0
|
2853 return f;
|
Daniel@0
|
2854 };
|
Daniel@0
|
2855
|
Daniel@0
|
2856 gen.random.normal = function(mean, stdev) {
|
Daniel@0
|
2857 mean = mean || 0;
|
Daniel@0
|
2858 stdev = stdev || 1;
|
Daniel@0
|
2859 var next;
|
Daniel@0
|
2860 var f = function() {
|
Daniel@0
|
2861 var x = 0, y = 0, rds, c;
|
Daniel@0
|
2862 if (next !== undefined) {
|
Daniel@0
|
2863 x = next;
|
Daniel@0
|
2864 next = undefined;
|
Daniel@0
|
2865 return x;
|
Daniel@0
|
2866 }
|
Daniel@0
|
2867 do {
|
Daniel@0
|
2868 x = Math.random()*2-1;
|
Daniel@0
|
2869 y = Math.random()*2-1;
|
Daniel@0
|
2870 rds = x*x + y*y;
|
Daniel@0
|
2871 } while (rds === 0 || rds > 1);
|
Daniel@0
|
2872 c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform
|
Daniel@0
|
2873 next = mean + y*c*stdev;
|
Daniel@0
|
2874 return mean + x*c*stdev;
|
Daniel@0
|
2875 };
|
Daniel@0
|
2876 f.samples = function(n) { return gen.zeros(n).map(f); };
|
Daniel@0
|
2877 return f;
|
Daniel@0
|
2878 };
|
Daniel@0
|
2879 },{}],15:[function(require,module,exports){
|
Daniel@0
|
2880 var util = require('../../util');
|
Daniel@0
|
2881 var d3_dsv = require('d3-dsv');
|
Daniel@0
|
2882
|
Daniel@0
|
2883 function dsv(data, format) {
|
Daniel@0
|
2884 if (data) {
|
Daniel@0
|
2885 var h = format.header;
|
Daniel@0
|
2886 data = (h ? h.join(format.delimiter) + '\n' : '') + data;
|
Daniel@0
|
2887 }
|
Daniel@0
|
2888 return d3_dsv.dsv(format.delimiter).parse(data);
|
Daniel@0
|
2889 }
|
Daniel@0
|
2890
|
Daniel@0
|
2891 dsv.delimiter = function(delim) {
|
Daniel@0
|
2892 var fmt = {delimiter: delim};
|
Daniel@0
|
2893 return function(data, format) {
|
Daniel@0
|
2894 return dsv(data, format ? util.extend(format, fmt) : fmt);
|
Daniel@0
|
2895 };
|
Daniel@0
|
2896 };
|
Daniel@0
|
2897
|
Daniel@0
|
2898 module.exports = dsv;
|
Daniel@0
|
2899 },{"../../util":29,"d3-dsv":3}],16:[function(require,module,exports){
|
Daniel@0
|
2900 var dsv = require('./dsv');
|
Daniel@0
|
2901
|
Daniel@0
|
2902 module.exports = {
|
Daniel@0
|
2903 json: require('./json'),
|
Daniel@0
|
2904 topojson: require('./topojson'),
|
Daniel@0
|
2905 treejson: require('./treejson'),
|
Daniel@0
|
2906 dsv: dsv,
|
Daniel@0
|
2907 csv: dsv.delimiter(','),
|
Daniel@0
|
2908 tsv: dsv.delimiter('\t')
|
Daniel@0
|
2909 };
|
Daniel@0
|
2910 },{"./dsv":15,"./json":17,"./topojson":18,"./treejson":19}],17:[function(require,module,exports){
|
Daniel@0
|
2911 var util = require('../../util');
|
Daniel@0
|
2912
|
Daniel@0
|
2913 module.exports = function(data, format) {
|
Daniel@0
|
2914 var d = util.isObject(data) && !util.isBuffer(data) ?
|
Daniel@0
|
2915 data : JSON.parse(data);
|
Daniel@0
|
2916 if (format && format.property) {
|
Daniel@0
|
2917 d = util.accessor(format.property)(d);
|
Daniel@0
|
2918 }
|
Daniel@0
|
2919 return d;
|
Daniel@0
|
2920 };
|
Daniel@0
|
2921
|
Daniel@0
|
2922 },{"../../util":29}],18:[function(require,module,exports){
|
Daniel@0
|
2923 (function (global){
|
Daniel@0
|
2924 var json = require('./json');
|
Daniel@0
|
2925
|
Daniel@0
|
2926 var reader = function(data, format) {
|
Daniel@0
|
2927 var topojson = reader.topojson;
|
Daniel@0
|
2928 if (topojson == null) { throw Error('TopoJSON library not loaded.'); }
|
Daniel@0
|
2929
|
Daniel@0
|
2930 var t = json(data, format), obj;
|
Daniel@0
|
2931
|
Daniel@0
|
2932 if (format && format.feature) {
|
Daniel@0
|
2933 if ((obj = t.objects[format.feature])) {
|
Daniel@0
|
2934 return topojson.feature(t, obj).features;
|
Daniel@0
|
2935 } else {
|
Daniel@0
|
2936 throw Error('Invalid TopoJSON object: ' + format.feature);
|
Daniel@0
|
2937 }
|
Daniel@0
|
2938 } else if (format && format.mesh) {
|
Daniel@0
|
2939 if ((obj = t.objects[format.mesh])) {
|
Daniel@0
|
2940 return [topojson.mesh(t, t.objects[format.mesh])];
|
Daniel@0
|
2941 } else {
|
Daniel@0
|
2942 throw Error('Invalid TopoJSON object: ' + format.mesh);
|
Daniel@0
|
2943 }
|
Daniel@0
|
2944 } else {
|
Daniel@0
|
2945 throw Error('Missing TopoJSON feature or mesh parameter.');
|
Daniel@0
|
2946 }
|
Daniel@0
|
2947 };
|
Daniel@0
|
2948
|
Daniel@0
|
2949 reader.topojson = (typeof window !== "undefined" ? window['topojson'] : typeof global !== "undefined" ? global['topojson'] : null);
|
Daniel@0
|
2950 module.exports = reader;
|
Daniel@0
|
2951 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
2952
|
Daniel@0
|
2953 },{"./json":17}],19:[function(require,module,exports){
|
Daniel@0
|
2954 var json = require('./json');
|
Daniel@0
|
2955
|
Daniel@0
|
2956 module.exports = function(data, format) {
|
Daniel@0
|
2957 data = json(data, format);
|
Daniel@0
|
2958 return toTable(data, (format && format.children));
|
Daniel@0
|
2959 };
|
Daniel@0
|
2960
|
Daniel@0
|
2961 function toTable(root, childrenField) {
|
Daniel@0
|
2962 childrenField = childrenField || 'children';
|
Daniel@0
|
2963 var table = [];
|
Daniel@0
|
2964
|
Daniel@0
|
2965 function visit(node) {
|
Daniel@0
|
2966 table.push(node);
|
Daniel@0
|
2967 var children = node[childrenField];
|
Daniel@0
|
2968 if (children) {
|
Daniel@0
|
2969 for (var i=0; i<children.length; ++i) {
|
Daniel@0
|
2970 visit(children[i], node);
|
Daniel@0
|
2971 }
|
Daniel@0
|
2972 }
|
Daniel@0
|
2973 }
|
Daniel@0
|
2974
|
Daniel@0
|
2975 visit(root, null);
|
Daniel@0
|
2976 return (table.root = root, table);
|
Daniel@0
|
2977 }
|
Daniel@0
|
2978 },{"./json":17}],20:[function(require,module,exports){
|
Daniel@0
|
2979 // Matches absolute URLs with optional protocol
|
Daniel@0
|
2980 // https://... file://... //...
|
Daniel@0
|
2981 var protocol_re = /^([A-Za-z]+:)?\/\//;
|
Daniel@0
|
2982
|
Daniel@0
|
2983 // Special treatment in node.js for the file: protocol
|
Daniel@0
|
2984 var fileProtocol = 'file://';
|
Daniel@0
|
2985
|
Daniel@0
|
2986 // Validate and cleanup URL to ensure that it is allowed to be accessed
|
Daniel@0
|
2987 // Returns cleaned up URL, or false if access is not allowed
|
Daniel@0
|
2988 function sanitizeUrl(opt) {
|
Daniel@0
|
2989 var url = opt.url;
|
Daniel@0
|
2990 if (!url && opt.file) { return fileProtocol + opt.file; }
|
Daniel@0
|
2991
|
Daniel@0
|
2992 // In case this is a relative url (has no host), prepend opt.baseURL
|
Daniel@0
|
2993 if (opt.baseURL && !protocol_re.test(url)) {
|
Daniel@0
|
2994 if (!startsWith(url, '/') && opt.baseURL[opt.baseURL.length-1] !== '/') {
|
Daniel@0
|
2995 url = '/' + url; // Ensure that there is a slash between the baseURL (e.g. hostname) and url
|
Daniel@0
|
2996 }
|
Daniel@0
|
2997 url = opt.baseURL + url;
|
Daniel@0
|
2998 }
|
Daniel@0
|
2999 // relative protocol, starts with '//'
|
Daniel@0
|
3000 if (!load.useXHR && startsWith(url, '//')) {
|
Daniel@0
|
3001 url = (opt.defaultProtocol || 'http') + ':' + url;
|
Daniel@0
|
3002 }
|
Daniel@0
|
3003 // If opt.domainWhiteList is set, only allows url, whose hostname
|
Daniel@0
|
3004 // * Is the same as the origin (window.location.hostname)
|
Daniel@0
|
3005 // * Equals one of the values in the whitelist
|
Daniel@0
|
3006 // * Is a proper subdomain of one of the values in the whitelist
|
Daniel@0
|
3007 if (opt.domainWhiteList) {
|
Daniel@0
|
3008 var domain, origin;
|
Daniel@0
|
3009 if (load.useXHR) {
|
Daniel@0
|
3010 var a = document.createElement('a');
|
Daniel@0
|
3011 a.href = url;
|
Daniel@0
|
3012 // From http://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript
|
Daniel@0
|
3013 // IE doesn't populate all link properties when setting .href with a relative URL,
|
Daniel@0
|
3014 // however .href will return an absolute URL which then can be used on itself
|
Daniel@0
|
3015 // to populate these additional fields.
|
Daniel@0
|
3016 if (a.host === '') {
|
Daniel@0
|
3017 a.href = a.href;
|
Daniel@0
|
3018 }
|
Daniel@0
|
3019 domain = a.hostname.toLowerCase();
|
Daniel@0
|
3020 origin = window.location.hostname;
|
Daniel@0
|
3021 } else {
|
Daniel@0
|
3022 // relative protocol is broken: https://github.com/defunctzombie/node-url/issues/5
|
Daniel@0
|
3023 var parts = require('url').parse(url);
|
Daniel@0
|
3024 domain = parts.hostname;
|
Daniel@0
|
3025 origin = null;
|
Daniel@0
|
3026 }
|
Daniel@0
|
3027
|
Daniel@0
|
3028 if (origin !== domain) {
|
Daniel@0
|
3029 var whiteListed = opt.domainWhiteList.some(function(d) {
|
Daniel@0
|
3030 var idx = domain.length - d.length;
|
Daniel@0
|
3031 return d === domain ||
|
Daniel@0
|
3032 (idx > 1 && domain[idx-1] === '.' && domain.lastIndexOf(d) === idx);
|
Daniel@0
|
3033 });
|
Daniel@0
|
3034 if (!whiteListed) {
|
Daniel@0
|
3035 throw 'URL is not whitelisted: ' + url;
|
Daniel@0
|
3036 }
|
Daniel@0
|
3037 }
|
Daniel@0
|
3038 }
|
Daniel@0
|
3039 return url;
|
Daniel@0
|
3040 }
|
Daniel@0
|
3041
|
Daniel@0
|
3042 function load(opt, callback) {
|
Daniel@0
|
3043 var error = callback || function(e) { throw e; }, url;
|
Daniel@0
|
3044
|
Daniel@0
|
3045 try {
|
Daniel@0
|
3046 url = load.sanitizeUrl(opt); // enable override
|
Daniel@0
|
3047 } catch (err) {
|
Daniel@0
|
3048 error(err);
|
Daniel@0
|
3049 return;
|
Daniel@0
|
3050 }
|
Daniel@0
|
3051
|
Daniel@0
|
3052 if (!url) {
|
Daniel@0
|
3053 error('Invalid URL: ' + opt.url);
|
Daniel@0
|
3054 } else if (load.useXHR) {
|
Daniel@0
|
3055 // on client, use xhr
|
Daniel@0
|
3056 return xhr(url, callback);
|
Daniel@0
|
3057 } else if (startsWith(url, fileProtocol)) {
|
Daniel@0
|
3058 // on server, if url starts with 'file://', strip it and load from file
|
Daniel@0
|
3059 return file(url.slice(fileProtocol.length), callback);
|
Daniel@0
|
3060 } else if (url.indexOf('://') < 0) { // TODO better protocol check?
|
Daniel@0
|
3061 // on server, if no protocol assume file
|
Daniel@0
|
3062 return file(url, callback);
|
Daniel@0
|
3063 } else {
|
Daniel@0
|
3064 // for regular URLs on server
|
Daniel@0
|
3065 return http(url, callback);
|
Daniel@0
|
3066 }
|
Daniel@0
|
3067 }
|
Daniel@0
|
3068
|
Daniel@0
|
3069 function xhrHasResponse(request) {
|
Daniel@0
|
3070 var type = request.responseType;
|
Daniel@0
|
3071 return type && type !== 'text' ?
|
Daniel@0
|
3072 request.response : // null on error
|
Daniel@0
|
3073 request.responseText; // '' on error
|
Daniel@0
|
3074 }
|
Daniel@0
|
3075
|
Daniel@0
|
3076 function xhr(url, callback) {
|
Daniel@0
|
3077 var async = !!callback;
|
Daniel@0
|
3078 var request = new XMLHttpRequest();
|
Daniel@0
|
3079 // If IE does not support CORS, use XDomainRequest (copied from d3.xhr)
|
Daniel@0
|
3080 if (this.XDomainRequest &&
|
Daniel@0
|
3081 !('withCredentials' in request) &&
|
Daniel@0
|
3082 /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
|
Daniel@0
|
3083
|
Daniel@0
|
3084 function respond() {
|
Daniel@0
|
3085 var status = request.status;
|
Daniel@0
|
3086 if (!status && xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
|
Daniel@0
|
3087 callback(null, request.responseText);
|
Daniel@0
|
3088 } else {
|
Daniel@0
|
3089 callback(request, null);
|
Daniel@0
|
3090 }
|
Daniel@0
|
3091 }
|
Daniel@0
|
3092
|
Daniel@0
|
3093 if (async) {
|
Daniel@0
|
3094 if ('onload' in request) {
|
Daniel@0
|
3095 request.onload = request.onerror = respond;
|
Daniel@0
|
3096 } else {
|
Daniel@0
|
3097 request.onreadystatechange = function() {
|
Daniel@0
|
3098 if (request.readyState > 3) respond();
|
Daniel@0
|
3099 };
|
Daniel@0
|
3100 }
|
Daniel@0
|
3101 }
|
Daniel@0
|
3102
|
Daniel@0
|
3103 request.open('GET', url, async);
|
Daniel@0
|
3104 request.send();
|
Daniel@0
|
3105
|
Daniel@0
|
3106 if (!async && xhrHasResponse(request)) {
|
Daniel@0
|
3107 return request.responseText;
|
Daniel@0
|
3108 }
|
Daniel@0
|
3109 }
|
Daniel@0
|
3110
|
Daniel@0
|
3111 function file(filename, callback) {
|
Daniel@0
|
3112 var fs = require('fs');
|
Daniel@0
|
3113 if (!callback) {
|
Daniel@0
|
3114 return fs.readFileSync(filename, 'utf8');
|
Daniel@0
|
3115 }
|
Daniel@0
|
3116 fs.readFile(filename, callback);
|
Daniel@0
|
3117 }
|
Daniel@0
|
3118
|
Daniel@0
|
3119 function http(url, callback) {
|
Daniel@0
|
3120 if (!callback) {
|
Daniel@0
|
3121 return require('sync-request')('GET', url).getBody();
|
Daniel@0
|
3122 }
|
Daniel@0
|
3123
|
Daniel@0
|
3124 var options = {url: url, encoding: null, gzip: true};
|
Daniel@0
|
3125 require('request')(options, function(error, response, body) {
|
Daniel@0
|
3126 if (!error && response.statusCode === 200) {
|
Daniel@0
|
3127 callback(null, body);
|
Daniel@0
|
3128 } else {
|
Daniel@0
|
3129 error = error ||
|
Daniel@0
|
3130 'Load failed with response code ' + response.statusCode + '.';
|
Daniel@0
|
3131 callback(error, null);
|
Daniel@0
|
3132 }
|
Daniel@0
|
3133 });
|
Daniel@0
|
3134 }
|
Daniel@0
|
3135
|
Daniel@0
|
3136 function startsWith(string, searchString) {
|
Daniel@0
|
3137 return string == null ? false : string.lastIndexOf(searchString, 0) === 0;
|
Daniel@0
|
3138 }
|
Daniel@0
|
3139
|
Daniel@0
|
3140 load.sanitizeUrl = sanitizeUrl;
|
Daniel@0
|
3141
|
Daniel@0
|
3142 load.useXHR = (typeof XMLHttpRequest !== 'undefined');
|
Daniel@0
|
3143
|
Daniel@0
|
3144 module.exports = load;
|
Daniel@0
|
3145
|
Daniel@0
|
3146 },{"fs":2,"request":2,"sync-request":2,"url":2}],21:[function(require,module,exports){
|
Daniel@0
|
3147 var util = require('../util');
|
Daniel@0
|
3148 var type = require('./type');
|
Daniel@0
|
3149 var formats = require('./formats');
|
Daniel@0
|
3150
|
Daniel@0
|
3151 function read(data, format) {
|
Daniel@0
|
3152 var type = (format && format.type) || 'json';
|
Daniel@0
|
3153 data = formats[type](data, format);
|
Daniel@0
|
3154 if (format && format.parse) parse(data, format.parse);
|
Daniel@0
|
3155 return data;
|
Daniel@0
|
3156 }
|
Daniel@0
|
3157
|
Daniel@0
|
3158 function parse(data, types) {
|
Daniel@0
|
3159 var cols, parsers, d, i, j, clen, len = data.length;
|
Daniel@0
|
3160
|
Daniel@0
|
3161 types = (types==='auto') ? type.inferAll(data) : util.duplicate(types);
|
Daniel@0
|
3162 cols = util.keys(types);
|
Daniel@0
|
3163 parsers = cols.map(function(c) { return type.parsers[types[c]]; });
|
Daniel@0
|
3164
|
Daniel@0
|
3165 for (i=0, clen=cols.length; i<len; ++i) {
|
Daniel@0
|
3166 d = data[i];
|
Daniel@0
|
3167 for (j=0; j<clen; ++j) {
|
Daniel@0
|
3168 d[cols[j]] = parsers[j](d[cols[j]]);
|
Daniel@0
|
3169 }
|
Daniel@0
|
3170 }
|
Daniel@0
|
3171 type.annotation(data, types);
|
Daniel@0
|
3172 }
|
Daniel@0
|
3173
|
Daniel@0
|
3174 read.formats = formats;
|
Daniel@0
|
3175 module.exports = read;
|
Daniel@0
|
3176
|
Daniel@0
|
3177 },{"../util":29,"./formats":16,"./type":23}],22:[function(require,module,exports){
|
Daniel@0
|
3178 var util = require('../util');
|
Daniel@0
|
3179 var load = require('./load');
|
Daniel@0
|
3180 var read = require('./read');
|
Daniel@0
|
3181
|
Daniel@0
|
3182 module.exports = util
|
Daniel@0
|
3183 .keys(read.formats)
|
Daniel@0
|
3184 .reduce(function(out, type) {
|
Daniel@0
|
3185 out[type] = function(opt, format, callback) {
|
Daniel@0
|
3186 // process arguments
|
Daniel@0
|
3187 if (util.isString(opt)) { opt = {url: opt}; }
|
Daniel@0
|
3188 if (arguments.length === 2 && util.isFunction(format)) {
|
Daniel@0
|
3189 callback = format;
|
Daniel@0
|
3190 format = undefined;
|
Daniel@0
|
3191 }
|
Daniel@0
|
3192
|
Daniel@0
|
3193 // set up read format
|
Daniel@0
|
3194 format = util.extend({parse: 'auto'}, format);
|
Daniel@0
|
3195 format.type = type;
|
Daniel@0
|
3196
|
Daniel@0
|
3197 // load data
|
Daniel@0
|
3198 var data = load(opt, callback ? function(error, data) {
|
Daniel@0
|
3199 if (error) { callback(error, null); return; }
|
Daniel@0
|
3200 try {
|
Daniel@0
|
3201 // data loaded, now parse it (async)
|
Daniel@0
|
3202 data = read(data, format);
|
Daniel@0
|
3203 callback(null, data);
|
Daniel@0
|
3204 } catch (e) {
|
Daniel@0
|
3205 callback(e, null);
|
Daniel@0
|
3206 }
|
Daniel@0
|
3207 } : undefined);
|
Daniel@0
|
3208
|
Daniel@0
|
3209 // data loaded, now parse it (sync)
|
Daniel@0
|
3210 if (!callback) return read(data, format);
|
Daniel@0
|
3211 };
|
Daniel@0
|
3212 return out;
|
Daniel@0
|
3213 }, {});
|
Daniel@0
|
3214
|
Daniel@0
|
3215 },{"../util":29,"./load":20,"./read":21}],23:[function(require,module,exports){
|
Daniel@0
|
3216 var util = require('../util');
|
Daniel@0
|
3217
|
Daniel@0
|
3218 var TYPES = '__types__';
|
Daniel@0
|
3219
|
Daniel@0
|
3220 var PARSERS = {
|
Daniel@0
|
3221 boolean: util.boolean,
|
Daniel@0
|
3222 integer: util.number,
|
Daniel@0
|
3223 number: util.number,
|
Daniel@0
|
3224 date: util.date,
|
Daniel@0
|
3225 string: function(x) { return x==='' ? null : x; }
|
Daniel@0
|
3226 };
|
Daniel@0
|
3227
|
Daniel@0
|
3228 var TESTS = {
|
Daniel@0
|
3229 boolean: function(x) { return x==='true' || x==='false' || util.isBoolean(x); },
|
Daniel@0
|
3230 integer: function(x) { return TESTS.number(x) && (x=+x) === ~~x; },
|
Daniel@0
|
3231 number: function(x) { return !isNaN(+x) && !util.isDate(x); },
|
Daniel@0
|
3232 date: function(x) { return !isNaN(Date.parse(x)); }
|
Daniel@0
|
3233 };
|
Daniel@0
|
3234
|
Daniel@0
|
3235 function annotation(data, types) {
|
Daniel@0
|
3236 if (!types) return data && data[TYPES] || null;
|
Daniel@0
|
3237 data[TYPES] = types;
|
Daniel@0
|
3238 }
|
Daniel@0
|
3239
|
Daniel@0
|
3240 function type(values, f) {
|
Daniel@0
|
3241 f = util.$(f);
|
Daniel@0
|
3242 var v, i, n;
|
Daniel@0
|
3243
|
Daniel@0
|
3244 // if data array has type annotations, use them
|
Daniel@0
|
3245 if (values[TYPES]) {
|
Daniel@0
|
3246 v = f(values[TYPES]);
|
Daniel@0
|
3247 if (util.isString(v)) return v;
|
Daniel@0
|
3248 }
|
Daniel@0
|
3249
|
Daniel@0
|
3250 for (i=0, n=values.length; !util.isValid(v) && i<n; ++i) {
|
Daniel@0
|
3251 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3252 }
|
Daniel@0
|
3253
|
Daniel@0
|
3254 return util.isDate(v) ? 'date' :
|
Daniel@0
|
3255 util.isNumber(v) ? 'number' :
|
Daniel@0
|
3256 util.isBoolean(v) ? 'boolean' :
|
Daniel@0
|
3257 util.isString(v) ? 'string' : null;
|
Daniel@0
|
3258 }
|
Daniel@0
|
3259
|
Daniel@0
|
3260 function typeAll(data, fields) {
|
Daniel@0
|
3261 if (!data.length) return;
|
Daniel@0
|
3262 fields = fields || util.keys(data[0]);
|
Daniel@0
|
3263 return fields.reduce(function(types, f) {
|
Daniel@0
|
3264 return (types[f] = type(data, f), types);
|
Daniel@0
|
3265 }, {});
|
Daniel@0
|
3266 }
|
Daniel@0
|
3267
|
Daniel@0
|
3268 function infer(values, f) {
|
Daniel@0
|
3269 f = util.$(f);
|
Daniel@0
|
3270 var i, j, v;
|
Daniel@0
|
3271
|
Daniel@0
|
3272 // types to test for, in precedence order
|
Daniel@0
|
3273 var types = ['boolean', 'integer', 'number', 'date'];
|
Daniel@0
|
3274
|
Daniel@0
|
3275 for (i=0; i<values.length; ++i) {
|
Daniel@0
|
3276 // get next value to test
|
Daniel@0
|
3277 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3278 // test value against remaining types
|
Daniel@0
|
3279 for (j=0; j<types.length; ++j) {
|
Daniel@0
|
3280 if (util.isValid(v) && !TESTS[types[j]](v)) {
|
Daniel@0
|
3281 types.splice(j, 1);
|
Daniel@0
|
3282 j -= 1;
|
Daniel@0
|
3283 }
|
Daniel@0
|
3284 }
|
Daniel@0
|
3285 // if no types left, return 'string'
|
Daniel@0
|
3286 if (types.length === 0) return 'string';
|
Daniel@0
|
3287 }
|
Daniel@0
|
3288
|
Daniel@0
|
3289 return types[0];
|
Daniel@0
|
3290 }
|
Daniel@0
|
3291
|
Daniel@0
|
3292 function inferAll(data, fields) {
|
Daniel@0
|
3293 fields = fields || util.keys(data[0]);
|
Daniel@0
|
3294 return fields.reduce(function(types, f) {
|
Daniel@0
|
3295 types[f] = infer(data, f);
|
Daniel@0
|
3296 return types;
|
Daniel@0
|
3297 }, {});
|
Daniel@0
|
3298 }
|
Daniel@0
|
3299
|
Daniel@0
|
3300 type.annotation = annotation;
|
Daniel@0
|
3301 type.all = typeAll;
|
Daniel@0
|
3302 type.infer = infer;
|
Daniel@0
|
3303 type.inferAll = inferAll;
|
Daniel@0
|
3304 type.parsers = PARSERS;
|
Daniel@0
|
3305 module.exports = type;
|
Daniel@0
|
3306 },{"../util":29}],24:[function(require,module,exports){
|
Daniel@0
|
3307 var util = require('./util');
|
Daniel@0
|
3308
|
Daniel@0
|
3309 var dl = {
|
Daniel@0
|
3310 version: '1.4.6',
|
Daniel@0
|
3311 load: require('./import/load'),
|
Daniel@0
|
3312 read: require('./import/read'),
|
Daniel@0
|
3313 type: require('./import/type'),
|
Daniel@0
|
3314 Aggregator: require('./aggregate/aggregator'),
|
Daniel@0
|
3315 groupby: require('./aggregate/groupby'),
|
Daniel@0
|
3316 bins: require('./bins/bins'),
|
Daniel@0
|
3317 $bin: require('./bins/histogram').$bin,
|
Daniel@0
|
3318 histogram: require('./bins/histogram').histogram,
|
Daniel@0
|
3319 format: require('./format'),
|
Daniel@0
|
3320 print: require('./print'),
|
Daniel@0
|
3321 template: require('./template'),
|
Daniel@0
|
3322 time: require('./time')
|
Daniel@0
|
3323 };
|
Daniel@0
|
3324
|
Daniel@0
|
3325 util.extend(dl, util);
|
Daniel@0
|
3326 util.extend(dl, require('./generate'));
|
Daniel@0
|
3327 util.extend(dl, require('./stats'));
|
Daniel@0
|
3328 util.extend(dl, require('./import/readers'));
|
Daniel@0
|
3329
|
Daniel@0
|
3330 module.exports = dl;
|
Daniel@0
|
3331 },{"./aggregate/aggregator":7,"./aggregate/groupby":9,"./bins/bins":11,"./bins/histogram":12,"./format":13,"./generate":14,"./import/load":20,"./import/read":21,"./import/readers":22,"./import/type":23,"./print":25,"./stats":26,"./template":27,"./time":28,"./util":29}],25:[function(require,module,exports){
|
Daniel@0
|
3332 var util = require('./util');
|
Daniel@0
|
3333 var type = require('./import/type');
|
Daniel@0
|
3334 var stats = require('./stats');
|
Daniel@0
|
3335 var template = require('./template');
|
Daniel@0
|
3336
|
Daniel@0
|
3337 var FMT = {
|
Daniel@0
|
3338 'date': '|time:"%m/%d/%Y %H:%M:%S"',
|
Daniel@0
|
3339 'number': '|number:".4f"',
|
Daniel@0
|
3340 'integer': '|number:"d"'
|
Daniel@0
|
3341 };
|
Daniel@0
|
3342
|
Daniel@0
|
3343 var POS = {
|
Daniel@0
|
3344 'number': 'left',
|
Daniel@0
|
3345 'integer': 'left'
|
Daniel@0
|
3346 };
|
Daniel@0
|
3347
|
Daniel@0
|
3348 module.exports.table = function(data, opt) {
|
Daniel@0
|
3349 opt = util.extend({separator:' ', minwidth: 8, maxwidth: 15}, opt);
|
Daniel@0
|
3350 var fields = opt.fields || util.keys(data[0]),
|
Daniel@0
|
3351 types = type.all(data);
|
Daniel@0
|
3352
|
Daniel@0
|
3353 if (opt.start || opt.limit) {
|
Daniel@0
|
3354 var a = opt.start || 0,
|
Daniel@0
|
3355 b = opt.limit ? a + opt.limit : data.length;
|
Daniel@0
|
3356 data = data.slice(a, b);
|
Daniel@0
|
3357 }
|
Daniel@0
|
3358
|
Daniel@0
|
3359 // determine char width of fields
|
Daniel@0
|
3360 var lens = fields.map(function(name) {
|
Daniel@0
|
3361 var format = FMT[types[name]] || '',
|
Daniel@0
|
3362 t = template('{{' + name + format + '}}'),
|
Daniel@0
|
3363 l = stats.max(data, function(x) { return t(x).length; });
|
Daniel@0
|
3364 l = Math.max(Math.min(name.length, opt.minwidth), l);
|
Daniel@0
|
3365 return opt.maxwidth > 0 ? Math.min(l, opt.maxwidth) : l;
|
Daniel@0
|
3366 });
|
Daniel@0
|
3367
|
Daniel@0
|
3368 // print header row
|
Daniel@0
|
3369 var head = fields.map(function(name, i) {
|
Daniel@0
|
3370 return util.truncate(util.pad(name, lens[i], 'center'), lens[i]);
|
Daniel@0
|
3371 }).join(opt.separator);
|
Daniel@0
|
3372
|
Daniel@0
|
3373 // build template function for each row
|
Daniel@0
|
3374 var tmpl = template(fields.map(function(name, i) {
|
Daniel@0
|
3375 return '{{' +
|
Daniel@0
|
3376 name +
|
Daniel@0
|
3377 (FMT[types[name]] || '') +
|
Daniel@0
|
3378 ('|pad:' + lens[i] + ',' + (POS[types[name]] || 'right')) +
|
Daniel@0
|
3379 ('|truncate:' + lens[i]) +
|
Daniel@0
|
3380 '}}';
|
Daniel@0
|
3381 }).join(opt.separator));
|
Daniel@0
|
3382
|
Daniel@0
|
3383 // print table
|
Daniel@0
|
3384 return head + "\n" + data.map(tmpl).join('\n');
|
Daniel@0
|
3385 };
|
Daniel@0
|
3386
|
Daniel@0
|
3387 module.exports.summary = function(s) {
|
Daniel@0
|
3388 s = s ? s.__summary__ ? s : stats.summary(s) : this;
|
Daniel@0
|
3389 var str = [], i, n;
|
Daniel@0
|
3390 for (i=0, n=s.length; i<n; ++i) {
|
Daniel@0
|
3391 str.push('-- ' + s[i].field + ' --');
|
Daniel@0
|
3392 if (s[i].type === 'string' || s[i].distinct < 10) {
|
Daniel@0
|
3393 str.push(printCategoricalProfile(s[i]));
|
Daniel@0
|
3394 } else {
|
Daniel@0
|
3395 str.push(printQuantitativeProfile(s[i]));
|
Daniel@0
|
3396 }
|
Daniel@0
|
3397 str.push('');
|
Daniel@0
|
3398 }
|
Daniel@0
|
3399 return str.join('\n');
|
Daniel@0
|
3400 };
|
Daniel@0
|
3401
|
Daniel@0
|
3402 function printQuantitativeProfile(p) {
|
Daniel@0
|
3403 return [
|
Daniel@0
|
3404 'valid: ' + p.valid,
|
Daniel@0
|
3405 'missing: ' + p.missing,
|
Daniel@0
|
3406 'distinct: ' + p.distinct,
|
Daniel@0
|
3407 'min: ' + p.min,
|
Daniel@0
|
3408 'max: ' + p.max,
|
Daniel@0
|
3409 'median: ' + p.median,
|
Daniel@0
|
3410 'mean: ' + p.mean,
|
Daniel@0
|
3411 'stdev: ' + p.stdev,
|
Daniel@0
|
3412 'modeskew: ' + p.modeskew
|
Daniel@0
|
3413 ].join('\n');
|
Daniel@0
|
3414 }
|
Daniel@0
|
3415
|
Daniel@0
|
3416 function printCategoricalProfile(p) {
|
Daniel@0
|
3417 var list = [
|
Daniel@0
|
3418 'valid: ' + p.valid,
|
Daniel@0
|
3419 'missing: ' + p.missing,
|
Daniel@0
|
3420 'distinct: ' + p.distinct,
|
Daniel@0
|
3421 'top values: '
|
Daniel@0
|
3422 ];
|
Daniel@0
|
3423 var u = p.unique;
|
Daniel@0
|
3424 var top = util.keys(u)
|
Daniel@0
|
3425 .sort(function(a,b) { return u[b] - u[a]; })
|
Daniel@0
|
3426 .slice(0, 6)
|
Daniel@0
|
3427 .map(function(v) { return ' \'' + v + '\' (' + u[v] + ')'; });
|
Daniel@0
|
3428 return list.concat(top).join('\n');
|
Daniel@0
|
3429 }
|
Daniel@0
|
3430 },{"./import/type":23,"./stats":26,"./template":27,"./util":29}],26:[function(require,module,exports){
|
Daniel@0
|
3431 var util = require('./util');
|
Daniel@0
|
3432 var type = require('./import/type');
|
Daniel@0
|
3433 var gen = require('./generate');
|
Daniel@0
|
3434 var stats = {};
|
Daniel@0
|
3435
|
Daniel@0
|
3436 // Collect unique values.
|
Daniel@0
|
3437 // Output: an array of unique values, in first-observed order
|
Daniel@0
|
3438 stats.unique = function(values, f, results) {
|
Daniel@0
|
3439 f = util.$(f);
|
Daniel@0
|
3440 results = results || [];
|
Daniel@0
|
3441 var u = {}, v, i, n;
|
Daniel@0
|
3442 for (i=0, n=values.length; i<n; ++i) {
|
Daniel@0
|
3443 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3444 if (v in u) continue;
|
Daniel@0
|
3445 u[v] = 1;
|
Daniel@0
|
3446 results.push(v);
|
Daniel@0
|
3447 }
|
Daniel@0
|
3448 return results;
|
Daniel@0
|
3449 };
|
Daniel@0
|
3450
|
Daniel@0
|
3451 // Return the length of the input array.
|
Daniel@0
|
3452 stats.count = function(values) {
|
Daniel@0
|
3453 return values && values.length || 0;
|
Daniel@0
|
3454 };
|
Daniel@0
|
3455
|
Daniel@0
|
3456 // Count the number of non-null, non-undefined, non-NaN values.
|
Daniel@0
|
3457 stats.count.valid = function(values, f) {
|
Daniel@0
|
3458 f = util.$(f);
|
Daniel@0
|
3459 var v, i, n, valid = 0;
|
Daniel@0
|
3460 for (i=0, n=values.length; i<n; ++i) {
|
Daniel@0
|
3461 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3462 if (util.isValid(v)) valid += 1;
|
Daniel@0
|
3463 }
|
Daniel@0
|
3464 return valid;
|
Daniel@0
|
3465 };
|
Daniel@0
|
3466
|
Daniel@0
|
3467 // Count the number of null or undefined values.
|
Daniel@0
|
3468 stats.count.missing = function(values, f) {
|
Daniel@0
|
3469 f = util.$(f);
|
Daniel@0
|
3470 var v, i, n, count = 0;
|
Daniel@0
|
3471 for (i=0, n=values.length; i<n; ++i) {
|
Daniel@0
|
3472 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3473 if (v == null) count += 1;
|
Daniel@0
|
3474 }
|
Daniel@0
|
3475 return count;
|
Daniel@0
|
3476 };
|
Daniel@0
|
3477
|
Daniel@0
|
3478 // Count the number of distinct values.
|
Daniel@0
|
3479 // Null, undefined and NaN are each considered distinct values.
|
Daniel@0
|
3480 stats.count.distinct = function(values, f) {
|
Daniel@0
|
3481 f = util.$(f);
|
Daniel@0
|
3482 var u = {}, v, i, n, count = 0;
|
Daniel@0
|
3483 for (i=0, n=values.length; i<n; ++i) {
|
Daniel@0
|
3484 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3485 if (v in u) continue;
|
Daniel@0
|
3486 u[v] = 1;
|
Daniel@0
|
3487 count += 1;
|
Daniel@0
|
3488 }
|
Daniel@0
|
3489 return count;
|
Daniel@0
|
3490 };
|
Daniel@0
|
3491
|
Daniel@0
|
3492 // Construct a map from distinct values to occurrence counts.
|
Daniel@0
|
3493 stats.count.map = function(values, f) {
|
Daniel@0
|
3494 f = util.$(f);
|
Daniel@0
|
3495 var map = {}, v, i, n;
|
Daniel@0
|
3496 for (i=0, n=values.length; i<n; ++i) {
|
Daniel@0
|
3497 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3498 map[v] = (v in map) ? map[v] + 1 : 1;
|
Daniel@0
|
3499 }
|
Daniel@0
|
3500 return map;
|
Daniel@0
|
3501 };
|
Daniel@0
|
3502
|
Daniel@0
|
3503 // Compute the median of an array of numbers.
|
Daniel@0
|
3504 stats.median = function(values, f) {
|
Daniel@0
|
3505 if (f) values = values.map(util.$(f));
|
Daniel@0
|
3506 values = values.filter(util.isValid).sort(util.cmp);
|
Daniel@0
|
3507 return stats.quantile(values, 0.5);
|
Daniel@0
|
3508 };
|
Daniel@0
|
3509
|
Daniel@0
|
3510 // Computes the quartile boundaries of an array of numbers.
|
Daniel@0
|
3511 stats.quartile = function(values, f) {
|
Daniel@0
|
3512 if (f) values = values.map(util.$(f));
|
Daniel@0
|
3513 values = values.filter(util.isValid).sort(util.cmp);
|
Daniel@0
|
3514 var q = stats.quantile;
|
Daniel@0
|
3515 return [q(values, 0.25), q(values, 0.50), q(values, 0.75)];
|
Daniel@0
|
3516 };
|
Daniel@0
|
3517
|
Daniel@0
|
3518 // Compute the quantile of a sorted array of numbers.
|
Daniel@0
|
3519 // Adapted from the D3.js implementation.
|
Daniel@0
|
3520 stats.quantile = function(values, f, p) {
|
Daniel@0
|
3521 if (p === undefined) { p = f; f = util.identity; }
|
Daniel@0
|
3522 f = util.$(f);
|
Daniel@0
|
3523 var H = (values.length - 1) * p + 1,
|
Daniel@0
|
3524 h = Math.floor(H),
|
Daniel@0
|
3525 v = +f(values[h - 1]),
|
Daniel@0
|
3526 e = H - h;
|
Daniel@0
|
3527 return e ? v + e * (f(values[h]) - v) : v;
|
Daniel@0
|
3528 };
|
Daniel@0
|
3529
|
Daniel@0
|
3530 // Compute the sum of an array of numbers.
|
Daniel@0
|
3531 stats.sum = function(values, f) {
|
Daniel@0
|
3532 f = util.$(f);
|
Daniel@0
|
3533 for (var sum=0, i=0, n=values.length, v; i<n; ++i) {
|
Daniel@0
|
3534 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3535 if (util.isValid(v)) sum += v;
|
Daniel@0
|
3536 }
|
Daniel@0
|
3537 return sum;
|
Daniel@0
|
3538 };
|
Daniel@0
|
3539
|
Daniel@0
|
3540 // Compute the mean (average) of an array of numbers.
|
Daniel@0
|
3541 stats.mean = function(values, f) {
|
Daniel@0
|
3542 f = util.$(f);
|
Daniel@0
|
3543 var mean = 0, delta, i, n, c, v;
|
Daniel@0
|
3544 for (i=0, c=0, n=values.length; i<n; ++i) {
|
Daniel@0
|
3545 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3546 if (util.isValid(v)) {
|
Daniel@0
|
3547 delta = v - mean;
|
Daniel@0
|
3548 mean = mean + delta / (++c);
|
Daniel@0
|
3549 }
|
Daniel@0
|
3550 }
|
Daniel@0
|
3551 return mean;
|
Daniel@0
|
3552 };
|
Daniel@0
|
3553
|
Daniel@0
|
3554 // Compute the sample variance of an array of numbers.
|
Daniel@0
|
3555 stats.variance = function(values, f) {
|
Daniel@0
|
3556 f = util.$(f);
|
Daniel@0
|
3557 if (!util.isArray(values) || values.length < 2) return 0;
|
Daniel@0
|
3558 var mean = 0, M2 = 0, delta, i, c, v;
|
Daniel@0
|
3559 for (i=0, c=0; i<values.length; ++i) {
|
Daniel@0
|
3560 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3561 if (util.isValid(v)) {
|
Daniel@0
|
3562 delta = v - mean;
|
Daniel@0
|
3563 mean = mean + delta / (++c);
|
Daniel@0
|
3564 M2 = M2 + delta * (v - mean);
|
Daniel@0
|
3565 }
|
Daniel@0
|
3566 }
|
Daniel@0
|
3567 M2 = M2 / (c - 1);
|
Daniel@0
|
3568 return M2;
|
Daniel@0
|
3569 };
|
Daniel@0
|
3570
|
Daniel@0
|
3571 // Compute the sample standard deviation of an array of numbers.
|
Daniel@0
|
3572 stats.stdev = function(values, f) {
|
Daniel@0
|
3573 return Math.sqrt(stats.variance(values, f));
|
Daniel@0
|
3574 };
|
Daniel@0
|
3575
|
Daniel@0
|
3576 // Compute the Pearson mode skewness ((median-mean)/stdev) of an array of numbers.
|
Daniel@0
|
3577 stats.modeskew = function(values, f) {
|
Daniel@0
|
3578 var avg = stats.mean(values, f),
|
Daniel@0
|
3579 med = stats.median(values, f),
|
Daniel@0
|
3580 std = stats.stdev(values, f);
|
Daniel@0
|
3581 return std === 0 ? 0 : (avg - med) / std;
|
Daniel@0
|
3582 };
|
Daniel@0
|
3583
|
Daniel@0
|
3584 // Find the minimum value in an array.
|
Daniel@0
|
3585 stats.min = function(values, f) {
|
Daniel@0
|
3586 return stats.extent(values, f)[0];
|
Daniel@0
|
3587 };
|
Daniel@0
|
3588
|
Daniel@0
|
3589 // Find the maximum value in an array.
|
Daniel@0
|
3590 stats.max = function(values, f) {
|
Daniel@0
|
3591 return stats.extent(values, f)[1];
|
Daniel@0
|
3592 };
|
Daniel@0
|
3593
|
Daniel@0
|
3594 // Find the minimum and maximum of an array of values.
|
Daniel@0
|
3595 stats.extent = function(values, f) {
|
Daniel@0
|
3596 f = util.$(f);
|
Daniel@0
|
3597 var a, b, v, i, n = values.length;
|
Daniel@0
|
3598 for (i=0; i<n; ++i) {
|
Daniel@0
|
3599 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3600 if (util.isValid(v)) { a = b = v; break; }
|
Daniel@0
|
3601 }
|
Daniel@0
|
3602 for (; i<n; ++i) {
|
Daniel@0
|
3603 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3604 if (util.isValid(v)) {
|
Daniel@0
|
3605 if (v < a) a = v;
|
Daniel@0
|
3606 if (v > b) b = v;
|
Daniel@0
|
3607 }
|
Daniel@0
|
3608 }
|
Daniel@0
|
3609 return [a, b];
|
Daniel@0
|
3610 };
|
Daniel@0
|
3611
|
Daniel@0
|
3612 // Find the integer indices of the minimum and maximum values.
|
Daniel@0
|
3613 stats.extent.index = function(values, f) {
|
Daniel@0
|
3614 f = util.$(f);
|
Daniel@0
|
3615 var x = -1, y = -1, a, b, v, i, n = values.length;
|
Daniel@0
|
3616 for (i=0; i<n; ++i) {
|
Daniel@0
|
3617 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3618 if (util.isValid(v)) { a = b = v; x = y = i; break; }
|
Daniel@0
|
3619 }
|
Daniel@0
|
3620 for (; i<n; ++i) {
|
Daniel@0
|
3621 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3622 if (util.isValid(v)) {
|
Daniel@0
|
3623 if (v < a) { a = v; x = i; }
|
Daniel@0
|
3624 if (v > b) { b = v; y = i; }
|
Daniel@0
|
3625 }
|
Daniel@0
|
3626 }
|
Daniel@0
|
3627 return [x, y];
|
Daniel@0
|
3628 };
|
Daniel@0
|
3629
|
Daniel@0
|
3630 // Compute the dot product of two arrays of numbers.
|
Daniel@0
|
3631 stats.dot = function(values, a, b) {
|
Daniel@0
|
3632 var sum = 0, i, v;
|
Daniel@0
|
3633 if (!b) {
|
Daniel@0
|
3634 if (values.length !== a.length) {
|
Daniel@0
|
3635 throw Error('Array lengths must match.');
|
Daniel@0
|
3636 }
|
Daniel@0
|
3637 for (i=0; i<values.length; ++i) {
|
Daniel@0
|
3638 v = values[i] * a[i];
|
Daniel@0
|
3639 if (v === v) sum += v;
|
Daniel@0
|
3640 }
|
Daniel@0
|
3641 } else {
|
Daniel@0
|
3642 a = util.$(a);
|
Daniel@0
|
3643 b = util.$(b);
|
Daniel@0
|
3644 for (i=0; i<values.length; ++i) {
|
Daniel@0
|
3645 v = a(values[i]) * b(values[i]);
|
Daniel@0
|
3646 if (v === v) sum += v;
|
Daniel@0
|
3647 }
|
Daniel@0
|
3648 }
|
Daniel@0
|
3649 return sum;
|
Daniel@0
|
3650 };
|
Daniel@0
|
3651
|
Daniel@0
|
3652 // Compute ascending rank scores for an array of values.
|
Daniel@0
|
3653 // Ties are assigned their collective mean rank.
|
Daniel@0
|
3654 stats.rank = function(values, f) {
|
Daniel@0
|
3655 f = util.$(f) || util.identity;
|
Daniel@0
|
3656 var a = values.map(function(v, i) {
|
Daniel@0
|
3657 return {idx: i, val: f(v)};
|
Daniel@0
|
3658 })
|
Daniel@0
|
3659 .sort(util.comparator('val'));
|
Daniel@0
|
3660
|
Daniel@0
|
3661 var n = values.length,
|
Daniel@0
|
3662 r = Array(n),
|
Daniel@0
|
3663 tie = -1, p = {}, i, v, mu;
|
Daniel@0
|
3664
|
Daniel@0
|
3665 for (i=0; i<n; ++i) {
|
Daniel@0
|
3666 v = a[i].val;
|
Daniel@0
|
3667 if (tie < 0 && p === v) {
|
Daniel@0
|
3668 tie = i - 1;
|
Daniel@0
|
3669 } else if (tie > -1 && p !== v) {
|
Daniel@0
|
3670 mu = 1 + (i-1 + tie) / 2;
|
Daniel@0
|
3671 for (; tie<i; ++tie) r[a[tie].idx] = mu;
|
Daniel@0
|
3672 tie = -1;
|
Daniel@0
|
3673 }
|
Daniel@0
|
3674 r[a[i].idx] = i + 1;
|
Daniel@0
|
3675 p = v;
|
Daniel@0
|
3676 }
|
Daniel@0
|
3677
|
Daniel@0
|
3678 if (tie > -1) {
|
Daniel@0
|
3679 mu = 1 + (n-1 + tie) / 2;
|
Daniel@0
|
3680 for (; tie<n; ++tie) r[a[tie].idx] = mu;
|
Daniel@0
|
3681 }
|
Daniel@0
|
3682
|
Daniel@0
|
3683 return r;
|
Daniel@0
|
3684 };
|
Daniel@0
|
3685
|
Daniel@0
|
3686 // Compute the sample Pearson product-moment correlation of two arrays of numbers.
|
Daniel@0
|
3687 stats.cor = function(values, a, b) {
|
Daniel@0
|
3688 var fn = b;
|
Daniel@0
|
3689 b = fn ? values.map(util.$(b)) : a;
|
Daniel@0
|
3690 a = fn ? values.map(util.$(a)) : values;
|
Daniel@0
|
3691
|
Daniel@0
|
3692 var dot = stats.dot(a, b),
|
Daniel@0
|
3693 mua = stats.mean(a),
|
Daniel@0
|
3694 mub = stats.mean(b),
|
Daniel@0
|
3695 sda = stats.stdev(a),
|
Daniel@0
|
3696 sdb = stats.stdev(b),
|
Daniel@0
|
3697 n = values.length;
|
Daniel@0
|
3698
|
Daniel@0
|
3699 return (dot - n*mua*mub) / ((n-1) * sda * sdb);
|
Daniel@0
|
3700 };
|
Daniel@0
|
3701
|
Daniel@0
|
3702 // Compute the Spearman rank correlation of two arrays of values.
|
Daniel@0
|
3703 stats.cor.rank = function(values, a, b) {
|
Daniel@0
|
3704 var ra = b ? stats.rank(values, util.$(a)) : stats.rank(values),
|
Daniel@0
|
3705 rb = b ? stats.rank(values, util.$(b)) : stats.rank(a),
|
Daniel@0
|
3706 n = values.length, i, s, d;
|
Daniel@0
|
3707
|
Daniel@0
|
3708 for (i=0, s=0; i<n; ++i) {
|
Daniel@0
|
3709 d = ra[i] - rb[i];
|
Daniel@0
|
3710 s += d * d;
|
Daniel@0
|
3711 }
|
Daniel@0
|
3712
|
Daniel@0
|
3713 return 1 - 6*s / (n * (n*n-1));
|
Daniel@0
|
3714 };
|
Daniel@0
|
3715
|
Daniel@0
|
3716 // Compute the distance correlation of two arrays of numbers.
|
Daniel@0
|
3717 // http://en.wikipedia.org/wiki/Distance_correlation
|
Daniel@0
|
3718 stats.cor.dist = function(values, a, b) {
|
Daniel@0
|
3719 var X = b ? values.map(util.$(a)) : values,
|
Daniel@0
|
3720 Y = b ? values.map(util.$(b)) : a;
|
Daniel@0
|
3721
|
Daniel@0
|
3722 var A = stats.dist.mat(X),
|
Daniel@0
|
3723 B = stats.dist.mat(Y),
|
Daniel@0
|
3724 n = A.length,
|
Daniel@0
|
3725 i, aa, bb, ab;
|
Daniel@0
|
3726
|
Daniel@0
|
3727 for (i=0, aa=0, bb=0, ab=0; i<n; ++i) {
|
Daniel@0
|
3728 aa += A[i]*A[i];
|
Daniel@0
|
3729 bb += B[i]*B[i];
|
Daniel@0
|
3730 ab += A[i]*B[i];
|
Daniel@0
|
3731 }
|
Daniel@0
|
3732
|
Daniel@0
|
3733 return Math.sqrt(ab / Math.sqrt(aa*bb));
|
Daniel@0
|
3734 };
|
Daniel@0
|
3735
|
Daniel@0
|
3736 // Compute the vector distance between two arrays of numbers.
|
Daniel@0
|
3737 // Default is Euclidean (exp=2) distance, configurable via exp argument.
|
Daniel@0
|
3738 stats.dist = function(values, a, b, exp) {
|
Daniel@0
|
3739 var f = util.isFunction(b) || util.isString(b),
|
Daniel@0
|
3740 X = values,
|
Daniel@0
|
3741 Y = f ? values : a,
|
Daniel@0
|
3742 e = f ? exp : b,
|
Daniel@0
|
3743 L2 = e === 2 || e == null,
|
Daniel@0
|
3744 n = values.length, s = 0, d, i;
|
Daniel@0
|
3745 if (f) {
|
Daniel@0
|
3746 a = util.$(a);
|
Daniel@0
|
3747 b = util.$(b);
|
Daniel@0
|
3748 }
|
Daniel@0
|
3749 for (i=0; i<n; ++i) {
|
Daniel@0
|
3750 d = f ? (a(X[i])-b(Y[i])) : (X[i]-Y[i]);
|
Daniel@0
|
3751 s += L2 ? d*d : Math.pow(Math.abs(d), e);
|
Daniel@0
|
3752 }
|
Daniel@0
|
3753 return L2 ? Math.sqrt(s) : Math.pow(s, 1/e);
|
Daniel@0
|
3754 };
|
Daniel@0
|
3755
|
Daniel@0
|
3756 // Construct a mean-centered distance matrix for an array of numbers.
|
Daniel@0
|
3757 stats.dist.mat = function(X) {
|
Daniel@0
|
3758 var n = X.length,
|
Daniel@0
|
3759 m = n*n,
|
Daniel@0
|
3760 A = Array(m),
|
Daniel@0
|
3761 R = gen.zeros(n),
|
Daniel@0
|
3762 M = 0, v, i, j;
|
Daniel@0
|
3763
|
Daniel@0
|
3764 for (i=0; i<n; ++i) {
|
Daniel@0
|
3765 A[i*n+i] = 0;
|
Daniel@0
|
3766 for (j=i+1; j<n; ++j) {
|
Daniel@0
|
3767 A[i*n+j] = (v = Math.abs(X[i] - X[j]));
|
Daniel@0
|
3768 A[j*n+i] = v;
|
Daniel@0
|
3769 R[i] += v;
|
Daniel@0
|
3770 R[j] += v;
|
Daniel@0
|
3771 }
|
Daniel@0
|
3772 }
|
Daniel@0
|
3773
|
Daniel@0
|
3774 for (i=0; i<n; ++i) {
|
Daniel@0
|
3775 M += R[i];
|
Daniel@0
|
3776 R[i] /= n;
|
Daniel@0
|
3777 }
|
Daniel@0
|
3778 M /= m;
|
Daniel@0
|
3779
|
Daniel@0
|
3780 for (i=0; i<n; ++i) {
|
Daniel@0
|
3781 for (j=i; j<n; ++j) {
|
Daniel@0
|
3782 A[i*n+j] += M - R[i] - R[j];
|
Daniel@0
|
3783 A[j*n+i] = A[i*n+j];
|
Daniel@0
|
3784 }
|
Daniel@0
|
3785 }
|
Daniel@0
|
3786
|
Daniel@0
|
3787 return A;
|
Daniel@0
|
3788 };
|
Daniel@0
|
3789
|
Daniel@0
|
3790 // Compute the Shannon entropy (log base 2) of an array of counts.
|
Daniel@0
|
3791 stats.entropy = function(counts, f) {
|
Daniel@0
|
3792 f = util.$(f);
|
Daniel@0
|
3793 var i, p, s = 0, H = 0, n = counts.length;
|
Daniel@0
|
3794 for (i=0; i<n; ++i) {
|
Daniel@0
|
3795 s += (f ? f(counts[i]) : counts[i]);
|
Daniel@0
|
3796 }
|
Daniel@0
|
3797 if (s === 0) return 0;
|
Daniel@0
|
3798 for (i=0; i<n; ++i) {
|
Daniel@0
|
3799 p = (f ? f(counts[i]) : counts[i]) / s;
|
Daniel@0
|
3800 if (p) H += p * Math.log(p);
|
Daniel@0
|
3801 }
|
Daniel@0
|
3802 return -H / Math.LN2;
|
Daniel@0
|
3803 };
|
Daniel@0
|
3804
|
Daniel@0
|
3805 // Compute the mutual information between two discrete variables.
|
Daniel@0
|
3806 // Returns an array of the form [MI, MI_distance]
|
Daniel@0
|
3807 // MI_distance is defined as 1 - I(a,b) / H(a,b).
|
Daniel@0
|
3808 // http://en.wikipedia.org/wiki/Mutual_information
|
Daniel@0
|
3809 stats.mutual = function(values, a, b, counts) {
|
Daniel@0
|
3810 var x = counts ? values.map(util.$(a)) : values,
|
Daniel@0
|
3811 y = counts ? values.map(util.$(b)) : a,
|
Daniel@0
|
3812 z = counts ? values.map(util.$(counts)) : b;
|
Daniel@0
|
3813
|
Daniel@0
|
3814 var px = {},
|
Daniel@0
|
3815 py = {},
|
Daniel@0
|
3816 n = z.length,
|
Daniel@0
|
3817 s = 0, I = 0, H = 0, p, t, i;
|
Daniel@0
|
3818
|
Daniel@0
|
3819 for (i=0; i<n; ++i) {
|
Daniel@0
|
3820 px[x[i]] = 0;
|
Daniel@0
|
3821 py[y[i]] = 0;
|
Daniel@0
|
3822 }
|
Daniel@0
|
3823
|
Daniel@0
|
3824 for (i=0; i<n; ++i) {
|
Daniel@0
|
3825 px[x[i]] += z[i];
|
Daniel@0
|
3826 py[y[i]] += z[i];
|
Daniel@0
|
3827 s += z[i];
|
Daniel@0
|
3828 }
|
Daniel@0
|
3829
|
Daniel@0
|
3830 t = 1 / (s * Math.LN2);
|
Daniel@0
|
3831 for (i=0; i<n; ++i) {
|
Daniel@0
|
3832 if (z[i] === 0) continue;
|
Daniel@0
|
3833 p = (s * z[i]) / (px[x[i]] * py[y[i]]);
|
Daniel@0
|
3834 I += z[i] * t * Math.log(p);
|
Daniel@0
|
3835 H += z[i] * t * Math.log(z[i]/s);
|
Daniel@0
|
3836 }
|
Daniel@0
|
3837
|
Daniel@0
|
3838 return [I, 1 + I/H];
|
Daniel@0
|
3839 };
|
Daniel@0
|
3840
|
Daniel@0
|
3841 // Compute the mutual information between two discrete variables.
|
Daniel@0
|
3842 stats.mutual.info = function(values, a, b, counts) {
|
Daniel@0
|
3843 return stats.mutual(values, a, b, counts)[0];
|
Daniel@0
|
3844 };
|
Daniel@0
|
3845
|
Daniel@0
|
3846 // Compute the mutual information distance between two discrete variables.
|
Daniel@0
|
3847 // MI_distance is defined as 1 - I(a,b) / H(a,b).
|
Daniel@0
|
3848 stats.mutual.dist = function(values, a, b, counts) {
|
Daniel@0
|
3849 return stats.mutual(values, a, b, counts)[1];
|
Daniel@0
|
3850 };
|
Daniel@0
|
3851
|
Daniel@0
|
3852 // Compute a profile of summary statistics for a variable.
|
Daniel@0
|
3853 stats.profile = function(values, f) {
|
Daniel@0
|
3854 var mean = 0,
|
Daniel@0
|
3855 valid = 0,
|
Daniel@0
|
3856 missing = 0,
|
Daniel@0
|
3857 distinct = 0,
|
Daniel@0
|
3858 min = null,
|
Daniel@0
|
3859 max = null,
|
Daniel@0
|
3860 M2 = 0,
|
Daniel@0
|
3861 vals = [],
|
Daniel@0
|
3862 u = {}, delta, sd, i, v, x;
|
Daniel@0
|
3863
|
Daniel@0
|
3864 // compute summary stats
|
Daniel@0
|
3865 for (i=0; i<values.length; ++i) {
|
Daniel@0
|
3866 v = f ? f(values[i]) : values[i];
|
Daniel@0
|
3867
|
Daniel@0
|
3868 // update unique values
|
Daniel@0
|
3869 u[v] = (v in u) ? u[v] + 1 : (distinct += 1, 1);
|
Daniel@0
|
3870
|
Daniel@0
|
3871 if (v == null) {
|
Daniel@0
|
3872 ++missing;
|
Daniel@0
|
3873 } else if (util.isValid(v)) {
|
Daniel@0
|
3874 // update stats
|
Daniel@0
|
3875 x = (typeof v === 'string') ? v.length : v;
|
Daniel@0
|
3876 if (min===null || x < min) min = x;
|
Daniel@0
|
3877 if (max===null || x > max) max = x;
|
Daniel@0
|
3878 delta = x - mean;
|
Daniel@0
|
3879 mean = mean + delta / (++valid);
|
Daniel@0
|
3880 M2 = M2 + delta * (x - mean);
|
Daniel@0
|
3881 vals.push(x);
|
Daniel@0
|
3882 }
|
Daniel@0
|
3883 }
|
Daniel@0
|
3884 M2 = M2 / (valid - 1);
|
Daniel@0
|
3885 sd = Math.sqrt(M2);
|
Daniel@0
|
3886
|
Daniel@0
|
3887 // sort values for median and iqr
|
Daniel@0
|
3888 vals.sort(util.cmp);
|
Daniel@0
|
3889
|
Daniel@0
|
3890 return {
|
Daniel@0
|
3891 type: type(values, f),
|
Daniel@0
|
3892 unique: u,
|
Daniel@0
|
3893 count: values.length,
|
Daniel@0
|
3894 valid: valid,
|
Daniel@0
|
3895 missing: missing,
|
Daniel@0
|
3896 distinct: distinct,
|
Daniel@0
|
3897 min: min,
|
Daniel@0
|
3898 max: max,
|
Daniel@0
|
3899 mean: mean,
|
Daniel@0
|
3900 stdev: sd,
|
Daniel@0
|
3901 median: (v = stats.quantile(vals, 0.5)),
|
Daniel@0
|
3902 q1: stats.quantile(vals, 0.25),
|
Daniel@0
|
3903 q3: stats.quantile(vals, 0.75),
|
Daniel@0
|
3904 modeskew: sd === 0 ? 0 : (mean - v) / sd
|
Daniel@0
|
3905 };
|
Daniel@0
|
3906 };
|
Daniel@0
|
3907
|
Daniel@0
|
3908 // Compute profiles for all variables in a data set.
|
Daniel@0
|
3909 stats.summary = function(data, fields) {
|
Daniel@0
|
3910 fields = fields || util.keys(data[0]);
|
Daniel@0
|
3911 var s = fields.map(function(f) {
|
Daniel@0
|
3912 var p = stats.profile(data, util.$(f));
|
Daniel@0
|
3913 return (p.field = f, p);
|
Daniel@0
|
3914 });
|
Daniel@0
|
3915 return (s.__summary__ = true, s);
|
Daniel@0
|
3916 };
|
Daniel@0
|
3917
|
Daniel@0
|
3918 module.exports = stats;
|
Daniel@0
|
3919 },{"./generate":14,"./import/type":23,"./util":29}],27:[function(require,module,exports){
|
Daniel@0
|
3920 var util = require('./util'),
|
Daniel@0
|
3921 format = require('./format');
|
Daniel@0
|
3922
|
Daniel@0
|
3923 var context = {
|
Daniel@0
|
3924 formats: [],
|
Daniel@0
|
3925 format_map: {},
|
Daniel@0
|
3926 truncate: util.truncate,
|
Daniel@0
|
3927 pad: util.pad
|
Daniel@0
|
3928 };
|
Daniel@0
|
3929
|
Daniel@0
|
3930 function template(text) {
|
Daniel@0
|
3931 var src = source(text, 'd');
|
Daniel@0
|
3932 src = 'var __t; return ' + src + ';';
|
Daniel@0
|
3933
|
Daniel@0
|
3934 /* jshint evil: true */
|
Daniel@0
|
3935 return (new Function('d', src)).bind(context);
|
Daniel@0
|
3936 }
|
Daniel@0
|
3937
|
Daniel@0
|
3938 template.source = source;
|
Daniel@0
|
3939 template.context = context;
|
Daniel@0
|
3940 module.exports = template;
|
Daniel@0
|
3941
|
Daniel@0
|
3942 // Clear cache of format objects.
|
Daniel@0
|
3943 // This can *break* prior template functions, so invoke with care!
|
Daniel@0
|
3944 template.clearFormatCache = function() {
|
Daniel@0
|
3945 context.formats = [];
|
Daniel@0
|
3946 context.format_map = {};
|
Daniel@0
|
3947 };
|
Daniel@0
|
3948
|
Daniel@0
|
3949 // Generate property access code for use within template source.
|
Daniel@0
|
3950 // object: the name of the object (variable) containing template data
|
Daniel@0
|
3951 // property: the property access string, verbatim from template tag
|
Daniel@0
|
3952 template.property = function(object, property) {
|
Daniel@0
|
3953 var src = util.field(property).map(util.str).join('][');
|
Daniel@0
|
3954 return object + '[' + src + ']';
|
Daniel@0
|
3955 };
|
Daniel@0
|
3956
|
Daniel@0
|
3957 // Generate source code for a template function.
|
Daniel@0
|
3958 // text: the template text
|
Daniel@0
|
3959 // variable: the name of the data object variable ('obj' by default)
|
Daniel@0
|
3960 // properties: optional hash for collecting all accessed properties
|
Daniel@0
|
3961 function source(text, variable, properties) {
|
Daniel@0
|
3962 variable = variable || 'obj';
|
Daniel@0
|
3963 var index = 0;
|
Daniel@0
|
3964 var src = '\'';
|
Daniel@0
|
3965 var regex = template_re;
|
Daniel@0
|
3966
|
Daniel@0
|
3967 // Compile the template source, escaping string literals appropriately.
|
Daniel@0
|
3968 text.replace(regex, function(match, interpolate, offset) {
|
Daniel@0
|
3969 src += text
|
Daniel@0
|
3970 .slice(index, offset)
|
Daniel@0
|
3971 .replace(template_escaper, template_escapeChar);
|
Daniel@0
|
3972 index = offset + match.length;
|
Daniel@0
|
3973
|
Daniel@0
|
3974 if (interpolate) {
|
Daniel@0
|
3975 src += '\'\n+((__t=(' +
|
Daniel@0
|
3976 template_var(interpolate, variable, properties) +
|
Daniel@0
|
3977 '))==null?\'\':__t)+\n\'';
|
Daniel@0
|
3978 }
|
Daniel@0
|
3979
|
Daniel@0
|
3980 // Adobe VMs need the match returned to produce the correct offest.
|
Daniel@0
|
3981 return match;
|
Daniel@0
|
3982 });
|
Daniel@0
|
3983 return src + '\'';
|
Daniel@0
|
3984 }
|
Daniel@0
|
3985
|
Daniel@0
|
3986 function template_var(text, variable, properties) {
|
Daniel@0
|
3987 var filters = text.match(filter_re);
|
Daniel@0
|
3988 var prop = filters.shift().trim();
|
Daniel@0
|
3989 var stringCast = true;
|
Daniel@0
|
3990
|
Daniel@0
|
3991 function strcall(fn) {
|
Daniel@0
|
3992 fn = fn || '';
|
Daniel@0
|
3993 if (stringCast) {
|
Daniel@0
|
3994 stringCast = false;
|
Daniel@0
|
3995 src = 'String(' + src + ')' + fn;
|
Daniel@0
|
3996 } else {
|
Daniel@0
|
3997 src += fn;
|
Daniel@0
|
3998 }
|
Daniel@0
|
3999 return src;
|
Daniel@0
|
4000 }
|
Daniel@0
|
4001
|
Daniel@0
|
4002 function date() {
|
Daniel@0
|
4003 return '(typeof ' + src + '==="number"?new Date('+src+'):'+src+')';
|
Daniel@0
|
4004 }
|
Daniel@0
|
4005
|
Daniel@0
|
4006 function number_format(fmt, key) {
|
Daniel@0
|
4007 a = template_format(args[0], key, fmt);
|
Daniel@0
|
4008 stringCast = false;
|
Daniel@0
|
4009 src = 'this.formats['+a+']('+src+')';
|
Daniel@0
|
4010 }
|
Daniel@0
|
4011
|
Daniel@0
|
4012 function time_format(fmt, key) {
|
Daniel@0
|
4013 a = template_format(args[0], key, fmt);
|
Daniel@0
|
4014 stringCast = false;
|
Daniel@0
|
4015 src = 'this.formats['+a+']('+date()+')';
|
Daniel@0
|
4016 }
|
Daniel@0
|
4017
|
Daniel@0
|
4018 if (properties) properties[prop] = 1;
|
Daniel@0
|
4019 var src = template.property(variable, prop);
|
Daniel@0
|
4020
|
Daniel@0
|
4021 for (var i=0; i<filters.length; ++i) {
|
Daniel@0
|
4022 var f = filters[i], args = null, pidx, a, b;
|
Daniel@0
|
4023
|
Daniel@0
|
4024 if ((pidx=f.indexOf(':')) > 0) {
|
Daniel@0
|
4025 f = f.slice(0, pidx);
|
Daniel@0
|
4026 args = filters[i].slice(pidx+1)
|
Daniel@0
|
4027 .match(args_re)
|
Daniel@0
|
4028 .map(function(s) { return s.trim(); });
|
Daniel@0
|
4029 }
|
Daniel@0
|
4030 f = f.trim();
|
Daniel@0
|
4031
|
Daniel@0
|
4032 switch (f) {
|
Daniel@0
|
4033 case 'length':
|
Daniel@0
|
4034 strcall('.length');
|
Daniel@0
|
4035 break;
|
Daniel@0
|
4036 case 'lower':
|
Daniel@0
|
4037 strcall('.toLowerCase()');
|
Daniel@0
|
4038 break;
|
Daniel@0
|
4039 case 'upper':
|
Daniel@0
|
4040 strcall('.toUpperCase()');
|
Daniel@0
|
4041 break;
|
Daniel@0
|
4042 case 'lower-locale':
|
Daniel@0
|
4043 strcall('.toLocaleLowerCase()');
|
Daniel@0
|
4044 break;
|
Daniel@0
|
4045 case 'upper-locale':
|
Daniel@0
|
4046 strcall('.toLocaleUpperCase()');
|
Daniel@0
|
4047 break;
|
Daniel@0
|
4048 case 'trim':
|
Daniel@0
|
4049 strcall('.trim()');
|
Daniel@0
|
4050 break;
|
Daniel@0
|
4051 case 'left':
|
Daniel@0
|
4052 a = util.number(args[0]);
|
Daniel@0
|
4053 strcall('.slice(0,' + a + ')');
|
Daniel@0
|
4054 break;
|
Daniel@0
|
4055 case 'right':
|
Daniel@0
|
4056 a = util.number(args[0]);
|
Daniel@0
|
4057 strcall('.slice(-' + a +')');
|
Daniel@0
|
4058 break;
|
Daniel@0
|
4059 case 'mid':
|
Daniel@0
|
4060 a = util.number(args[0]);
|
Daniel@0
|
4061 b = a + util.number(args[1]);
|
Daniel@0
|
4062 strcall('.slice(+'+a+','+b+')');
|
Daniel@0
|
4063 break;
|
Daniel@0
|
4064 case 'slice':
|
Daniel@0
|
4065 a = util.number(args[0]);
|
Daniel@0
|
4066 strcall('.slice('+ a +
|
Daniel@0
|
4067 (args.length > 1 ? ',' + util.number(args[1]) : '') +
|
Daniel@0
|
4068 ')');
|
Daniel@0
|
4069 break;
|
Daniel@0
|
4070 case 'truncate':
|
Daniel@0
|
4071 a = util.number(args[0]);
|
Daniel@0
|
4072 b = args[1];
|
Daniel@0
|
4073 b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b;
|
Daniel@0
|
4074 src = 'this.truncate(' + strcall() + ',' + a + ',\'' + b + '\')';
|
Daniel@0
|
4075 break;
|
Daniel@0
|
4076 case 'pad':
|
Daniel@0
|
4077 a = util.number(args[0]);
|
Daniel@0
|
4078 b = args[1];
|
Daniel@0
|
4079 b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b;
|
Daniel@0
|
4080 src = 'this.pad(' + strcall() + ',' + a + ',\'' + b + '\')';
|
Daniel@0
|
4081 break;
|
Daniel@0
|
4082 case 'number':
|
Daniel@0
|
4083 number_format(format.number, 'number');
|
Daniel@0
|
4084 break;
|
Daniel@0
|
4085 case 'time':
|
Daniel@0
|
4086 time_format(format.time, 'time');
|
Daniel@0
|
4087 break;
|
Daniel@0
|
4088 case 'time-utc':
|
Daniel@0
|
4089 time_format(format.utc, 'time-utc');
|
Daniel@0
|
4090 break;
|
Daniel@0
|
4091 default:
|
Daniel@0
|
4092 throw Error('Unrecognized template filter: ' + f);
|
Daniel@0
|
4093 }
|
Daniel@0
|
4094 }
|
Daniel@0
|
4095
|
Daniel@0
|
4096 return src;
|
Daniel@0
|
4097 }
|
Daniel@0
|
4098
|
Daniel@0
|
4099 var template_re = /\{\{(.+?)\}\}|$/g,
|
Daniel@0
|
4100 filter_re = /(?:"[^"]*"|\'[^\']*\'|[^\|"]+|[^\|\']+)+/g,
|
Daniel@0
|
4101 args_re = /(?:"[^"]*"|\'[^\']*\'|[^,"]+|[^,\']+)+/g;
|
Daniel@0
|
4102
|
Daniel@0
|
4103 // Certain characters need to be escaped so that they can be put into a
|
Daniel@0
|
4104 // string literal.
|
Daniel@0
|
4105 var template_escapes = {
|
Daniel@0
|
4106 '\'': '\'',
|
Daniel@0
|
4107 '\\': '\\',
|
Daniel@0
|
4108 '\r': 'r',
|
Daniel@0
|
4109 '\n': 'n',
|
Daniel@0
|
4110 '\u2028': 'u2028',
|
Daniel@0
|
4111 '\u2029': 'u2029'
|
Daniel@0
|
4112 };
|
Daniel@0
|
4113
|
Daniel@0
|
4114 var template_escaper = /\\|'|\r|\n|\u2028|\u2029/g;
|
Daniel@0
|
4115
|
Daniel@0
|
4116 function template_escapeChar(match) {
|
Daniel@0
|
4117 return '\\' + template_escapes[match];
|
Daniel@0
|
4118 }
|
Daniel@0
|
4119
|
Daniel@0
|
4120 function template_format(pattern, key, fmt) {
|
Daniel@0
|
4121 if ((pattern[0] === '\'' && pattern[pattern.length-1] === '\'') ||
|
Daniel@0
|
4122 (pattern[0] === '"' && pattern[pattern.length-1] === '"')) {
|
Daniel@0
|
4123 pattern = pattern.slice(1, -1);
|
Daniel@0
|
4124 } else {
|
Daniel@0
|
4125 throw Error('Format pattern must be quoted: ' + pattern);
|
Daniel@0
|
4126 }
|
Daniel@0
|
4127 key = key + ':' + pattern;
|
Daniel@0
|
4128 if (!context.format_map[key]) {
|
Daniel@0
|
4129 var f = fmt(pattern);
|
Daniel@0
|
4130 var i = context.formats.length;
|
Daniel@0
|
4131 context.formats.push(f);
|
Daniel@0
|
4132 context.format_map[key] = i;
|
Daniel@0
|
4133 }
|
Daniel@0
|
4134 return context.format_map[key];
|
Daniel@0
|
4135 }
|
Daniel@0
|
4136
|
Daniel@0
|
4137 },{"./format":13,"./util":29}],28:[function(require,module,exports){
|
Daniel@0
|
4138 var d3_time = require('d3-time');
|
Daniel@0
|
4139
|
Daniel@0
|
4140 var tempDate = new Date(),
|
Daniel@0
|
4141 baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD
|
Daniel@0
|
4142 utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0);
|
Daniel@0
|
4143
|
Daniel@0
|
4144 function date(d) {
|
Daniel@0
|
4145 return (tempDate.setTime(+d), tempDate);
|
Daniel@0
|
4146 }
|
Daniel@0
|
4147
|
Daniel@0
|
4148 // create a time unit entry
|
Daniel@0
|
4149 function entry(type, date, unit, step, min, max) {
|
Daniel@0
|
4150 var e = {
|
Daniel@0
|
4151 type: type,
|
Daniel@0
|
4152 date: date,
|
Daniel@0
|
4153 unit: unit
|
Daniel@0
|
4154 };
|
Daniel@0
|
4155 if (step) {
|
Daniel@0
|
4156 e.step = step;
|
Daniel@0
|
4157 } else {
|
Daniel@0
|
4158 e.minstep = 1;
|
Daniel@0
|
4159 }
|
Daniel@0
|
4160 if (min != null) e.min = min;
|
Daniel@0
|
4161 if (max != null) e.max = max;
|
Daniel@0
|
4162 return e;
|
Daniel@0
|
4163 }
|
Daniel@0
|
4164
|
Daniel@0
|
4165 function create(type, unit, base, step, min, max) {
|
Daniel@0
|
4166 return entry(type,
|
Daniel@0
|
4167 function(d) { return unit.offset(base, d); },
|
Daniel@0
|
4168 function(d) { return unit.count(base, d); },
|
Daniel@0
|
4169 step, min, max);
|
Daniel@0
|
4170 }
|
Daniel@0
|
4171
|
Daniel@0
|
4172 var locale = [
|
Daniel@0
|
4173 create('second', d3_time.second, baseDate),
|
Daniel@0
|
4174 create('minute', d3_time.minute, baseDate),
|
Daniel@0
|
4175 create('hour', d3_time.hour, baseDate),
|
Daniel@0
|
4176 create('day', d3_time.day, baseDate, [1, 7]),
|
Daniel@0
|
4177 create('month', d3_time.month, baseDate, [1, 3, 6]),
|
Daniel@0
|
4178 create('year', d3_time.year, baseDate),
|
Daniel@0
|
4179
|
Daniel@0
|
4180 // periodic units
|
Daniel@0
|
4181 entry('seconds',
|
Daniel@0
|
4182 function(d) { return new Date(1970, 0, 1, 0, 0, d); },
|
Daniel@0
|
4183 function(d) { return date(d).getSeconds(); },
|
Daniel@0
|
4184 null, 0, 59
|
Daniel@0
|
4185 ),
|
Daniel@0
|
4186 entry('minutes',
|
Daniel@0
|
4187 function(d) { return new Date(1970, 0, 1, 0, d); },
|
Daniel@0
|
4188 function(d) { return date(d).getMinutes(); },
|
Daniel@0
|
4189 null, 0, 59
|
Daniel@0
|
4190 ),
|
Daniel@0
|
4191 entry('hours',
|
Daniel@0
|
4192 function(d) { return new Date(1970, 0, 1, d); },
|
Daniel@0
|
4193 function(d) { return date(d).getHours(); },
|
Daniel@0
|
4194 null, 0, 23
|
Daniel@0
|
4195 ),
|
Daniel@0
|
4196 entry('weekdays',
|
Daniel@0
|
4197 function(d) { return new Date(1970, 0, 4+d); },
|
Daniel@0
|
4198 function(d) { return date(d).getDay(); },
|
Daniel@0
|
4199 [1], 0, 6
|
Daniel@0
|
4200 ),
|
Daniel@0
|
4201 entry('dates',
|
Daniel@0
|
4202 function(d) { return new Date(1970, 0, d); },
|
Daniel@0
|
4203 function(d) { return date(d).getDate(); },
|
Daniel@0
|
4204 [1], 1, 31
|
Daniel@0
|
4205 ),
|
Daniel@0
|
4206 entry('months',
|
Daniel@0
|
4207 function(d) { return new Date(1970, d % 12, 1); },
|
Daniel@0
|
4208 function(d) { return date(d).getMonth(); },
|
Daniel@0
|
4209 [1], 0, 11
|
Daniel@0
|
4210 )
|
Daniel@0
|
4211 ];
|
Daniel@0
|
4212
|
Daniel@0
|
4213 var utc = [
|
Daniel@0
|
4214 create('second', d3_time.utcSecond, utcBaseDate),
|
Daniel@0
|
4215 create('minute', d3_time.utcMinute, utcBaseDate),
|
Daniel@0
|
4216 create('hour', d3_time.utcHour, utcBaseDate),
|
Daniel@0
|
4217 create('day', d3_time.utcDay, utcBaseDate, [1, 7]),
|
Daniel@0
|
4218 create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]),
|
Daniel@0
|
4219 create('year', d3_time.utcYear, utcBaseDate),
|
Daniel@0
|
4220
|
Daniel@0
|
4221 // periodic units
|
Daniel@0
|
4222 entry('seconds',
|
Daniel@0
|
4223 function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); },
|
Daniel@0
|
4224 function(d) { return date(d).getUTCSeconds(); },
|
Daniel@0
|
4225 null, 0, 59
|
Daniel@0
|
4226 ),
|
Daniel@0
|
4227 entry('minutes',
|
Daniel@0
|
4228 function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); },
|
Daniel@0
|
4229 function(d) { return date(d).getUTCMinutes(); },
|
Daniel@0
|
4230 null, 0, 59
|
Daniel@0
|
4231 ),
|
Daniel@0
|
4232 entry('hours',
|
Daniel@0
|
4233 function(d) { return new Date(Date.UTC(1970, 0, 1, d)); },
|
Daniel@0
|
4234 function(d) { return date(d).getUTCHours(); },
|
Daniel@0
|
4235 null, 0, 23
|
Daniel@0
|
4236 ),
|
Daniel@0
|
4237 entry('weekdays',
|
Daniel@0
|
4238 function(d) { return new Date(Date.UTC(1970, 0, 4+d)); },
|
Daniel@0
|
4239 function(d) { return date(d).getUTCDay(); },
|
Daniel@0
|
4240 [1], 0, 6
|
Daniel@0
|
4241 ),
|
Daniel@0
|
4242 entry('dates',
|
Daniel@0
|
4243 function(d) { return new Date(Date.UTC(1970, 0, d)); },
|
Daniel@0
|
4244 function(d) { return date(d).getUTCDate(); },
|
Daniel@0
|
4245 [1], 1, 31
|
Daniel@0
|
4246 ),
|
Daniel@0
|
4247 entry('months',
|
Daniel@0
|
4248 function(d) { return new Date(Date.UTC(1970, d % 12, 1)); },
|
Daniel@0
|
4249 function(d) { return date(d).getUTCMonth(); },
|
Daniel@0
|
4250 [1], 0, 11
|
Daniel@0
|
4251 )
|
Daniel@0
|
4252 ];
|
Daniel@0
|
4253
|
Daniel@0
|
4254 var STEPS = [
|
Daniel@0
|
4255 [31536e6, 5], // 1-year
|
Daniel@0
|
4256 [7776e6, 4], // 3-month
|
Daniel@0
|
4257 [2592e6, 4], // 1-month
|
Daniel@0
|
4258 [12096e5, 3], // 2-week
|
Daniel@0
|
4259 [6048e5, 3], // 1-week
|
Daniel@0
|
4260 [1728e5, 3], // 2-day
|
Daniel@0
|
4261 [864e5, 3], // 1-day
|
Daniel@0
|
4262 [432e5, 2], // 12-hour
|
Daniel@0
|
4263 [216e5, 2], // 6-hour
|
Daniel@0
|
4264 [108e5, 2], // 3-hour
|
Daniel@0
|
4265 [36e5, 2], // 1-hour
|
Daniel@0
|
4266 [18e5, 1], // 30-minute
|
Daniel@0
|
4267 [9e5, 1], // 15-minute
|
Daniel@0
|
4268 [3e5, 1], // 5-minute
|
Daniel@0
|
4269 [6e4, 1], // 1-minute
|
Daniel@0
|
4270 [3e4, 0], // 30-second
|
Daniel@0
|
4271 [15e3, 0], // 15-second
|
Daniel@0
|
4272 [5e3, 0], // 5-second
|
Daniel@0
|
4273 [1e3, 0] // 1-second
|
Daniel@0
|
4274 ];
|
Daniel@0
|
4275
|
Daniel@0
|
4276 function find(units, span, minb, maxb) {
|
Daniel@0
|
4277 var step = STEPS[0], i, n, bins;
|
Daniel@0
|
4278
|
Daniel@0
|
4279 for (i=1, n=STEPS.length; i<n; ++i) {
|
Daniel@0
|
4280 step = STEPS[i];
|
Daniel@0
|
4281 if (span > step[0]) {
|
Daniel@0
|
4282 bins = span / step[0];
|
Daniel@0
|
4283 if (bins > maxb) {
|
Daniel@0
|
4284 return units[STEPS[i-1][1]];
|
Daniel@0
|
4285 }
|
Daniel@0
|
4286 if (bins >= minb) {
|
Daniel@0
|
4287 return units[step[1]];
|
Daniel@0
|
4288 }
|
Daniel@0
|
4289 }
|
Daniel@0
|
4290 }
|
Daniel@0
|
4291 return units[STEPS[n-1][1]];
|
Daniel@0
|
4292 }
|
Daniel@0
|
4293
|
Daniel@0
|
4294 function toUnitMap(units) {
|
Daniel@0
|
4295 var map = {}, i, n;
|
Daniel@0
|
4296 for (i=0, n=units.length; i<n; ++i) {
|
Daniel@0
|
4297 map[units[i].type] = units[i];
|
Daniel@0
|
4298 }
|
Daniel@0
|
4299 map.find = function(span, minb, maxb) {
|
Daniel@0
|
4300 return find(units, span, minb, maxb);
|
Daniel@0
|
4301 };
|
Daniel@0
|
4302 return map;
|
Daniel@0
|
4303 }
|
Daniel@0
|
4304
|
Daniel@0
|
4305 module.exports = toUnitMap(locale);
|
Daniel@0
|
4306 module.exports.utc = toUnitMap(utc);
|
Daniel@0
|
4307
|
Daniel@0
|
4308 },{"d3-time":6}],29:[function(require,module,exports){
|
Daniel@0
|
4309 var buffer = require('buffer'),
|
Daniel@0
|
4310 time = require('./time'),
|
Daniel@0
|
4311 utc = time.utc;
|
Daniel@0
|
4312
|
Daniel@0
|
4313 var u = module.exports = {};
|
Daniel@0
|
4314
|
Daniel@0
|
4315 // utility functions
|
Daniel@0
|
4316
|
Daniel@0
|
4317 var FNAME = '__name__';
|
Daniel@0
|
4318
|
Daniel@0
|
4319 u.namedfunc = function(name, f) { return (f[FNAME] = name, f); };
|
Daniel@0
|
4320
|
Daniel@0
|
4321 u.name = function(f) { return f==null ? null : f[FNAME]; };
|
Daniel@0
|
4322
|
Daniel@0
|
4323 u.identity = function(x) { return x; };
|
Daniel@0
|
4324
|
Daniel@0
|
4325 u.true = u.namedfunc('true', function() { return true; });
|
Daniel@0
|
4326
|
Daniel@0
|
4327 u.false = u.namedfunc('false', function() { return false; });
|
Daniel@0
|
4328
|
Daniel@0
|
4329 u.duplicate = function(obj) {
|
Daniel@0
|
4330 return JSON.parse(JSON.stringify(obj));
|
Daniel@0
|
4331 };
|
Daniel@0
|
4332
|
Daniel@0
|
4333 u.equal = function(a, b) {
|
Daniel@0
|
4334 return JSON.stringify(a) === JSON.stringify(b);
|
Daniel@0
|
4335 };
|
Daniel@0
|
4336
|
Daniel@0
|
4337 u.extend = function(obj) {
|
Daniel@0
|
4338 for (var x, name, i=1, len=arguments.length; i<len; ++i) {
|
Daniel@0
|
4339 x = arguments[i];
|
Daniel@0
|
4340 for (name in x) { obj[name] = x[name]; }
|
Daniel@0
|
4341 }
|
Daniel@0
|
4342 return obj;
|
Daniel@0
|
4343 };
|
Daniel@0
|
4344
|
Daniel@0
|
4345 u.length = function(x) {
|
Daniel@0
|
4346 return x != null && x.length != null ? x.length : null;
|
Daniel@0
|
4347 };
|
Daniel@0
|
4348
|
Daniel@0
|
4349 u.keys = function(x) {
|
Daniel@0
|
4350 var keys = [], k;
|
Daniel@0
|
4351 for (k in x) keys.push(k);
|
Daniel@0
|
4352 return keys;
|
Daniel@0
|
4353 };
|
Daniel@0
|
4354
|
Daniel@0
|
4355 u.vals = function(x) {
|
Daniel@0
|
4356 var vals = [], k;
|
Daniel@0
|
4357 for (k in x) vals.push(x[k]);
|
Daniel@0
|
4358 return vals;
|
Daniel@0
|
4359 };
|
Daniel@0
|
4360
|
Daniel@0
|
4361 u.toMap = function(list, f) {
|
Daniel@0
|
4362 return (f = u.$(f)) ?
|
Daniel@0
|
4363 list.reduce(function(obj, x) { return (obj[f(x)] = 1, obj); }, {}) :
|
Daniel@0
|
4364 list.reduce(function(obj, x) { return (obj[x] = 1, obj); }, {});
|
Daniel@0
|
4365 };
|
Daniel@0
|
4366
|
Daniel@0
|
4367 u.keystr = function(values) {
|
Daniel@0
|
4368 // use to ensure consistent key generation across modules
|
Daniel@0
|
4369 var n = values.length;
|
Daniel@0
|
4370 if (!n) return '';
|
Daniel@0
|
4371 for (var s=String(values[0]), i=1; i<n; ++i) {
|
Daniel@0
|
4372 s += '|' + String(values[i]);
|
Daniel@0
|
4373 }
|
Daniel@0
|
4374 return s;
|
Daniel@0
|
4375 };
|
Daniel@0
|
4376
|
Daniel@0
|
4377 // type checking functions
|
Daniel@0
|
4378
|
Daniel@0
|
4379 var toString = Object.prototype.toString;
|
Daniel@0
|
4380
|
Daniel@0
|
4381 u.isObject = function(obj) {
|
Daniel@0
|
4382 return obj === Object(obj);
|
Daniel@0
|
4383 };
|
Daniel@0
|
4384
|
Daniel@0
|
4385 u.isFunction = function(obj) {
|
Daniel@0
|
4386 return toString.call(obj) === '[object Function]';
|
Daniel@0
|
4387 };
|
Daniel@0
|
4388
|
Daniel@0
|
4389 u.isString = function(obj) {
|
Daniel@0
|
4390 return typeof value === 'string' || toString.call(obj) === '[object String]';
|
Daniel@0
|
4391 };
|
Daniel@0
|
4392
|
Daniel@0
|
4393 u.isArray = Array.isArray || function(obj) {
|
Daniel@0
|
4394 return toString.call(obj) === '[object Array]';
|
Daniel@0
|
4395 };
|
Daniel@0
|
4396
|
Daniel@0
|
4397 u.isNumber = function(obj) {
|
Daniel@0
|
4398 return typeof obj === 'number' || toString.call(obj) === '[object Number]';
|
Daniel@0
|
4399 };
|
Daniel@0
|
4400
|
Daniel@0
|
4401 u.isBoolean = function(obj) {
|
Daniel@0
|
4402 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
Daniel@0
|
4403 };
|
Daniel@0
|
4404
|
Daniel@0
|
4405 u.isDate = function(obj) {
|
Daniel@0
|
4406 return toString.call(obj) === '[object Date]';
|
Daniel@0
|
4407 };
|
Daniel@0
|
4408
|
Daniel@0
|
4409 u.isValid = function(obj) {
|
Daniel@0
|
4410 return obj != null && obj === obj;
|
Daniel@0
|
4411 };
|
Daniel@0
|
4412
|
Daniel@0
|
4413 u.isBuffer = (buffer.Buffer && buffer.Buffer.isBuffer) || u.false;
|
Daniel@0
|
4414
|
Daniel@0
|
4415 // type coercion functions
|
Daniel@0
|
4416
|
Daniel@0
|
4417 u.number = function(s) {
|
Daniel@0
|
4418 return s == null || s === '' ? null : +s;
|
Daniel@0
|
4419 };
|
Daniel@0
|
4420
|
Daniel@0
|
4421 u.boolean = function(s) {
|
Daniel@0
|
4422 return s == null || s === '' ? null : s==='false' ? false : !!s;
|
Daniel@0
|
4423 };
|
Daniel@0
|
4424
|
Daniel@0
|
4425 u.date = function(s) {
|
Daniel@0
|
4426 return s == null || s === '' ? null : Date.parse(s);
|
Daniel@0
|
4427 };
|
Daniel@0
|
4428
|
Daniel@0
|
4429 u.array = function(x) {
|
Daniel@0
|
4430 return x != null ? (u.isArray(x) ? x : [x]) : [];
|
Daniel@0
|
4431 };
|
Daniel@0
|
4432
|
Daniel@0
|
4433 u.str = function(x) {
|
Daniel@0
|
4434 return u.isArray(x) ? '[' + x.map(u.str) + ']'
|
Daniel@0
|
4435 : u.isObject(x) ? JSON.stringify(x)
|
Daniel@0
|
4436 : u.isString(x) ? ('\''+util_escape_str(x)+'\'') : x;
|
Daniel@0
|
4437 };
|
Daniel@0
|
4438
|
Daniel@0
|
4439 var escape_str_re = /(^|[^\\])'/g;
|
Daniel@0
|
4440
|
Daniel@0
|
4441 function util_escape_str(x) {
|
Daniel@0
|
4442 return x.replace(escape_str_re, '$1\\\'');
|
Daniel@0
|
4443 }
|
Daniel@0
|
4444
|
Daniel@0
|
4445 // data access functions
|
Daniel@0
|
4446
|
Daniel@0
|
4447 var field_re = /\[(.*?)\]|[^.\[]+/g;
|
Daniel@0
|
4448
|
Daniel@0
|
4449 u.field = function(f) {
|
Daniel@0
|
4450 return String(f).match(field_re).map(function(d) {
|
Daniel@0
|
4451 return d[0] !== '[' ? d :
|
Daniel@0
|
4452 d[1] !== "'" && d[1] !== '"' ? d.slice(1, -1) :
|
Daniel@0
|
4453 d.slice(2, -2).replace(/\\(["'])/g, '$1');
|
Daniel@0
|
4454 });
|
Daniel@0
|
4455 };
|
Daniel@0
|
4456
|
Daniel@0
|
4457 u.accessor = function(f) {
|
Daniel@0
|
4458 var s;
|
Daniel@0
|
4459 return f==null || u.isFunction(f) ? f :
|
Daniel@0
|
4460 u.namedfunc(f, (s = u.field(f)).length > 1 ?
|
Daniel@0
|
4461 function(x) { return s.reduce(function(x,f) { return x[f]; }, x); } :
|
Daniel@0
|
4462 function(x) { return x[f]; }
|
Daniel@0
|
4463 );
|
Daniel@0
|
4464 };
|
Daniel@0
|
4465
|
Daniel@0
|
4466 // short-cut for accessor
|
Daniel@0
|
4467 u.$ = u.accessor;
|
Daniel@0
|
4468
|
Daniel@0
|
4469 u.mutator = function(f) {
|
Daniel@0
|
4470 var s;
|
Daniel@0
|
4471 return u.isString(f) && (s=u.field(f)).length > 1 ?
|
Daniel@0
|
4472 function(x, v) {
|
Daniel@0
|
4473 for (var i=0; i<s.length-1; ++i) x = x[s[i]];
|
Daniel@0
|
4474 x[s[i]] = v;
|
Daniel@0
|
4475 } :
|
Daniel@0
|
4476 function(x, v) { x[f] = v; };
|
Daniel@0
|
4477 };
|
Daniel@0
|
4478
|
Daniel@0
|
4479
|
Daniel@0
|
4480 u.$func = function(name, op) {
|
Daniel@0
|
4481 return function(f) {
|
Daniel@0
|
4482 f = u.$(f) || u.identity;
|
Daniel@0
|
4483 var n = name + (u.name(f) ? '_'+u.name(f) : '');
|
Daniel@0
|
4484 return u.namedfunc(n, function(d) { return op(f(d)); });
|
Daniel@0
|
4485 };
|
Daniel@0
|
4486 };
|
Daniel@0
|
4487
|
Daniel@0
|
4488 u.$valid = u.$func('valid', u.isValid);
|
Daniel@0
|
4489 u.$length = u.$func('length', u.length);
|
Daniel@0
|
4490
|
Daniel@0
|
4491 u.$in = function(f, values) {
|
Daniel@0
|
4492 f = u.$(f);
|
Daniel@0
|
4493 var map = u.isArray(values) ? u.toMap(values) : values;
|
Daniel@0
|
4494 return function(d) { return !!map[f(d)]; };
|
Daniel@0
|
4495 };
|
Daniel@0
|
4496
|
Daniel@0
|
4497 u.$year = u.$func('year', time.year.unit);
|
Daniel@0
|
4498 u.$month = u.$func('month', time.months.unit);
|
Daniel@0
|
4499 u.$date = u.$func('date', time.dates.unit);
|
Daniel@0
|
4500 u.$day = u.$func('day', time.weekdays.unit);
|
Daniel@0
|
4501 u.$hour = u.$func('hour', time.hours.unit);
|
Daniel@0
|
4502 u.$minute = u.$func('minute', time.minutes.unit);
|
Daniel@0
|
4503 u.$second = u.$func('second', time.seconds.unit);
|
Daniel@0
|
4504
|
Daniel@0
|
4505 u.$utcYear = u.$func('utcYear', utc.year.unit);
|
Daniel@0
|
4506 u.$utcMonth = u.$func('utcMonth', utc.months.unit);
|
Daniel@0
|
4507 u.$utcDate = u.$func('utcDate', utc.dates.unit);
|
Daniel@0
|
4508 u.$utcDay = u.$func('utcDay', utc.weekdays.unit);
|
Daniel@0
|
4509 u.$utcHour = u.$func('utcHour', utc.hours.unit);
|
Daniel@0
|
4510 u.$utcMinute = u.$func('utcMinute', utc.minutes.unit);
|
Daniel@0
|
4511 u.$utcSecond = u.$func('utcSecond', utc.seconds.unit);
|
Daniel@0
|
4512
|
Daniel@0
|
4513 // comparison / sorting functions
|
Daniel@0
|
4514
|
Daniel@0
|
4515 u.comparator = function(sort) {
|
Daniel@0
|
4516 var sign = [];
|
Daniel@0
|
4517 if (sort === undefined) sort = [];
|
Daniel@0
|
4518 sort = u.array(sort).map(function(f) {
|
Daniel@0
|
4519 var s = 1;
|
Daniel@0
|
4520 if (f[0] === '-') { s = -1; f = f.slice(1); }
|
Daniel@0
|
4521 else if (f[0] === '+') { s = +1; f = f.slice(1); }
|
Daniel@0
|
4522 sign.push(s);
|
Daniel@0
|
4523 return u.accessor(f);
|
Daniel@0
|
4524 });
|
Daniel@0
|
4525 return function(a,b) {
|
Daniel@0
|
4526 var i, n, f, x, y;
|
Daniel@0
|
4527 for (i=0, n=sort.length; i<n; ++i) {
|
Daniel@0
|
4528 f = sort[i]; x = f(a); y = f(b);
|
Daniel@0
|
4529 if (x < y) return -1 * sign[i];
|
Daniel@0
|
4530 if (x > y) return sign[i];
|
Daniel@0
|
4531 }
|
Daniel@0
|
4532 return 0;
|
Daniel@0
|
4533 };
|
Daniel@0
|
4534 };
|
Daniel@0
|
4535
|
Daniel@0
|
4536 u.cmp = function(a, b) {
|
Daniel@0
|
4537 if (a < b) {
|
Daniel@0
|
4538 return -1;
|
Daniel@0
|
4539 } else if (a > b) {
|
Daniel@0
|
4540 return 1;
|
Daniel@0
|
4541 } else if (a >= b) {
|
Daniel@0
|
4542 return 0;
|
Daniel@0
|
4543 } else if (a === null) {
|
Daniel@0
|
4544 return -1;
|
Daniel@0
|
4545 } else if (b === null) {
|
Daniel@0
|
4546 return 1;
|
Daniel@0
|
4547 }
|
Daniel@0
|
4548 return NaN;
|
Daniel@0
|
4549 };
|
Daniel@0
|
4550
|
Daniel@0
|
4551 u.numcmp = function(a, b) { return a - b; };
|
Daniel@0
|
4552
|
Daniel@0
|
4553 u.stablesort = function(array, sortBy, keyFn) {
|
Daniel@0
|
4554 var indices = array.reduce(function(idx, v, i) {
|
Daniel@0
|
4555 return (idx[keyFn(v)] = i, idx);
|
Daniel@0
|
4556 }, {});
|
Daniel@0
|
4557
|
Daniel@0
|
4558 array.sort(function(a, b) {
|
Daniel@0
|
4559 var sa = sortBy(a),
|
Daniel@0
|
4560 sb = sortBy(b);
|
Daniel@0
|
4561 return sa < sb ? -1 : sa > sb ? 1
|
Daniel@0
|
4562 : (indices[keyFn(a)] - indices[keyFn(b)]);
|
Daniel@0
|
4563 });
|
Daniel@0
|
4564
|
Daniel@0
|
4565 return array;
|
Daniel@0
|
4566 };
|
Daniel@0
|
4567
|
Daniel@0
|
4568
|
Daniel@0
|
4569 // string functions
|
Daniel@0
|
4570
|
Daniel@0
|
4571 u.pad = function(s, length, pos, padchar) {
|
Daniel@0
|
4572 padchar = padchar || " ";
|
Daniel@0
|
4573 var d = length - s.length;
|
Daniel@0
|
4574 if (d <= 0) return s;
|
Daniel@0
|
4575 switch (pos) {
|
Daniel@0
|
4576 case 'left':
|
Daniel@0
|
4577 return strrep(d, padchar) + s;
|
Daniel@0
|
4578 case 'middle':
|
Daniel@0
|
4579 case 'center':
|
Daniel@0
|
4580 return strrep(Math.floor(d/2), padchar) +
|
Daniel@0
|
4581 s + strrep(Math.ceil(d/2), padchar);
|
Daniel@0
|
4582 default:
|
Daniel@0
|
4583 return s + strrep(d, padchar);
|
Daniel@0
|
4584 }
|
Daniel@0
|
4585 };
|
Daniel@0
|
4586
|
Daniel@0
|
4587 function strrep(n, str) {
|
Daniel@0
|
4588 var s = "", i;
|
Daniel@0
|
4589 for (i=0; i<n; ++i) s += str;
|
Daniel@0
|
4590 return s;
|
Daniel@0
|
4591 }
|
Daniel@0
|
4592
|
Daniel@0
|
4593 u.truncate = function(s, length, pos, word, ellipsis) {
|
Daniel@0
|
4594 var len = s.length;
|
Daniel@0
|
4595 if (len <= length) return s;
|
Daniel@0
|
4596 ellipsis = ellipsis !== undefined ? String(ellipsis) : '\u2026';
|
Daniel@0
|
4597 var l = Math.max(0, length - ellipsis.length);
|
Daniel@0
|
4598
|
Daniel@0
|
4599 switch (pos) {
|
Daniel@0
|
4600 case 'left':
|
Daniel@0
|
4601 return ellipsis + (word ? truncateOnWord(s,l,1) : s.slice(len-l));
|
Daniel@0
|
4602 case 'middle':
|
Daniel@0
|
4603 case 'center':
|
Daniel@0
|
4604 var l1 = Math.ceil(l/2), l2 = Math.floor(l/2);
|
Daniel@0
|
4605 return (word ? truncateOnWord(s,l1) : s.slice(0,l1)) +
|
Daniel@0
|
4606 ellipsis + (word ? truncateOnWord(s,l2,1) : s.slice(len-l2));
|
Daniel@0
|
4607 default:
|
Daniel@0
|
4608 return (word ? truncateOnWord(s,l) : s.slice(0,l)) + ellipsis;
|
Daniel@0
|
4609 }
|
Daniel@0
|
4610 };
|
Daniel@0
|
4611
|
Daniel@0
|
4612 function truncateOnWord(s, len, rev) {
|
Daniel@0
|
4613 var cnt = 0, tok = s.split(truncate_word_re);
|
Daniel@0
|
4614 if (rev) {
|
Daniel@0
|
4615 s = (tok = tok.reverse())
|
Daniel@0
|
4616 .filter(function(w) { cnt += w.length; return cnt <= len; })
|
Daniel@0
|
4617 .reverse();
|
Daniel@0
|
4618 } else {
|
Daniel@0
|
4619 s = tok.filter(function(w) { cnt += w.length; return cnt <= len; });
|
Daniel@0
|
4620 }
|
Daniel@0
|
4621 return s.length ? s.join('').trim() : tok[0].slice(0, len);
|
Daniel@0
|
4622 }
|
Daniel@0
|
4623
|
Daniel@0
|
4624 var truncate_word_re = /([\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF])/;
|
Daniel@0
|
4625
|
Daniel@0
|
4626 },{"./time":28,"buffer":2}],30:[function(require,module,exports){
|
Daniel@0
|
4627 var DEPS = require('./Dependencies').ALL;
|
Daniel@0
|
4628
|
Daniel@0
|
4629 function create(cs, reflow) {
|
Daniel@0
|
4630 var out = {};
|
Daniel@0
|
4631 copy(cs, out);
|
Daniel@0
|
4632
|
Daniel@0
|
4633 out.add = [];
|
Daniel@0
|
4634 out.mod = [];
|
Daniel@0
|
4635 out.rem = [];
|
Daniel@0
|
4636
|
Daniel@0
|
4637 out.reflow = reflow;
|
Daniel@0
|
4638
|
Daniel@0
|
4639 return out;
|
Daniel@0
|
4640 }
|
Daniel@0
|
4641
|
Daniel@0
|
4642 function copy(a, b) {
|
Daniel@0
|
4643 b.stamp = a ? a.stamp : 0;
|
Daniel@0
|
4644 b.sort = a ? a.sort : null;
|
Daniel@0
|
4645 b.facet = a ? a.facet : null;
|
Daniel@0
|
4646 b.trans = a ? a.trans : null;
|
Daniel@0
|
4647 b.dirty = a ? a.dirty : [];
|
Daniel@0
|
4648 b.request = a ? a.request : null;
|
Daniel@0
|
4649 for (var d, i=0, n=DEPS.length; i<n; ++i) {
|
Daniel@0
|
4650 b[d=DEPS[i]] = a ? a[d] : {};
|
Daniel@0
|
4651 }
|
Daniel@0
|
4652 }
|
Daniel@0
|
4653
|
Daniel@0
|
4654 module.exports = {
|
Daniel@0
|
4655 create: create,
|
Daniel@0
|
4656 copy: copy
|
Daniel@0
|
4657 };
|
Daniel@0
|
4658 },{"./Dependencies":33}],31:[function(require,module,exports){
|
Daniel@0
|
4659 var log = require('vega-logging'),
|
Daniel@0
|
4660 Tuple = require('./Tuple'),
|
Daniel@0
|
4661 Base = require('./Node').prototype;
|
Daniel@0
|
4662
|
Daniel@0
|
4663 function Collector(graph) {
|
Daniel@0
|
4664 Base.init.call(this, graph);
|
Daniel@0
|
4665 this._data = [];
|
Daniel@0
|
4666 this.router(true).collector(true);
|
Daniel@0
|
4667 }
|
Daniel@0
|
4668
|
Daniel@0
|
4669 var prototype = (Collector.prototype = Object.create(Base));
|
Daniel@0
|
4670 prototype.constructor = Collector;
|
Daniel@0
|
4671
|
Daniel@0
|
4672 prototype.data = function() {
|
Daniel@0
|
4673 return this._data;
|
Daniel@0
|
4674 };
|
Daniel@0
|
4675
|
Daniel@0
|
4676 prototype.evaluate = function(input) {
|
Daniel@0
|
4677 log.debug(input, ["collecting"]);
|
Daniel@0
|
4678
|
Daniel@0
|
4679 if (input.rem.length) {
|
Daniel@0
|
4680 this._data = Tuple.idFilter(this._data, input.rem);
|
Daniel@0
|
4681 }
|
Daniel@0
|
4682
|
Daniel@0
|
4683 if (input.add.length) {
|
Daniel@0
|
4684 this._data = this._data.length ? this._data.concat(input.add) : input.add;
|
Daniel@0
|
4685 }
|
Daniel@0
|
4686
|
Daniel@0
|
4687 if (input.sort) {
|
Daniel@0
|
4688 this._data.sort(input.sort);
|
Daniel@0
|
4689 }
|
Daniel@0
|
4690
|
Daniel@0
|
4691 if (input.reflow) {
|
Daniel@0
|
4692 input.mod = input.mod.concat(
|
Daniel@0
|
4693 Tuple.idFilter(this._data, input.add, input.mod, input.rem));
|
Daniel@0
|
4694 input.reflow = false;
|
Daniel@0
|
4695 }
|
Daniel@0
|
4696
|
Daniel@0
|
4697 return input;
|
Daniel@0
|
4698 };
|
Daniel@0
|
4699
|
Daniel@0
|
4700 module.exports = Collector;
|
Daniel@0
|
4701 },{"./Node":36,"./Tuple":38,"vega-logging":45}],32:[function(require,module,exports){
|
Daniel@0
|
4702 var log = require('vega-logging'),
|
Daniel@0
|
4703 ChangeSet = require('./ChangeSet'),
|
Daniel@0
|
4704 Collector = require('./Collector'),
|
Daniel@0
|
4705 Tuple = require('./Tuple'),
|
Daniel@0
|
4706 Node = require('./Node'); // jshint ignore:line
|
Daniel@0
|
4707
|
Daniel@0
|
4708 function DataSource(graph, name, facet) {
|
Daniel@0
|
4709 this._graph = graph;
|
Daniel@0
|
4710 this._name = name;
|
Daniel@0
|
4711 this._data = [];
|
Daniel@0
|
4712 this._source = null;
|
Daniel@0
|
4713 this._facet = facet;
|
Daniel@0
|
4714 this._input = ChangeSet.create();
|
Daniel@0
|
4715 this._output = null; // Output changeset
|
Daniel@0
|
4716
|
Daniel@0
|
4717 this._inputNode = null;
|
Daniel@0
|
4718 this._outputNode = null;
|
Daniel@0
|
4719 this._pipeline = null; // Pipeline of transformations.
|
Daniel@0
|
4720 this._collector = null; // Collector to materialize output of pipeline.
|
Daniel@0
|
4721 this._mutates = false; // Does any pipeline operator mutate tuples?
|
Daniel@0
|
4722 }
|
Daniel@0
|
4723
|
Daniel@0
|
4724 var prototype = DataSource.prototype;
|
Daniel@0
|
4725
|
Daniel@0
|
4726 prototype.name = function(name) {
|
Daniel@0
|
4727 if (!arguments.length) return this._name;
|
Daniel@0
|
4728 return (this._name = name, this);
|
Daniel@0
|
4729 };
|
Daniel@0
|
4730
|
Daniel@0
|
4731 prototype.source = function(src) {
|
Daniel@0
|
4732 if (!arguments.length) return this._source;
|
Daniel@0
|
4733 return (this._source = this._graph.data(src));
|
Daniel@0
|
4734 };
|
Daniel@0
|
4735
|
Daniel@0
|
4736 prototype.insert = function(tuples) {
|
Daniel@0
|
4737 this._input.add = this._input.add.concat(tuples.map(Tuple.ingest));
|
Daniel@0
|
4738 return this;
|
Daniel@0
|
4739 };
|
Daniel@0
|
4740
|
Daniel@0
|
4741 prototype.remove = function(where) {
|
Daniel@0
|
4742 var remove = this._data.filter(where);
|
Daniel@0
|
4743 this._input.rem = this._input.rem.concat(remove);
|
Daniel@0
|
4744 return this;
|
Daniel@0
|
4745 };
|
Daniel@0
|
4746
|
Daniel@0
|
4747 prototype.update = function(where, field, func) {
|
Daniel@0
|
4748 var mod = this._input.mod,
|
Daniel@0
|
4749 ids = Tuple.idMap(mod);
|
Daniel@0
|
4750
|
Daniel@0
|
4751 this._input.fields[field] = 1;
|
Daniel@0
|
4752
|
Daniel@0
|
4753 this._data.filter(where).forEach(function(x) {
|
Daniel@0
|
4754 var prev = x[field],
|
Daniel@0
|
4755 next = func(x);
|
Daniel@0
|
4756 if (prev !== next) {
|
Daniel@0
|
4757 Tuple.set(x, field, next);
|
Daniel@0
|
4758 if (ids[x._id] !== 1) {
|
Daniel@0
|
4759 mod.push(x);
|
Daniel@0
|
4760 ids[x._id] = 1;
|
Daniel@0
|
4761 }
|
Daniel@0
|
4762 }
|
Daniel@0
|
4763 });
|
Daniel@0
|
4764
|
Daniel@0
|
4765 return this;
|
Daniel@0
|
4766 };
|
Daniel@0
|
4767
|
Daniel@0
|
4768 prototype.values = function(data) {
|
Daniel@0
|
4769 if (!arguments.length) return this._collector.data();
|
Daniel@0
|
4770
|
Daniel@0
|
4771 // Replace backing data
|
Daniel@0
|
4772 this._input.rem = this._data.slice();
|
Daniel@0
|
4773 if (data) { this.insert(data); }
|
Daniel@0
|
4774 return this;
|
Daniel@0
|
4775 };
|
Daniel@0
|
4776
|
Daniel@0
|
4777 prototype.mutates = function(m) {
|
Daniel@0
|
4778 if (!arguments.length) return this._mutates;
|
Daniel@0
|
4779 this._mutates = this._mutates || m;
|
Daniel@0
|
4780 return this;
|
Daniel@0
|
4781 };
|
Daniel@0
|
4782
|
Daniel@0
|
4783 prototype.last = function() {
|
Daniel@0
|
4784 return this._output;
|
Daniel@0
|
4785 };
|
Daniel@0
|
4786
|
Daniel@0
|
4787 prototype.fire = function(input) {
|
Daniel@0
|
4788 if (input) this._input = input;
|
Daniel@0
|
4789 this._graph.propagate(this._input, this._pipeline[0]);
|
Daniel@0
|
4790 return this;
|
Daniel@0
|
4791 };
|
Daniel@0
|
4792
|
Daniel@0
|
4793 prototype.pipeline = function(pipeline) {
|
Daniel@0
|
4794 if (!arguments.length) return this._pipeline;
|
Daniel@0
|
4795
|
Daniel@0
|
4796 var graph = this._graph,
|
Daniel@0
|
4797 status;
|
Daniel@0
|
4798
|
Daniel@0
|
4799 pipeline.unshift(this._inputNode = DataSourceInput(this));
|
Daniel@0
|
4800 status = graph.preprocess(pipeline);
|
Daniel@0
|
4801
|
Daniel@0
|
4802 if (status.router) {
|
Daniel@0
|
4803 pipeline.push(status.collector = new Collector(graph));
|
Daniel@0
|
4804 }
|
Daniel@0
|
4805
|
Daniel@0
|
4806 pipeline.push(this._outputNode = DataSourceOutput(this));
|
Daniel@0
|
4807 this._collector = status.collector;
|
Daniel@0
|
4808 this._mutates = !!status.mutates;
|
Daniel@0
|
4809 graph.connect(this._pipeline = pipeline);
|
Daniel@0
|
4810
|
Daniel@0
|
4811 return this;
|
Daniel@0
|
4812 };
|
Daniel@0
|
4813
|
Daniel@0
|
4814 prototype.synchronize = function() {
|
Daniel@0
|
4815 this._graph.synchronize(this._pipeline);
|
Daniel@0
|
4816 return this;
|
Daniel@0
|
4817 };
|
Daniel@0
|
4818
|
Daniel@0
|
4819 prototype.listener = function() {
|
Daniel@0
|
4820 return DataSourceListener(this).addListener(this._inputNode);
|
Daniel@0
|
4821 };
|
Daniel@0
|
4822
|
Daniel@0
|
4823 prototype.addListener = function(l) {
|
Daniel@0
|
4824 if (l instanceof DataSource) {
|
Daniel@0
|
4825 this._collector.addListener(l.listener());
|
Daniel@0
|
4826 } else {
|
Daniel@0
|
4827 this._outputNode.addListener(l);
|
Daniel@0
|
4828 }
|
Daniel@0
|
4829 return this;
|
Daniel@0
|
4830 };
|
Daniel@0
|
4831
|
Daniel@0
|
4832 prototype.removeListener = function(l) {
|
Daniel@0
|
4833 this._outputNode.removeListener(l);
|
Daniel@0
|
4834 };
|
Daniel@0
|
4835
|
Daniel@0
|
4836 prototype.listeners = function(ds) {
|
Daniel@0
|
4837 return (ds ? this._collector : this._outputNode).listeners();
|
Daniel@0
|
4838 };
|
Daniel@0
|
4839
|
Daniel@0
|
4840 // Input node applies the datasource's delta, and propagates it to
|
Daniel@0
|
4841 // the rest of the pipeline. It receives touches to reflow data.
|
Daniel@0
|
4842 function DataSourceInput(ds) {
|
Daniel@0
|
4843 var input = new Node(ds._graph)
|
Daniel@0
|
4844 .router(true)
|
Daniel@0
|
4845 .collector(true);
|
Daniel@0
|
4846
|
Daniel@0
|
4847 input.data = function() {
|
Daniel@0
|
4848 return ds._data;
|
Daniel@0
|
4849 };
|
Daniel@0
|
4850
|
Daniel@0
|
4851 input.evaluate = function(input) {
|
Daniel@0
|
4852 log.debug(input, ['input', ds._name]);
|
Daniel@0
|
4853
|
Daniel@0
|
4854 var delta = ds._input,
|
Daniel@0
|
4855 out = ChangeSet.create(input), f;
|
Daniel@0
|
4856
|
Daniel@0
|
4857 // Delta might contain fields updated through API
|
Daniel@0
|
4858 for (f in delta.fields) {
|
Daniel@0
|
4859 out.fields[f] = 1;
|
Daniel@0
|
4860 }
|
Daniel@0
|
4861
|
Daniel@0
|
4862 // update data
|
Daniel@0
|
4863 if (delta.rem.length) {
|
Daniel@0
|
4864 ds._data = Tuple.idFilter(ds._data, delta.rem);
|
Daniel@0
|
4865 }
|
Daniel@0
|
4866
|
Daniel@0
|
4867 if (delta.add.length) {
|
Daniel@0
|
4868 ds._data = ds._data.concat(delta.add);
|
Daniel@0
|
4869 }
|
Daniel@0
|
4870
|
Daniel@0
|
4871 // if reflowing, add any other tuples not currently in changeset
|
Daniel@0
|
4872 if (input.reflow) {
|
Daniel@0
|
4873 delta.mod = delta.mod.concat(
|
Daniel@0
|
4874 Tuple.idFilter(ds._data, delta.add, delta.mod, delta.rem));
|
Daniel@0
|
4875 }
|
Daniel@0
|
4876
|
Daniel@0
|
4877 // reset change list
|
Daniel@0
|
4878 ds._input = ChangeSet.create();
|
Daniel@0
|
4879
|
Daniel@0
|
4880 out.add = delta.add;
|
Daniel@0
|
4881 out.mod = delta.mod;
|
Daniel@0
|
4882 out.rem = delta.rem;
|
Daniel@0
|
4883 out.facet = ds._facet;
|
Daniel@0
|
4884 return out;
|
Daniel@0
|
4885 };
|
Daniel@0
|
4886
|
Daniel@0
|
4887 return input;
|
Daniel@0
|
4888 }
|
Daniel@0
|
4889
|
Daniel@0
|
4890 // Output node captures the last changeset seen by this datasource
|
Daniel@0
|
4891 // (needed for joins and builds) and materializes any nested data.
|
Daniel@0
|
4892 // If this datasource is faceted, materializes the values in the facet.
|
Daniel@0
|
4893 function DataSourceOutput(ds) {
|
Daniel@0
|
4894 var output = new Node(ds._graph)
|
Daniel@0
|
4895 .router(true)
|
Daniel@0
|
4896 .reflows(true)
|
Daniel@0
|
4897 .collector(true);
|
Daniel@0
|
4898
|
Daniel@0
|
4899 output.data = function() {
|
Daniel@0
|
4900 return ds._collector ? ds._collector.data() : ds._data;
|
Daniel@0
|
4901 };
|
Daniel@0
|
4902
|
Daniel@0
|
4903 output.evaluate = function(input) {
|
Daniel@0
|
4904 log.debug(input, ['output', ds._name]);
|
Daniel@0
|
4905
|
Daniel@0
|
4906 var out = ChangeSet.create(input, true);
|
Daniel@0
|
4907
|
Daniel@0
|
4908 if (ds._facet) {
|
Daniel@0
|
4909 ds._facet.values = ds.values();
|
Daniel@0
|
4910 input.facet = null;
|
Daniel@0
|
4911 }
|
Daniel@0
|
4912
|
Daniel@0
|
4913 ds._output = input;
|
Daniel@0
|
4914 out.data[ds._name] = 1;
|
Daniel@0
|
4915 return out;
|
Daniel@0
|
4916 };
|
Daniel@0
|
4917
|
Daniel@0
|
4918 return output;
|
Daniel@0
|
4919 }
|
Daniel@0
|
4920
|
Daniel@0
|
4921 function DataSourceListener(ds) {
|
Daniel@0
|
4922 var l = new Node(ds._graph).router(true);
|
Daniel@0
|
4923
|
Daniel@0
|
4924 l.evaluate = function(input) {
|
Daniel@0
|
4925 // Tuple derivation carries a cost. So only derive if the pipeline has
|
Daniel@0
|
4926 // operators that mutate, and thus would override the source data.
|
Daniel@0
|
4927 if (ds.mutates()) {
|
Daniel@0
|
4928 var map = ds._srcMap || (ds._srcMap = {}), // to propagate tuples correctly
|
Daniel@0
|
4929 output = ChangeSet.create(input);
|
Daniel@0
|
4930
|
Daniel@0
|
4931 output.add = input.add.map(function(t) {
|
Daniel@0
|
4932 return (map[t._id] = Tuple.derive(t));
|
Daniel@0
|
4933 });
|
Daniel@0
|
4934
|
Daniel@0
|
4935 output.mod = input.mod.map(function(t) {
|
Daniel@0
|
4936 return Tuple.rederive(t, map[t._id]);
|
Daniel@0
|
4937 });
|
Daniel@0
|
4938
|
Daniel@0
|
4939 output.rem = input.rem.map(function(t) {
|
Daniel@0
|
4940 var o = map[t._id];
|
Daniel@0
|
4941 return (map[t._id] = null, o);
|
Daniel@0
|
4942 });
|
Daniel@0
|
4943
|
Daniel@0
|
4944 return (ds._input = output);
|
Daniel@0
|
4945 } else {
|
Daniel@0
|
4946 return (ds._input = input);
|
Daniel@0
|
4947 }
|
Daniel@0
|
4948 };
|
Daniel@0
|
4949
|
Daniel@0
|
4950 return l;
|
Daniel@0
|
4951 }
|
Daniel@0
|
4952
|
Daniel@0
|
4953 module.exports = DataSource;
|
Daniel@0
|
4954
|
Daniel@0
|
4955 },{"./ChangeSet":30,"./Collector":31,"./Node":36,"./Tuple":38,"vega-logging":45}],33:[function(require,module,exports){
|
Daniel@0
|
4956 var deps = module.exports = {
|
Daniel@0
|
4957 ALL: ['data', 'fields', 'scales', 'signals']
|
Daniel@0
|
4958 };
|
Daniel@0
|
4959 deps.ALL.forEach(function(k) { deps[k.toUpperCase()] = k; });
|
Daniel@0
|
4960
|
Daniel@0
|
4961 },{}],34:[function(require,module,exports){
|
Daniel@0
|
4962 var dl = require('datalib'),
|
Daniel@0
|
4963 Heap = require('./Heap'),
|
Daniel@0
|
4964 ChangeSet = require('./ChangeSet'),
|
Daniel@0
|
4965 DataSource = require('./DataSource'),
|
Daniel@0
|
4966 Collector = require('./Collector'),
|
Daniel@0
|
4967 Tuple = require('./Tuple'),
|
Daniel@0
|
4968 Signal = require('./Signal'),
|
Daniel@0
|
4969 Deps = require('./Dependencies');
|
Daniel@0
|
4970
|
Daniel@0
|
4971 function Graph() {
|
Daniel@0
|
4972 }
|
Daniel@0
|
4973
|
Daniel@0
|
4974 var prototype = Graph.prototype;
|
Daniel@0
|
4975
|
Daniel@0
|
4976 prototype.init = function() {
|
Daniel@0
|
4977 this._stamp = 0;
|
Daniel@0
|
4978 this._rank = 0;
|
Daniel@0
|
4979
|
Daniel@0
|
4980 this._data = {};
|
Daniel@0
|
4981 this._signals = {};
|
Daniel@0
|
4982
|
Daniel@0
|
4983 this.doNotPropagate = {};
|
Daniel@0
|
4984 };
|
Daniel@0
|
4985
|
Daniel@0
|
4986 prototype.rank = function() {
|
Daniel@0
|
4987 return ++this._rank;
|
Daniel@0
|
4988 };
|
Daniel@0
|
4989
|
Daniel@0
|
4990 prototype.values = function(type, names, hash) {
|
Daniel@0
|
4991 var data = (type === Deps.SIGNALS ? this._signals : this._data),
|
Daniel@0
|
4992 n = (names !== undefined ? names : dl.keys(data)),
|
Daniel@0
|
4993 vals, i;
|
Daniel@0
|
4994
|
Daniel@0
|
4995 if (Array.isArray(n)) {
|
Daniel@0
|
4996 vals = hash || {};
|
Daniel@0
|
4997 for (i=0; i<n.length; ++i) {
|
Daniel@0
|
4998 vals[n[i]] = data[n[i]].values();
|
Daniel@0
|
4999 }
|
Daniel@0
|
5000 return vals;
|
Daniel@0
|
5001 } else {
|
Daniel@0
|
5002 return data[n].values();
|
Daniel@0
|
5003 }
|
Daniel@0
|
5004 };
|
Daniel@0
|
5005
|
Daniel@0
|
5006 // Retain for backwards-compatibility
|
Daniel@0
|
5007 prototype.dataValues = function(names) {
|
Daniel@0
|
5008 return this.values(Deps.DATA, names);
|
Daniel@0
|
5009 };
|
Daniel@0
|
5010
|
Daniel@0
|
5011 // Retain for backwards-compatibility
|
Daniel@0
|
5012 prototype.signalValues = function(names) {
|
Daniel@0
|
5013 return this.values(Deps.SIGNALS, names);
|
Daniel@0
|
5014 };
|
Daniel@0
|
5015
|
Daniel@0
|
5016 prototype.data = function(name, pipeline, facet) {
|
Daniel@0
|
5017 var db = this._data;
|
Daniel@0
|
5018 if (!arguments.length) {
|
Daniel@0
|
5019 var all = [], key;
|
Daniel@0
|
5020 for (key in db) { all.push(db[key]); }
|
Daniel@0
|
5021 return all;
|
Daniel@0
|
5022 } else if (arguments.length === 1) {
|
Daniel@0
|
5023 return db[name];
|
Daniel@0
|
5024 } else {
|
Daniel@0
|
5025 return (db[name] = new DataSource(this, name, facet).pipeline(pipeline));
|
Daniel@0
|
5026 }
|
Daniel@0
|
5027 };
|
Daniel@0
|
5028
|
Daniel@0
|
5029 prototype.signal = function(name, init) {
|
Daniel@0
|
5030 if (arguments.length === 1) {
|
Daniel@0
|
5031 var m = this;
|
Daniel@0
|
5032 return Array.isArray(name) ?
|
Daniel@0
|
5033 name.map(function(n) { return m._signals[n]; }) :
|
Daniel@0
|
5034 this._signals[name];
|
Daniel@0
|
5035 } else {
|
Daniel@0
|
5036 return (this._signals[name] = new Signal(this, name, init));
|
Daniel@0
|
5037 }
|
Daniel@0
|
5038 };
|
Daniel@0
|
5039
|
Daniel@0
|
5040 prototype.signalRef = function(ref) {
|
Daniel@0
|
5041 if (!Array.isArray(ref)) {
|
Daniel@0
|
5042 ref = dl.field(ref);
|
Daniel@0
|
5043 }
|
Daniel@0
|
5044
|
Daniel@0
|
5045 var value = this.signal(ref[0]).value();
|
Daniel@0
|
5046 if (ref.length > 1) {
|
Daniel@0
|
5047 for (var i=1, n=ref.length; i<n; ++i) {
|
Daniel@0
|
5048 value = value[ref[i]];
|
Daniel@0
|
5049 }
|
Daniel@0
|
5050 }
|
Daniel@0
|
5051 return value;
|
Daniel@0
|
5052 };
|
Daniel@0
|
5053
|
Daniel@0
|
5054 // Stamp should be specified with caution. It is necessary for inline datasources,
|
Daniel@0
|
5055 // which need to be populated during the same cycle even though propagation has
|
Daniel@0
|
5056 // passed that part of the dataflow graph.
|
Daniel@0
|
5057 prototype.propagate = function(pulse, node, stamp) {
|
Daniel@0
|
5058 var pulses = {},
|
Daniel@0
|
5059 listeners, next, nplse, tpls, ntpls, i, len;
|
Daniel@0
|
5060
|
Daniel@0
|
5061 // new PQ with each propagation cycle so that we can pulse branches
|
Daniel@0
|
5062 // of the dataflow graph during a propagation (e.g., when creating
|
Daniel@0
|
5063 // a new inline datasource).
|
Daniel@0
|
5064 var pq = new Heap(function(a, b) {
|
Daniel@0
|
5065 // Sort on qrank (queue-rank).
|
Daniel@0
|
5066 // Rank can change during propagation due to rewiring.
|
Daniel@0
|
5067 return a._qrank - b._qrank;
|
Daniel@0
|
5068 });
|
Daniel@0
|
5069
|
Daniel@0
|
5070 if (pulse.stamp) throw Error('Pulse already has a non-zero stamp.');
|
Daniel@0
|
5071
|
Daniel@0
|
5072 pulse.stamp = stamp || ++this._stamp;
|
Daniel@0
|
5073 pulses[node._id] = pulse;
|
Daniel@0
|
5074 pq.push(node.qrank(true));
|
Daniel@0
|
5075
|
Daniel@0
|
5076 while (pq.size() > 0) {
|
Daniel@0
|
5077 node = pq.peek();
|
Daniel@0
|
5078 pulse = pulses[node._id];
|
Daniel@0
|
5079
|
Daniel@0
|
5080 if (node.rank() !== node.qrank()) {
|
Daniel@0
|
5081 // A node's rank might change during a propagation. Re-queue if so.
|
Daniel@0
|
5082 pq.replace(node.qrank(true));
|
Daniel@0
|
5083 } else {
|
Daniel@0
|
5084 // Evaluate node and propagate pulse.
|
Daniel@0
|
5085 pq.pop();
|
Daniel@0
|
5086 pulses[node._id] = null;
|
Daniel@0
|
5087 listeners = node._listeners;
|
Daniel@0
|
5088 pulse = this.evaluate(pulse, node);
|
Daniel@0
|
5089
|
Daniel@0
|
5090 // Propagate the pulse.
|
Daniel@0
|
5091 if (pulse !== this.doNotPropagate) {
|
Daniel@0
|
5092 // Ensure reflow pulses always send reflow pulses even if skipped.
|
Daniel@0
|
5093 if (!pulse.reflow && node.reflows()) {
|
Daniel@0
|
5094 pulse = ChangeSet.create(pulse, true);
|
Daniel@0
|
5095 }
|
Daniel@0
|
5096
|
Daniel@0
|
5097 for (i=0, len=listeners.length; i<len; ++i) {
|
Daniel@0
|
5098 next = listeners[i];
|
Daniel@0
|
5099
|
Daniel@0
|
5100 if ((nplse = pulses[next._id]) !== undefined) {
|
Daniel@0
|
5101 if (nplse === null) throw Error('Already propagated to node.');
|
Daniel@0
|
5102 if (nplse === pulse) continue; // Re-queueing the same pulse.
|
Daniel@0
|
5103
|
Daniel@0
|
5104 // We've already queued this node. Ensure there should be at most one
|
Daniel@0
|
5105 // pulse with tuples (add/mod/rem), and the remainder will be reflows.
|
Daniel@0
|
5106 tpls = pulse.add.length || pulse.mod.length || pulse.rem.length;
|
Daniel@0
|
5107 ntpls = nplse.add.length || nplse.mod.length || nplse.rem.length;
|
Daniel@0
|
5108
|
Daniel@0
|
5109 if (tpls && ntpls) throw Error('Multiple changeset pulses to same node');
|
Daniel@0
|
5110
|
Daniel@0
|
5111 // Combine reflow and tuples into a single pulse.
|
Daniel@0
|
5112 pulses[next._id] = tpls ? pulse : nplse;
|
Daniel@0
|
5113 pulses[next._id].reflow = pulse.reflow || nplse.reflow;
|
Daniel@0
|
5114 } else {
|
Daniel@0
|
5115 // First time we're seeing this node, queue it for propagation.
|
Daniel@0
|
5116 pq.push(next.qrank(true));
|
Daniel@0
|
5117 pulses[next._id] = pulse;
|
Daniel@0
|
5118 }
|
Daniel@0
|
5119 }
|
Daniel@0
|
5120 }
|
Daniel@0
|
5121 }
|
Daniel@0
|
5122 }
|
Daniel@0
|
5123 };
|
Daniel@0
|
5124
|
Daniel@0
|
5125 // Process a new branch of the dataflow graph prior to connection:
|
Daniel@0
|
5126 // (1) Insert new Collector nodes as needed.
|
Daniel@0
|
5127 // (2) Track + return mutation/routing status of the branch.
|
Daniel@0
|
5128 prototype.preprocess = function(branch) {
|
Daniel@0
|
5129 var graph = this,
|
Daniel@0
|
5130 mutates = 0,
|
Daniel@0
|
5131 node, router, collector, collects;
|
Daniel@0
|
5132
|
Daniel@0
|
5133 for (var i=0; i<branch.length; ++i) {
|
Daniel@0
|
5134 node = branch[i];
|
Daniel@0
|
5135
|
Daniel@0
|
5136 // Batch nodes need access to a materialized dataset.
|
Daniel@0
|
5137 if (node.batch() && !node._collector) {
|
Daniel@0
|
5138 if (router || !collector) {
|
Daniel@0
|
5139 node = new Collector(graph);
|
Daniel@0
|
5140 branch.splice(i, 0, node);
|
Daniel@0
|
5141 router = false;
|
Daniel@0
|
5142 } else {
|
Daniel@0
|
5143 node._collector = collector;
|
Daniel@0
|
5144 }
|
Daniel@0
|
5145 }
|
Daniel@0
|
5146
|
Daniel@0
|
5147 if ((collects = node.collector())) collector = node;
|
Daniel@0
|
5148 router = router || node.router() && !collects;
|
Daniel@0
|
5149 mutates = mutates || node.mutates();
|
Daniel@0
|
5150
|
Daniel@0
|
5151 // A collector needs to be inserted after tuple-producing
|
Daniel@0
|
5152 // nodes for correct previous value tracking.
|
Daniel@0
|
5153 if (node.produces()) {
|
Daniel@0
|
5154 branch.splice(i+1, 0, new Collector(graph));
|
Daniel@0
|
5155 router = false;
|
Daniel@0
|
5156 }
|
Daniel@0
|
5157 }
|
Daniel@0
|
5158
|
Daniel@0
|
5159 return {router: router, collector: collector, mutates: mutates};
|
Daniel@0
|
5160 };
|
Daniel@0
|
5161
|
Daniel@0
|
5162 prototype.connect = function(branch) {
|
Daniel@0
|
5163 var collector, node, data, signals, i, n, j, m;
|
Daniel@0
|
5164
|
Daniel@0
|
5165 // connect the pipeline
|
Daniel@0
|
5166 for (i=0, n=branch.length; i<n; ++i) {
|
Daniel@0
|
5167 node = branch[i];
|
Daniel@0
|
5168 if (node.collector()) collector = node;
|
Daniel@0
|
5169
|
Daniel@0
|
5170 data = node.dependency(Deps.DATA);
|
Daniel@0
|
5171 for (j=0, m=data.length; j<m; ++j) {
|
Daniel@0
|
5172 this.data(data[j]).addListener(collector);
|
Daniel@0
|
5173 }
|
Daniel@0
|
5174
|
Daniel@0
|
5175 signals = node.dependency(Deps.SIGNALS);
|
Daniel@0
|
5176 for (j=0, m=signals.length; j<m; ++j) {
|
Daniel@0
|
5177 this.signal(signals[j]).addListener(collector);
|
Daniel@0
|
5178 }
|
Daniel@0
|
5179
|
Daniel@0
|
5180 if (i > 0) branch[i-1].addListener(node);
|
Daniel@0
|
5181 }
|
Daniel@0
|
5182
|
Daniel@0
|
5183 return branch;
|
Daniel@0
|
5184 };
|
Daniel@0
|
5185
|
Daniel@0
|
5186 prototype.disconnect = function(branch) {
|
Daniel@0
|
5187 var collector, node, data, signals, i, n, j, m;
|
Daniel@0
|
5188
|
Daniel@0
|
5189 for (i=0, n=branch.length; i<n; ++i) {
|
Daniel@0
|
5190 node = branch[i];
|
Daniel@0
|
5191 if (node.collector()) collector = node;
|
Daniel@0
|
5192
|
Daniel@0
|
5193 data = node.dependency(Deps.DATA);
|
Daniel@0
|
5194 for (j=0, m=data.length; j<m; ++j) {
|
Daniel@0
|
5195 this.data(data[j]).removeListener(collector);
|
Daniel@0
|
5196 }
|
Daniel@0
|
5197
|
Daniel@0
|
5198 signals = node.dependency(Deps.SIGNALS);
|
Daniel@0
|
5199 for (j=0, m=signals.length; j<m; ++j) {
|
Daniel@0
|
5200 this.signal(signals[j]).removeListener(collector);
|
Daniel@0
|
5201 }
|
Daniel@0
|
5202
|
Daniel@0
|
5203 node.disconnect();
|
Daniel@0
|
5204 }
|
Daniel@0
|
5205
|
Daniel@0
|
5206 return branch;
|
Daniel@0
|
5207 };
|
Daniel@0
|
5208
|
Daniel@0
|
5209 prototype.synchronize = function(branch) {
|
Daniel@0
|
5210 var ids = {},
|
Daniel@0
|
5211 node, data, i, n, j, m, d, id;
|
Daniel@0
|
5212
|
Daniel@0
|
5213 for (i=0, n=branch.length; i<n; ++i) {
|
Daniel@0
|
5214 node = branch[i];
|
Daniel@0
|
5215 if (!node.collector()) continue;
|
Daniel@0
|
5216
|
Daniel@0
|
5217 for (j=0, data=node.data(), m=data.length; j<m; ++j) {
|
Daniel@0
|
5218 id = (d = data[j])._id;
|
Daniel@0
|
5219 if (ids[id]) continue;
|
Daniel@0
|
5220 Tuple.prev_update(d);
|
Daniel@0
|
5221 ids[id] = 1;
|
Daniel@0
|
5222 }
|
Daniel@0
|
5223 }
|
Daniel@0
|
5224
|
Daniel@0
|
5225 return this;
|
Daniel@0
|
5226 };
|
Daniel@0
|
5227
|
Daniel@0
|
5228 prototype.reevaluate = function(pulse, node) {
|
Daniel@0
|
5229 var reflowed = pulse.reflow && node.last() >= pulse.stamp,
|
Daniel@0
|
5230 run = node.router() || pulse.add.length || pulse.rem.length;
|
Daniel@0
|
5231
|
Daniel@0
|
5232 return run || !reflowed || node.reevaluate(pulse);
|
Daniel@0
|
5233 };
|
Daniel@0
|
5234
|
Daniel@0
|
5235 prototype.evaluate = function(pulse, node) {
|
Daniel@0
|
5236 if (!this.reevaluate(pulse, node)) return pulse;
|
Daniel@0
|
5237 pulse = node.evaluate(pulse);
|
Daniel@0
|
5238 node.last(pulse.stamp);
|
Daniel@0
|
5239 return pulse;
|
Daniel@0
|
5240 };
|
Daniel@0
|
5241
|
Daniel@0
|
5242 module.exports = Graph;
|
Daniel@0
|
5243
|
Daniel@0
|
5244 },{"./ChangeSet":30,"./Collector":31,"./DataSource":32,"./Dependencies":33,"./Heap":35,"./Signal":37,"./Tuple":38,"datalib":24}],35:[function(require,module,exports){
|
Daniel@0
|
5245 function Heap(comparator) {
|
Daniel@0
|
5246 this.cmp = comparator;
|
Daniel@0
|
5247 this.nodes = [];
|
Daniel@0
|
5248 }
|
Daniel@0
|
5249
|
Daniel@0
|
5250 var prototype = Heap.prototype;
|
Daniel@0
|
5251
|
Daniel@0
|
5252 prototype.size = function() {
|
Daniel@0
|
5253 return this.nodes.length;
|
Daniel@0
|
5254 };
|
Daniel@0
|
5255
|
Daniel@0
|
5256 prototype.clear = function() {
|
Daniel@0
|
5257 return (this.nodes = [], this);
|
Daniel@0
|
5258 };
|
Daniel@0
|
5259
|
Daniel@0
|
5260 prototype.peek = function() {
|
Daniel@0
|
5261 return this.nodes[0];
|
Daniel@0
|
5262 };
|
Daniel@0
|
5263
|
Daniel@0
|
5264 prototype.push = function(x) {
|
Daniel@0
|
5265 var array = this.nodes;
|
Daniel@0
|
5266 array.push(x);
|
Daniel@0
|
5267 return _siftdown(array, 0, array.length-1, this.cmp);
|
Daniel@0
|
5268 };
|
Daniel@0
|
5269
|
Daniel@0
|
5270 prototype.pop = function() {
|
Daniel@0
|
5271 var array = this.nodes,
|
Daniel@0
|
5272 last = array.pop(),
|
Daniel@0
|
5273 item;
|
Daniel@0
|
5274
|
Daniel@0
|
5275 if (array.length) {
|
Daniel@0
|
5276 item = array[0];
|
Daniel@0
|
5277 array[0] = last;
|
Daniel@0
|
5278 _siftup(array, 0, this.cmp);
|
Daniel@0
|
5279 } else {
|
Daniel@0
|
5280 item = last;
|
Daniel@0
|
5281 }
|
Daniel@0
|
5282 return item;
|
Daniel@0
|
5283 };
|
Daniel@0
|
5284
|
Daniel@0
|
5285 prototype.replace = function(item) {
|
Daniel@0
|
5286 var array = this.nodes,
|
Daniel@0
|
5287 retval = array[0];
|
Daniel@0
|
5288 array[0] = item;
|
Daniel@0
|
5289 _siftup(array, 0, this.cmp);
|
Daniel@0
|
5290 return retval;
|
Daniel@0
|
5291 };
|
Daniel@0
|
5292
|
Daniel@0
|
5293 prototype.pushpop = function(item) {
|
Daniel@0
|
5294 var array = this.nodes, ref = array[0];
|
Daniel@0
|
5295 if (array.length && this.cmp(ref, item) < 0) {
|
Daniel@0
|
5296 array[0] = item;
|
Daniel@0
|
5297 item = ref;
|
Daniel@0
|
5298 _siftup(array, 0, this.cmp);
|
Daniel@0
|
5299 }
|
Daniel@0
|
5300 return item;
|
Daniel@0
|
5301 };
|
Daniel@0
|
5302
|
Daniel@0
|
5303 function _siftdown(array, start, idx, cmp) {
|
Daniel@0
|
5304 var item, parent, pidx;
|
Daniel@0
|
5305
|
Daniel@0
|
5306 item = array[idx];
|
Daniel@0
|
5307 while (idx > start) {
|
Daniel@0
|
5308 pidx = (idx - 1) >> 1;
|
Daniel@0
|
5309 parent = array[pidx];
|
Daniel@0
|
5310 if (cmp(item, parent) < 0) {
|
Daniel@0
|
5311 array[idx] = parent;
|
Daniel@0
|
5312 idx = pidx;
|
Daniel@0
|
5313 continue;
|
Daniel@0
|
5314 }
|
Daniel@0
|
5315 break;
|
Daniel@0
|
5316 }
|
Daniel@0
|
5317 return (array[idx] = item);
|
Daniel@0
|
5318 }
|
Daniel@0
|
5319
|
Daniel@0
|
5320 function _siftup(array, idx, cmp) {
|
Daniel@0
|
5321 var start = idx,
|
Daniel@0
|
5322 end = array.length,
|
Daniel@0
|
5323 item = array[idx],
|
Daniel@0
|
5324 cidx = 2 * idx + 1, ridx;
|
Daniel@0
|
5325
|
Daniel@0
|
5326 while (cidx < end) {
|
Daniel@0
|
5327 ridx = cidx + 1;
|
Daniel@0
|
5328 if (ridx < end && cmp(array[cidx], array[ridx]) >= 0) {
|
Daniel@0
|
5329 cidx = ridx;
|
Daniel@0
|
5330 }
|
Daniel@0
|
5331 array[idx] = array[cidx];
|
Daniel@0
|
5332 idx = cidx;
|
Daniel@0
|
5333 cidx = 2 * idx + 1;
|
Daniel@0
|
5334 }
|
Daniel@0
|
5335 array[idx] = item;
|
Daniel@0
|
5336 return _siftdown(array, start, idx, cmp);
|
Daniel@0
|
5337 }
|
Daniel@0
|
5338
|
Daniel@0
|
5339 module.exports = Heap;
|
Daniel@0
|
5340
|
Daniel@0
|
5341 },{}],36:[function(require,module,exports){
|
Daniel@0
|
5342 var DEPS = require('./Dependencies').ALL,
|
Daniel@0
|
5343 nodeID = 0;
|
Daniel@0
|
5344
|
Daniel@0
|
5345 function Node(graph) {
|
Daniel@0
|
5346 if (graph) this.init(graph);
|
Daniel@0
|
5347 }
|
Daniel@0
|
5348
|
Daniel@0
|
5349 var Flags = Node.Flags = {
|
Daniel@0
|
5350 Router: 0x01, // Responsible for propagating tuples, cannot be skipped.
|
Daniel@0
|
5351 Collector: 0x02, // Holds a materialized dataset, pulse node to reflow.
|
Daniel@0
|
5352 Produces: 0x04, // Produces new tuples.
|
Daniel@0
|
5353 Mutates: 0x08, // Sets properties of incoming tuples.
|
Daniel@0
|
5354 Reflows: 0x10, // Forwards a reflow pulse.
|
Daniel@0
|
5355 Batch: 0x20 // Performs batch data processing, needs collector.
|
Daniel@0
|
5356 };
|
Daniel@0
|
5357
|
Daniel@0
|
5358 var prototype = Node.prototype;
|
Daniel@0
|
5359
|
Daniel@0
|
5360 prototype.init = function(graph) {
|
Daniel@0
|
5361 this._id = ++nodeID;
|
Daniel@0
|
5362 this._graph = graph;
|
Daniel@0
|
5363 this._rank = graph.rank(); // Topological sort by rank
|
Daniel@0
|
5364 this._qrank = null; // Rank when enqueued for propagation
|
Daniel@0
|
5365 this._stamp = 0; // Last stamp seen
|
Daniel@0
|
5366
|
Daniel@0
|
5367 this._listeners = [];
|
Daniel@0
|
5368 this._listeners._ids = {}; // To prevent duplicate listeners
|
Daniel@0
|
5369
|
Daniel@0
|
5370 // Initialize dependencies.
|
Daniel@0
|
5371 this._deps = {};
|
Daniel@0
|
5372 for (var i=0, n=DEPS.length; i<n; ++i) {
|
Daniel@0
|
5373 this._deps[DEPS[i]] = [];
|
Daniel@0
|
5374 }
|
Daniel@0
|
5375
|
Daniel@0
|
5376 // Initialize status flags.
|
Daniel@0
|
5377 this._flags = 0;
|
Daniel@0
|
5378
|
Daniel@0
|
5379 return this;
|
Daniel@0
|
5380 };
|
Daniel@0
|
5381
|
Daniel@0
|
5382 prototype.rank = function() {
|
Daniel@0
|
5383 return this._rank;
|
Daniel@0
|
5384 };
|
Daniel@0
|
5385
|
Daniel@0
|
5386 prototype.qrank = function(/* set */) {
|
Daniel@0
|
5387 if (!arguments.length) return this._qrank;
|
Daniel@0
|
5388 return (this._qrank = this._rank, this);
|
Daniel@0
|
5389 };
|
Daniel@0
|
5390
|
Daniel@0
|
5391 prototype.last = function(stamp) {
|
Daniel@0
|
5392 if (!arguments.length) return this._stamp;
|
Daniel@0
|
5393 return (this._stamp = stamp, this);
|
Daniel@0
|
5394 };
|
Daniel@0
|
5395
|
Daniel@0
|
5396 // -- status flags ---
|
Daniel@0
|
5397
|
Daniel@0
|
5398 prototype._setf = function(v, b) {
|
Daniel@0
|
5399 if (b) { this._flags |= v; } else { this._flags &= ~v; }
|
Daniel@0
|
5400 return this;
|
Daniel@0
|
5401 };
|
Daniel@0
|
5402
|
Daniel@0
|
5403 prototype.router = function(state) {
|
Daniel@0
|
5404 if (!arguments.length) return (this._flags & Flags.Router);
|
Daniel@0
|
5405 return this._setf(Flags.Router, state);
|
Daniel@0
|
5406 };
|
Daniel@0
|
5407
|
Daniel@0
|
5408 prototype.collector = function(state) {
|
Daniel@0
|
5409 if (!arguments.length) return (this._flags & Flags.Collector);
|
Daniel@0
|
5410 return this._setf(Flags.Collector, state);
|
Daniel@0
|
5411 };
|
Daniel@0
|
5412
|
Daniel@0
|
5413 prototype.produces = function(state) {
|
Daniel@0
|
5414 if (!arguments.length) return (this._flags & Flags.Produces);
|
Daniel@0
|
5415 return this._setf(Flags.Produces, state);
|
Daniel@0
|
5416 };
|
Daniel@0
|
5417
|
Daniel@0
|
5418 prototype.mutates = function(state) {
|
Daniel@0
|
5419 if (!arguments.length) return (this._flags & Flags.Mutates);
|
Daniel@0
|
5420 return this._setf(Flags.Mutates, state);
|
Daniel@0
|
5421 };
|
Daniel@0
|
5422
|
Daniel@0
|
5423 prototype.reflows = function(state) {
|
Daniel@0
|
5424 if (!arguments.length) return (this._flags & Flags.Reflows);
|
Daniel@0
|
5425 return this._setf(Flags.Reflows, state);
|
Daniel@0
|
5426 };
|
Daniel@0
|
5427
|
Daniel@0
|
5428 prototype.batch = function(state) {
|
Daniel@0
|
5429 if (!arguments.length) return (this._flags & Flags.Batch);
|
Daniel@0
|
5430 return this._setf(Flags.Batch, state);
|
Daniel@0
|
5431 };
|
Daniel@0
|
5432
|
Daniel@0
|
5433 prototype.dependency = function(type, deps) {
|
Daniel@0
|
5434 var d = this._deps[type],
|
Daniel@0
|
5435 n = d._names || (d._names = {}); // To prevent dupe deps
|
Daniel@0
|
5436
|
Daniel@0
|
5437 // Get dependencies of the given type
|
Daniel@0
|
5438 if (arguments.length === 1) {
|
Daniel@0
|
5439 return d;
|
Daniel@0
|
5440 }
|
Daniel@0
|
5441
|
Daniel@0
|
5442 if (deps === null) {
|
Daniel@0
|
5443 // Clear dependencies of the given type
|
Daniel@0
|
5444 d.splice(0, d.length);
|
Daniel@0
|
5445 d._names = {};
|
Daniel@0
|
5446 } else if (!Array.isArray(deps)) {
|
Daniel@0
|
5447 // Separate this case to avoid cost of array creation
|
Daniel@0
|
5448 if (n[deps]) return this;
|
Daniel@0
|
5449 d.push(deps);
|
Daniel@0
|
5450 n[deps] = 1;
|
Daniel@0
|
5451 } else {
|
Daniel@0
|
5452 for (var i=0, len=deps.length, dep; i<len; ++i) {
|
Daniel@0
|
5453 dep = deps[i];
|
Daniel@0
|
5454 if (n[dep]) continue;
|
Daniel@0
|
5455 d.push(dep);
|
Daniel@0
|
5456 n[dep] = 1;
|
Daniel@0
|
5457 }
|
Daniel@0
|
5458 }
|
Daniel@0
|
5459
|
Daniel@0
|
5460 return this;
|
Daniel@0
|
5461 };
|
Daniel@0
|
5462
|
Daniel@0
|
5463 prototype.listeners = function() {
|
Daniel@0
|
5464 return this._listeners;
|
Daniel@0
|
5465 };
|
Daniel@0
|
5466
|
Daniel@0
|
5467 prototype.addListener = function(l) {
|
Daniel@0
|
5468 if (!(l instanceof Node)) {
|
Daniel@0
|
5469 throw Error('Listener is not a Node');
|
Daniel@0
|
5470 }
|
Daniel@0
|
5471 if (this._listeners._ids[l._id]) return this;
|
Daniel@0
|
5472
|
Daniel@0
|
5473 this._listeners.push(l);
|
Daniel@0
|
5474 this._listeners._ids[l._id] = 1;
|
Daniel@0
|
5475 if (this._rank > l._rank) {
|
Daniel@0
|
5476 var q = [l],
|
Daniel@0
|
5477 g = this._graph, cur;
|
Daniel@0
|
5478 while (q.length) {
|
Daniel@0
|
5479 cur = q.shift();
|
Daniel@0
|
5480 cur._rank = g.rank();
|
Daniel@0
|
5481 q.unshift.apply(q, cur.listeners());
|
Daniel@0
|
5482 }
|
Daniel@0
|
5483 }
|
Daniel@0
|
5484
|
Daniel@0
|
5485 return this;
|
Daniel@0
|
5486 };
|
Daniel@0
|
5487
|
Daniel@0
|
5488 prototype.removeListener = function(l) {
|
Daniel@0
|
5489 if (!this._listeners._ids[l._id]) return false;
|
Daniel@0
|
5490
|
Daniel@0
|
5491 var idx = this._listeners.indexOf(l),
|
Daniel@0
|
5492 b = idx >= 0;
|
Daniel@0
|
5493
|
Daniel@0
|
5494 if (b) {
|
Daniel@0
|
5495 this._listeners.splice(idx, 1);
|
Daniel@0
|
5496 this._listeners._ids[l._id] = null;
|
Daniel@0
|
5497 }
|
Daniel@0
|
5498 return b;
|
Daniel@0
|
5499 };
|
Daniel@0
|
5500
|
Daniel@0
|
5501 prototype.disconnect = function() {
|
Daniel@0
|
5502 this._listeners = [];
|
Daniel@0
|
5503 this._listeners._ids = {};
|
Daniel@0
|
5504 };
|
Daniel@0
|
5505
|
Daniel@0
|
5506 // Evaluate this dataflow node for the current pulse.
|
Daniel@0
|
5507 // Subclasses should override to perform custom processing.
|
Daniel@0
|
5508 prototype.evaluate = function(pulse) {
|
Daniel@0
|
5509 return pulse;
|
Daniel@0
|
5510 };
|
Daniel@0
|
5511
|
Daniel@0
|
5512 // Should this node be re-evaluated for the current pulse?
|
Daniel@0
|
5513 // Searches pulse to see if any dependencies have updated.
|
Daniel@0
|
5514 prototype.reevaluate = function(pulse) {
|
Daniel@0
|
5515 var prop, dep, i, n, j, m;
|
Daniel@0
|
5516
|
Daniel@0
|
5517 for (i=0, n=DEPS.length; i<n; ++i) {
|
Daniel@0
|
5518 prop = DEPS[i];
|
Daniel@0
|
5519 dep = this._deps[prop];
|
Daniel@0
|
5520 for (j=0, m=dep.length; j<m; ++j) {
|
Daniel@0
|
5521 if (pulse[prop][dep[j]]) return true;
|
Daniel@0
|
5522 }
|
Daniel@0
|
5523 }
|
Daniel@0
|
5524
|
Daniel@0
|
5525 return false;
|
Daniel@0
|
5526 };
|
Daniel@0
|
5527
|
Daniel@0
|
5528 Node.reset = function() { nodeID = 0; };
|
Daniel@0
|
5529
|
Daniel@0
|
5530 module.exports = Node;
|
Daniel@0
|
5531
|
Daniel@0
|
5532 },{"./Dependencies":33}],37:[function(require,module,exports){
|
Daniel@0
|
5533 var ChangeSet = require('./ChangeSet'),
|
Daniel@0
|
5534 Node = require('./Node'), // jshint ignore:line
|
Daniel@0
|
5535 Base = Node.prototype;
|
Daniel@0
|
5536
|
Daniel@0
|
5537 function Signal(graph, name, initialValue) {
|
Daniel@0
|
5538 Base.init.call(this, graph);
|
Daniel@0
|
5539 this._name = name;
|
Daniel@0
|
5540 this._value = initialValue;
|
Daniel@0
|
5541 this._verbose = false; // Verbose signals re-pulse the graph even if prev === val.
|
Daniel@0
|
5542 this._handlers = [];
|
Daniel@0
|
5543 return this;
|
Daniel@0
|
5544 }
|
Daniel@0
|
5545
|
Daniel@0
|
5546 var prototype = (Signal.prototype = Object.create(Base));
|
Daniel@0
|
5547 prototype.constructor = Signal;
|
Daniel@0
|
5548
|
Daniel@0
|
5549 prototype.name = function() {
|
Daniel@0
|
5550 return this._name;
|
Daniel@0
|
5551 };
|
Daniel@0
|
5552
|
Daniel@0
|
5553 prototype.value = function(val) {
|
Daniel@0
|
5554 if (!arguments.length) return this._value;
|
Daniel@0
|
5555 return (this._value = val, this);
|
Daniel@0
|
5556 };
|
Daniel@0
|
5557
|
Daniel@0
|
5558 // Alias to value, for shared API with DataSource
|
Daniel@0
|
5559 prototype.values = prototype.value;
|
Daniel@0
|
5560
|
Daniel@0
|
5561 prototype.verbose = function(v) {
|
Daniel@0
|
5562 if (!arguments.length) return this._verbose;
|
Daniel@0
|
5563 return (this._verbose = !!v, this);
|
Daniel@0
|
5564 };
|
Daniel@0
|
5565
|
Daniel@0
|
5566 prototype.evaluate = function(input) {
|
Daniel@0
|
5567 return input.signals[this._name] ? input : this._graph.doNotPropagate;
|
Daniel@0
|
5568 };
|
Daniel@0
|
5569
|
Daniel@0
|
5570 prototype.fire = function(cs) {
|
Daniel@0
|
5571 if (!cs) cs = ChangeSet.create(null, true);
|
Daniel@0
|
5572 cs.signals[this._name] = 1;
|
Daniel@0
|
5573 this._graph.propagate(cs, this);
|
Daniel@0
|
5574 };
|
Daniel@0
|
5575
|
Daniel@0
|
5576 prototype.on = function(handler) {
|
Daniel@0
|
5577 var signal = this,
|
Daniel@0
|
5578 node = new Node(this._graph);
|
Daniel@0
|
5579
|
Daniel@0
|
5580 node.evaluate = function(input) {
|
Daniel@0
|
5581 handler(signal.name(), signal.value());
|
Daniel@0
|
5582 return input;
|
Daniel@0
|
5583 };
|
Daniel@0
|
5584
|
Daniel@0
|
5585 this._handlers.push({
|
Daniel@0
|
5586 handler: handler,
|
Daniel@0
|
5587 node: node
|
Daniel@0
|
5588 });
|
Daniel@0
|
5589
|
Daniel@0
|
5590 return this.addListener(node);
|
Daniel@0
|
5591 };
|
Daniel@0
|
5592
|
Daniel@0
|
5593 prototype.off = function(handler) {
|
Daniel@0
|
5594 var h = this._handlers, i, x;
|
Daniel@0
|
5595
|
Daniel@0
|
5596 for (i=h.length; --i>=0;) {
|
Daniel@0
|
5597 if (!handler || h[i].handler === handler) {
|
Daniel@0
|
5598 x = h.splice(i, 1)[0];
|
Daniel@0
|
5599 this.removeListener(x.node);
|
Daniel@0
|
5600 }
|
Daniel@0
|
5601 }
|
Daniel@0
|
5602
|
Daniel@0
|
5603 return this;
|
Daniel@0
|
5604 };
|
Daniel@0
|
5605
|
Daniel@0
|
5606 module.exports = Signal;
|
Daniel@0
|
5607
|
Daniel@0
|
5608 },{"./ChangeSet":30,"./Node":36}],38:[function(require,module,exports){
|
Daniel@0
|
5609 var tupleID = 0;
|
Daniel@0
|
5610
|
Daniel@0
|
5611 function ingest(datum) {
|
Daniel@0
|
5612 datum = (datum === Object(datum)) ? datum : {data: datum};
|
Daniel@0
|
5613 datum._id = ++tupleID;
|
Daniel@0
|
5614 if (datum._prev) datum._prev = null;
|
Daniel@0
|
5615 return datum;
|
Daniel@0
|
5616 }
|
Daniel@0
|
5617
|
Daniel@0
|
5618 function idMap(a, ids) {
|
Daniel@0
|
5619 ids = ids || {};
|
Daniel@0
|
5620 for (var i=0, n=a.length; i<n; ++i) {
|
Daniel@0
|
5621 ids[a[i]._id] = 1;
|
Daniel@0
|
5622 }
|
Daniel@0
|
5623 return ids;
|
Daniel@0
|
5624 }
|
Daniel@0
|
5625
|
Daniel@0
|
5626 function copy(t, c) {
|
Daniel@0
|
5627 c = c || {};
|
Daniel@0
|
5628 for (var k in t) {
|
Daniel@0
|
5629 if (k !== '_prev' && k !== '_id') c[k] = t[k];
|
Daniel@0
|
5630 }
|
Daniel@0
|
5631 return c;
|
Daniel@0
|
5632 }
|
Daniel@0
|
5633
|
Daniel@0
|
5634 module.exports = {
|
Daniel@0
|
5635 ingest: ingest,
|
Daniel@0
|
5636 idMap: idMap,
|
Daniel@0
|
5637
|
Daniel@0
|
5638 derive: function(d) {
|
Daniel@0
|
5639 return ingest(copy(d));
|
Daniel@0
|
5640 },
|
Daniel@0
|
5641
|
Daniel@0
|
5642 rederive: function(d, t) {
|
Daniel@0
|
5643 return copy(d, t);
|
Daniel@0
|
5644 },
|
Daniel@0
|
5645
|
Daniel@0
|
5646 set: function(t, k, v) {
|
Daniel@0
|
5647 return t[k] === v ? 0 : (t[k] = v, 1);
|
Daniel@0
|
5648 },
|
Daniel@0
|
5649
|
Daniel@0
|
5650 prev: function(t) {
|
Daniel@0
|
5651 return t._prev || t;
|
Daniel@0
|
5652 },
|
Daniel@0
|
5653
|
Daniel@0
|
5654 prev_init: function(t) {
|
Daniel@0
|
5655 if (!t._prev) { t._prev = {_id: t._id}; }
|
Daniel@0
|
5656 },
|
Daniel@0
|
5657
|
Daniel@0
|
5658 prev_update: function(t) {
|
Daniel@0
|
5659 var p = t._prev, k, v;
|
Daniel@0
|
5660 if (p) for (k in t) {
|
Daniel@0
|
5661 if (k !== '_prev' && k !== '_id') {
|
Daniel@0
|
5662 p[k] = ((v=t[k]) instanceof Object && v._prev) ? v._prev : v;
|
Daniel@0
|
5663 }
|
Daniel@0
|
5664 }
|
Daniel@0
|
5665 },
|
Daniel@0
|
5666
|
Daniel@0
|
5667 reset: function() { tupleID = 0; },
|
Daniel@0
|
5668
|
Daniel@0
|
5669 idFilter: function(data) {
|
Daniel@0
|
5670 var ids = {};
|
Daniel@0
|
5671 for (var i=arguments.length; --i>0;) {
|
Daniel@0
|
5672 idMap(arguments[i], ids);
|
Daniel@0
|
5673 }
|
Daniel@0
|
5674 return data.filter(function(x) { return !ids[x._id]; });
|
Daniel@0
|
5675 }
|
Daniel@0
|
5676 };
|
Daniel@0
|
5677
|
Daniel@0
|
5678 },{}],39:[function(require,module,exports){
|
Daniel@0
|
5679 module.exports = {
|
Daniel@0
|
5680 ChangeSet: require('./ChangeSet'),
|
Daniel@0
|
5681 Collector: require('./Collector'),
|
Daniel@0
|
5682 DataSource: require('./DataSource'),
|
Daniel@0
|
5683 Dependencies: require('./Dependencies'),
|
Daniel@0
|
5684 Graph: require('./Graph'),
|
Daniel@0
|
5685 Node: require('./Node'),
|
Daniel@0
|
5686 Signal: require('./Signal'),
|
Daniel@0
|
5687 Tuple: require('./Tuple'),
|
Daniel@0
|
5688 debug: require('vega-logging').debug
|
Daniel@0
|
5689 };
|
Daniel@0
|
5690
|
Daniel@0
|
5691 },{"./ChangeSet":30,"./Collector":31,"./DataSource":32,"./Dependencies":33,"./Graph":34,"./Node":36,"./Signal":37,"./Tuple":38,"vega-logging":45}],40:[function(require,module,exports){
|
Daniel@0
|
5692 function toMap(list) {
|
Daniel@0
|
5693 var map = {}, i, n;
|
Daniel@0
|
5694 for (i=0, n=list.length; i<n; ++i) map[list[i]] = 1;
|
Daniel@0
|
5695 return map;
|
Daniel@0
|
5696 }
|
Daniel@0
|
5697
|
Daniel@0
|
5698 function keys(object) {
|
Daniel@0
|
5699 var list = [], k;
|
Daniel@0
|
5700 for (k in object) list.push(k);
|
Daniel@0
|
5701 return list;
|
Daniel@0
|
5702 }
|
Daniel@0
|
5703
|
Daniel@0
|
5704 module.exports = function(opt) {
|
Daniel@0
|
5705 opt = opt || {};
|
Daniel@0
|
5706 var constants = opt.constants || require('./constants'),
|
Daniel@0
|
5707 functions = (opt.functions || require('./functions'))(codegen),
|
Daniel@0
|
5708 idWhiteList = opt.idWhiteList ? toMap(opt.idWhiteList) : null,
|
Daniel@0
|
5709 idBlackList = opt.idBlackList ? toMap(opt.idBlackList) : null,
|
Daniel@0
|
5710 memberDepth = 0,
|
Daniel@0
|
5711 FIELD_VAR = opt.fieldVar || 'datum',
|
Daniel@0
|
5712 GLOBAL_VAR = opt.globalVar || 'signals',
|
Daniel@0
|
5713 globals = {},
|
Daniel@0
|
5714 fields = {};
|
Daniel@0
|
5715
|
Daniel@0
|
5716 function codegen_wrap(ast) {
|
Daniel@0
|
5717 var retval = {
|
Daniel@0
|
5718 code: codegen(ast),
|
Daniel@0
|
5719 globals: keys(globals),
|
Daniel@0
|
5720 fields: keys(fields)
|
Daniel@0
|
5721 };
|
Daniel@0
|
5722 globals = {};
|
Daniel@0
|
5723 fields = {};
|
Daniel@0
|
5724 return retval;
|
Daniel@0
|
5725 }
|
Daniel@0
|
5726
|
Daniel@0
|
5727 function lookupGlobal(id) {
|
Daniel@0
|
5728 return GLOBAL_VAR + '["' + id + '"]';
|
Daniel@0
|
5729 }
|
Daniel@0
|
5730
|
Daniel@0
|
5731 function codegen(ast) {
|
Daniel@0
|
5732 if (typeof ast === 'string') return ast;
|
Daniel@0
|
5733 var generator = CODEGEN_TYPES[ast.type];
|
Daniel@0
|
5734 if (generator == null) {
|
Daniel@0
|
5735 throw new Error('Unsupported type: ' + ast.type);
|
Daniel@0
|
5736 }
|
Daniel@0
|
5737 return generator(ast);
|
Daniel@0
|
5738 }
|
Daniel@0
|
5739
|
Daniel@0
|
5740 var CODEGEN_TYPES = {
|
Daniel@0
|
5741 'Literal': function(n) {
|
Daniel@0
|
5742 return n.raw;
|
Daniel@0
|
5743 },
|
Daniel@0
|
5744 'Identifier': function(n) {
|
Daniel@0
|
5745 var id = n.name;
|
Daniel@0
|
5746 if (memberDepth > 0) {
|
Daniel@0
|
5747 return id;
|
Daniel@0
|
5748 }
|
Daniel@0
|
5749 if (constants.hasOwnProperty(id)) {
|
Daniel@0
|
5750 return constants[id];
|
Daniel@0
|
5751 }
|
Daniel@0
|
5752 if (idWhiteList) {
|
Daniel@0
|
5753 if (idWhiteList.hasOwnProperty(id)) {
|
Daniel@0
|
5754 return id;
|
Daniel@0
|
5755 } else {
|
Daniel@0
|
5756 globals[id] = 1;
|
Daniel@0
|
5757 return lookupGlobal(id);
|
Daniel@0
|
5758 }
|
Daniel@0
|
5759 }
|
Daniel@0
|
5760 if (idBlackList && idBlackList.hasOwnProperty(id)) {
|
Daniel@0
|
5761 throw new Error('Illegal identifier: ' + id);
|
Daniel@0
|
5762 }
|
Daniel@0
|
5763 return id;
|
Daniel@0
|
5764 },
|
Daniel@0
|
5765 'Program': function(n) {
|
Daniel@0
|
5766 return n.body.map(codegen).join('\n');
|
Daniel@0
|
5767 },
|
Daniel@0
|
5768 'MemberExpression': function(n) {
|
Daniel@0
|
5769 var d = !n.computed;
|
Daniel@0
|
5770 var o = codegen(n.object);
|
Daniel@0
|
5771 if (d) memberDepth += 1;
|
Daniel@0
|
5772 var p = codegen(n.property);
|
Daniel@0
|
5773 if (o === FIELD_VAR) { fields[p] = 1; } // HACKish...
|
Daniel@0
|
5774 if (d) memberDepth -= 1;
|
Daniel@0
|
5775 return o + (d ? '.'+p : '['+p+']');
|
Daniel@0
|
5776 },
|
Daniel@0
|
5777 'CallExpression': function(n) {
|
Daniel@0
|
5778 if (n.callee.type !== 'Identifier') {
|
Daniel@0
|
5779 throw new Error('Illegal callee type: ' + n.callee.type);
|
Daniel@0
|
5780 }
|
Daniel@0
|
5781 var callee = n.callee.name;
|
Daniel@0
|
5782 var args = n.arguments;
|
Daniel@0
|
5783 var fn = functions.hasOwnProperty(callee) && functions[callee];
|
Daniel@0
|
5784 if (!fn) throw new Error('Unrecognized function: ' + callee);
|
Daniel@0
|
5785 return fn instanceof Function ?
|
Daniel@0
|
5786 fn(args) :
|
Daniel@0
|
5787 fn + '(' + args.map(codegen).join(',') + ')';
|
Daniel@0
|
5788 },
|
Daniel@0
|
5789 'ArrayExpression': function(n) {
|
Daniel@0
|
5790 return '[' + n.elements.map(codegen).join(',') + ']';
|
Daniel@0
|
5791 },
|
Daniel@0
|
5792 'BinaryExpression': function(n) {
|
Daniel@0
|
5793 return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')';
|
Daniel@0
|
5794 },
|
Daniel@0
|
5795 'UnaryExpression': function(n) {
|
Daniel@0
|
5796 return '(' + n.operator + codegen(n.argument) + ')';
|
Daniel@0
|
5797 },
|
Daniel@0
|
5798 'ConditionalExpression': function(n) {
|
Daniel@0
|
5799 return '(' + codegen(n.test) +
|
Daniel@0
|
5800 '?' + codegen(n.consequent) +
|
Daniel@0
|
5801 ':' + codegen(n.alternate) +
|
Daniel@0
|
5802 ')';
|
Daniel@0
|
5803 },
|
Daniel@0
|
5804 'LogicalExpression': function(n) {
|
Daniel@0
|
5805 return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')';
|
Daniel@0
|
5806 },
|
Daniel@0
|
5807 'ObjectExpression': function(n) {
|
Daniel@0
|
5808 return '{' + n.properties.map(codegen).join(',') + '}';
|
Daniel@0
|
5809 },
|
Daniel@0
|
5810 'Property': function(n) {
|
Daniel@0
|
5811 memberDepth += 1;
|
Daniel@0
|
5812 var k = codegen(n.key);
|
Daniel@0
|
5813 memberDepth -= 1;
|
Daniel@0
|
5814 return k + ':' + codegen(n.value);
|
Daniel@0
|
5815 },
|
Daniel@0
|
5816 'ExpressionStatement': function(n) {
|
Daniel@0
|
5817 return codegen(n.expression);
|
Daniel@0
|
5818 }
|
Daniel@0
|
5819 };
|
Daniel@0
|
5820
|
Daniel@0
|
5821 codegen_wrap.functions = functions;
|
Daniel@0
|
5822 codegen_wrap.constants = constants;
|
Daniel@0
|
5823 return codegen_wrap;
|
Daniel@0
|
5824 };
|
Daniel@0
|
5825
|
Daniel@0
|
5826 },{"./constants":41,"./functions":42}],41:[function(require,module,exports){
|
Daniel@0
|
5827 module.exports = {
|
Daniel@0
|
5828 'NaN': 'NaN',
|
Daniel@0
|
5829 'E': 'Math.E',
|
Daniel@0
|
5830 'LN2': 'Math.LN2',
|
Daniel@0
|
5831 'LN10': 'Math.LN10',
|
Daniel@0
|
5832 'LOG2E': 'Math.LOG2E',
|
Daniel@0
|
5833 'LOG10E': 'Math.LOG10E',
|
Daniel@0
|
5834 'PI': 'Math.PI',
|
Daniel@0
|
5835 'SQRT1_2': 'Math.SQRT1_2',
|
Daniel@0
|
5836 'SQRT2': 'Math.SQRT2'
|
Daniel@0
|
5837 };
|
Daniel@0
|
5838 },{}],42:[function(require,module,exports){
|
Daniel@0
|
5839 module.exports = function(codegen) {
|
Daniel@0
|
5840
|
Daniel@0
|
5841 function fncall(name, args, cast, type) {
|
Daniel@0
|
5842 var obj = codegen(args[0]);
|
Daniel@0
|
5843 if (cast) {
|
Daniel@0
|
5844 obj = cast + '(' + obj + ')';
|
Daniel@0
|
5845 if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
|
Daniel@0
|
5846 }
|
Daniel@0
|
5847 return obj + '.' + name + (type < 0 ? '' : type === 0 ?
|
Daniel@0
|
5848 '()' :
|
Daniel@0
|
5849 '(' + args.slice(1).map(codegen).join(',') + ')');
|
Daniel@0
|
5850 }
|
Daniel@0
|
5851
|
Daniel@0
|
5852 function fn(name, cast, type) {
|
Daniel@0
|
5853 return function(args) {
|
Daniel@0
|
5854 return fncall(name, args, cast, type);
|
Daniel@0
|
5855 };
|
Daniel@0
|
5856 }
|
Daniel@0
|
5857
|
Daniel@0
|
5858 var DATE = 'new Date',
|
Daniel@0
|
5859 STRING = 'String',
|
Daniel@0
|
5860 REGEXP = 'RegExp';
|
Daniel@0
|
5861
|
Daniel@0
|
5862 return {
|
Daniel@0
|
5863 // MATH functions
|
Daniel@0
|
5864 'isNaN': 'isNaN',
|
Daniel@0
|
5865 'isFinite': 'isFinite',
|
Daniel@0
|
5866 'abs': 'Math.abs',
|
Daniel@0
|
5867 'acos': 'Math.acos',
|
Daniel@0
|
5868 'asin': 'Math.asin',
|
Daniel@0
|
5869 'atan': 'Math.atan',
|
Daniel@0
|
5870 'atan2': 'Math.atan2',
|
Daniel@0
|
5871 'ceil': 'Math.ceil',
|
Daniel@0
|
5872 'cos': 'Math.cos',
|
Daniel@0
|
5873 'exp': 'Math.exp',
|
Daniel@0
|
5874 'floor': 'Math.floor',
|
Daniel@0
|
5875 'log': 'Math.log',
|
Daniel@0
|
5876 'max': 'Math.max',
|
Daniel@0
|
5877 'min': 'Math.min',
|
Daniel@0
|
5878 'pow': 'Math.pow',
|
Daniel@0
|
5879 'random': 'Math.random',
|
Daniel@0
|
5880 'round': 'Math.round',
|
Daniel@0
|
5881 'sin': 'Math.sin',
|
Daniel@0
|
5882 'sqrt': 'Math.sqrt',
|
Daniel@0
|
5883 'tan': 'Math.tan',
|
Daniel@0
|
5884
|
Daniel@0
|
5885 'clamp': function(args) {
|
Daniel@0
|
5886 if (args.length < 3)
|
Daniel@0
|
5887 throw new Error('Missing arguments to clamp function.');
|
Daniel@0
|
5888 if (args.length > 3)
|
Daniel@0
|
5889 throw new Error('Too many arguments to clamp function.');
|
Daniel@0
|
5890 var a = args.map(codegen);
|
Daniel@0
|
5891 return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))';
|
Daniel@0
|
5892 },
|
Daniel@0
|
5893
|
Daniel@0
|
5894 // DATE functions
|
Daniel@0
|
5895 'now': 'Date.now',
|
Daniel@0
|
5896 'datetime': DATE,
|
Daniel@0
|
5897 'date': fn('getDate', DATE, 0),
|
Daniel@0
|
5898 'day': fn('getDay', DATE, 0),
|
Daniel@0
|
5899 'year': fn('getFullYear', DATE, 0),
|
Daniel@0
|
5900 'month': fn('getMonth', DATE, 0),
|
Daniel@0
|
5901 'hours': fn('getHours', DATE, 0),
|
Daniel@0
|
5902 'minutes': fn('getMinutes', DATE, 0),
|
Daniel@0
|
5903 'seconds': fn('getSeconds', DATE, 0),
|
Daniel@0
|
5904 'milliseconds': fn('getMilliseconds', DATE, 0),
|
Daniel@0
|
5905 'time': fn('getTime', DATE, 0),
|
Daniel@0
|
5906 'timezoneoffset': fn('getTimezoneOffset', DATE, 0),
|
Daniel@0
|
5907 'utcdate': fn('getUTCDate', DATE, 0),
|
Daniel@0
|
5908 'utcday': fn('getUTCDay', DATE, 0),
|
Daniel@0
|
5909 'utcyear': fn('getUTCFullYear', DATE, 0),
|
Daniel@0
|
5910 'utcmonth': fn('getUTCMonth', DATE, 0),
|
Daniel@0
|
5911 'utchours': fn('getUTCHours', DATE, 0),
|
Daniel@0
|
5912 'utcminutes': fn('getUTCMinutes', DATE, 0),
|
Daniel@0
|
5913 'utcseconds': fn('getUTCSeconds', DATE, 0),
|
Daniel@0
|
5914 'utcmilliseconds': fn('getUTCMilliseconds', DATE, 0),
|
Daniel@0
|
5915
|
Daniel@0
|
5916 // shared sequence functions
|
Daniel@0
|
5917 'length': fn('length', null, -1),
|
Daniel@0
|
5918 'indexof': fn('indexOf', null),
|
Daniel@0
|
5919 'lastindexof': fn('lastIndexOf', null),
|
Daniel@0
|
5920
|
Daniel@0
|
5921 // STRING functions
|
Daniel@0
|
5922 'parseFloat': 'parseFloat',
|
Daniel@0
|
5923 'parseInt': 'parseInt',
|
Daniel@0
|
5924 'upper': fn('toUpperCase', STRING, 0),
|
Daniel@0
|
5925 'lower': fn('toLowerCase', STRING, 0),
|
Daniel@0
|
5926 'slice': fn('slice', STRING),
|
Daniel@0
|
5927 'substring': fn('substring', STRING),
|
Daniel@0
|
5928
|
Daniel@0
|
5929 // REGEXP functions
|
Daniel@0
|
5930 'regexp': REGEXP,
|
Daniel@0
|
5931 'test': fn('test', REGEXP),
|
Daniel@0
|
5932
|
Daniel@0
|
5933 // Control Flow functions
|
Daniel@0
|
5934 'if': function(args) {
|
Daniel@0
|
5935 if (args.length < 3)
|
Daniel@0
|
5936 throw new Error('Missing arguments to if function.');
|
Daniel@0
|
5937 if (args.length > 3)
|
Daniel@0
|
5938 throw new Error('Too many arguments to if function.');
|
Daniel@0
|
5939 var a = args.map(codegen);
|
Daniel@0
|
5940 return a[0]+'?'+a[1]+':'+a[2];
|
Daniel@0
|
5941 }
|
Daniel@0
|
5942 };
|
Daniel@0
|
5943 };
|
Daniel@0
|
5944 },{}],43:[function(require,module,exports){
|
Daniel@0
|
5945 var parser = require('./parser'),
|
Daniel@0
|
5946 codegen = require('./codegen');
|
Daniel@0
|
5947
|
Daniel@0
|
5948 var expr = module.exports = {
|
Daniel@0
|
5949 parse: function(input, opt) {
|
Daniel@0
|
5950 return parser.parse('('+input+')', opt);
|
Daniel@0
|
5951 },
|
Daniel@0
|
5952 code: function(opt) {
|
Daniel@0
|
5953 return codegen(opt);
|
Daniel@0
|
5954 },
|
Daniel@0
|
5955 compiler: function(args, opt) {
|
Daniel@0
|
5956 args = args.slice();
|
Daniel@0
|
5957 var generator = codegen(opt),
|
Daniel@0
|
5958 len = args.length,
|
Daniel@0
|
5959 compile = function(str) {
|
Daniel@0
|
5960 var value = generator(expr.parse(str));
|
Daniel@0
|
5961 args[len] = '"use strict"; return (' + value.code + ');';
|
Daniel@0
|
5962 value.fn = Function.apply(null, args);
|
Daniel@0
|
5963 return value;
|
Daniel@0
|
5964 };
|
Daniel@0
|
5965 compile.codegen = generator;
|
Daniel@0
|
5966 return compile;
|
Daniel@0
|
5967 },
|
Daniel@0
|
5968 functions: require('./functions'),
|
Daniel@0
|
5969 constants: require('./constants')
|
Daniel@0
|
5970 };
|
Daniel@0
|
5971
|
Daniel@0
|
5972 },{"./codegen":40,"./constants":41,"./functions":42,"./parser":44}],44:[function(require,module,exports){
|
Daniel@0
|
5973 /*
|
Daniel@0
|
5974 The following expression parser is based on Esprima (http://esprima.org/).
|
Daniel@0
|
5975 Original header comment and license for Esprima is included here:
|
Daniel@0
|
5976
|
Daniel@0
|
5977 Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
|
Daniel@0
|
5978 Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
|
Daniel@0
|
5979 Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be>
|
Daniel@0
|
5980 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
|
Daniel@0
|
5981 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
|
Daniel@0
|
5982 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
|
Daniel@0
|
5983 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
|
Daniel@0
|
5984 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
|
Daniel@0
|
5985 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
|
Daniel@0
|
5986 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
Daniel@0
|
5987
|
Daniel@0
|
5988 Redistribution and use in source and binary forms, with or without
|
Daniel@0
|
5989 modification, are permitted provided that the following conditions are met:
|
Daniel@0
|
5990
|
Daniel@0
|
5991 * Redistributions of source code must retain the above copyright
|
Daniel@0
|
5992 notice, this list of conditions and the following disclaimer.
|
Daniel@0
|
5993 * Redistributions in binary form must reproduce the above copyright
|
Daniel@0
|
5994 notice, this list of conditions and the following disclaimer in the
|
Daniel@0
|
5995 documentation and/or other materials provided with the distribution.
|
Daniel@0
|
5996
|
Daniel@0
|
5997 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
Daniel@0
|
5998 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
Daniel@0
|
5999 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
Daniel@0
|
6000 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
Daniel@0
|
6001 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
Daniel@0
|
6002 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
Daniel@0
|
6003 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
Daniel@0
|
6004 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
Daniel@0
|
6005 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
Daniel@0
|
6006 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Daniel@0
|
6007 */
|
Daniel@0
|
6008 /* istanbul ignore next */
|
Daniel@0
|
6009 module.exports = (function() {
|
Daniel@0
|
6010 'use strict';
|
Daniel@0
|
6011
|
Daniel@0
|
6012 var Token,
|
Daniel@0
|
6013 TokenName,
|
Daniel@0
|
6014 Syntax,
|
Daniel@0
|
6015 PropertyKind,
|
Daniel@0
|
6016 Messages,
|
Daniel@0
|
6017 Regex,
|
Daniel@0
|
6018 source,
|
Daniel@0
|
6019 strict,
|
Daniel@0
|
6020 index,
|
Daniel@0
|
6021 lineNumber,
|
Daniel@0
|
6022 lineStart,
|
Daniel@0
|
6023 length,
|
Daniel@0
|
6024 lookahead,
|
Daniel@0
|
6025 state,
|
Daniel@0
|
6026 extra;
|
Daniel@0
|
6027
|
Daniel@0
|
6028 Token = {
|
Daniel@0
|
6029 BooleanLiteral: 1,
|
Daniel@0
|
6030 EOF: 2,
|
Daniel@0
|
6031 Identifier: 3,
|
Daniel@0
|
6032 Keyword: 4,
|
Daniel@0
|
6033 NullLiteral: 5,
|
Daniel@0
|
6034 NumericLiteral: 6,
|
Daniel@0
|
6035 Punctuator: 7,
|
Daniel@0
|
6036 StringLiteral: 8,
|
Daniel@0
|
6037 RegularExpression: 9
|
Daniel@0
|
6038 };
|
Daniel@0
|
6039
|
Daniel@0
|
6040 TokenName = {};
|
Daniel@0
|
6041 TokenName[Token.BooleanLiteral] = 'Boolean';
|
Daniel@0
|
6042 TokenName[Token.EOF] = '<end>';
|
Daniel@0
|
6043 TokenName[Token.Identifier] = 'Identifier';
|
Daniel@0
|
6044 TokenName[Token.Keyword] = 'Keyword';
|
Daniel@0
|
6045 TokenName[Token.NullLiteral] = 'Null';
|
Daniel@0
|
6046 TokenName[Token.NumericLiteral] = 'Numeric';
|
Daniel@0
|
6047 TokenName[Token.Punctuator] = 'Punctuator';
|
Daniel@0
|
6048 TokenName[Token.StringLiteral] = 'String';
|
Daniel@0
|
6049 TokenName[Token.RegularExpression] = 'RegularExpression';
|
Daniel@0
|
6050
|
Daniel@0
|
6051 Syntax = {
|
Daniel@0
|
6052 AssignmentExpression: 'AssignmentExpression',
|
Daniel@0
|
6053 ArrayExpression: 'ArrayExpression',
|
Daniel@0
|
6054 BinaryExpression: 'BinaryExpression',
|
Daniel@0
|
6055 CallExpression: 'CallExpression',
|
Daniel@0
|
6056 ConditionalExpression: 'ConditionalExpression',
|
Daniel@0
|
6057 ExpressionStatement: 'ExpressionStatement',
|
Daniel@0
|
6058 Identifier: 'Identifier',
|
Daniel@0
|
6059 Literal: 'Literal',
|
Daniel@0
|
6060 LogicalExpression: 'LogicalExpression',
|
Daniel@0
|
6061 MemberExpression: 'MemberExpression',
|
Daniel@0
|
6062 ObjectExpression: 'ObjectExpression',
|
Daniel@0
|
6063 Program: 'Program',
|
Daniel@0
|
6064 Property: 'Property',
|
Daniel@0
|
6065 UnaryExpression: 'UnaryExpression'
|
Daniel@0
|
6066 };
|
Daniel@0
|
6067
|
Daniel@0
|
6068 PropertyKind = {
|
Daniel@0
|
6069 Data: 1,
|
Daniel@0
|
6070 Get: 2,
|
Daniel@0
|
6071 Set: 4
|
Daniel@0
|
6072 };
|
Daniel@0
|
6073
|
Daniel@0
|
6074 // Error messages should be identical to V8.
|
Daniel@0
|
6075 Messages = {
|
Daniel@0
|
6076 UnexpectedToken: 'Unexpected token %0',
|
Daniel@0
|
6077 UnexpectedNumber: 'Unexpected number',
|
Daniel@0
|
6078 UnexpectedString: 'Unexpected string',
|
Daniel@0
|
6079 UnexpectedIdentifier: 'Unexpected identifier',
|
Daniel@0
|
6080 UnexpectedReserved: 'Unexpected reserved word',
|
Daniel@0
|
6081 UnexpectedEOS: 'Unexpected end of input',
|
Daniel@0
|
6082 NewlineAfterThrow: 'Illegal newline after throw',
|
Daniel@0
|
6083 InvalidRegExp: 'Invalid regular expression',
|
Daniel@0
|
6084 UnterminatedRegExp: 'Invalid regular expression: missing /',
|
Daniel@0
|
6085 InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
|
Daniel@0
|
6086 InvalidLHSInForIn: 'Invalid left-hand side in for-in',
|
Daniel@0
|
6087 MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
|
Daniel@0
|
6088 NoCatchOrFinally: 'Missing catch or finally after try',
|
Daniel@0
|
6089 UnknownLabel: 'Undefined label \'%0\'',
|
Daniel@0
|
6090 Redeclaration: '%0 \'%1\' has already been declared',
|
Daniel@0
|
6091 IllegalContinue: 'Illegal continue statement',
|
Daniel@0
|
6092 IllegalBreak: 'Illegal break statement',
|
Daniel@0
|
6093 IllegalReturn: 'Illegal return statement',
|
Daniel@0
|
6094 StrictModeWith: 'Strict mode code may not include a with statement',
|
Daniel@0
|
6095 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
|
Daniel@0
|
6096 StrictVarName: 'Variable name may not be eval or arguments in strict mode',
|
Daniel@0
|
6097 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
|
Daniel@0
|
6098 StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
|
Daniel@0
|
6099 StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
|
Daniel@0
|
6100 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
|
Daniel@0
|
6101 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
|
Daniel@0
|
6102 StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
|
Daniel@0
|
6103 AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
|
Daniel@0
|
6104 AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
|
Daniel@0
|
6105 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
|
Daniel@0
|
6106 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
|
Daniel@0
|
6107 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
|
Daniel@0
|
6108 StrictReservedWord: 'Use of future reserved word in strict mode'
|
Daniel@0
|
6109 };
|
Daniel@0
|
6110
|
Daniel@0
|
6111 // See also tools/generate-unicode-regex.py.
|
Daniel@0
|
6112 Regex = {
|
Daniel@0
|
6113 NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]'),
|
Daniel@0
|
6114 NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]')
|
Daniel@0
|
6115 };
|
Daniel@0
|
6116
|
Daniel@0
|
6117 // Ensure the condition is true, otherwise throw an error.
|
Daniel@0
|
6118 // This is only to have a better contract semantic, i.e. another safety net
|
Daniel@0
|
6119 // to catch a logic error. The condition shall be fulfilled in normal case.
|
Daniel@0
|
6120 // Do NOT use this to enforce a certain condition on any user input.
|
Daniel@0
|
6121
|
Daniel@0
|
6122 function assert(condition, message) {
|
Daniel@0
|
6123 if (!condition) {
|
Daniel@0
|
6124 throw new Error('ASSERT: ' + message);
|
Daniel@0
|
6125 }
|
Daniel@0
|
6126 }
|
Daniel@0
|
6127
|
Daniel@0
|
6128 function isDecimalDigit(ch) {
|
Daniel@0
|
6129 return (ch >= 0x30 && ch <= 0x39); // 0..9
|
Daniel@0
|
6130 }
|
Daniel@0
|
6131
|
Daniel@0
|
6132 function isHexDigit(ch) {
|
Daniel@0
|
6133 return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
|
Daniel@0
|
6134 }
|
Daniel@0
|
6135
|
Daniel@0
|
6136 function isOctalDigit(ch) {
|
Daniel@0
|
6137 return '01234567'.indexOf(ch) >= 0;
|
Daniel@0
|
6138 }
|
Daniel@0
|
6139
|
Daniel@0
|
6140 // 7.2 White Space
|
Daniel@0
|
6141
|
Daniel@0
|
6142 function isWhiteSpace(ch) {
|
Daniel@0
|
6143 return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
|
Daniel@0
|
6144 (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
|
Daniel@0
|
6145 }
|
Daniel@0
|
6146
|
Daniel@0
|
6147 // 7.3 Line Terminators
|
Daniel@0
|
6148
|
Daniel@0
|
6149 function isLineTerminator(ch) {
|
Daniel@0
|
6150 return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
|
Daniel@0
|
6151 }
|
Daniel@0
|
6152
|
Daniel@0
|
6153 // 7.6 Identifier Names and Identifiers
|
Daniel@0
|
6154
|
Daniel@0
|
6155 function isIdentifierStart(ch) {
|
Daniel@0
|
6156 return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
|
Daniel@0
|
6157 (ch >= 0x41 && ch <= 0x5A) || // A..Z
|
Daniel@0
|
6158 (ch >= 0x61 && ch <= 0x7A) || // a..z
|
Daniel@0
|
6159 (ch === 0x5C) || // \ (backslash)
|
Daniel@0
|
6160 ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
|
Daniel@0
|
6161 }
|
Daniel@0
|
6162
|
Daniel@0
|
6163 function isIdentifierPart(ch) {
|
Daniel@0
|
6164 return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
|
Daniel@0
|
6165 (ch >= 0x41 && ch <= 0x5A) || // A..Z
|
Daniel@0
|
6166 (ch >= 0x61 && ch <= 0x7A) || // a..z
|
Daniel@0
|
6167 (ch >= 0x30 && ch <= 0x39) || // 0..9
|
Daniel@0
|
6168 (ch === 0x5C) || // \ (backslash)
|
Daniel@0
|
6169 ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
|
Daniel@0
|
6170 }
|
Daniel@0
|
6171
|
Daniel@0
|
6172 // 7.6.1.2 Future Reserved Words
|
Daniel@0
|
6173
|
Daniel@0
|
6174 function isFutureReservedWord(id) {
|
Daniel@0
|
6175 switch (id) {
|
Daniel@0
|
6176 case 'class':
|
Daniel@0
|
6177 case 'enum':
|
Daniel@0
|
6178 case 'export':
|
Daniel@0
|
6179 case 'extends':
|
Daniel@0
|
6180 case 'import':
|
Daniel@0
|
6181 case 'super':
|
Daniel@0
|
6182 return true;
|
Daniel@0
|
6183 default:
|
Daniel@0
|
6184 return false;
|
Daniel@0
|
6185 }
|
Daniel@0
|
6186 }
|
Daniel@0
|
6187
|
Daniel@0
|
6188 function isStrictModeReservedWord(id) {
|
Daniel@0
|
6189 switch (id) {
|
Daniel@0
|
6190 case 'implements':
|
Daniel@0
|
6191 case 'interface':
|
Daniel@0
|
6192 case 'package':
|
Daniel@0
|
6193 case 'private':
|
Daniel@0
|
6194 case 'protected':
|
Daniel@0
|
6195 case 'public':
|
Daniel@0
|
6196 case 'static':
|
Daniel@0
|
6197 case 'yield':
|
Daniel@0
|
6198 case 'let':
|
Daniel@0
|
6199 return true;
|
Daniel@0
|
6200 default:
|
Daniel@0
|
6201 return false;
|
Daniel@0
|
6202 }
|
Daniel@0
|
6203 }
|
Daniel@0
|
6204
|
Daniel@0
|
6205 // 7.6.1.1 Keywords
|
Daniel@0
|
6206
|
Daniel@0
|
6207 function isKeyword(id) {
|
Daniel@0
|
6208 if (strict && isStrictModeReservedWord(id)) {
|
Daniel@0
|
6209 return true;
|
Daniel@0
|
6210 }
|
Daniel@0
|
6211
|
Daniel@0
|
6212 // 'const' is specialized as Keyword in V8.
|
Daniel@0
|
6213 // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
|
Daniel@0
|
6214 // Some others are from future reserved words.
|
Daniel@0
|
6215
|
Daniel@0
|
6216 switch (id.length) {
|
Daniel@0
|
6217 case 2:
|
Daniel@0
|
6218 return (id === 'if') || (id === 'in') || (id === 'do');
|
Daniel@0
|
6219 case 3:
|
Daniel@0
|
6220 return (id === 'var') || (id === 'for') || (id === 'new') ||
|
Daniel@0
|
6221 (id === 'try') || (id === 'let');
|
Daniel@0
|
6222 case 4:
|
Daniel@0
|
6223 return (id === 'this') || (id === 'else') || (id === 'case') ||
|
Daniel@0
|
6224 (id === 'void') || (id === 'with') || (id === 'enum');
|
Daniel@0
|
6225 case 5:
|
Daniel@0
|
6226 return (id === 'while') || (id === 'break') || (id === 'catch') ||
|
Daniel@0
|
6227 (id === 'throw') || (id === 'const') || (id === 'yield') ||
|
Daniel@0
|
6228 (id === 'class') || (id === 'super');
|
Daniel@0
|
6229 case 6:
|
Daniel@0
|
6230 return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
|
Daniel@0
|
6231 (id === 'switch') || (id === 'export') || (id === 'import');
|
Daniel@0
|
6232 case 7:
|
Daniel@0
|
6233 return (id === 'default') || (id === 'finally') || (id === 'extends');
|
Daniel@0
|
6234 case 8:
|
Daniel@0
|
6235 return (id === 'function') || (id === 'continue') || (id === 'debugger');
|
Daniel@0
|
6236 case 10:
|
Daniel@0
|
6237 return (id === 'instanceof');
|
Daniel@0
|
6238 default:
|
Daniel@0
|
6239 return false;
|
Daniel@0
|
6240 }
|
Daniel@0
|
6241 }
|
Daniel@0
|
6242
|
Daniel@0
|
6243 function skipComment() {
|
Daniel@0
|
6244 var ch, start;
|
Daniel@0
|
6245
|
Daniel@0
|
6246 start = (index === 0);
|
Daniel@0
|
6247 while (index < length) {
|
Daniel@0
|
6248 ch = source.charCodeAt(index);
|
Daniel@0
|
6249
|
Daniel@0
|
6250 if (isWhiteSpace(ch)) {
|
Daniel@0
|
6251 ++index;
|
Daniel@0
|
6252 } else if (isLineTerminator(ch)) {
|
Daniel@0
|
6253 ++index;
|
Daniel@0
|
6254 if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
|
Daniel@0
|
6255 ++index;
|
Daniel@0
|
6256 }
|
Daniel@0
|
6257 ++lineNumber;
|
Daniel@0
|
6258 lineStart = index;
|
Daniel@0
|
6259 start = true;
|
Daniel@0
|
6260 } else {
|
Daniel@0
|
6261 break;
|
Daniel@0
|
6262 }
|
Daniel@0
|
6263 }
|
Daniel@0
|
6264 }
|
Daniel@0
|
6265
|
Daniel@0
|
6266 function scanHexEscape(prefix) {
|
Daniel@0
|
6267 var i, len, ch, code = 0;
|
Daniel@0
|
6268
|
Daniel@0
|
6269 len = (prefix === 'u') ? 4 : 2;
|
Daniel@0
|
6270 for (i = 0; i < len; ++i) {
|
Daniel@0
|
6271 if (index < length && isHexDigit(source[index])) {
|
Daniel@0
|
6272 ch = source[index++];
|
Daniel@0
|
6273 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
|
Daniel@0
|
6274 } else {
|
Daniel@0
|
6275 return '';
|
Daniel@0
|
6276 }
|
Daniel@0
|
6277 }
|
Daniel@0
|
6278 return String.fromCharCode(code);
|
Daniel@0
|
6279 }
|
Daniel@0
|
6280
|
Daniel@0
|
6281 function scanUnicodeCodePointEscape() {
|
Daniel@0
|
6282 var ch, code, cu1, cu2;
|
Daniel@0
|
6283
|
Daniel@0
|
6284 ch = source[index];
|
Daniel@0
|
6285 code = 0;
|
Daniel@0
|
6286
|
Daniel@0
|
6287 // At least, one hex digit is required.
|
Daniel@0
|
6288 if (ch === '}') {
|
Daniel@0
|
6289 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6290 }
|
Daniel@0
|
6291
|
Daniel@0
|
6292 while (index < length) {
|
Daniel@0
|
6293 ch = source[index++];
|
Daniel@0
|
6294 if (!isHexDigit(ch)) {
|
Daniel@0
|
6295 break;
|
Daniel@0
|
6296 }
|
Daniel@0
|
6297 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
|
Daniel@0
|
6298 }
|
Daniel@0
|
6299
|
Daniel@0
|
6300 if (code > 0x10FFFF || ch !== '}') {
|
Daniel@0
|
6301 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6302 }
|
Daniel@0
|
6303
|
Daniel@0
|
6304 // UTF-16 Encoding
|
Daniel@0
|
6305 if (code <= 0xFFFF) {
|
Daniel@0
|
6306 return String.fromCharCode(code);
|
Daniel@0
|
6307 }
|
Daniel@0
|
6308 cu1 = ((code - 0x10000) >> 10) + 0xD800;
|
Daniel@0
|
6309 cu2 = ((code - 0x10000) & 1023) + 0xDC00;
|
Daniel@0
|
6310 return String.fromCharCode(cu1, cu2);
|
Daniel@0
|
6311 }
|
Daniel@0
|
6312
|
Daniel@0
|
6313 function getEscapedIdentifier() {
|
Daniel@0
|
6314 var ch, id;
|
Daniel@0
|
6315
|
Daniel@0
|
6316 ch = source.charCodeAt(index++);
|
Daniel@0
|
6317 id = String.fromCharCode(ch);
|
Daniel@0
|
6318
|
Daniel@0
|
6319 // '\u' (U+005C, U+0075) denotes an escaped character.
|
Daniel@0
|
6320 if (ch === 0x5C) {
|
Daniel@0
|
6321 if (source.charCodeAt(index) !== 0x75) {
|
Daniel@0
|
6322 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6323 }
|
Daniel@0
|
6324 ++index;
|
Daniel@0
|
6325 ch = scanHexEscape('u');
|
Daniel@0
|
6326 if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
|
Daniel@0
|
6327 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6328 }
|
Daniel@0
|
6329 id = ch;
|
Daniel@0
|
6330 }
|
Daniel@0
|
6331
|
Daniel@0
|
6332 while (index < length) {
|
Daniel@0
|
6333 ch = source.charCodeAt(index);
|
Daniel@0
|
6334 if (!isIdentifierPart(ch)) {
|
Daniel@0
|
6335 break;
|
Daniel@0
|
6336 }
|
Daniel@0
|
6337 ++index;
|
Daniel@0
|
6338 id += String.fromCharCode(ch);
|
Daniel@0
|
6339
|
Daniel@0
|
6340 // '\u' (U+005C, U+0075) denotes an escaped character.
|
Daniel@0
|
6341 if (ch === 0x5C) {
|
Daniel@0
|
6342 id = id.substr(0, id.length - 1);
|
Daniel@0
|
6343 if (source.charCodeAt(index) !== 0x75) {
|
Daniel@0
|
6344 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6345 }
|
Daniel@0
|
6346 ++index;
|
Daniel@0
|
6347 ch = scanHexEscape('u');
|
Daniel@0
|
6348 if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
|
Daniel@0
|
6349 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6350 }
|
Daniel@0
|
6351 id += ch;
|
Daniel@0
|
6352 }
|
Daniel@0
|
6353 }
|
Daniel@0
|
6354
|
Daniel@0
|
6355 return id;
|
Daniel@0
|
6356 }
|
Daniel@0
|
6357
|
Daniel@0
|
6358 function getIdentifier() {
|
Daniel@0
|
6359 var start, ch;
|
Daniel@0
|
6360
|
Daniel@0
|
6361 start = index++;
|
Daniel@0
|
6362 while (index < length) {
|
Daniel@0
|
6363 ch = source.charCodeAt(index);
|
Daniel@0
|
6364 if (ch === 0x5C) {
|
Daniel@0
|
6365 // Blackslash (U+005C) marks Unicode escape sequence.
|
Daniel@0
|
6366 index = start;
|
Daniel@0
|
6367 return getEscapedIdentifier();
|
Daniel@0
|
6368 }
|
Daniel@0
|
6369 if (isIdentifierPart(ch)) {
|
Daniel@0
|
6370 ++index;
|
Daniel@0
|
6371 } else {
|
Daniel@0
|
6372 break;
|
Daniel@0
|
6373 }
|
Daniel@0
|
6374 }
|
Daniel@0
|
6375
|
Daniel@0
|
6376 return source.slice(start, index);
|
Daniel@0
|
6377 }
|
Daniel@0
|
6378
|
Daniel@0
|
6379 function scanIdentifier() {
|
Daniel@0
|
6380 var start, id, type;
|
Daniel@0
|
6381
|
Daniel@0
|
6382 start = index;
|
Daniel@0
|
6383
|
Daniel@0
|
6384 // Backslash (U+005C) starts an escaped character.
|
Daniel@0
|
6385 id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier();
|
Daniel@0
|
6386
|
Daniel@0
|
6387 // There is no keyword or literal with only one character.
|
Daniel@0
|
6388 // Thus, it must be an identifier.
|
Daniel@0
|
6389 if (id.length === 1) {
|
Daniel@0
|
6390 type = Token.Identifier;
|
Daniel@0
|
6391 } else if (isKeyword(id)) {
|
Daniel@0
|
6392 type = Token.Keyword;
|
Daniel@0
|
6393 } else if (id === 'null') {
|
Daniel@0
|
6394 type = Token.NullLiteral;
|
Daniel@0
|
6395 } else if (id === 'true' || id === 'false') {
|
Daniel@0
|
6396 type = Token.BooleanLiteral;
|
Daniel@0
|
6397 } else {
|
Daniel@0
|
6398 type = Token.Identifier;
|
Daniel@0
|
6399 }
|
Daniel@0
|
6400
|
Daniel@0
|
6401 return {
|
Daniel@0
|
6402 type: type,
|
Daniel@0
|
6403 value: id,
|
Daniel@0
|
6404 lineNumber: lineNumber,
|
Daniel@0
|
6405 lineStart: lineStart,
|
Daniel@0
|
6406 start: start,
|
Daniel@0
|
6407 end: index
|
Daniel@0
|
6408 };
|
Daniel@0
|
6409 }
|
Daniel@0
|
6410
|
Daniel@0
|
6411 // 7.7 Punctuators
|
Daniel@0
|
6412
|
Daniel@0
|
6413 function scanPunctuator() {
|
Daniel@0
|
6414 var start = index,
|
Daniel@0
|
6415 code = source.charCodeAt(index),
|
Daniel@0
|
6416 code2,
|
Daniel@0
|
6417 ch1 = source[index],
|
Daniel@0
|
6418 ch2,
|
Daniel@0
|
6419 ch3,
|
Daniel@0
|
6420 ch4;
|
Daniel@0
|
6421
|
Daniel@0
|
6422 switch (code) {
|
Daniel@0
|
6423
|
Daniel@0
|
6424 // Check for most common single-character punctuators.
|
Daniel@0
|
6425 case 0x2E: // . dot
|
Daniel@0
|
6426 case 0x28: // ( open bracket
|
Daniel@0
|
6427 case 0x29: // ) close bracket
|
Daniel@0
|
6428 case 0x3B: // ; semicolon
|
Daniel@0
|
6429 case 0x2C: // , comma
|
Daniel@0
|
6430 case 0x7B: // { open curly brace
|
Daniel@0
|
6431 case 0x7D: // } close curly brace
|
Daniel@0
|
6432 case 0x5B: // [
|
Daniel@0
|
6433 case 0x5D: // ]
|
Daniel@0
|
6434 case 0x3A: // :
|
Daniel@0
|
6435 case 0x3F: // ?
|
Daniel@0
|
6436 case 0x7E: // ~
|
Daniel@0
|
6437 ++index;
|
Daniel@0
|
6438 if (extra.tokenize) {
|
Daniel@0
|
6439 if (code === 0x28) {
|
Daniel@0
|
6440 extra.openParenToken = extra.tokens.length;
|
Daniel@0
|
6441 } else if (code === 0x7B) {
|
Daniel@0
|
6442 extra.openCurlyToken = extra.tokens.length;
|
Daniel@0
|
6443 }
|
Daniel@0
|
6444 }
|
Daniel@0
|
6445 return {
|
Daniel@0
|
6446 type: Token.Punctuator,
|
Daniel@0
|
6447 value: String.fromCharCode(code),
|
Daniel@0
|
6448 lineNumber: lineNumber,
|
Daniel@0
|
6449 lineStart: lineStart,
|
Daniel@0
|
6450 start: start,
|
Daniel@0
|
6451 end: index
|
Daniel@0
|
6452 };
|
Daniel@0
|
6453
|
Daniel@0
|
6454 default:
|
Daniel@0
|
6455 code2 = source.charCodeAt(index + 1);
|
Daniel@0
|
6456
|
Daniel@0
|
6457 // '=' (U+003D) marks an assignment or comparison operator.
|
Daniel@0
|
6458 if (code2 === 0x3D) {
|
Daniel@0
|
6459 switch (code) {
|
Daniel@0
|
6460 case 0x2B: // +
|
Daniel@0
|
6461 case 0x2D: // -
|
Daniel@0
|
6462 case 0x2F: // /
|
Daniel@0
|
6463 case 0x3C: // <
|
Daniel@0
|
6464 case 0x3E: // >
|
Daniel@0
|
6465 case 0x5E: // ^
|
Daniel@0
|
6466 case 0x7C: // |
|
Daniel@0
|
6467 case 0x25: // %
|
Daniel@0
|
6468 case 0x26: // &
|
Daniel@0
|
6469 case 0x2A: // *
|
Daniel@0
|
6470 index += 2;
|
Daniel@0
|
6471 return {
|
Daniel@0
|
6472 type: Token.Punctuator,
|
Daniel@0
|
6473 value: String.fromCharCode(code) + String.fromCharCode(code2),
|
Daniel@0
|
6474 lineNumber: lineNumber,
|
Daniel@0
|
6475 lineStart: lineStart,
|
Daniel@0
|
6476 start: start,
|
Daniel@0
|
6477 end: index
|
Daniel@0
|
6478 };
|
Daniel@0
|
6479
|
Daniel@0
|
6480 case 0x21: // !
|
Daniel@0
|
6481 case 0x3D: // =
|
Daniel@0
|
6482 index += 2;
|
Daniel@0
|
6483
|
Daniel@0
|
6484 // !== and ===
|
Daniel@0
|
6485 if (source.charCodeAt(index) === 0x3D) {
|
Daniel@0
|
6486 ++index;
|
Daniel@0
|
6487 }
|
Daniel@0
|
6488 return {
|
Daniel@0
|
6489 type: Token.Punctuator,
|
Daniel@0
|
6490 value: source.slice(start, index),
|
Daniel@0
|
6491 lineNumber: lineNumber,
|
Daniel@0
|
6492 lineStart: lineStart,
|
Daniel@0
|
6493 start: start,
|
Daniel@0
|
6494 end: index
|
Daniel@0
|
6495 };
|
Daniel@0
|
6496 }
|
Daniel@0
|
6497 }
|
Daniel@0
|
6498 }
|
Daniel@0
|
6499
|
Daniel@0
|
6500 // 4-character punctuator: >>>=
|
Daniel@0
|
6501
|
Daniel@0
|
6502 ch4 = source.substr(index, 4);
|
Daniel@0
|
6503
|
Daniel@0
|
6504 if (ch4 === '>>>=') {
|
Daniel@0
|
6505 index += 4;
|
Daniel@0
|
6506 return {
|
Daniel@0
|
6507 type: Token.Punctuator,
|
Daniel@0
|
6508 value: ch4,
|
Daniel@0
|
6509 lineNumber: lineNumber,
|
Daniel@0
|
6510 lineStart: lineStart,
|
Daniel@0
|
6511 start: start,
|
Daniel@0
|
6512 end: index
|
Daniel@0
|
6513 };
|
Daniel@0
|
6514 }
|
Daniel@0
|
6515
|
Daniel@0
|
6516 // 3-character punctuators: === !== >>> <<= >>=
|
Daniel@0
|
6517
|
Daniel@0
|
6518 ch3 = ch4.substr(0, 3);
|
Daniel@0
|
6519
|
Daniel@0
|
6520 if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
|
Daniel@0
|
6521 index += 3;
|
Daniel@0
|
6522 return {
|
Daniel@0
|
6523 type: Token.Punctuator,
|
Daniel@0
|
6524 value: ch3,
|
Daniel@0
|
6525 lineNumber: lineNumber,
|
Daniel@0
|
6526 lineStart: lineStart,
|
Daniel@0
|
6527 start: start,
|
Daniel@0
|
6528 end: index
|
Daniel@0
|
6529 };
|
Daniel@0
|
6530 }
|
Daniel@0
|
6531
|
Daniel@0
|
6532 // Other 2-character punctuators: ++ -- << >> && ||
|
Daniel@0
|
6533 ch2 = ch3.substr(0, 2);
|
Daniel@0
|
6534
|
Daniel@0
|
6535 if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') {
|
Daniel@0
|
6536 index += 2;
|
Daniel@0
|
6537 return {
|
Daniel@0
|
6538 type: Token.Punctuator,
|
Daniel@0
|
6539 value: ch2,
|
Daniel@0
|
6540 lineNumber: lineNumber,
|
Daniel@0
|
6541 lineStart: lineStart,
|
Daniel@0
|
6542 start: start,
|
Daniel@0
|
6543 end: index
|
Daniel@0
|
6544 };
|
Daniel@0
|
6545 }
|
Daniel@0
|
6546
|
Daniel@0
|
6547 // 1-character punctuators: < > = ! + - * % & | ^ /
|
Daniel@0
|
6548
|
Daniel@0
|
6549 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
|
Daniel@0
|
6550 ++index;
|
Daniel@0
|
6551 return {
|
Daniel@0
|
6552 type: Token.Punctuator,
|
Daniel@0
|
6553 value: ch1,
|
Daniel@0
|
6554 lineNumber: lineNumber,
|
Daniel@0
|
6555 lineStart: lineStart,
|
Daniel@0
|
6556 start: start,
|
Daniel@0
|
6557 end: index
|
Daniel@0
|
6558 };
|
Daniel@0
|
6559 }
|
Daniel@0
|
6560
|
Daniel@0
|
6561 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6562 }
|
Daniel@0
|
6563
|
Daniel@0
|
6564 // 7.8.3 Numeric Literals
|
Daniel@0
|
6565
|
Daniel@0
|
6566 function scanHexLiteral(start) {
|
Daniel@0
|
6567 var number = '';
|
Daniel@0
|
6568
|
Daniel@0
|
6569 while (index < length) {
|
Daniel@0
|
6570 if (!isHexDigit(source[index])) {
|
Daniel@0
|
6571 break;
|
Daniel@0
|
6572 }
|
Daniel@0
|
6573 number += source[index++];
|
Daniel@0
|
6574 }
|
Daniel@0
|
6575
|
Daniel@0
|
6576 if (number.length === 0) {
|
Daniel@0
|
6577 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6578 }
|
Daniel@0
|
6579
|
Daniel@0
|
6580 if (isIdentifierStart(source.charCodeAt(index))) {
|
Daniel@0
|
6581 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6582 }
|
Daniel@0
|
6583
|
Daniel@0
|
6584 return {
|
Daniel@0
|
6585 type: Token.NumericLiteral,
|
Daniel@0
|
6586 value: parseInt('0x' + number, 16),
|
Daniel@0
|
6587 lineNumber: lineNumber,
|
Daniel@0
|
6588 lineStart: lineStart,
|
Daniel@0
|
6589 start: start,
|
Daniel@0
|
6590 end: index
|
Daniel@0
|
6591 };
|
Daniel@0
|
6592 }
|
Daniel@0
|
6593
|
Daniel@0
|
6594 function scanOctalLiteral(start) {
|
Daniel@0
|
6595 var number = '0' + source[index++];
|
Daniel@0
|
6596 while (index < length) {
|
Daniel@0
|
6597 if (!isOctalDigit(source[index])) {
|
Daniel@0
|
6598 break;
|
Daniel@0
|
6599 }
|
Daniel@0
|
6600 number += source[index++];
|
Daniel@0
|
6601 }
|
Daniel@0
|
6602
|
Daniel@0
|
6603 if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
|
Daniel@0
|
6604 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6605 }
|
Daniel@0
|
6606
|
Daniel@0
|
6607 return {
|
Daniel@0
|
6608 type: Token.NumericLiteral,
|
Daniel@0
|
6609 value: parseInt(number, 8),
|
Daniel@0
|
6610 octal: true,
|
Daniel@0
|
6611 lineNumber: lineNumber,
|
Daniel@0
|
6612 lineStart: lineStart,
|
Daniel@0
|
6613 start: start,
|
Daniel@0
|
6614 end: index
|
Daniel@0
|
6615 };
|
Daniel@0
|
6616 }
|
Daniel@0
|
6617
|
Daniel@0
|
6618 function scanNumericLiteral() {
|
Daniel@0
|
6619 var number, start, ch;
|
Daniel@0
|
6620
|
Daniel@0
|
6621 ch = source[index];
|
Daniel@0
|
6622 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
|
Daniel@0
|
6623 'Numeric literal must start with a decimal digit or a decimal point');
|
Daniel@0
|
6624
|
Daniel@0
|
6625 start = index;
|
Daniel@0
|
6626 number = '';
|
Daniel@0
|
6627 if (ch !== '.') {
|
Daniel@0
|
6628 number = source[index++];
|
Daniel@0
|
6629 ch = source[index];
|
Daniel@0
|
6630
|
Daniel@0
|
6631 // Hex number starts with '0x'.
|
Daniel@0
|
6632 // Octal number starts with '0'.
|
Daniel@0
|
6633 if (number === '0') {
|
Daniel@0
|
6634 if (ch === 'x' || ch === 'X') {
|
Daniel@0
|
6635 ++index;
|
Daniel@0
|
6636 return scanHexLiteral(start);
|
Daniel@0
|
6637 }
|
Daniel@0
|
6638 if (isOctalDigit(ch)) {
|
Daniel@0
|
6639 return scanOctalLiteral(start);
|
Daniel@0
|
6640 }
|
Daniel@0
|
6641
|
Daniel@0
|
6642 // decimal number starts with '0' such as '09' is illegal.
|
Daniel@0
|
6643 if (ch && isDecimalDigit(ch.charCodeAt(0))) {
|
Daniel@0
|
6644 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6645 }
|
Daniel@0
|
6646 }
|
Daniel@0
|
6647
|
Daniel@0
|
6648 while (isDecimalDigit(source.charCodeAt(index))) {
|
Daniel@0
|
6649 number += source[index++];
|
Daniel@0
|
6650 }
|
Daniel@0
|
6651 ch = source[index];
|
Daniel@0
|
6652 }
|
Daniel@0
|
6653
|
Daniel@0
|
6654 if (ch === '.') {
|
Daniel@0
|
6655 number += source[index++];
|
Daniel@0
|
6656 while (isDecimalDigit(source.charCodeAt(index))) {
|
Daniel@0
|
6657 number += source[index++];
|
Daniel@0
|
6658 }
|
Daniel@0
|
6659 ch = source[index];
|
Daniel@0
|
6660 }
|
Daniel@0
|
6661
|
Daniel@0
|
6662 if (ch === 'e' || ch === 'E') {
|
Daniel@0
|
6663 number += source[index++];
|
Daniel@0
|
6664
|
Daniel@0
|
6665 ch = source[index];
|
Daniel@0
|
6666 if (ch === '+' || ch === '-') {
|
Daniel@0
|
6667 number += source[index++];
|
Daniel@0
|
6668 }
|
Daniel@0
|
6669 if (isDecimalDigit(source.charCodeAt(index))) {
|
Daniel@0
|
6670 while (isDecimalDigit(source.charCodeAt(index))) {
|
Daniel@0
|
6671 number += source[index++];
|
Daniel@0
|
6672 }
|
Daniel@0
|
6673 } else {
|
Daniel@0
|
6674 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6675 }
|
Daniel@0
|
6676 }
|
Daniel@0
|
6677
|
Daniel@0
|
6678 if (isIdentifierStart(source.charCodeAt(index))) {
|
Daniel@0
|
6679 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6680 }
|
Daniel@0
|
6681
|
Daniel@0
|
6682 return {
|
Daniel@0
|
6683 type: Token.NumericLiteral,
|
Daniel@0
|
6684 value: parseFloat(number),
|
Daniel@0
|
6685 lineNumber: lineNumber,
|
Daniel@0
|
6686 lineStart: lineStart,
|
Daniel@0
|
6687 start: start,
|
Daniel@0
|
6688 end: index
|
Daniel@0
|
6689 };
|
Daniel@0
|
6690 }
|
Daniel@0
|
6691
|
Daniel@0
|
6692 // 7.8.4 String Literals
|
Daniel@0
|
6693
|
Daniel@0
|
6694 function scanStringLiteral() {
|
Daniel@0
|
6695 var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart;
|
Daniel@0
|
6696 startLineNumber = lineNumber;
|
Daniel@0
|
6697 startLineStart = lineStart;
|
Daniel@0
|
6698
|
Daniel@0
|
6699 quote = source[index];
|
Daniel@0
|
6700 assert((quote === '\'' || quote === '"'),
|
Daniel@0
|
6701 'String literal must starts with a quote');
|
Daniel@0
|
6702
|
Daniel@0
|
6703 start = index;
|
Daniel@0
|
6704 ++index;
|
Daniel@0
|
6705
|
Daniel@0
|
6706 while (index < length) {
|
Daniel@0
|
6707 ch = source[index++];
|
Daniel@0
|
6708
|
Daniel@0
|
6709 if (ch === quote) {
|
Daniel@0
|
6710 quote = '';
|
Daniel@0
|
6711 break;
|
Daniel@0
|
6712 } else if (ch === '\\') {
|
Daniel@0
|
6713 ch = source[index++];
|
Daniel@0
|
6714 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
|
Daniel@0
|
6715 switch (ch) {
|
Daniel@0
|
6716 case 'u':
|
Daniel@0
|
6717 case 'x':
|
Daniel@0
|
6718 if (source[index] === '{') {
|
Daniel@0
|
6719 ++index;
|
Daniel@0
|
6720 str += scanUnicodeCodePointEscape();
|
Daniel@0
|
6721 } else {
|
Daniel@0
|
6722 restore = index;
|
Daniel@0
|
6723 unescaped = scanHexEscape(ch);
|
Daniel@0
|
6724 if (unescaped) {
|
Daniel@0
|
6725 str += unescaped;
|
Daniel@0
|
6726 } else {
|
Daniel@0
|
6727 index = restore;
|
Daniel@0
|
6728 str += ch;
|
Daniel@0
|
6729 }
|
Daniel@0
|
6730 }
|
Daniel@0
|
6731 break;
|
Daniel@0
|
6732 case 'n':
|
Daniel@0
|
6733 str += '\n';
|
Daniel@0
|
6734 break;
|
Daniel@0
|
6735 case 'r':
|
Daniel@0
|
6736 str += '\r';
|
Daniel@0
|
6737 break;
|
Daniel@0
|
6738 case 't':
|
Daniel@0
|
6739 str += '\t';
|
Daniel@0
|
6740 break;
|
Daniel@0
|
6741 case 'b':
|
Daniel@0
|
6742 str += '\b';
|
Daniel@0
|
6743 break;
|
Daniel@0
|
6744 case 'f':
|
Daniel@0
|
6745 str += '\f';
|
Daniel@0
|
6746 break;
|
Daniel@0
|
6747 case 'v':
|
Daniel@0
|
6748 str += '\x0B';
|
Daniel@0
|
6749 break;
|
Daniel@0
|
6750
|
Daniel@0
|
6751 default:
|
Daniel@0
|
6752 if (isOctalDigit(ch)) {
|
Daniel@0
|
6753 code = '01234567'.indexOf(ch);
|
Daniel@0
|
6754
|
Daniel@0
|
6755 // \0 is not octal escape sequence
|
Daniel@0
|
6756 if (code !== 0) {
|
Daniel@0
|
6757 octal = true;
|
Daniel@0
|
6758 }
|
Daniel@0
|
6759
|
Daniel@0
|
6760 if (index < length && isOctalDigit(source[index])) {
|
Daniel@0
|
6761 octal = true;
|
Daniel@0
|
6762 code = code * 8 + '01234567'.indexOf(source[index++]);
|
Daniel@0
|
6763
|
Daniel@0
|
6764 // 3 digits are only allowed when string starts
|
Daniel@0
|
6765 // with 0, 1, 2, 3
|
Daniel@0
|
6766 if ('0123'.indexOf(ch) >= 0 &&
|
Daniel@0
|
6767 index < length &&
|
Daniel@0
|
6768 isOctalDigit(source[index])) {
|
Daniel@0
|
6769 code = code * 8 + '01234567'.indexOf(source[index++]);
|
Daniel@0
|
6770 }
|
Daniel@0
|
6771 }
|
Daniel@0
|
6772 str += String.fromCharCode(code);
|
Daniel@0
|
6773 } else {
|
Daniel@0
|
6774 str += ch;
|
Daniel@0
|
6775 }
|
Daniel@0
|
6776 break;
|
Daniel@0
|
6777 }
|
Daniel@0
|
6778 } else {
|
Daniel@0
|
6779 ++lineNumber;
|
Daniel@0
|
6780 if (ch === '\r' && source[index] === '\n') {
|
Daniel@0
|
6781 ++index;
|
Daniel@0
|
6782 }
|
Daniel@0
|
6783 lineStart = index;
|
Daniel@0
|
6784 }
|
Daniel@0
|
6785 } else if (isLineTerminator(ch.charCodeAt(0))) {
|
Daniel@0
|
6786 break;
|
Daniel@0
|
6787 } else {
|
Daniel@0
|
6788 str += ch;
|
Daniel@0
|
6789 }
|
Daniel@0
|
6790 }
|
Daniel@0
|
6791
|
Daniel@0
|
6792 if (quote !== '') {
|
Daniel@0
|
6793 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6794 }
|
Daniel@0
|
6795
|
Daniel@0
|
6796 return {
|
Daniel@0
|
6797 type: Token.StringLiteral,
|
Daniel@0
|
6798 value: str,
|
Daniel@0
|
6799 octal: octal,
|
Daniel@0
|
6800 startLineNumber: startLineNumber,
|
Daniel@0
|
6801 startLineStart: startLineStart,
|
Daniel@0
|
6802 lineNumber: lineNumber,
|
Daniel@0
|
6803 lineStart: lineStart,
|
Daniel@0
|
6804 start: start,
|
Daniel@0
|
6805 end: index
|
Daniel@0
|
6806 };
|
Daniel@0
|
6807 }
|
Daniel@0
|
6808
|
Daniel@0
|
6809 function testRegExp(pattern, flags) {
|
Daniel@0
|
6810 var tmp = pattern,
|
Daniel@0
|
6811 value;
|
Daniel@0
|
6812
|
Daniel@0
|
6813 if (flags.indexOf('u') >= 0) {
|
Daniel@0
|
6814 // Replace each astral symbol and every Unicode code point
|
Daniel@0
|
6815 // escape sequence with a single ASCII symbol to avoid throwing on
|
Daniel@0
|
6816 // regular expressions that are only valid in combination with the
|
Daniel@0
|
6817 // `/u` flag.
|
Daniel@0
|
6818 // Note: replacing with the ASCII symbol `x` might cause false
|
Daniel@0
|
6819 // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
|
Daniel@0
|
6820 // perfectly valid pattern that is equivalent to `[a-b]`, but it
|
Daniel@0
|
6821 // would be replaced by `[x-b]` which throws an error.
|
Daniel@0
|
6822 tmp = tmp
|
Daniel@0
|
6823 .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
|
Daniel@0
|
6824 if (parseInt($1, 16) <= 0x10FFFF) {
|
Daniel@0
|
6825 return 'x';
|
Daniel@0
|
6826 }
|
Daniel@0
|
6827 throwError({}, Messages.InvalidRegExp);
|
Daniel@0
|
6828 })
|
Daniel@0
|
6829 .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
|
Daniel@0
|
6830 }
|
Daniel@0
|
6831
|
Daniel@0
|
6832 // First, detect invalid regular expressions.
|
Daniel@0
|
6833 try {
|
Daniel@0
|
6834 value = new RegExp(tmp);
|
Daniel@0
|
6835 } catch (e) {
|
Daniel@0
|
6836 throwError({}, Messages.InvalidRegExp);
|
Daniel@0
|
6837 }
|
Daniel@0
|
6838
|
Daniel@0
|
6839 // Return a regular expression object for this pattern-flag pair, or
|
Daniel@0
|
6840 // `null` in case the current environment doesn't support the flags it
|
Daniel@0
|
6841 // uses.
|
Daniel@0
|
6842 try {
|
Daniel@0
|
6843 return new RegExp(pattern, flags);
|
Daniel@0
|
6844 } catch (exception) {
|
Daniel@0
|
6845 return null;
|
Daniel@0
|
6846 }
|
Daniel@0
|
6847 }
|
Daniel@0
|
6848
|
Daniel@0
|
6849 function scanRegExpBody() {
|
Daniel@0
|
6850 var ch, str, classMarker, terminated, body;
|
Daniel@0
|
6851
|
Daniel@0
|
6852 ch = source[index];
|
Daniel@0
|
6853 assert(ch === '/', 'Regular expression literal must start with a slash');
|
Daniel@0
|
6854 str = source[index++];
|
Daniel@0
|
6855
|
Daniel@0
|
6856 classMarker = false;
|
Daniel@0
|
6857 terminated = false;
|
Daniel@0
|
6858 while (index < length) {
|
Daniel@0
|
6859 ch = source[index++];
|
Daniel@0
|
6860 str += ch;
|
Daniel@0
|
6861 if (ch === '\\') {
|
Daniel@0
|
6862 ch = source[index++];
|
Daniel@0
|
6863 // ECMA-262 7.8.5
|
Daniel@0
|
6864 if (isLineTerminator(ch.charCodeAt(0))) {
|
Daniel@0
|
6865 throwError({}, Messages.UnterminatedRegExp);
|
Daniel@0
|
6866 }
|
Daniel@0
|
6867 str += ch;
|
Daniel@0
|
6868 } else if (isLineTerminator(ch.charCodeAt(0))) {
|
Daniel@0
|
6869 throwError({}, Messages.UnterminatedRegExp);
|
Daniel@0
|
6870 } else if (classMarker) {
|
Daniel@0
|
6871 if (ch === ']') {
|
Daniel@0
|
6872 classMarker = false;
|
Daniel@0
|
6873 }
|
Daniel@0
|
6874 } else {
|
Daniel@0
|
6875 if (ch === '/') {
|
Daniel@0
|
6876 terminated = true;
|
Daniel@0
|
6877 break;
|
Daniel@0
|
6878 } else if (ch === '[') {
|
Daniel@0
|
6879 classMarker = true;
|
Daniel@0
|
6880 }
|
Daniel@0
|
6881 }
|
Daniel@0
|
6882 }
|
Daniel@0
|
6883
|
Daniel@0
|
6884 if (!terminated) {
|
Daniel@0
|
6885 throwError({}, Messages.UnterminatedRegExp);
|
Daniel@0
|
6886 }
|
Daniel@0
|
6887
|
Daniel@0
|
6888 // Exclude leading and trailing slash.
|
Daniel@0
|
6889 body = str.substr(1, str.length - 2);
|
Daniel@0
|
6890 return {
|
Daniel@0
|
6891 value: body,
|
Daniel@0
|
6892 literal: str
|
Daniel@0
|
6893 };
|
Daniel@0
|
6894 }
|
Daniel@0
|
6895
|
Daniel@0
|
6896 function scanRegExpFlags() {
|
Daniel@0
|
6897 var ch, str, flags, restore;
|
Daniel@0
|
6898
|
Daniel@0
|
6899 str = '';
|
Daniel@0
|
6900 flags = '';
|
Daniel@0
|
6901 while (index < length) {
|
Daniel@0
|
6902 ch = source[index];
|
Daniel@0
|
6903 if (!isIdentifierPart(ch.charCodeAt(0))) {
|
Daniel@0
|
6904 break;
|
Daniel@0
|
6905 }
|
Daniel@0
|
6906
|
Daniel@0
|
6907 ++index;
|
Daniel@0
|
6908 if (ch === '\\' && index < length) {
|
Daniel@0
|
6909 ch = source[index];
|
Daniel@0
|
6910 if (ch === 'u') {
|
Daniel@0
|
6911 ++index;
|
Daniel@0
|
6912 restore = index;
|
Daniel@0
|
6913 ch = scanHexEscape('u');
|
Daniel@0
|
6914 if (ch) {
|
Daniel@0
|
6915 flags += ch;
|
Daniel@0
|
6916 for (str += '\\u'; restore < index; ++restore) {
|
Daniel@0
|
6917 str += source[restore];
|
Daniel@0
|
6918 }
|
Daniel@0
|
6919 } else {
|
Daniel@0
|
6920 index = restore;
|
Daniel@0
|
6921 flags += 'u';
|
Daniel@0
|
6922 str += '\\u';
|
Daniel@0
|
6923 }
|
Daniel@0
|
6924 throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6925 } else {
|
Daniel@0
|
6926 str += '\\';
|
Daniel@0
|
6927 throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
|
Daniel@0
|
6928 }
|
Daniel@0
|
6929 } else {
|
Daniel@0
|
6930 flags += ch;
|
Daniel@0
|
6931 str += ch;
|
Daniel@0
|
6932 }
|
Daniel@0
|
6933 }
|
Daniel@0
|
6934
|
Daniel@0
|
6935 return {
|
Daniel@0
|
6936 value: flags,
|
Daniel@0
|
6937 literal: str
|
Daniel@0
|
6938 };
|
Daniel@0
|
6939 }
|
Daniel@0
|
6940
|
Daniel@0
|
6941 function scanRegExp() {
|
Daniel@0
|
6942 var start, body, flags, value;
|
Daniel@0
|
6943
|
Daniel@0
|
6944 lookahead = null;
|
Daniel@0
|
6945 skipComment();
|
Daniel@0
|
6946 start = index;
|
Daniel@0
|
6947
|
Daniel@0
|
6948 body = scanRegExpBody();
|
Daniel@0
|
6949 flags = scanRegExpFlags();
|
Daniel@0
|
6950 value = testRegExp(body.value, flags.value);
|
Daniel@0
|
6951
|
Daniel@0
|
6952 if (extra.tokenize) {
|
Daniel@0
|
6953 return {
|
Daniel@0
|
6954 type: Token.RegularExpression,
|
Daniel@0
|
6955 value: value,
|
Daniel@0
|
6956 regex: {
|
Daniel@0
|
6957 pattern: body.value,
|
Daniel@0
|
6958 flags: flags.value
|
Daniel@0
|
6959 },
|
Daniel@0
|
6960 lineNumber: lineNumber,
|
Daniel@0
|
6961 lineStart: lineStart,
|
Daniel@0
|
6962 start: start,
|
Daniel@0
|
6963 end: index
|
Daniel@0
|
6964 };
|
Daniel@0
|
6965 }
|
Daniel@0
|
6966
|
Daniel@0
|
6967 return {
|
Daniel@0
|
6968 literal: body.literal + flags.literal,
|
Daniel@0
|
6969 value: value,
|
Daniel@0
|
6970 regex: {
|
Daniel@0
|
6971 pattern: body.value,
|
Daniel@0
|
6972 flags: flags.value
|
Daniel@0
|
6973 },
|
Daniel@0
|
6974 start: start,
|
Daniel@0
|
6975 end: index
|
Daniel@0
|
6976 };
|
Daniel@0
|
6977 }
|
Daniel@0
|
6978
|
Daniel@0
|
6979 function collectRegex() {
|
Daniel@0
|
6980 var pos, loc, regex, token;
|
Daniel@0
|
6981
|
Daniel@0
|
6982 skipComment();
|
Daniel@0
|
6983
|
Daniel@0
|
6984 pos = index;
|
Daniel@0
|
6985 loc = {
|
Daniel@0
|
6986 start: {
|
Daniel@0
|
6987 line: lineNumber,
|
Daniel@0
|
6988 column: index - lineStart
|
Daniel@0
|
6989 }
|
Daniel@0
|
6990 };
|
Daniel@0
|
6991
|
Daniel@0
|
6992 regex = scanRegExp();
|
Daniel@0
|
6993
|
Daniel@0
|
6994 loc.end = {
|
Daniel@0
|
6995 line: lineNumber,
|
Daniel@0
|
6996 column: index - lineStart
|
Daniel@0
|
6997 };
|
Daniel@0
|
6998
|
Daniel@0
|
6999 if (!extra.tokenize) {
|
Daniel@0
|
7000 // Pop the previous token, which is likely '/' or '/='
|
Daniel@0
|
7001 if (extra.tokens.length > 0) {
|
Daniel@0
|
7002 token = extra.tokens[extra.tokens.length - 1];
|
Daniel@0
|
7003 if (token.range[0] === pos && token.type === 'Punctuator') {
|
Daniel@0
|
7004 if (token.value === '/' || token.value === '/=') {
|
Daniel@0
|
7005 extra.tokens.pop();
|
Daniel@0
|
7006 }
|
Daniel@0
|
7007 }
|
Daniel@0
|
7008 }
|
Daniel@0
|
7009
|
Daniel@0
|
7010 extra.tokens.push({
|
Daniel@0
|
7011 type: 'RegularExpression',
|
Daniel@0
|
7012 value: regex.literal,
|
Daniel@0
|
7013 regex: regex.regex,
|
Daniel@0
|
7014 range: [pos, index],
|
Daniel@0
|
7015 loc: loc
|
Daniel@0
|
7016 });
|
Daniel@0
|
7017 }
|
Daniel@0
|
7018
|
Daniel@0
|
7019 return regex;
|
Daniel@0
|
7020 }
|
Daniel@0
|
7021
|
Daniel@0
|
7022 function isIdentifierName(token) {
|
Daniel@0
|
7023 return token.type === Token.Identifier ||
|
Daniel@0
|
7024 token.type === Token.Keyword ||
|
Daniel@0
|
7025 token.type === Token.BooleanLiteral ||
|
Daniel@0
|
7026 token.type === Token.NullLiteral;
|
Daniel@0
|
7027 }
|
Daniel@0
|
7028
|
Daniel@0
|
7029 function advanceSlash() {
|
Daniel@0
|
7030 var prevToken,
|
Daniel@0
|
7031 checkToken;
|
Daniel@0
|
7032 // Using the following algorithm:
|
Daniel@0
|
7033 // https://github.com/mozilla/sweet.js/wiki/design
|
Daniel@0
|
7034 prevToken = extra.tokens[extra.tokens.length - 1];
|
Daniel@0
|
7035 if (!prevToken) {
|
Daniel@0
|
7036 // Nothing before that: it cannot be a division.
|
Daniel@0
|
7037 return collectRegex();
|
Daniel@0
|
7038 }
|
Daniel@0
|
7039 if (prevToken.type === 'Punctuator') {
|
Daniel@0
|
7040 if (prevToken.value === ']') {
|
Daniel@0
|
7041 return scanPunctuator();
|
Daniel@0
|
7042 }
|
Daniel@0
|
7043 if (prevToken.value === ')') {
|
Daniel@0
|
7044 checkToken = extra.tokens[extra.openParenToken - 1];
|
Daniel@0
|
7045 if (checkToken &&
|
Daniel@0
|
7046 checkToken.type === 'Keyword' &&
|
Daniel@0
|
7047 (checkToken.value === 'if' ||
|
Daniel@0
|
7048 checkToken.value === 'while' ||
|
Daniel@0
|
7049 checkToken.value === 'for' ||
|
Daniel@0
|
7050 checkToken.value === 'with')) {
|
Daniel@0
|
7051 return collectRegex();
|
Daniel@0
|
7052 }
|
Daniel@0
|
7053 return scanPunctuator();
|
Daniel@0
|
7054 }
|
Daniel@0
|
7055 if (prevToken.value === '}') {
|
Daniel@0
|
7056 // Dividing a function by anything makes little sense,
|
Daniel@0
|
7057 // but we have to check for that.
|
Daniel@0
|
7058 if (extra.tokens[extra.openCurlyToken - 3] &&
|
Daniel@0
|
7059 extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
|
Daniel@0
|
7060 // Anonymous function.
|
Daniel@0
|
7061 checkToken = extra.tokens[extra.openCurlyToken - 4];
|
Daniel@0
|
7062 if (!checkToken) {
|
Daniel@0
|
7063 return scanPunctuator();
|
Daniel@0
|
7064 }
|
Daniel@0
|
7065 } else if (extra.tokens[extra.openCurlyToken - 4] &&
|
Daniel@0
|
7066 extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
|
Daniel@0
|
7067 // Named function.
|
Daniel@0
|
7068 checkToken = extra.tokens[extra.openCurlyToken - 5];
|
Daniel@0
|
7069 if (!checkToken) {
|
Daniel@0
|
7070 return collectRegex();
|
Daniel@0
|
7071 }
|
Daniel@0
|
7072 } else {
|
Daniel@0
|
7073 return scanPunctuator();
|
Daniel@0
|
7074 }
|
Daniel@0
|
7075 return scanPunctuator();
|
Daniel@0
|
7076 }
|
Daniel@0
|
7077 return collectRegex();
|
Daniel@0
|
7078 }
|
Daniel@0
|
7079 if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
|
Daniel@0
|
7080 return collectRegex();
|
Daniel@0
|
7081 }
|
Daniel@0
|
7082 return scanPunctuator();
|
Daniel@0
|
7083 }
|
Daniel@0
|
7084
|
Daniel@0
|
7085 function advance() {
|
Daniel@0
|
7086 var ch;
|
Daniel@0
|
7087
|
Daniel@0
|
7088 skipComment();
|
Daniel@0
|
7089
|
Daniel@0
|
7090 if (index >= length) {
|
Daniel@0
|
7091 return {
|
Daniel@0
|
7092 type: Token.EOF,
|
Daniel@0
|
7093 lineNumber: lineNumber,
|
Daniel@0
|
7094 lineStart: lineStart,
|
Daniel@0
|
7095 start: index,
|
Daniel@0
|
7096 end: index
|
Daniel@0
|
7097 };
|
Daniel@0
|
7098 }
|
Daniel@0
|
7099
|
Daniel@0
|
7100 ch = source.charCodeAt(index);
|
Daniel@0
|
7101
|
Daniel@0
|
7102 if (isIdentifierStart(ch)) {
|
Daniel@0
|
7103 return scanIdentifier();
|
Daniel@0
|
7104 }
|
Daniel@0
|
7105
|
Daniel@0
|
7106 // Very common: ( and ) and ;
|
Daniel@0
|
7107 if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
|
Daniel@0
|
7108 return scanPunctuator();
|
Daniel@0
|
7109 }
|
Daniel@0
|
7110
|
Daniel@0
|
7111 // String literal starts with single quote (U+0027) or double quote (U+0022).
|
Daniel@0
|
7112 if (ch === 0x27 || ch === 0x22) {
|
Daniel@0
|
7113 return scanStringLiteral();
|
Daniel@0
|
7114 }
|
Daniel@0
|
7115
|
Daniel@0
|
7116
|
Daniel@0
|
7117 // Dot (.) U+002E can also start a floating-point number, hence the need
|
Daniel@0
|
7118 // to check the next character.
|
Daniel@0
|
7119 if (ch === 0x2E) {
|
Daniel@0
|
7120 if (isDecimalDigit(source.charCodeAt(index + 1))) {
|
Daniel@0
|
7121 return scanNumericLiteral();
|
Daniel@0
|
7122 }
|
Daniel@0
|
7123 return scanPunctuator();
|
Daniel@0
|
7124 }
|
Daniel@0
|
7125
|
Daniel@0
|
7126 if (isDecimalDigit(ch)) {
|
Daniel@0
|
7127 return scanNumericLiteral();
|
Daniel@0
|
7128 }
|
Daniel@0
|
7129
|
Daniel@0
|
7130 // Slash (/) U+002F can also start a regex.
|
Daniel@0
|
7131 if (extra.tokenize && ch === 0x2F) {
|
Daniel@0
|
7132 return advanceSlash();
|
Daniel@0
|
7133 }
|
Daniel@0
|
7134
|
Daniel@0
|
7135 return scanPunctuator();
|
Daniel@0
|
7136 }
|
Daniel@0
|
7137
|
Daniel@0
|
7138 function collectToken() {
|
Daniel@0
|
7139 var loc, token, value, entry;
|
Daniel@0
|
7140
|
Daniel@0
|
7141 skipComment();
|
Daniel@0
|
7142 loc = {
|
Daniel@0
|
7143 start: {
|
Daniel@0
|
7144 line: lineNumber,
|
Daniel@0
|
7145 column: index - lineStart
|
Daniel@0
|
7146 }
|
Daniel@0
|
7147 };
|
Daniel@0
|
7148
|
Daniel@0
|
7149 token = advance();
|
Daniel@0
|
7150 loc.end = {
|
Daniel@0
|
7151 line: lineNumber,
|
Daniel@0
|
7152 column: index - lineStart
|
Daniel@0
|
7153 };
|
Daniel@0
|
7154
|
Daniel@0
|
7155 if (token.type !== Token.EOF) {
|
Daniel@0
|
7156 value = source.slice(token.start, token.end);
|
Daniel@0
|
7157 entry = {
|
Daniel@0
|
7158 type: TokenName[token.type],
|
Daniel@0
|
7159 value: value,
|
Daniel@0
|
7160 range: [token.start, token.end],
|
Daniel@0
|
7161 loc: loc
|
Daniel@0
|
7162 };
|
Daniel@0
|
7163 if (token.regex) {
|
Daniel@0
|
7164 entry.regex = {
|
Daniel@0
|
7165 pattern: token.regex.pattern,
|
Daniel@0
|
7166 flags: token.regex.flags
|
Daniel@0
|
7167 };
|
Daniel@0
|
7168 }
|
Daniel@0
|
7169 extra.tokens.push(entry);
|
Daniel@0
|
7170 }
|
Daniel@0
|
7171
|
Daniel@0
|
7172 return token;
|
Daniel@0
|
7173 }
|
Daniel@0
|
7174
|
Daniel@0
|
7175 function lex() {
|
Daniel@0
|
7176 var token;
|
Daniel@0
|
7177
|
Daniel@0
|
7178 token = lookahead;
|
Daniel@0
|
7179 index = token.end;
|
Daniel@0
|
7180 lineNumber = token.lineNumber;
|
Daniel@0
|
7181 lineStart = token.lineStart;
|
Daniel@0
|
7182
|
Daniel@0
|
7183 lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
|
Daniel@0
|
7184
|
Daniel@0
|
7185 index = token.end;
|
Daniel@0
|
7186 lineNumber = token.lineNumber;
|
Daniel@0
|
7187 lineStart = token.lineStart;
|
Daniel@0
|
7188
|
Daniel@0
|
7189 return token;
|
Daniel@0
|
7190 }
|
Daniel@0
|
7191
|
Daniel@0
|
7192 function peek() {
|
Daniel@0
|
7193 var pos, line, start;
|
Daniel@0
|
7194
|
Daniel@0
|
7195 pos = index;
|
Daniel@0
|
7196 line = lineNumber;
|
Daniel@0
|
7197 start = lineStart;
|
Daniel@0
|
7198 lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
|
Daniel@0
|
7199 index = pos;
|
Daniel@0
|
7200 lineNumber = line;
|
Daniel@0
|
7201 lineStart = start;
|
Daniel@0
|
7202 }
|
Daniel@0
|
7203
|
Daniel@0
|
7204 function Position() {
|
Daniel@0
|
7205 this.line = lineNumber;
|
Daniel@0
|
7206 this.column = index - lineStart;
|
Daniel@0
|
7207 }
|
Daniel@0
|
7208
|
Daniel@0
|
7209 function SourceLocation() {
|
Daniel@0
|
7210 this.start = new Position();
|
Daniel@0
|
7211 this.end = null;
|
Daniel@0
|
7212 }
|
Daniel@0
|
7213
|
Daniel@0
|
7214 function WrappingSourceLocation(startToken) {
|
Daniel@0
|
7215 if (startToken.type === Token.StringLiteral) {
|
Daniel@0
|
7216 this.start = {
|
Daniel@0
|
7217 line: startToken.startLineNumber,
|
Daniel@0
|
7218 column: startToken.start - startToken.startLineStart
|
Daniel@0
|
7219 };
|
Daniel@0
|
7220 } else {
|
Daniel@0
|
7221 this.start = {
|
Daniel@0
|
7222 line: startToken.lineNumber,
|
Daniel@0
|
7223 column: startToken.start - startToken.lineStart
|
Daniel@0
|
7224 };
|
Daniel@0
|
7225 }
|
Daniel@0
|
7226 this.end = null;
|
Daniel@0
|
7227 }
|
Daniel@0
|
7228
|
Daniel@0
|
7229 function Node() {
|
Daniel@0
|
7230 // Skip comment.
|
Daniel@0
|
7231 index = lookahead.start;
|
Daniel@0
|
7232 if (lookahead.type === Token.StringLiteral) {
|
Daniel@0
|
7233 lineNumber = lookahead.startLineNumber;
|
Daniel@0
|
7234 lineStart = lookahead.startLineStart;
|
Daniel@0
|
7235 } else {
|
Daniel@0
|
7236 lineNumber = lookahead.lineNumber;
|
Daniel@0
|
7237 lineStart = lookahead.lineStart;
|
Daniel@0
|
7238 }
|
Daniel@0
|
7239 if (extra.range) {
|
Daniel@0
|
7240 this.range = [index, 0];
|
Daniel@0
|
7241 }
|
Daniel@0
|
7242 if (extra.loc) {
|
Daniel@0
|
7243 this.loc = new SourceLocation();
|
Daniel@0
|
7244 }
|
Daniel@0
|
7245 }
|
Daniel@0
|
7246
|
Daniel@0
|
7247 function WrappingNode(startToken) {
|
Daniel@0
|
7248 if (extra.range) {
|
Daniel@0
|
7249 this.range = [startToken.start, 0];
|
Daniel@0
|
7250 }
|
Daniel@0
|
7251 if (extra.loc) {
|
Daniel@0
|
7252 this.loc = new WrappingSourceLocation(startToken);
|
Daniel@0
|
7253 }
|
Daniel@0
|
7254 }
|
Daniel@0
|
7255
|
Daniel@0
|
7256 WrappingNode.prototype = Node.prototype = {
|
Daniel@0
|
7257
|
Daniel@0
|
7258 finish: function () {
|
Daniel@0
|
7259 if (extra.range) {
|
Daniel@0
|
7260 this.range[1] = index;
|
Daniel@0
|
7261 }
|
Daniel@0
|
7262 if (extra.loc) {
|
Daniel@0
|
7263 this.loc.end = new Position();
|
Daniel@0
|
7264 if (extra.source) {
|
Daniel@0
|
7265 this.loc.source = extra.source;
|
Daniel@0
|
7266 }
|
Daniel@0
|
7267 }
|
Daniel@0
|
7268 },
|
Daniel@0
|
7269
|
Daniel@0
|
7270 finishArrayExpression: function (elements) {
|
Daniel@0
|
7271 this.type = Syntax.ArrayExpression;
|
Daniel@0
|
7272 this.elements = elements;
|
Daniel@0
|
7273 this.finish();
|
Daniel@0
|
7274 return this;
|
Daniel@0
|
7275 },
|
Daniel@0
|
7276
|
Daniel@0
|
7277 finishAssignmentExpression: function (operator, left, right) {
|
Daniel@0
|
7278 this.type = Syntax.AssignmentExpression;
|
Daniel@0
|
7279 this.operator = operator;
|
Daniel@0
|
7280 this.left = left;
|
Daniel@0
|
7281 this.right = right;
|
Daniel@0
|
7282 this.finish();
|
Daniel@0
|
7283 return this;
|
Daniel@0
|
7284 },
|
Daniel@0
|
7285
|
Daniel@0
|
7286 finishBinaryExpression: function (operator, left, right) {
|
Daniel@0
|
7287 this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
|
Daniel@0
|
7288 this.operator = operator;
|
Daniel@0
|
7289 this.left = left;
|
Daniel@0
|
7290 this.right = right;
|
Daniel@0
|
7291 this.finish();
|
Daniel@0
|
7292 return this;
|
Daniel@0
|
7293 },
|
Daniel@0
|
7294
|
Daniel@0
|
7295 finishCallExpression: function (callee, args) {
|
Daniel@0
|
7296 this.type = Syntax.CallExpression;
|
Daniel@0
|
7297 this.callee = callee;
|
Daniel@0
|
7298 this.arguments = args;
|
Daniel@0
|
7299 this.finish();
|
Daniel@0
|
7300 return this;
|
Daniel@0
|
7301 },
|
Daniel@0
|
7302
|
Daniel@0
|
7303 finishConditionalExpression: function (test, consequent, alternate) {
|
Daniel@0
|
7304 this.type = Syntax.ConditionalExpression;
|
Daniel@0
|
7305 this.test = test;
|
Daniel@0
|
7306 this.consequent = consequent;
|
Daniel@0
|
7307 this.alternate = alternate;
|
Daniel@0
|
7308 this.finish();
|
Daniel@0
|
7309 return this;
|
Daniel@0
|
7310 },
|
Daniel@0
|
7311
|
Daniel@0
|
7312 finishExpressionStatement: function (expression) {
|
Daniel@0
|
7313 this.type = Syntax.ExpressionStatement;
|
Daniel@0
|
7314 this.expression = expression;
|
Daniel@0
|
7315 this.finish();
|
Daniel@0
|
7316 return this;
|
Daniel@0
|
7317 },
|
Daniel@0
|
7318
|
Daniel@0
|
7319 finishIdentifier: function (name) {
|
Daniel@0
|
7320 this.type = Syntax.Identifier;
|
Daniel@0
|
7321 this.name = name;
|
Daniel@0
|
7322 this.finish();
|
Daniel@0
|
7323 return this;
|
Daniel@0
|
7324 },
|
Daniel@0
|
7325
|
Daniel@0
|
7326 finishLiteral: function (token) {
|
Daniel@0
|
7327 this.type = Syntax.Literal;
|
Daniel@0
|
7328 this.value = token.value;
|
Daniel@0
|
7329 this.raw = source.slice(token.start, token.end);
|
Daniel@0
|
7330 if (token.regex) {
|
Daniel@0
|
7331 if (this.raw == '//') {
|
Daniel@0
|
7332 this.raw = '/(?:)/';
|
Daniel@0
|
7333 }
|
Daniel@0
|
7334 this.regex = token.regex;
|
Daniel@0
|
7335 }
|
Daniel@0
|
7336 this.finish();
|
Daniel@0
|
7337 return this;
|
Daniel@0
|
7338 },
|
Daniel@0
|
7339
|
Daniel@0
|
7340 finishMemberExpression: function (accessor, object, property) {
|
Daniel@0
|
7341 this.type = Syntax.MemberExpression;
|
Daniel@0
|
7342 this.computed = accessor === '[';
|
Daniel@0
|
7343 this.object = object;
|
Daniel@0
|
7344 this.property = property;
|
Daniel@0
|
7345 this.finish();
|
Daniel@0
|
7346 return this;
|
Daniel@0
|
7347 },
|
Daniel@0
|
7348
|
Daniel@0
|
7349 finishObjectExpression: function (properties) {
|
Daniel@0
|
7350 this.type = Syntax.ObjectExpression;
|
Daniel@0
|
7351 this.properties = properties;
|
Daniel@0
|
7352 this.finish();
|
Daniel@0
|
7353 return this;
|
Daniel@0
|
7354 },
|
Daniel@0
|
7355
|
Daniel@0
|
7356 finishProgram: function (body) {
|
Daniel@0
|
7357 this.type = Syntax.Program;
|
Daniel@0
|
7358 this.body = body;
|
Daniel@0
|
7359 this.finish();
|
Daniel@0
|
7360 return this;
|
Daniel@0
|
7361 },
|
Daniel@0
|
7362
|
Daniel@0
|
7363 finishProperty: function (kind, key, value) {
|
Daniel@0
|
7364 this.type = Syntax.Property;
|
Daniel@0
|
7365 this.key = key;
|
Daniel@0
|
7366 this.value = value;
|
Daniel@0
|
7367 this.kind = kind;
|
Daniel@0
|
7368 this.finish();
|
Daniel@0
|
7369 return this;
|
Daniel@0
|
7370 },
|
Daniel@0
|
7371
|
Daniel@0
|
7372 finishUnaryExpression: function (operator, argument) {
|
Daniel@0
|
7373 this.type = Syntax.UnaryExpression;
|
Daniel@0
|
7374 this.operator = operator;
|
Daniel@0
|
7375 this.argument = argument;
|
Daniel@0
|
7376 this.prefix = true;
|
Daniel@0
|
7377 this.finish();
|
Daniel@0
|
7378 return this;
|
Daniel@0
|
7379 }
|
Daniel@0
|
7380 };
|
Daniel@0
|
7381
|
Daniel@0
|
7382 // Return true if there is a line terminator before the next token.
|
Daniel@0
|
7383
|
Daniel@0
|
7384 function peekLineTerminator() {
|
Daniel@0
|
7385 var pos, line, start, found;
|
Daniel@0
|
7386
|
Daniel@0
|
7387 pos = index;
|
Daniel@0
|
7388 line = lineNumber;
|
Daniel@0
|
7389 start = lineStart;
|
Daniel@0
|
7390 skipComment();
|
Daniel@0
|
7391 found = lineNumber !== line;
|
Daniel@0
|
7392 index = pos;
|
Daniel@0
|
7393 lineNumber = line;
|
Daniel@0
|
7394 lineStart = start;
|
Daniel@0
|
7395
|
Daniel@0
|
7396 return found;
|
Daniel@0
|
7397 }
|
Daniel@0
|
7398
|
Daniel@0
|
7399 // Throw an exception
|
Daniel@0
|
7400
|
Daniel@0
|
7401 function throwError(token, messageFormat) {
|
Daniel@0
|
7402 var error,
|
Daniel@0
|
7403 args = Array.prototype.slice.call(arguments, 2),
|
Daniel@0
|
7404 msg = messageFormat.replace(
|
Daniel@0
|
7405 /%(\d)/g,
|
Daniel@0
|
7406 function (whole, index) {
|
Daniel@0
|
7407 assert(index < args.length, 'Message reference must be in range');
|
Daniel@0
|
7408 return args[index];
|
Daniel@0
|
7409 }
|
Daniel@0
|
7410 );
|
Daniel@0
|
7411
|
Daniel@0
|
7412 if (typeof token.lineNumber === 'number') {
|
Daniel@0
|
7413 error = new Error('Line ' + token.lineNumber + ': ' + msg);
|
Daniel@0
|
7414 error.index = token.start;
|
Daniel@0
|
7415 error.lineNumber = token.lineNumber;
|
Daniel@0
|
7416 error.column = token.start - lineStart + 1;
|
Daniel@0
|
7417 } else {
|
Daniel@0
|
7418 error = new Error('Line ' + lineNumber + ': ' + msg);
|
Daniel@0
|
7419 error.index = index;
|
Daniel@0
|
7420 error.lineNumber = lineNumber;
|
Daniel@0
|
7421 error.column = index - lineStart + 1;
|
Daniel@0
|
7422 }
|
Daniel@0
|
7423
|
Daniel@0
|
7424 error.description = msg;
|
Daniel@0
|
7425 throw error;
|
Daniel@0
|
7426 }
|
Daniel@0
|
7427
|
Daniel@0
|
7428 function throwErrorTolerant() {
|
Daniel@0
|
7429 try {
|
Daniel@0
|
7430 throwError.apply(null, arguments);
|
Daniel@0
|
7431 } catch (e) {
|
Daniel@0
|
7432 if (extra.errors) {
|
Daniel@0
|
7433 extra.errors.push(e);
|
Daniel@0
|
7434 } else {
|
Daniel@0
|
7435 throw e;
|
Daniel@0
|
7436 }
|
Daniel@0
|
7437 }
|
Daniel@0
|
7438 }
|
Daniel@0
|
7439
|
Daniel@0
|
7440
|
Daniel@0
|
7441 // Throw an exception because of the token.
|
Daniel@0
|
7442
|
Daniel@0
|
7443 function throwUnexpected(token) {
|
Daniel@0
|
7444 if (token.type === Token.EOF) {
|
Daniel@0
|
7445 throwError(token, Messages.UnexpectedEOS);
|
Daniel@0
|
7446 }
|
Daniel@0
|
7447
|
Daniel@0
|
7448 if (token.type === Token.NumericLiteral) {
|
Daniel@0
|
7449 throwError(token, Messages.UnexpectedNumber);
|
Daniel@0
|
7450 }
|
Daniel@0
|
7451
|
Daniel@0
|
7452 if (token.type === Token.StringLiteral) {
|
Daniel@0
|
7453 throwError(token, Messages.UnexpectedString);
|
Daniel@0
|
7454 }
|
Daniel@0
|
7455
|
Daniel@0
|
7456 if (token.type === Token.Identifier) {
|
Daniel@0
|
7457 throwError(token, Messages.UnexpectedIdentifier);
|
Daniel@0
|
7458 }
|
Daniel@0
|
7459
|
Daniel@0
|
7460 if (token.type === Token.Keyword) {
|
Daniel@0
|
7461 if (isFutureReservedWord(token.value)) {
|
Daniel@0
|
7462 throwError(token, Messages.UnexpectedReserved);
|
Daniel@0
|
7463 } else if (strict && isStrictModeReservedWord(token.value)) {
|
Daniel@0
|
7464 throwErrorTolerant(token, Messages.StrictReservedWord);
|
Daniel@0
|
7465 return;
|
Daniel@0
|
7466 }
|
Daniel@0
|
7467 throwError(token, Messages.UnexpectedToken, token.value);
|
Daniel@0
|
7468 }
|
Daniel@0
|
7469
|
Daniel@0
|
7470 // BooleanLiteral, NullLiteral, or Punctuator.
|
Daniel@0
|
7471 throwError(token, Messages.UnexpectedToken, token.value);
|
Daniel@0
|
7472 }
|
Daniel@0
|
7473
|
Daniel@0
|
7474 // Expect the next token to match the specified punctuator.
|
Daniel@0
|
7475 // If not, an exception will be thrown.
|
Daniel@0
|
7476
|
Daniel@0
|
7477 function expect(value) {
|
Daniel@0
|
7478 var token = lex();
|
Daniel@0
|
7479 if (token.type !== Token.Punctuator || token.value !== value) {
|
Daniel@0
|
7480 throwUnexpected(token);
|
Daniel@0
|
7481 }
|
Daniel@0
|
7482 }
|
Daniel@0
|
7483
|
Daniel@0
|
7484 /**
|
Daniel@0
|
7485 * @name expectTolerant
|
Daniel@0
|
7486 * @description Quietly expect the given token value when in tolerant mode, otherwise delegates
|
Daniel@0
|
7487 * to <code>expect(value)</code>
|
Daniel@0
|
7488 * @param {String} value The value we are expecting the lookahead token to have
|
Daniel@0
|
7489 * @since 2.0
|
Daniel@0
|
7490 */
|
Daniel@0
|
7491 function expectTolerant(value) {
|
Daniel@0
|
7492 if (extra.errors) {
|
Daniel@0
|
7493 var token = lookahead;
|
Daniel@0
|
7494 if (token.type !== Token.Punctuator && token.value !== value) {
|
Daniel@0
|
7495 throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
|
Daniel@0
|
7496 } else {
|
Daniel@0
|
7497 lex();
|
Daniel@0
|
7498 }
|
Daniel@0
|
7499 } else {
|
Daniel@0
|
7500 expect(value);
|
Daniel@0
|
7501 }
|
Daniel@0
|
7502 }
|
Daniel@0
|
7503
|
Daniel@0
|
7504 // Return true if the next token matches the specified punctuator.
|
Daniel@0
|
7505
|
Daniel@0
|
7506 function match(value) {
|
Daniel@0
|
7507 return lookahead.type === Token.Punctuator && lookahead.value === value;
|
Daniel@0
|
7508 }
|
Daniel@0
|
7509
|
Daniel@0
|
7510 // Return true if the next token matches the specified keyword
|
Daniel@0
|
7511
|
Daniel@0
|
7512 function matchKeyword(keyword) {
|
Daniel@0
|
7513 return lookahead.type === Token.Keyword && lookahead.value === keyword;
|
Daniel@0
|
7514 }
|
Daniel@0
|
7515
|
Daniel@0
|
7516 function consumeSemicolon() {
|
Daniel@0
|
7517 var line;
|
Daniel@0
|
7518
|
Daniel@0
|
7519 // Catch the very common case first: immediately a semicolon (U+003B).
|
Daniel@0
|
7520 if (source.charCodeAt(index) === 0x3B || match(';')) {
|
Daniel@0
|
7521 lex();
|
Daniel@0
|
7522 return;
|
Daniel@0
|
7523 }
|
Daniel@0
|
7524
|
Daniel@0
|
7525 line = lineNumber;
|
Daniel@0
|
7526 skipComment();
|
Daniel@0
|
7527 if (lineNumber !== line) {
|
Daniel@0
|
7528 return;
|
Daniel@0
|
7529 }
|
Daniel@0
|
7530
|
Daniel@0
|
7531 if (lookahead.type !== Token.EOF && !match('}')) {
|
Daniel@0
|
7532 throwUnexpected(lookahead);
|
Daniel@0
|
7533 }
|
Daniel@0
|
7534 }
|
Daniel@0
|
7535
|
Daniel@0
|
7536 // 11.1.4 Array Initialiser
|
Daniel@0
|
7537
|
Daniel@0
|
7538 function parseArrayInitialiser() {
|
Daniel@0
|
7539 var elements = [], node = new Node();
|
Daniel@0
|
7540
|
Daniel@0
|
7541 expect('[');
|
Daniel@0
|
7542
|
Daniel@0
|
7543 while (!match(']')) {
|
Daniel@0
|
7544 if (match(',')) {
|
Daniel@0
|
7545 lex();
|
Daniel@0
|
7546 elements.push(null);
|
Daniel@0
|
7547 } else {
|
Daniel@0
|
7548 elements.push(parseAssignmentExpression());
|
Daniel@0
|
7549
|
Daniel@0
|
7550 if (!match(']')) {
|
Daniel@0
|
7551 expect(',');
|
Daniel@0
|
7552 }
|
Daniel@0
|
7553 }
|
Daniel@0
|
7554 }
|
Daniel@0
|
7555
|
Daniel@0
|
7556 lex();
|
Daniel@0
|
7557
|
Daniel@0
|
7558 return node.finishArrayExpression(elements);
|
Daniel@0
|
7559 }
|
Daniel@0
|
7560
|
Daniel@0
|
7561 // 11.1.5 Object Initialiser
|
Daniel@0
|
7562
|
Daniel@0
|
7563 function parseObjectPropertyKey() {
|
Daniel@0
|
7564 var token, node = new Node();
|
Daniel@0
|
7565
|
Daniel@0
|
7566 token = lex();
|
Daniel@0
|
7567
|
Daniel@0
|
7568 // Note: This function is called only from parseObjectProperty(), where
|
Daniel@0
|
7569 // EOF and Punctuator tokens are already filtered out.
|
Daniel@0
|
7570
|
Daniel@0
|
7571 if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
|
Daniel@0
|
7572 if (strict && token.octal) {
|
Daniel@0
|
7573 throwErrorTolerant(token, Messages.StrictOctalLiteral);
|
Daniel@0
|
7574 }
|
Daniel@0
|
7575 return node.finishLiteral(token);
|
Daniel@0
|
7576 }
|
Daniel@0
|
7577
|
Daniel@0
|
7578 return node.finishIdentifier(token.value);
|
Daniel@0
|
7579 }
|
Daniel@0
|
7580
|
Daniel@0
|
7581 function parseObjectProperty() {
|
Daniel@0
|
7582 var token, key, id, value, node = new Node();
|
Daniel@0
|
7583
|
Daniel@0
|
7584 token = lookahead;
|
Daniel@0
|
7585
|
Daniel@0
|
7586 if (token.type === Token.Identifier) {
|
Daniel@0
|
7587 id = parseObjectPropertyKey();
|
Daniel@0
|
7588 expect(':');
|
Daniel@0
|
7589 value = parseAssignmentExpression();
|
Daniel@0
|
7590 return node.finishProperty('init', id, value);
|
Daniel@0
|
7591 }
|
Daniel@0
|
7592 if (token.type === Token.EOF || token.type === Token.Punctuator) {
|
Daniel@0
|
7593 throwUnexpected(token);
|
Daniel@0
|
7594 } else {
|
Daniel@0
|
7595 key = parseObjectPropertyKey();
|
Daniel@0
|
7596 expect(':');
|
Daniel@0
|
7597 value = parseAssignmentExpression();
|
Daniel@0
|
7598 return node.finishProperty('init', key, value);
|
Daniel@0
|
7599 }
|
Daniel@0
|
7600 }
|
Daniel@0
|
7601
|
Daniel@0
|
7602 function parseObjectInitialiser() {
|
Daniel@0
|
7603 var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node();
|
Daniel@0
|
7604
|
Daniel@0
|
7605 expect('{');
|
Daniel@0
|
7606
|
Daniel@0
|
7607 while (!match('}')) {
|
Daniel@0
|
7608 property = parseObjectProperty();
|
Daniel@0
|
7609
|
Daniel@0
|
7610 if (property.key.type === Syntax.Identifier) {
|
Daniel@0
|
7611 name = property.key.name;
|
Daniel@0
|
7612 } else {
|
Daniel@0
|
7613 name = toString(property.key.value);
|
Daniel@0
|
7614 }
|
Daniel@0
|
7615 kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
|
Daniel@0
|
7616
|
Daniel@0
|
7617 key = '$' + name;
|
Daniel@0
|
7618 if (Object.prototype.hasOwnProperty.call(map, key)) {
|
Daniel@0
|
7619 if (map[key] === PropertyKind.Data) {
|
Daniel@0
|
7620 if (strict && kind === PropertyKind.Data) {
|
Daniel@0
|
7621 throwErrorTolerant({}, Messages.StrictDuplicateProperty);
|
Daniel@0
|
7622 } else if (kind !== PropertyKind.Data) {
|
Daniel@0
|
7623 throwErrorTolerant({}, Messages.AccessorDataProperty);
|
Daniel@0
|
7624 }
|
Daniel@0
|
7625 } else {
|
Daniel@0
|
7626 if (kind === PropertyKind.Data) {
|
Daniel@0
|
7627 throwErrorTolerant({}, Messages.AccessorDataProperty);
|
Daniel@0
|
7628 } else if (map[key] & kind) {
|
Daniel@0
|
7629 throwErrorTolerant({}, Messages.AccessorGetSet);
|
Daniel@0
|
7630 }
|
Daniel@0
|
7631 }
|
Daniel@0
|
7632 map[key] |= kind;
|
Daniel@0
|
7633 } else {
|
Daniel@0
|
7634 map[key] = kind;
|
Daniel@0
|
7635 }
|
Daniel@0
|
7636
|
Daniel@0
|
7637 properties.push(property);
|
Daniel@0
|
7638
|
Daniel@0
|
7639 if (!match('}')) {
|
Daniel@0
|
7640 expectTolerant(',');
|
Daniel@0
|
7641 }
|
Daniel@0
|
7642 }
|
Daniel@0
|
7643
|
Daniel@0
|
7644 expect('}');
|
Daniel@0
|
7645
|
Daniel@0
|
7646 return node.finishObjectExpression(properties);
|
Daniel@0
|
7647 }
|
Daniel@0
|
7648
|
Daniel@0
|
7649 // 11.1.6 The Grouping Operator
|
Daniel@0
|
7650
|
Daniel@0
|
7651 function parseGroupExpression() {
|
Daniel@0
|
7652 var expr;
|
Daniel@0
|
7653
|
Daniel@0
|
7654 expect('(');
|
Daniel@0
|
7655
|
Daniel@0
|
7656 ++state.parenthesisCount;
|
Daniel@0
|
7657
|
Daniel@0
|
7658 expr = parseExpression();
|
Daniel@0
|
7659
|
Daniel@0
|
7660 expect(')');
|
Daniel@0
|
7661
|
Daniel@0
|
7662 return expr;
|
Daniel@0
|
7663 }
|
Daniel@0
|
7664
|
Daniel@0
|
7665
|
Daniel@0
|
7666 // 11.1 Primary Expressions
|
Daniel@0
|
7667
|
Daniel@0
|
7668 var legalKeywords = {"if":1, "this":1};
|
Daniel@0
|
7669
|
Daniel@0
|
7670 function parsePrimaryExpression() {
|
Daniel@0
|
7671 var type, token, expr, node;
|
Daniel@0
|
7672
|
Daniel@0
|
7673 if (match('(')) {
|
Daniel@0
|
7674 return parseGroupExpression();
|
Daniel@0
|
7675 }
|
Daniel@0
|
7676
|
Daniel@0
|
7677 if (match('[')) {
|
Daniel@0
|
7678 return parseArrayInitialiser();
|
Daniel@0
|
7679 }
|
Daniel@0
|
7680
|
Daniel@0
|
7681 if (match('{')) {
|
Daniel@0
|
7682 return parseObjectInitialiser();
|
Daniel@0
|
7683 }
|
Daniel@0
|
7684
|
Daniel@0
|
7685 type = lookahead.type;
|
Daniel@0
|
7686 node = new Node();
|
Daniel@0
|
7687
|
Daniel@0
|
7688 if (type === Token.Identifier || legalKeywords[lookahead.value]) {
|
Daniel@0
|
7689 expr = node.finishIdentifier(lex().value);
|
Daniel@0
|
7690 } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
|
Daniel@0
|
7691 if (strict && lookahead.octal) {
|
Daniel@0
|
7692 throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
|
Daniel@0
|
7693 }
|
Daniel@0
|
7694 expr = node.finishLiteral(lex());
|
Daniel@0
|
7695 } else if (type === Token.Keyword) {
|
Daniel@0
|
7696 throw new Error("Disabled.");
|
Daniel@0
|
7697 } else if (type === Token.BooleanLiteral) {
|
Daniel@0
|
7698 token = lex();
|
Daniel@0
|
7699 token.value = (token.value === 'true');
|
Daniel@0
|
7700 expr = node.finishLiteral(token);
|
Daniel@0
|
7701 } else if (type === Token.NullLiteral) {
|
Daniel@0
|
7702 token = lex();
|
Daniel@0
|
7703 token.value = null;
|
Daniel@0
|
7704 expr = node.finishLiteral(token);
|
Daniel@0
|
7705 } else if (match('/') || match('/=')) {
|
Daniel@0
|
7706 if (typeof extra.tokens !== 'undefined') {
|
Daniel@0
|
7707 expr = node.finishLiteral(collectRegex());
|
Daniel@0
|
7708 } else {
|
Daniel@0
|
7709 expr = node.finishLiteral(scanRegExp());
|
Daniel@0
|
7710 }
|
Daniel@0
|
7711 peek();
|
Daniel@0
|
7712 } else {
|
Daniel@0
|
7713 throwUnexpected(lex());
|
Daniel@0
|
7714 }
|
Daniel@0
|
7715
|
Daniel@0
|
7716 return expr;
|
Daniel@0
|
7717 }
|
Daniel@0
|
7718
|
Daniel@0
|
7719 // 11.2 Left-Hand-Side Expressions
|
Daniel@0
|
7720
|
Daniel@0
|
7721 function parseArguments() {
|
Daniel@0
|
7722 var args = [];
|
Daniel@0
|
7723
|
Daniel@0
|
7724 expect('(');
|
Daniel@0
|
7725
|
Daniel@0
|
7726 if (!match(')')) {
|
Daniel@0
|
7727 while (index < length) {
|
Daniel@0
|
7728 args.push(parseAssignmentExpression());
|
Daniel@0
|
7729 if (match(')')) {
|
Daniel@0
|
7730 break;
|
Daniel@0
|
7731 }
|
Daniel@0
|
7732 expectTolerant(',');
|
Daniel@0
|
7733 }
|
Daniel@0
|
7734 }
|
Daniel@0
|
7735
|
Daniel@0
|
7736 expect(')');
|
Daniel@0
|
7737
|
Daniel@0
|
7738 return args;
|
Daniel@0
|
7739 }
|
Daniel@0
|
7740
|
Daniel@0
|
7741 function parseNonComputedProperty() {
|
Daniel@0
|
7742 var token, node = new Node();
|
Daniel@0
|
7743
|
Daniel@0
|
7744 token = lex();
|
Daniel@0
|
7745
|
Daniel@0
|
7746 if (!isIdentifierName(token)) {
|
Daniel@0
|
7747 throwUnexpected(token);
|
Daniel@0
|
7748 }
|
Daniel@0
|
7749
|
Daniel@0
|
7750 return node.finishIdentifier(token.value);
|
Daniel@0
|
7751 }
|
Daniel@0
|
7752
|
Daniel@0
|
7753 function parseNonComputedMember() {
|
Daniel@0
|
7754 expect('.');
|
Daniel@0
|
7755
|
Daniel@0
|
7756 return parseNonComputedProperty();
|
Daniel@0
|
7757 }
|
Daniel@0
|
7758
|
Daniel@0
|
7759 function parseComputedMember() {
|
Daniel@0
|
7760 var expr;
|
Daniel@0
|
7761
|
Daniel@0
|
7762 expect('[');
|
Daniel@0
|
7763
|
Daniel@0
|
7764 expr = parseExpression();
|
Daniel@0
|
7765
|
Daniel@0
|
7766 expect(']');
|
Daniel@0
|
7767
|
Daniel@0
|
7768 return expr;
|
Daniel@0
|
7769 }
|
Daniel@0
|
7770
|
Daniel@0
|
7771 function parseLeftHandSideExpressionAllowCall() {
|
Daniel@0
|
7772 var expr, args, property, startToken, previousAllowIn = state.allowIn;
|
Daniel@0
|
7773
|
Daniel@0
|
7774 startToken = lookahead;
|
Daniel@0
|
7775 state.allowIn = true;
|
Daniel@0
|
7776 expr = parsePrimaryExpression();
|
Daniel@0
|
7777
|
Daniel@0
|
7778 for (;;) {
|
Daniel@0
|
7779 if (match('.')) {
|
Daniel@0
|
7780 property = parseNonComputedMember();
|
Daniel@0
|
7781 expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
|
Daniel@0
|
7782 } else if (match('(')) {
|
Daniel@0
|
7783 args = parseArguments();
|
Daniel@0
|
7784 expr = new WrappingNode(startToken).finishCallExpression(expr, args);
|
Daniel@0
|
7785 } else if (match('[')) {
|
Daniel@0
|
7786 property = parseComputedMember();
|
Daniel@0
|
7787 expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
|
Daniel@0
|
7788 } else {
|
Daniel@0
|
7789 break;
|
Daniel@0
|
7790 }
|
Daniel@0
|
7791 }
|
Daniel@0
|
7792 state.allowIn = previousAllowIn;
|
Daniel@0
|
7793
|
Daniel@0
|
7794 return expr;
|
Daniel@0
|
7795 }
|
Daniel@0
|
7796
|
Daniel@0
|
7797 // 11.3 Postfix Expressions
|
Daniel@0
|
7798
|
Daniel@0
|
7799 function parsePostfixExpression() {
|
Daniel@0
|
7800 var expr = parseLeftHandSideExpressionAllowCall();
|
Daniel@0
|
7801
|
Daniel@0
|
7802 if (lookahead.type === Token.Punctuator) {
|
Daniel@0
|
7803 if ((match('++') || match('--')) && !peekLineTerminator()) {
|
Daniel@0
|
7804 throw new Error("Disabled.");
|
Daniel@0
|
7805 }
|
Daniel@0
|
7806 }
|
Daniel@0
|
7807
|
Daniel@0
|
7808 return expr;
|
Daniel@0
|
7809 }
|
Daniel@0
|
7810
|
Daniel@0
|
7811 // 11.4 Unary Operators
|
Daniel@0
|
7812
|
Daniel@0
|
7813 function parseUnaryExpression() {
|
Daniel@0
|
7814 var token, expr, startToken;
|
Daniel@0
|
7815
|
Daniel@0
|
7816 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
|
Daniel@0
|
7817 expr = parsePostfixExpression();
|
Daniel@0
|
7818 } else if (match('++') || match('--')) {
|
Daniel@0
|
7819 throw new Error("Disabled.");
|
Daniel@0
|
7820 } else if (match('+') || match('-') || match('~') || match('!')) {
|
Daniel@0
|
7821 startToken = lookahead;
|
Daniel@0
|
7822 token = lex();
|
Daniel@0
|
7823 expr = parseUnaryExpression();
|
Daniel@0
|
7824 expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
|
Daniel@0
|
7825 } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
|
Daniel@0
|
7826 throw new Error("Disabled.");
|
Daniel@0
|
7827 } else {
|
Daniel@0
|
7828 expr = parsePostfixExpression();
|
Daniel@0
|
7829 }
|
Daniel@0
|
7830
|
Daniel@0
|
7831 return expr;
|
Daniel@0
|
7832 }
|
Daniel@0
|
7833
|
Daniel@0
|
7834 function binaryPrecedence(token, allowIn) {
|
Daniel@0
|
7835 var prec = 0;
|
Daniel@0
|
7836
|
Daniel@0
|
7837 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
|
Daniel@0
|
7838 return 0;
|
Daniel@0
|
7839 }
|
Daniel@0
|
7840
|
Daniel@0
|
7841 switch (token.value) {
|
Daniel@0
|
7842 case '||':
|
Daniel@0
|
7843 prec = 1;
|
Daniel@0
|
7844 break;
|
Daniel@0
|
7845
|
Daniel@0
|
7846 case '&&':
|
Daniel@0
|
7847 prec = 2;
|
Daniel@0
|
7848 break;
|
Daniel@0
|
7849
|
Daniel@0
|
7850 case '|':
|
Daniel@0
|
7851 prec = 3;
|
Daniel@0
|
7852 break;
|
Daniel@0
|
7853
|
Daniel@0
|
7854 case '^':
|
Daniel@0
|
7855 prec = 4;
|
Daniel@0
|
7856 break;
|
Daniel@0
|
7857
|
Daniel@0
|
7858 case '&':
|
Daniel@0
|
7859 prec = 5;
|
Daniel@0
|
7860 break;
|
Daniel@0
|
7861
|
Daniel@0
|
7862 case '==':
|
Daniel@0
|
7863 case '!=':
|
Daniel@0
|
7864 case '===':
|
Daniel@0
|
7865 case '!==':
|
Daniel@0
|
7866 prec = 6;
|
Daniel@0
|
7867 break;
|
Daniel@0
|
7868
|
Daniel@0
|
7869 case '<':
|
Daniel@0
|
7870 case '>':
|
Daniel@0
|
7871 case '<=':
|
Daniel@0
|
7872 case '>=':
|
Daniel@0
|
7873 case 'instanceof':
|
Daniel@0
|
7874 prec = 7;
|
Daniel@0
|
7875 break;
|
Daniel@0
|
7876
|
Daniel@0
|
7877 case 'in':
|
Daniel@0
|
7878 prec = allowIn ? 7 : 0;
|
Daniel@0
|
7879 break;
|
Daniel@0
|
7880
|
Daniel@0
|
7881 case '<<':
|
Daniel@0
|
7882 case '>>':
|
Daniel@0
|
7883 case '>>>':
|
Daniel@0
|
7884 prec = 8;
|
Daniel@0
|
7885 break;
|
Daniel@0
|
7886
|
Daniel@0
|
7887 case '+':
|
Daniel@0
|
7888 case '-':
|
Daniel@0
|
7889 prec = 9;
|
Daniel@0
|
7890 break;
|
Daniel@0
|
7891
|
Daniel@0
|
7892 case '*':
|
Daniel@0
|
7893 case '/':
|
Daniel@0
|
7894 case '%':
|
Daniel@0
|
7895 prec = 11;
|
Daniel@0
|
7896 break;
|
Daniel@0
|
7897
|
Daniel@0
|
7898 default:
|
Daniel@0
|
7899 break;
|
Daniel@0
|
7900 }
|
Daniel@0
|
7901
|
Daniel@0
|
7902 return prec;
|
Daniel@0
|
7903 }
|
Daniel@0
|
7904
|
Daniel@0
|
7905 // 11.5 Multiplicative Operators
|
Daniel@0
|
7906 // 11.6 Additive Operators
|
Daniel@0
|
7907 // 11.7 Bitwise Shift Operators
|
Daniel@0
|
7908 // 11.8 Relational Operators
|
Daniel@0
|
7909 // 11.9 Equality Operators
|
Daniel@0
|
7910 // 11.10 Binary Bitwise Operators
|
Daniel@0
|
7911 // 11.11 Binary Logical Operators
|
Daniel@0
|
7912
|
Daniel@0
|
7913 function parseBinaryExpression() {
|
Daniel@0
|
7914 var marker, markers, expr, token, prec, stack, right, operator, left, i;
|
Daniel@0
|
7915
|
Daniel@0
|
7916 marker = lookahead;
|
Daniel@0
|
7917 left = parseUnaryExpression();
|
Daniel@0
|
7918
|
Daniel@0
|
7919 token = lookahead;
|
Daniel@0
|
7920 prec = binaryPrecedence(token, state.allowIn);
|
Daniel@0
|
7921 if (prec === 0) {
|
Daniel@0
|
7922 return left;
|
Daniel@0
|
7923 }
|
Daniel@0
|
7924 token.prec = prec;
|
Daniel@0
|
7925 lex();
|
Daniel@0
|
7926
|
Daniel@0
|
7927 markers = [marker, lookahead];
|
Daniel@0
|
7928 right = parseUnaryExpression();
|
Daniel@0
|
7929
|
Daniel@0
|
7930 stack = [left, token, right];
|
Daniel@0
|
7931
|
Daniel@0
|
7932 while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
|
Daniel@0
|
7933
|
Daniel@0
|
7934 // Reduce: make a binary expression from the three topmost entries.
|
Daniel@0
|
7935 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
|
Daniel@0
|
7936 right = stack.pop();
|
Daniel@0
|
7937 operator = stack.pop().value;
|
Daniel@0
|
7938 left = stack.pop();
|
Daniel@0
|
7939 markers.pop();
|
Daniel@0
|
7940 expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
|
Daniel@0
|
7941 stack.push(expr);
|
Daniel@0
|
7942 }
|
Daniel@0
|
7943
|
Daniel@0
|
7944 // Shift.
|
Daniel@0
|
7945 token = lex();
|
Daniel@0
|
7946 token.prec = prec;
|
Daniel@0
|
7947 stack.push(token);
|
Daniel@0
|
7948 markers.push(lookahead);
|
Daniel@0
|
7949 expr = parseUnaryExpression();
|
Daniel@0
|
7950 stack.push(expr);
|
Daniel@0
|
7951 }
|
Daniel@0
|
7952
|
Daniel@0
|
7953 // Final reduce to clean-up the stack.
|
Daniel@0
|
7954 i = stack.length - 1;
|
Daniel@0
|
7955 expr = stack[i];
|
Daniel@0
|
7956 markers.pop();
|
Daniel@0
|
7957 while (i > 1) {
|
Daniel@0
|
7958 expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
|
Daniel@0
|
7959 i -= 2;
|
Daniel@0
|
7960 }
|
Daniel@0
|
7961
|
Daniel@0
|
7962 return expr;
|
Daniel@0
|
7963 }
|
Daniel@0
|
7964
|
Daniel@0
|
7965 // 11.12 Conditional Operator
|
Daniel@0
|
7966
|
Daniel@0
|
7967 function parseConditionalExpression() {
|
Daniel@0
|
7968 var expr, previousAllowIn, consequent, alternate, startToken;
|
Daniel@0
|
7969
|
Daniel@0
|
7970 startToken = lookahead;
|
Daniel@0
|
7971
|
Daniel@0
|
7972 expr = parseBinaryExpression();
|
Daniel@0
|
7973
|
Daniel@0
|
7974 if (match('?')) {
|
Daniel@0
|
7975 lex();
|
Daniel@0
|
7976 previousAllowIn = state.allowIn;
|
Daniel@0
|
7977 state.allowIn = true;
|
Daniel@0
|
7978 consequent = parseAssignmentExpression();
|
Daniel@0
|
7979 state.allowIn = previousAllowIn;
|
Daniel@0
|
7980 expect(':');
|
Daniel@0
|
7981 alternate = parseAssignmentExpression();
|
Daniel@0
|
7982
|
Daniel@0
|
7983 expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
|
Daniel@0
|
7984 }
|
Daniel@0
|
7985
|
Daniel@0
|
7986 return expr;
|
Daniel@0
|
7987 }
|
Daniel@0
|
7988
|
Daniel@0
|
7989 // 11.13 Assignment Operators
|
Daniel@0
|
7990
|
Daniel@0
|
7991 function parseAssignmentExpression() {
|
Daniel@0
|
7992 var oldParenthesisCount, token, expr, startToken;
|
Daniel@0
|
7993
|
Daniel@0
|
7994 oldParenthesisCount = state.parenthesisCount;
|
Daniel@0
|
7995
|
Daniel@0
|
7996 startToken = lookahead;
|
Daniel@0
|
7997 token = lookahead;
|
Daniel@0
|
7998
|
Daniel@0
|
7999 expr = parseConditionalExpression();
|
Daniel@0
|
8000
|
Daniel@0
|
8001 return expr;
|
Daniel@0
|
8002 }
|
Daniel@0
|
8003
|
Daniel@0
|
8004 // 11.14 Comma Operator
|
Daniel@0
|
8005
|
Daniel@0
|
8006 function parseExpression() {
|
Daniel@0
|
8007 var expr = parseAssignmentExpression();
|
Daniel@0
|
8008
|
Daniel@0
|
8009 if (match(',')) {
|
Daniel@0
|
8010 throw new Error("Disabled."); // no sequence expressions
|
Daniel@0
|
8011 }
|
Daniel@0
|
8012
|
Daniel@0
|
8013 return expr;
|
Daniel@0
|
8014 }
|
Daniel@0
|
8015
|
Daniel@0
|
8016 // 12.4 Expression Statement
|
Daniel@0
|
8017
|
Daniel@0
|
8018 function parseExpressionStatement(node) {
|
Daniel@0
|
8019 var expr = parseExpression();
|
Daniel@0
|
8020 consumeSemicolon();
|
Daniel@0
|
8021 return node.finishExpressionStatement(expr);
|
Daniel@0
|
8022 }
|
Daniel@0
|
8023
|
Daniel@0
|
8024 // 12 Statements
|
Daniel@0
|
8025
|
Daniel@0
|
8026 function parseStatement() {
|
Daniel@0
|
8027 var type = lookahead.type,
|
Daniel@0
|
8028 expr,
|
Daniel@0
|
8029 node;
|
Daniel@0
|
8030
|
Daniel@0
|
8031 if (type === Token.EOF) {
|
Daniel@0
|
8032 throwUnexpected(lookahead);
|
Daniel@0
|
8033 }
|
Daniel@0
|
8034
|
Daniel@0
|
8035 if (type === Token.Punctuator && lookahead.value === '{') {
|
Daniel@0
|
8036 throw new Error("Disabled."); // block statement
|
Daniel@0
|
8037 }
|
Daniel@0
|
8038
|
Daniel@0
|
8039 node = new Node();
|
Daniel@0
|
8040
|
Daniel@0
|
8041 if (type === Token.Punctuator) {
|
Daniel@0
|
8042 switch (lookahead.value) {
|
Daniel@0
|
8043 case ';':
|
Daniel@0
|
8044 throw new Error("Disabled."); // empty statement
|
Daniel@0
|
8045 case '(':
|
Daniel@0
|
8046 return parseExpressionStatement(node);
|
Daniel@0
|
8047 default:
|
Daniel@0
|
8048 break;
|
Daniel@0
|
8049 }
|
Daniel@0
|
8050 } else if (type === Token.Keyword) {
|
Daniel@0
|
8051 throw new Error("Disabled."); // keyword
|
Daniel@0
|
8052 }
|
Daniel@0
|
8053
|
Daniel@0
|
8054 expr = parseExpression();
|
Daniel@0
|
8055 consumeSemicolon();
|
Daniel@0
|
8056 return node.finishExpressionStatement(expr);
|
Daniel@0
|
8057 }
|
Daniel@0
|
8058
|
Daniel@0
|
8059 // 14 Program
|
Daniel@0
|
8060
|
Daniel@0
|
8061 function parseSourceElement() {
|
Daniel@0
|
8062 if (lookahead.type === Token.Keyword) {
|
Daniel@0
|
8063 switch (lookahead.value) {
|
Daniel@0
|
8064 case 'const':
|
Daniel@0
|
8065 case 'let':
|
Daniel@0
|
8066 throw new Error("Disabled.");
|
Daniel@0
|
8067 case 'function':
|
Daniel@0
|
8068 throw new Error("Disabled.");
|
Daniel@0
|
8069 default:
|
Daniel@0
|
8070 return parseStatement();
|
Daniel@0
|
8071 }
|
Daniel@0
|
8072 }
|
Daniel@0
|
8073
|
Daniel@0
|
8074 if (lookahead.type !== Token.EOF) {
|
Daniel@0
|
8075 return parseStatement();
|
Daniel@0
|
8076 }
|
Daniel@0
|
8077 }
|
Daniel@0
|
8078
|
Daniel@0
|
8079 function parseSourceElements() {
|
Daniel@0
|
8080 var sourceElement, sourceElements = [], token, directive, firstRestricted;
|
Daniel@0
|
8081
|
Daniel@0
|
8082 while (index < length) {
|
Daniel@0
|
8083 token = lookahead;
|
Daniel@0
|
8084 if (token.type !== Token.StringLiteral) {
|
Daniel@0
|
8085 break;
|
Daniel@0
|
8086 }
|
Daniel@0
|
8087
|
Daniel@0
|
8088 sourceElement = parseSourceElement();
|
Daniel@0
|
8089 sourceElements.push(sourceElement);
|
Daniel@0
|
8090 if (sourceElement.expression.type !== Syntax.Literal) {
|
Daniel@0
|
8091 // this is not directive
|
Daniel@0
|
8092 break;
|
Daniel@0
|
8093 }
|
Daniel@0
|
8094 directive = source.slice(token.start + 1, token.end - 1);
|
Daniel@0
|
8095 if (directive === 'use strict') {
|
Daniel@0
|
8096 strict = true;
|
Daniel@0
|
8097 if (firstRestricted) {
|
Daniel@0
|
8098 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
|
Daniel@0
|
8099 }
|
Daniel@0
|
8100 } else {
|
Daniel@0
|
8101 if (!firstRestricted && token.octal) {
|
Daniel@0
|
8102 firstRestricted = token;
|
Daniel@0
|
8103 }
|
Daniel@0
|
8104 }
|
Daniel@0
|
8105 }
|
Daniel@0
|
8106
|
Daniel@0
|
8107 while (index < length) {
|
Daniel@0
|
8108 sourceElement = parseSourceElement();
|
Daniel@0
|
8109 if (typeof sourceElement === 'undefined') {
|
Daniel@0
|
8110 break;
|
Daniel@0
|
8111 }
|
Daniel@0
|
8112 sourceElements.push(sourceElement);
|
Daniel@0
|
8113 }
|
Daniel@0
|
8114 return sourceElements;
|
Daniel@0
|
8115 }
|
Daniel@0
|
8116
|
Daniel@0
|
8117 function parseProgram() {
|
Daniel@0
|
8118 var body, node;
|
Daniel@0
|
8119
|
Daniel@0
|
8120 skipComment();
|
Daniel@0
|
8121 peek();
|
Daniel@0
|
8122 node = new Node();
|
Daniel@0
|
8123 strict = true; // assume strict
|
Daniel@0
|
8124
|
Daniel@0
|
8125 body = parseSourceElements();
|
Daniel@0
|
8126 return node.finishProgram(body);
|
Daniel@0
|
8127 }
|
Daniel@0
|
8128
|
Daniel@0
|
8129 function filterTokenLocation() {
|
Daniel@0
|
8130 var i, entry, token, tokens = [];
|
Daniel@0
|
8131
|
Daniel@0
|
8132 for (i = 0; i < extra.tokens.length; ++i) {
|
Daniel@0
|
8133 entry = extra.tokens[i];
|
Daniel@0
|
8134 token = {
|
Daniel@0
|
8135 type: entry.type,
|
Daniel@0
|
8136 value: entry.value
|
Daniel@0
|
8137 };
|
Daniel@0
|
8138 if (entry.regex) {
|
Daniel@0
|
8139 token.regex = {
|
Daniel@0
|
8140 pattern: entry.regex.pattern,
|
Daniel@0
|
8141 flags: entry.regex.flags
|
Daniel@0
|
8142 };
|
Daniel@0
|
8143 }
|
Daniel@0
|
8144 if (extra.range) {
|
Daniel@0
|
8145 token.range = entry.range;
|
Daniel@0
|
8146 }
|
Daniel@0
|
8147 if (extra.loc) {
|
Daniel@0
|
8148 token.loc = entry.loc;
|
Daniel@0
|
8149 }
|
Daniel@0
|
8150 tokens.push(token);
|
Daniel@0
|
8151 }
|
Daniel@0
|
8152
|
Daniel@0
|
8153 extra.tokens = tokens;
|
Daniel@0
|
8154 }
|
Daniel@0
|
8155
|
Daniel@0
|
8156 function tokenize(code, options) {
|
Daniel@0
|
8157 var toString,
|
Daniel@0
|
8158 tokens;
|
Daniel@0
|
8159
|
Daniel@0
|
8160 toString = String;
|
Daniel@0
|
8161 if (typeof code !== 'string' && !(code instanceof String)) {
|
Daniel@0
|
8162 code = toString(code);
|
Daniel@0
|
8163 }
|
Daniel@0
|
8164
|
Daniel@0
|
8165 source = code;
|
Daniel@0
|
8166 index = 0;
|
Daniel@0
|
8167 lineNumber = (source.length > 0) ? 1 : 0;
|
Daniel@0
|
8168 lineStart = 0;
|
Daniel@0
|
8169 length = source.length;
|
Daniel@0
|
8170 lookahead = null;
|
Daniel@0
|
8171 state = {
|
Daniel@0
|
8172 allowIn: true,
|
Daniel@0
|
8173 labelSet: {},
|
Daniel@0
|
8174 inFunctionBody: false,
|
Daniel@0
|
8175 inIteration: false,
|
Daniel@0
|
8176 inSwitch: false,
|
Daniel@0
|
8177 lastCommentStart: -1
|
Daniel@0
|
8178 };
|
Daniel@0
|
8179
|
Daniel@0
|
8180 extra = {};
|
Daniel@0
|
8181
|
Daniel@0
|
8182 // Options matching.
|
Daniel@0
|
8183 options = options || {};
|
Daniel@0
|
8184
|
Daniel@0
|
8185 // Of course we collect tokens here.
|
Daniel@0
|
8186 options.tokens = true;
|
Daniel@0
|
8187 extra.tokens = [];
|
Daniel@0
|
8188 extra.tokenize = true;
|
Daniel@0
|
8189 // The following two fields are necessary to compute the Regex tokens.
|
Daniel@0
|
8190 extra.openParenToken = -1;
|
Daniel@0
|
8191 extra.openCurlyToken = -1;
|
Daniel@0
|
8192
|
Daniel@0
|
8193 extra.range = (typeof options.range === 'boolean') && options.range;
|
Daniel@0
|
8194 extra.loc = (typeof options.loc === 'boolean') && options.loc;
|
Daniel@0
|
8195
|
Daniel@0
|
8196 if (typeof options.tolerant === 'boolean' && options.tolerant) {
|
Daniel@0
|
8197 extra.errors = [];
|
Daniel@0
|
8198 }
|
Daniel@0
|
8199
|
Daniel@0
|
8200 try {
|
Daniel@0
|
8201 peek();
|
Daniel@0
|
8202 if (lookahead.type === Token.EOF) {
|
Daniel@0
|
8203 return extra.tokens;
|
Daniel@0
|
8204 }
|
Daniel@0
|
8205
|
Daniel@0
|
8206 lex();
|
Daniel@0
|
8207 while (lookahead.type !== Token.EOF) {
|
Daniel@0
|
8208 try {
|
Daniel@0
|
8209 lex();
|
Daniel@0
|
8210 } catch (lexError) {
|
Daniel@0
|
8211 if (extra.errors) {
|
Daniel@0
|
8212 extra.errors.push(lexError);
|
Daniel@0
|
8213 // We have to break on the first error
|
Daniel@0
|
8214 // to avoid infinite loops.
|
Daniel@0
|
8215 break;
|
Daniel@0
|
8216 } else {
|
Daniel@0
|
8217 throw lexError;
|
Daniel@0
|
8218 }
|
Daniel@0
|
8219 }
|
Daniel@0
|
8220 }
|
Daniel@0
|
8221
|
Daniel@0
|
8222 filterTokenLocation();
|
Daniel@0
|
8223 tokens = extra.tokens;
|
Daniel@0
|
8224 if (typeof extra.errors !== 'undefined') {
|
Daniel@0
|
8225 tokens.errors = extra.errors;
|
Daniel@0
|
8226 }
|
Daniel@0
|
8227 } catch (e) {
|
Daniel@0
|
8228 throw e;
|
Daniel@0
|
8229 } finally {
|
Daniel@0
|
8230 extra = {};
|
Daniel@0
|
8231 }
|
Daniel@0
|
8232 return tokens;
|
Daniel@0
|
8233 }
|
Daniel@0
|
8234
|
Daniel@0
|
8235 function parse(code, options) {
|
Daniel@0
|
8236 var program, toString;
|
Daniel@0
|
8237
|
Daniel@0
|
8238 toString = String;
|
Daniel@0
|
8239 if (typeof code !== 'string' && !(code instanceof String)) {
|
Daniel@0
|
8240 code = toString(code);
|
Daniel@0
|
8241 }
|
Daniel@0
|
8242
|
Daniel@0
|
8243 source = code;
|
Daniel@0
|
8244 index = 0;
|
Daniel@0
|
8245 lineNumber = (source.length > 0) ? 1 : 0;
|
Daniel@0
|
8246 lineStart = 0;
|
Daniel@0
|
8247 length = source.length;
|
Daniel@0
|
8248 lookahead = null;
|
Daniel@0
|
8249 state = {
|
Daniel@0
|
8250 allowIn: true,
|
Daniel@0
|
8251 labelSet: {},
|
Daniel@0
|
8252 parenthesisCount: 0,
|
Daniel@0
|
8253 inFunctionBody: false,
|
Daniel@0
|
8254 inIteration: false,
|
Daniel@0
|
8255 inSwitch: false,
|
Daniel@0
|
8256 lastCommentStart: -1
|
Daniel@0
|
8257 };
|
Daniel@0
|
8258
|
Daniel@0
|
8259 extra = {};
|
Daniel@0
|
8260 if (typeof options !== 'undefined') {
|
Daniel@0
|
8261 extra.range = (typeof options.range === 'boolean') && options.range;
|
Daniel@0
|
8262 extra.loc = (typeof options.loc === 'boolean') && options.loc;
|
Daniel@0
|
8263
|
Daniel@0
|
8264 if (extra.loc && options.source !== null && options.source !== undefined) {
|
Daniel@0
|
8265 extra.source = toString(options.source);
|
Daniel@0
|
8266 }
|
Daniel@0
|
8267
|
Daniel@0
|
8268 if (typeof options.tokens === 'boolean' && options.tokens) {
|
Daniel@0
|
8269 extra.tokens = [];
|
Daniel@0
|
8270 }
|
Daniel@0
|
8271 if (typeof options.tolerant === 'boolean' && options.tolerant) {
|
Daniel@0
|
8272 extra.errors = [];
|
Daniel@0
|
8273 }
|
Daniel@0
|
8274 }
|
Daniel@0
|
8275
|
Daniel@0
|
8276 try {
|
Daniel@0
|
8277 program = parseProgram();
|
Daniel@0
|
8278 if (typeof extra.tokens !== 'undefined') {
|
Daniel@0
|
8279 filterTokenLocation();
|
Daniel@0
|
8280 program.tokens = extra.tokens;
|
Daniel@0
|
8281 }
|
Daniel@0
|
8282 if (typeof extra.errors !== 'undefined') {
|
Daniel@0
|
8283 program.errors = extra.errors;
|
Daniel@0
|
8284 }
|
Daniel@0
|
8285 } catch (e) {
|
Daniel@0
|
8286 throw e;
|
Daniel@0
|
8287 } finally {
|
Daniel@0
|
8288 extra = {};
|
Daniel@0
|
8289 }
|
Daniel@0
|
8290
|
Daniel@0
|
8291 return program;
|
Daniel@0
|
8292 }
|
Daniel@0
|
8293
|
Daniel@0
|
8294 return {
|
Daniel@0
|
8295 tokenize: tokenize,
|
Daniel@0
|
8296 parse: parse
|
Daniel@0
|
8297 };
|
Daniel@0
|
8298
|
Daniel@0
|
8299 })();
|
Daniel@0
|
8300 },{}],45:[function(require,module,exports){
|
Daniel@0
|
8301 var ts = Date.now();
|
Daniel@0
|
8302
|
Daniel@0
|
8303 function write(msg) {
|
Daniel@0
|
8304 msg = '[Vega Log] ' + msg;
|
Daniel@0
|
8305 console.log(msg);
|
Daniel@0
|
8306 }
|
Daniel@0
|
8307
|
Daniel@0
|
8308 function error(msg) {
|
Daniel@0
|
8309 msg = '[Vega Err] ' + msg;
|
Daniel@0
|
8310 console.error(msg);
|
Daniel@0
|
8311 }
|
Daniel@0
|
8312
|
Daniel@0
|
8313 function debug(input, args) {
|
Daniel@0
|
8314 if (!debug.enable) return;
|
Daniel@0
|
8315 var log = Function.prototype.bind.call(console.log, console);
|
Daniel@0
|
8316 var state = {
|
Daniel@0
|
8317 prevTime: Date.now() - ts,
|
Daniel@0
|
8318 stamp: input.stamp
|
Daniel@0
|
8319 };
|
Daniel@0
|
8320
|
Daniel@0
|
8321 if (input.add) {
|
Daniel@0
|
8322 state.add = input.add.length;
|
Daniel@0
|
8323 state.mod = input.mod.length;
|
Daniel@0
|
8324 state.rem = input.rem.length;
|
Daniel@0
|
8325 state.reflow = !!input.reflow;
|
Daniel@0
|
8326 }
|
Daniel@0
|
8327
|
Daniel@0
|
8328 log.apply(console, (args.push(JSON.stringify(state)), args));
|
Daniel@0
|
8329 ts = Date.now();
|
Daniel@0
|
8330 }
|
Daniel@0
|
8331
|
Daniel@0
|
8332 module.exports = {
|
Daniel@0
|
8333 log: write,
|
Daniel@0
|
8334 error: error,
|
Daniel@0
|
8335 debug: (debug.enable = false, debug)
|
Daniel@0
|
8336 };
|
Daniel@0
|
8337
|
Daniel@0
|
8338 },{}],46:[function(require,module,exports){
|
Daniel@0
|
8339 module.exports = {
|
Daniel@0
|
8340 path: require('./path'),
|
Daniel@0
|
8341 render: require('./render'),
|
Daniel@0
|
8342 Item: require('./util/Item'),
|
Daniel@0
|
8343 bound: require('./util/bound'),
|
Daniel@0
|
8344 Bounds: require('./util/Bounds'),
|
Daniel@0
|
8345 Gradient: require('./util/Gradient'),
|
Daniel@0
|
8346 toJSON: require('./util/scene').toJSON,
|
Daniel@0
|
8347 fromJSON: require('./util/scene').fromJSON
|
Daniel@0
|
8348 };
|
Daniel@0
|
8349 },{"./path":48,"./render":68,"./util/Bounds":74,"./util/Gradient":76,"./util/Item":78,"./util/bound":79,"./util/scene":82}],47:[function(require,module,exports){
|
Daniel@0
|
8350 var segmentCache = {},
|
Daniel@0
|
8351 bezierCache = {},
|
Daniel@0
|
8352 join = [].join;
|
Daniel@0
|
8353
|
Daniel@0
|
8354 // Copied from Inkscape svgtopdf, thanks!
|
Daniel@0
|
8355 function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
|
Daniel@0
|
8356 var key = join.call(arguments);
|
Daniel@0
|
8357 if (segmentCache[key]) {
|
Daniel@0
|
8358 return segmentCache[key];
|
Daniel@0
|
8359 }
|
Daniel@0
|
8360
|
Daniel@0
|
8361 var th = rotateX * (Math.PI/180);
|
Daniel@0
|
8362 var sin_th = Math.sin(th);
|
Daniel@0
|
8363 var cos_th = Math.cos(th);
|
Daniel@0
|
8364 rx = Math.abs(rx);
|
Daniel@0
|
8365 ry = Math.abs(ry);
|
Daniel@0
|
8366 var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
|
Daniel@0
|
8367 var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
|
Daniel@0
|
8368 var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry);
|
Daniel@0
|
8369 if (pl > 1) {
|
Daniel@0
|
8370 pl = Math.sqrt(pl);
|
Daniel@0
|
8371 rx *= pl;
|
Daniel@0
|
8372 ry *= pl;
|
Daniel@0
|
8373 }
|
Daniel@0
|
8374
|
Daniel@0
|
8375 var a00 = cos_th / rx;
|
Daniel@0
|
8376 var a01 = sin_th / rx;
|
Daniel@0
|
8377 var a10 = (-sin_th) / ry;
|
Daniel@0
|
8378 var a11 = (cos_th) / ry;
|
Daniel@0
|
8379 var x0 = a00 * ox + a01 * oy;
|
Daniel@0
|
8380 var y0 = a10 * ox + a11 * oy;
|
Daniel@0
|
8381 var x1 = a00 * x + a01 * y;
|
Daniel@0
|
8382 var y1 = a10 * x + a11 * y;
|
Daniel@0
|
8383
|
Daniel@0
|
8384 var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0);
|
Daniel@0
|
8385 var sfactor_sq = 1 / d - 0.25;
|
Daniel@0
|
8386 if (sfactor_sq < 0) sfactor_sq = 0;
|
Daniel@0
|
8387 var sfactor = Math.sqrt(sfactor_sq);
|
Daniel@0
|
8388 if (sweep == large) sfactor = -sfactor;
|
Daniel@0
|
8389 var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0);
|
Daniel@0
|
8390 var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
|
Daniel@0
|
8391
|
Daniel@0
|
8392 var th0 = Math.atan2(y0-yc, x0-xc);
|
Daniel@0
|
8393 var th1 = Math.atan2(y1-yc, x1-xc);
|
Daniel@0
|
8394
|
Daniel@0
|
8395 var th_arc = th1-th0;
|
Daniel@0
|
8396 if (th_arc < 0 && sweep === 1){
|
Daniel@0
|
8397 th_arc += 2 * Math.PI;
|
Daniel@0
|
8398 } else if (th_arc > 0 && sweep === 0) {
|
Daniel@0
|
8399 th_arc -= 2 * Math.PI;
|
Daniel@0
|
8400 }
|
Daniel@0
|
8401
|
Daniel@0
|
8402 var segs = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
|
Daniel@0
|
8403 var result = [];
|
Daniel@0
|
8404 for (var i=0; i<segs; ++i) {
|
Daniel@0
|
8405 var th2 = th0 + i * th_arc / segs;
|
Daniel@0
|
8406 var th3 = th0 + (i+1) * th_arc / segs;
|
Daniel@0
|
8407 result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
|
Daniel@0
|
8408 }
|
Daniel@0
|
8409
|
Daniel@0
|
8410 return (segmentCache[key] = result);
|
Daniel@0
|
8411 }
|
Daniel@0
|
8412
|
Daniel@0
|
8413 function bezier(params) {
|
Daniel@0
|
8414 var key = join.call(params);
|
Daniel@0
|
8415 if (bezierCache[key]) {
|
Daniel@0
|
8416 return bezierCache[key];
|
Daniel@0
|
8417 }
|
Daniel@0
|
8418
|
Daniel@0
|
8419 var cx = params[0],
|
Daniel@0
|
8420 cy = params[1],
|
Daniel@0
|
8421 th0 = params[2],
|
Daniel@0
|
8422 th1 = params[3],
|
Daniel@0
|
8423 rx = params[4],
|
Daniel@0
|
8424 ry = params[5],
|
Daniel@0
|
8425 sin_th = params[6],
|
Daniel@0
|
8426 cos_th = params[7];
|
Daniel@0
|
8427
|
Daniel@0
|
8428 var a00 = cos_th * rx;
|
Daniel@0
|
8429 var a01 = -sin_th * ry;
|
Daniel@0
|
8430 var a10 = sin_th * rx;
|
Daniel@0
|
8431 var a11 = cos_th * ry;
|
Daniel@0
|
8432
|
Daniel@0
|
8433 var cos_th0 = Math.cos(th0);
|
Daniel@0
|
8434 var sin_th0 = Math.sin(th0);
|
Daniel@0
|
8435 var cos_th1 = Math.cos(th1);
|
Daniel@0
|
8436 var sin_th1 = Math.sin(th1);
|
Daniel@0
|
8437
|
Daniel@0
|
8438 var th_half = 0.5 * (th1 - th0);
|
Daniel@0
|
8439 var sin_th_h2 = Math.sin(th_half * 0.5);
|
Daniel@0
|
8440 var t = (8/3) * sin_th_h2 * sin_th_h2 / Math.sin(th_half);
|
Daniel@0
|
8441 var x1 = cx + cos_th0 - t * sin_th0;
|
Daniel@0
|
8442 var y1 = cy + sin_th0 + t * cos_th0;
|
Daniel@0
|
8443 var x3 = cx + cos_th1;
|
Daniel@0
|
8444 var y3 = cy + sin_th1;
|
Daniel@0
|
8445 var x2 = x3 + t * sin_th1;
|
Daniel@0
|
8446 var y2 = y3 - t * cos_th1;
|
Daniel@0
|
8447
|
Daniel@0
|
8448 return (bezierCache[key] = [
|
Daniel@0
|
8449 a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
|
Daniel@0
|
8450 a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
|
Daniel@0
|
8451 a00 * x3 + a01 * y3, a10 * x3 + a11 * y3
|
Daniel@0
|
8452 ]);
|
Daniel@0
|
8453 }
|
Daniel@0
|
8454
|
Daniel@0
|
8455 module.exports = {
|
Daniel@0
|
8456 segments: segments,
|
Daniel@0
|
8457 bezier: bezier,
|
Daniel@0
|
8458 cache: {
|
Daniel@0
|
8459 segments: segmentCache,
|
Daniel@0
|
8460 bezier: bezierCache
|
Daniel@0
|
8461 }
|
Daniel@0
|
8462 };
|
Daniel@0
|
8463
|
Daniel@0
|
8464 },{}],48:[function(require,module,exports){
|
Daniel@0
|
8465 module.exports = {
|
Daniel@0
|
8466 parse: require('./parse'),
|
Daniel@0
|
8467 render: require('./render')
|
Daniel@0
|
8468 };
|
Daniel@0
|
8469
|
Daniel@0
|
8470 },{"./parse":49,"./render":50}],49:[function(require,module,exports){
|
Daniel@0
|
8471 // Path parsing and rendering code adapted from fabric.js -- Thanks!
|
Daniel@0
|
8472 var cmdlen = { m:2, l:2, h:1, v:1, c:6, s:4, q:4, t:2, a:7 },
|
Daniel@0
|
8473 regexp = [/([MLHVCSQTAZmlhvcsqtaz])/g, /###/, /(\d)([-+])/g, /\s|,|###/];
|
Daniel@0
|
8474
|
Daniel@0
|
8475 module.exports = function(pathstr) {
|
Daniel@0
|
8476 var result = [],
|
Daniel@0
|
8477 path,
|
Daniel@0
|
8478 curr,
|
Daniel@0
|
8479 chunks,
|
Daniel@0
|
8480 parsed, param,
|
Daniel@0
|
8481 cmd, len, i, j, n, m;
|
Daniel@0
|
8482
|
Daniel@0
|
8483 // First, break path into command sequence
|
Daniel@0
|
8484 path = pathstr
|
Daniel@0
|
8485 .slice()
|
Daniel@0
|
8486 .replace(regexp[0], '###$1')
|
Daniel@0
|
8487 .split(regexp[1])
|
Daniel@0
|
8488 .slice(1);
|
Daniel@0
|
8489
|
Daniel@0
|
8490 // Next, parse each command in turn
|
Daniel@0
|
8491 for (i=0, n=path.length; i<n; ++i) {
|
Daniel@0
|
8492 curr = path[i];
|
Daniel@0
|
8493 chunks = curr
|
Daniel@0
|
8494 .slice(1)
|
Daniel@0
|
8495 .trim()
|
Daniel@0
|
8496 .replace(regexp[2],'$1###$2')
|
Daniel@0
|
8497 .split(regexp[3]);
|
Daniel@0
|
8498 cmd = curr.charAt(0);
|
Daniel@0
|
8499
|
Daniel@0
|
8500 parsed = [cmd];
|
Daniel@0
|
8501 for (j=0, m=chunks.length; j<m; ++j) {
|
Daniel@0
|
8502 if ((param = +chunks[j]) === param) { // not NaN
|
Daniel@0
|
8503 parsed.push(param);
|
Daniel@0
|
8504 }
|
Daniel@0
|
8505 }
|
Daniel@0
|
8506
|
Daniel@0
|
8507 len = cmdlen[cmd.toLowerCase()];
|
Daniel@0
|
8508 if (parsed.length-1 > len) {
|
Daniel@0
|
8509 for (j=1, m=parsed.length; j<m; j+=len) {
|
Daniel@0
|
8510 result.push([cmd].concat(parsed.slice(j, j+len)));
|
Daniel@0
|
8511 }
|
Daniel@0
|
8512 }
|
Daniel@0
|
8513 else {
|
Daniel@0
|
8514 result.push(parsed);
|
Daniel@0
|
8515 }
|
Daniel@0
|
8516 }
|
Daniel@0
|
8517
|
Daniel@0
|
8518 return result;
|
Daniel@0
|
8519 };
|
Daniel@0
|
8520
|
Daniel@0
|
8521 },{}],50:[function(require,module,exports){
|
Daniel@0
|
8522 var arc = require('./arc');
|
Daniel@0
|
8523
|
Daniel@0
|
8524 module.exports = function(g, path, l, t) {
|
Daniel@0
|
8525 var current, // current instruction
|
Daniel@0
|
8526 previous = null,
|
Daniel@0
|
8527 x = 0, // current x
|
Daniel@0
|
8528 y = 0, // current y
|
Daniel@0
|
8529 controlX = 0, // current control point x
|
Daniel@0
|
8530 controlY = 0, // current control point y
|
Daniel@0
|
8531 tempX,
|
Daniel@0
|
8532 tempY,
|
Daniel@0
|
8533 tempControlX,
|
Daniel@0
|
8534 tempControlY;
|
Daniel@0
|
8535
|
Daniel@0
|
8536 if (l == null) l = 0;
|
Daniel@0
|
8537 if (t == null) t = 0;
|
Daniel@0
|
8538
|
Daniel@0
|
8539 g.beginPath();
|
Daniel@0
|
8540
|
Daniel@0
|
8541 for (var i=0, len=path.length; i<len; ++i) {
|
Daniel@0
|
8542 current = path[i];
|
Daniel@0
|
8543
|
Daniel@0
|
8544 switch (current[0]) { // first letter
|
Daniel@0
|
8545
|
Daniel@0
|
8546 case 'l': // lineto, relative
|
Daniel@0
|
8547 x += current[1];
|
Daniel@0
|
8548 y += current[2];
|
Daniel@0
|
8549 g.lineTo(x + l, y + t);
|
Daniel@0
|
8550 break;
|
Daniel@0
|
8551
|
Daniel@0
|
8552 case 'L': // lineto, absolute
|
Daniel@0
|
8553 x = current[1];
|
Daniel@0
|
8554 y = current[2];
|
Daniel@0
|
8555 g.lineTo(x + l, y + t);
|
Daniel@0
|
8556 break;
|
Daniel@0
|
8557
|
Daniel@0
|
8558 case 'h': // horizontal lineto, relative
|
Daniel@0
|
8559 x += current[1];
|
Daniel@0
|
8560 g.lineTo(x + l, y + t);
|
Daniel@0
|
8561 break;
|
Daniel@0
|
8562
|
Daniel@0
|
8563 case 'H': // horizontal lineto, absolute
|
Daniel@0
|
8564 x = current[1];
|
Daniel@0
|
8565 g.lineTo(x + l, y + t);
|
Daniel@0
|
8566 break;
|
Daniel@0
|
8567
|
Daniel@0
|
8568 case 'v': // vertical lineto, relative
|
Daniel@0
|
8569 y += current[1];
|
Daniel@0
|
8570 g.lineTo(x + l, y + t);
|
Daniel@0
|
8571 break;
|
Daniel@0
|
8572
|
Daniel@0
|
8573 case 'V': // verical lineto, absolute
|
Daniel@0
|
8574 y = current[1];
|
Daniel@0
|
8575 g.lineTo(x + l, y + t);
|
Daniel@0
|
8576 break;
|
Daniel@0
|
8577
|
Daniel@0
|
8578 case 'm': // moveTo, relative
|
Daniel@0
|
8579 x += current[1];
|
Daniel@0
|
8580 y += current[2];
|
Daniel@0
|
8581 g.moveTo(x + l, y + t);
|
Daniel@0
|
8582 break;
|
Daniel@0
|
8583
|
Daniel@0
|
8584 case 'M': // moveTo, absolute
|
Daniel@0
|
8585 x = current[1];
|
Daniel@0
|
8586 y = current[2];
|
Daniel@0
|
8587 g.moveTo(x + l, y + t);
|
Daniel@0
|
8588 break;
|
Daniel@0
|
8589
|
Daniel@0
|
8590 case 'c': // bezierCurveTo, relative
|
Daniel@0
|
8591 tempX = x + current[5];
|
Daniel@0
|
8592 tempY = y + current[6];
|
Daniel@0
|
8593 controlX = x + current[3];
|
Daniel@0
|
8594 controlY = y + current[4];
|
Daniel@0
|
8595 g.bezierCurveTo(
|
Daniel@0
|
8596 x + current[1] + l, // x1
|
Daniel@0
|
8597 y + current[2] + t, // y1
|
Daniel@0
|
8598 controlX + l, // x2
|
Daniel@0
|
8599 controlY + t, // y2
|
Daniel@0
|
8600 tempX + l,
|
Daniel@0
|
8601 tempY + t
|
Daniel@0
|
8602 );
|
Daniel@0
|
8603 x = tempX;
|
Daniel@0
|
8604 y = tempY;
|
Daniel@0
|
8605 break;
|
Daniel@0
|
8606
|
Daniel@0
|
8607 case 'C': // bezierCurveTo, absolute
|
Daniel@0
|
8608 x = current[5];
|
Daniel@0
|
8609 y = current[6];
|
Daniel@0
|
8610 controlX = current[3];
|
Daniel@0
|
8611 controlY = current[4];
|
Daniel@0
|
8612 g.bezierCurveTo(
|
Daniel@0
|
8613 current[1] + l,
|
Daniel@0
|
8614 current[2] + t,
|
Daniel@0
|
8615 controlX + l,
|
Daniel@0
|
8616 controlY + t,
|
Daniel@0
|
8617 x + l,
|
Daniel@0
|
8618 y + t
|
Daniel@0
|
8619 );
|
Daniel@0
|
8620 break;
|
Daniel@0
|
8621
|
Daniel@0
|
8622 case 's': // shorthand cubic bezierCurveTo, relative
|
Daniel@0
|
8623 // transform to absolute x,y
|
Daniel@0
|
8624 tempX = x + current[3];
|
Daniel@0
|
8625 tempY = y + current[4];
|
Daniel@0
|
8626 // calculate reflection of previous control points
|
Daniel@0
|
8627 controlX = 2 * x - controlX;
|
Daniel@0
|
8628 controlY = 2 * y - controlY;
|
Daniel@0
|
8629 g.bezierCurveTo(
|
Daniel@0
|
8630 controlX + l,
|
Daniel@0
|
8631 controlY + t,
|
Daniel@0
|
8632 x + current[1] + l,
|
Daniel@0
|
8633 y + current[2] + t,
|
Daniel@0
|
8634 tempX + l,
|
Daniel@0
|
8635 tempY + t
|
Daniel@0
|
8636 );
|
Daniel@0
|
8637
|
Daniel@0
|
8638 // set control point to 2nd one of this command
|
Daniel@0
|
8639 // the first control point is assumed to be the reflection of
|
Daniel@0
|
8640 // the second control point on the previous command relative
|
Daniel@0
|
8641 // to the current point.
|
Daniel@0
|
8642 controlX = x + current[1];
|
Daniel@0
|
8643 controlY = y + current[2];
|
Daniel@0
|
8644
|
Daniel@0
|
8645 x = tempX;
|
Daniel@0
|
8646 y = tempY;
|
Daniel@0
|
8647 break;
|
Daniel@0
|
8648
|
Daniel@0
|
8649 case 'S': // shorthand cubic bezierCurveTo, absolute
|
Daniel@0
|
8650 tempX = current[3];
|
Daniel@0
|
8651 tempY = current[4];
|
Daniel@0
|
8652 // calculate reflection of previous control points
|
Daniel@0
|
8653 controlX = 2*x - controlX;
|
Daniel@0
|
8654 controlY = 2*y - controlY;
|
Daniel@0
|
8655 g.bezierCurveTo(
|
Daniel@0
|
8656 controlX + l,
|
Daniel@0
|
8657 controlY + t,
|
Daniel@0
|
8658 current[1] + l,
|
Daniel@0
|
8659 current[2] + t,
|
Daniel@0
|
8660 tempX + l,
|
Daniel@0
|
8661 tempY + t
|
Daniel@0
|
8662 );
|
Daniel@0
|
8663 x = tempX;
|
Daniel@0
|
8664 y = tempY;
|
Daniel@0
|
8665 // set control point to 2nd one of this command
|
Daniel@0
|
8666 // the first control point is assumed to be the reflection of
|
Daniel@0
|
8667 // the second control point on the previous command relative
|
Daniel@0
|
8668 // to the current point.
|
Daniel@0
|
8669 controlX = current[1];
|
Daniel@0
|
8670 controlY = current[2];
|
Daniel@0
|
8671
|
Daniel@0
|
8672 break;
|
Daniel@0
|
8673
|
Daniel@0
|
8674 case 'q': // quadraticCurveTo, relative
|
Daniel@0
|
8675 // transform to absolute x,y
|
Daniel@0
|
8676 tempX = x + current[3];
|
Daniel@0
|
8677 tempY = y + current[4];
|
Daniel@0
|
8678
|
Daniel@0
|
8679 controlX = x + current[1];
|
Daniel@0
|
8680 controlY = y + current[2];
|
Daniel@0
|
8681
|
Daniel@0
|
8682 g.quadraticCurveTo(
|
Daniel@0
|
8683 controlX + l,
|
Daniel@0
|
8684 controlY + t,
|
Daniel@0
|
8685 tempX + l,
|
Daniel@0
|
8686 tempY + t
|
Daniel@0
|
8687 );
|
Daniel@0
|
8688 x = tempX;
|
Daniel@0
|
8689 y = tempY;
|
Daniel@0
|
8690 break;
|
Daniel@0
|
8691
|
Daniel@0
|
8692 case 'Q': // quadraticCurveTo, absolute
|
Daniel@0
|
8693 tempX = current[3];
|
Daniel@0
|
8694 tempY = current[4];
|
Daniel@0
|
8695
|
Daniel@0
|
8696 g.quadraticCurveTo(
|
Daniel@0
|
8697 current[1] + l,
|
Daniel@0
|
8698 current[2] + t,
|
Daniel@0
|
8699 tempX + l,
|
Daniel@0
|
8700 tempY + t
|
Daniel@0
|
8701 );
|
Daniel@0
|
8702 x = tempX;
|
Daniel@0
|
8703 y = tempY;
|
Daniel@0
|
8704 controlX = current[1];
|
Daniel@0
|
8705 controlY = current[2];
|
Daniel@0
|
8706 break;
|
Daniel@0
|
8707
|
Daniel@0
|
8708 case 't': // shorthand quadraticCurveTo, relative
|
Daniel@0
|
8709
|
Daniel@0
|
8710 // transform to absolute x,y
|
Daniel@0
|
8711 tempX = x + current[1];
|
Daniel@0
|
8712 tempY = y + current[2];
|
Daniel@0
|
8713
|
Daniel@0
|
8714 if (previous[0].match(/[QqTt]/) === null) {
|
Daniel@0
|
8715 // If there is no previous command or if the previous command was not a Q, q, T or t,
|
Daniel@0
|
8716 // assume the control point is coincident with the current point
|
Daniel@0
|
8717 controlX = x;
|
Daniel@0
|
8718 controlY = y;
|
Daniel@0
|
8719 }
|
Daniel@0
|
8720 else if (previous[0] === 't') {
|
Daniel@0
|
8721 // calculate reflection of previous control points for t
|
Daniel@0
|
8722 controlX = 2 * x - tempControlX;
|
Daniel@0
|
8723 controlY = 2 * y - tempControlY;
|
Daniel@0
|
8724 }
|
Daniel@0
|
8725 else if (previous[0] === 'q') {
|
Daniel@0
|
8726 // calculate reflection of previous control points for q
|
Daniel@0
|
8727 controlX = 2 * x - controlX;
|
Daniel@0
|
8728 controlY = 2 * y - controlY;
|
Daniel@0
|
8729 }
|
Daniel@0
|
8730
|
Daniel@0
|
8731 tempControlX = controlX;
|
Daniel@0
|
8732 tempControlY = controlY;
|
Daniel@0
|
8733
|
Daniel@0
|
8734 g.quadraticCurveTo(
|
Daniel@0
|
8735 controlX + l,
|
Daniel@0
|
8736 controlY + t,
|
Daniel@0
|
8737 tempX + l,
|
Daniel@0
|
8738 tempY + t
|
Daniel@0
|
8739 );
|
Daniel@0
|
8740 x = tempX;
|
Daniel@0
|
8741 y = tempY;
|
Daniel@0
|
8742 controlX = x + current[1];
|
Daniel@0
|
8743 controlY = y + current[2];
|
Daniel@0
|
8744 break;
|
Daniel@0
|
8745
|
Daniel@0
|
8746 case 'T':
|
Daniel@0
|
8747 tempX = current[1];
|
Daniel@0
|
8748 tempY = current[2];
|
Daniel@0
|
8749
|
Daniel@0
|
8750 // calculate reflection of previous control points
|
Daniel@0
|
8751 controlX = 2 * x - controlX;
|
Daniel@0
|
8752 controlY = 2 * y - controlY;
|
Daniel@0
|
8753 g.quadraticCurveTo(
|
Daniel@0
|
8754 controlX + l,
|
Daniel@0
|
8755 controlY + t,
|
Daniel@0
|
8756 tempX + l,
|
Daniel@0
|
8757 tempY + t
|
Daniel@0
|
8758 );
|
Daniel@0
|
8759 x = tempX;
|
Daniel@0
|
8760 y = tempY;
|
Daniel@0
|
8761 break;
|
Daniel@0
|
8762
|
Daniel@0
|
8763 case 'a':
|
Daniel@0
|
8764 drawArc(g, x + l, y + t, [
|
Daniel@0
|
8765 current[1],
|
Daniel@0
|
8766 current[2],
|
Daniel@0
|
8767 current[3],
|
Daniel@0
|
8768 current[4],
|
Daniel@0
|
8769 current[5],
|
Daniel@0
|
8770 current[6] + x + l,
|
Daniel@0
|
8771 current[7] + y + t
|
Daniel@0
|
8772 ]);
|
Daniel@0
|
8773 x += current[6];
|
Daniel@0
|
8774 y += current[7];
|
Daniel@0
|
8775 break;
|
Daniel@0
|
8776
|
Daniel@0
|
8777 case 'A':
|
Daniel@0
|
8778 drawArc(g, x + l, y + t, [
|
Daniel@0
|
8779 current[1],
|
Daniel@0
|
8780 current[2],
|
Daniel@0
|
8781 current[3],
|
Daniel@0
|
8782 current[4],
|
Daniel@0
|
8783 current[5],
|
Daniel@0
|
8784 current[6] + l,
|
Daniel@0
|
8785 current[7] + t
|
Daniel@0
|
8786 ]);
|
Daniel@0
|
8787 x = current[6];
|
Daniel@0
|
8788 y = current[7];
|
Daniel@0
|
8789 break;
|
Daniel@0
|
8790
|
Daniel@0
|
8791 case 'z':
|
Daniel@0
|
8792 case 'Z':
|
Daniel@0
|
8793 g.closePath();
|
Daniel@0
|
8794 break;
|
Daniel@0
|
8795 }
|
Daniel@0
|
8796 previous = current;
|
Daniel@0
|
8797 }
|
Daniel@0
|
8798 };
|
Daniel@0
|
8799
|
Daniel@0
|
8800 function drawArc(g, x, y, coords) {
|
Daniel@0
|
8801 var seg = arc.segments(
|
Daniel@0
|
8802 coords[5], // end x
|
Daniel@0
|
8803 coords[6], // end y
|
Daniel@0
|
8804 coords[0], // radius x
|
Daniel@0
|
8805 coords[1], // radius y
|
Daniel@0
|
8806 coords[3], // large flag
|
Daniel@0
|
8807 coords[4], // sweep flag
|
Daniel@0
|
8808 coords[2], // rotation
|
Daniel@0
|
8809 x, y
|
Daniel@0
|
8810 );
|
Daniel@0
|
8811 for (var i=0; i<seg.length; ++i) {
|
Daniel@0
|
8812 var bez = arc.bezier(seg[i]);
|
Daniel@0
|
8813 g.bezierCurveTo.apply(g, bez);
|
Daniel@0
|
8814 }
|
Daniel@0
|
8815 }
|
Daniel@0
|
8816
|
Daniel@0
|
8817 },{"./arc":47}],51:[function(require,module,exports){
|
Daniel@0
|
8818 function Handler() {
|
Daniel@0
|
8819 this._active = null;
|
Daniel@0
|
8820 this._handlers = {};
|
Daniel@0
|
8821 }
|
Daniel@0
|
8822
|
Daniel@0
|
8823 var prototype = Handler.prototype;
|
Daniel@0
|
8824
|
Daniel@0
|
8825 prototype.initialize = function(el, pad, obj) {
|
Daniel@0
|
8826 this._el = el;
|
Daniel@0
|
8827 this._obj = obj || null;
|
Daniel@0
|
8828 return this.padding(pad);
|
Daniel@0
|
8829 };
|
Daniel@0
|
8830
|
Daniel@0
|
8831 prototype.element = function() {
|
Daniel@0
|
8832 return this._el;
|
Daniel@0
|
8833 };
|
Daniel@0
|
8834
|
Daniel@0
|
8835 prototype.padding = function(pad) {
|
Daniel@0
|
8836 this._padding = pad || {top:0, left:0, bottom:0, right:0};
|
Daniel@0
|
8837 return this;
|
Daniel@0
|
8838 };
|
Daniel@0
|
8839
|
Daniel@0
|
8840 prototype.scene = function(scene) {
|
Daniel@0
|
8841 if (!arguments.length) return this._scene;
|
Daniel@0
|
8842 this._scene = scene;
|
Daniel@0
|
8843 return this;
|
Daniel@0
|
8844 };
|
Daniel@0
|
8845
|
Daniel@0
|
8846 // add an event handler
|
Daniel@0
|
8847 // subclasses should override
|
Daniel@0
|
8848 prototype.on = function(/*type, handler*/) {};
|
Daniel@0
|
8849
|
Daniel@0
|
8850 // remove an event handler
|
Daniel@0
|
8851 // subclasses should override
|
Daniel@0
|
8852 prototype.off = function(/*type, handler*/) {};
|
Daniel@0
|
8853
|
Daniel@0
|
8854 // return an array with all registered event handlers
|
Daniel@0
|
8855 prototype.handlers = function() {
|
Daniel@0
|
8856 var h = this._handlers, a = [], k;
|
Daniel@0
|
8857 for (k in h) { a.push.apply(a, h[k]); }
|
Daniel@0
|
8858 return a;
|
Daniel@0
|
8859 };
|
Daniel@0
|
8860
|
Daniel@0
|
8861 prototype.eventName = function(name) {
|
Daniel@0
|
8862 var i = name.indexOf('.');
|
Daniel@0
|
8863 return i < 0 ? name : name.slice(0,i);
|
Daniel@0
|
8864 };
|
Daniel@0
|
8865
|
Daniel@0
|
8866 module.exports = Handler;
|
Daniel@0
|
8867 },{}],52:[function(require,module,exports){
|
Daniel@0
|
8868 function Renderer() {
|
Daniel@0
|
8869 this._el = null;
|
Daniel@0
|
8870 this._bgcolor = null;
|
Daniel@0
|
8871 }
|
Daniel@0
|
8872
|
Daniel@0
|
8873 var prototype = Renderer.prototype;
|
Daniel@0
|
8874
|
Daniel@0
|
8875 prototype.initialize = function(el, width, height, padding) {
|
Daniel@0
|
8876 this._el = el;
|
Daniel@0
|
8877 return this.resize(width, height, padding);
|
Daniel@0
|
8878 };
|
Daniel@0
|
8879
|
Daniel@0
|
8880 // Returns the parent container element for a visualization
|
Daniel@0
|
8881 prototype.element = function() {
|
Daniel@0
|
8882 return this._el;
|
Daniel@0
|
8883 };
|
Daniel@0
|
8884
|
Daniel@0
|
8885 // Returns the scene element (e.g., canvas or SVG) of the visualization
|
Daniel@0
|
8886 // Subclasses must override if the first child is not the scene element
|
Daniel@0
|
8887 prototype.scene = function() {
|
Daniel@0
|
8888 return this._el && this._el.firstChild;
|
Daniel@0
|
8889 };
|
Daniel@0
|
8890
|
Daniel@0
|
8891 prototype.background = function(bgcolor) {
|
Daniel@0
|
8892 if (arguments.length === 0) return this._bgcolor;
|
Daniel@0
|
8893 this._bgcolor = bgcolor;
|
Daniel@0
|
8894 return this;
|
Daniel@0
|
8895 };
|
Daniel@0
|
8896
|
Daniel@0
|
8897 prototype.resize = function(width, height, padding) {
|
Daniel@0
|
8898 this._width = width;
|
Daniel@0
|
8899 this._height = height;
|
Daniel@0
|
8900 this._padding = padding || {top:0, left:0, bottom:0, right:0};
|
Daniel@0
|
8901 return this;
|
Daniel@0
|
8902 };
|
Daniel@0
|
8903
|
Daniel@0
|
8904 prototype.render = function(/*scene, items*/) {
|
Daniel@0
|
8905 return this;
|
Daniel@0
|
8906 };
|
Daniel@0
|
8907
|
Daniel@0
|
8908 module.exports = Renderer;
|
Daniel@0
|
8909 },{}],53:[function(require,module,exports){
|
Daniel@0
|
8910 var DOM = require('../../util/dom'),
|
Daniel@0
|
8911 Handler = require('../Handler'),
|
Daniel@0
|
8912 marks = require('./marks');
|
Daniel@0
|
8913
|
Daniel@0
|
8914 function CanvasHandler() {
|
Daniel@0
|
8915 Handler.call(this);
|
Daniel@0
|
8916 this._down = null;
|
Daniel@0
|
8917 this._touch = null;
|
Daniel@0
|
8918 this._first = true;
|
Daniel@0
|
8919 }
|
Daniel@0
|
8920
|
Daniel@0
|
8921 var base = Handler.prototype;
|
Daniel@0
|
8922 var prototype = (CanvasHandler.prototype = Object.create(base));
|
Daniel@0
|
8923 prototype.constructor = CanvasHandler;
|
Daniel@0
|
8924
|
Daniel@0
|
8925 prototype.initialize = function(el, pad, obj) {
|
Daniel@0
|
8926 // add event listeners
|
Daniel@0
|
8927 var canvas = this._canvas = DOM.find(el, 'canvas'),
|
Daniel@0
|
8928 that = this;
|
Daniel@0
|
8929 this.events.forEach(function(type) {
|
Daniel@0
|
8930 canvas.addEventListener(type, function(evt) {
|
Daniel@0
|
8931 if (prototype[type]) {
|
Daniel@0
|
8932 prototype[type].call(that, evt);
|
Daniel@0
|
8933 } else {
|
Daniel@0
|
8934 that.fire(type, evt);
|
Daniel@0
|
8935 }
|
Daniel@0
|
8936 });
|
Daniel@0
|
8937 });
|
Daniel@0
|
8938
|
Daniel@0
|
8939 return base.initialize.call(this, el, pad, obj);
|
Daniel@0
|
8940 };
|
Daniel@0
|
8941
|
Daniel@0
|
8942 prototype.canvas = function() {
|
Daniel@0
|
8943 return this._canvas;
|
Daniel@0
|
8944 };
|
Daniel@0
|
8945
|
Daniel@0
|
8946 // retrieve the current canvas context
|
Daniel@0
|
8947 prototype.context = function() {
|
Daniel@0
|
8948 return this._canvas.getContext('2d');
|
Daniel@0
|
8949 };
|
Daniel@0
|
8950
|
Daniel@0
|
8951 // supported events
|
Daniel@0
|
8952 prototype.events = [
|
Daniel@0
|
8953 'keydown',
|
Daniel@0
|
8954 'keypress',
|
Daniel@0
|
8955 'keyup',
|
Daniel@0
|
8956 'mousedown',
|
Daniel@0
|
8957 'mouseup',
|
Daniel@0
|
8958 'mousemove',
|
Daniel@0
|
8959 'mouseout',
|
Daniel@0
|
8960 'mouseover',
|
Daniel@0
|
8961 'click',
|
Daniel@0
|
8962 'dblclick',
|
Daniel@0
|
8963 'wheel',
|
Daniel@0
|
8964 'mousewheel',
|
Daniel@0
|
8965 'touchstart',
|
Daniel@0
|
8966 'touchmove',
|
Daniel@0
|
8967 'touchend'
|
Daniel@0
|
8968 ];
|
Daniel@0
|
8969
|
Daniel@0
|
8970 // to keep firefox happy
|
Daniel@0
|
8971 prototype.DOMMouseScroll = function(evt) {
|
Daniel@0
|
8972 this.fire('mousewheel', evt);
|
Daniel@0
|
8973 };
|
Daniel@0
|
8974
|
Daniel@0
|
8975 prototype.mousemove = function(evt) {
|
Daniel@0
|
8976 var a = this._active,
|
Daniel@0
|
8977 p = this.pickEvent(evt);
|
Daniel@0
|
8978
|
Daniel@0
|
8979 if (p === a) {
|
Daniel@0
|
8980 // active item and picked item are the same
|
Daniel@0
|
8981 this.fire('mousemove', evt); // fire move
|
Daniel@0
|
8982 } else {
|
Daniel@0
|
8983 // active item and picked item are different
|
Daniel@0
|
8984 this.fire('mouseout', evt); // fire out for prior active item
|
Daniel@0
|
8985 this._active = p; // set new active item
|
Daniel@0
|
8986 this.fire('mouseover', evt); // fire over for new active item
|
Daniel@0
|
8987 this.fire('mousemove', evt); // fire move for new active item
|
Daniel@0
|
8988 }
|
Daniel@0
|
8989 };
|
Daniel@0
|
8990
|
Daniel@0
|
8991 prototype.mouseout = function(evt) {
|
Daniel@0
|
8992 this.fire('mouseout', evt);
|
Daniel@0
|
8993 this._active = null;
|
Daniel@0
|
8994 };
|
Daniel@0
|
8995
|
Daniel@0
|
8996 prototype.mousedown = function(evt) {
|
Daniel@0
|
8997 this._down = this._active;
|
Daniel@0
|
8998 this.fire('mousedown', evt);
|
Daniel@0
|
8999 };
|
Daniel@0
|
9000
|
Daniel@0
|
9001 prototype.click = function(evt) {
|
Daniel@0
|
9002 if (this._down === this._active) {
|
Daniel@0
|
9003 this.fire('click', evt);
|
Daniel@0
|
9004 this._down = null;
|
Daniel@0
|
9005 }
|
Daniel@0
|
9006 };
|
Daniel@0
|
9007
|
Daniel@0
|
9008 prototype.touchstart = function(evt) {
|
Daniel@0
|
9009 this._touch = this.pickEvent(evt.changedTouches[0]);
|
Daniel@0
|
9010
|
Daniel@0
|
9011 if (this._first) {
|
Daniel@0
|
9012 this._active = this._touch;
|
Daniel@0
|
9013 this._first = false;
|
Daniel@0
|
9014 }
|
Daniel@0
|
9015
|
Daniel@0
|
9016 this.fire('touchstart', evt, true);
|
Daniel@0
|
9017 };
|
Daniel@0
|
9018
|
Daniel@0
|
9019 prototype.touchmove = function(evt) {
|
Daniel@0
|
9020 this.fire('touchmove', evt, true);
|
Daniel@0
|
9021 };
|
Daniel@0
|
9022
|
Daniel@0
|
9023 prototype.touchend = function(evt) {
|
Daniel@0
|
9024 this.fire('touchend', evt, true);
|
Daniel@0
|
9025 this._touch = null;
|
Daniel@0
|
9026 };
|
Daniel@0
|
9027
|
Daniel@0
|
9028 // fire an event
|
Daniel@0
|
9029 prototype.fire = function(type, evt, touch) {
|
Daniel@0
|
9030 var a = touch ? this._touch : this._active,
|
Daniel@0
|
9031 h = this._handlers[type], i, len;
|
Daniel@0
|
9032 if (h) {
|
Daniel@0
|
9033 evt.vegaType = type;
|
Daniel@0
|
9034 for (i=0, len=h.length; i<len; ++i) {
|
Daniel@0
|
9035 h[i].handler.call(this._obj, evt, a);
|
Daniel@0
|
9036 }
|
Daniel@0
|
9037 }
|
Daniel@0
|
9038 };
|
Daniel@0
|
9039
|
Daniel@0
|
9040 // add an event handler
|
Daniel@0
|
9041 prototype.on = function(type, handler) {
|
Daniel@0
|
9042 var name = this.eventName(type),
|
Daniel@0
|
9043 h = this._handlers;
|
Daniel@0
|
9044 (h[name] || (h[name] = [])).push({
|
Daniel@0
|
9045 type: type,
|
Daniel@0
|
9046 handler: handler
|
Daniel@0
|
9047 });
|
Daniel@0
|
9048 return this;
|
Daniel@0
|
9049 };
|
Daniel@0
|
9050
|
Daniel@0
|
9051 // remove an event handler
|
Daniel@0
|
9052 prototype.off = function(type, handler) {
|
Daniel@0
|
9053 var name = this.eventName(type),
|
Daniel@0
|
9054 h = this._handlers[name], i;
|
Daniel@0
|
9055 if (!h) return;
|
Daniel@0
|
9056 for (i=h.length; --i>=0;) {
|
Daniel@0
|
9057 if (h[i].type !== type) continue;
|
Daniel@0
|
9058 if (!handler || h[i].handler === handler) h.splice(i, 1);
|
Daniel@0
|
9059 }
|
Daniel@0
|
9060 return this;
|
Daniel@0
|
9061 };
|
Daniel@0
|
9062
|
Daniel@0
|
9063 prototype.pickEvent = function(evt) {
|
Daniel@0
|
9064 var rect = this._canvas.getBoundingClientRect(),
|
Daniel@0
|
9065 pad = this._padding, x, y;
|
Daniel@0
|
9066 return this.pick(this._scene,
|
Daniel@0
|
9067 x = (evt.clientX - rect.left),
|
Daniel@0
|
9068 y = (evt.clientY - rect.top),
|
Daniel@0
|
9069 x - pad.left, y - pad.top);
|
Daniel@0
|
9070 };
|
Daniel@0
|
9071
|
Daniel@0
|
9072 // find the scenegraph item at the current mouse position
|
Daniel@0
|
9073 // x, y -- the absolute x, y mouse coordinates on the canvas element
|
Daniel@0
|
9074 // gx, gy -- the relative coordinates within the current group
|
Daniel@0
|
9075 prototype.pick = function(scene, x, y, gx, gy) {
|
Daniel@0
|
9076 var g = this.context(),
|
Daniel@0
|
9077 mark = marks[scene.marktype];
|
Daniel@0
|
9078 return mark.pick.call(this, g, scene, x, y, gx, gy);
|
Daniel@0
|
9079 };
|
Daniel@0
|
9080
|
Daniel@0
|
9081 module.exports = CanvasHandler;
|
Daniel@0
|
9082
|
Daniel@0
|
9083 },{"../../util/dom":81,"../Handler":51,"./marks":60}],54:[function(require,module,exports){
|
Daniel@0
|
9084 var DOM = require('../../util/dom'),
|
Daniel@0
|
9085 Bounds = require('../../util/Bounds'),
|
Daniel@0
|
9086 ImageLoader = require('../../util/ImageLoader'),
|
Daniel@0
|
9087 Canvas = require('../../util/canvas'),
|
Daniel@0
|
9088 Renderer = require('../Renderer'),
|
Daniel@0
|
9089 marks = require('./marks');
|
Daniel@0
|
9090
|
Daniel@0
|
9091 function CanvasRenderer(loadConfig) {
|
Daniel@0
|
9092 Renderer.call(this);
|
Daniel@0
|
9093 this._loader = new ImageLoader(loadConfig);
|
Daniel@0
|
9094 }
|
Daniel@0
|
9095
|
Daniel@0
|
9096 CanvasRenderer.RETINA = true;
|
Daniel@0
|
9097
|
Daniel@0
|
9098 var base = Renderer.prototype;
|
Daniel@0
|
9099 var prototype = (CanvasRenderer.prototype = Object.create(base));
|
Daniel@0
|
9100 prototype.constructor = CanvasRenderer;
|
Daniel@0
|
9101
|
Daniel@0
|
9102 prototype.initialize = function(el, width, height, padding) {
|
Daniel@0
|
9103 this._canvas = Canvas.instance(width, height);
|
Daniel@0
|
9104 if (el) {
|
Daniel@0
|
9105 DOM.clear(el, 0).appendChild(this._canvas);
|
Daniel@0
|
9106 this._canvas.setAttribute('class', 'marks');
|
Daniel@0
|
9107 }
|
Daniel@0
|
9108 return base.initialize.call(this, el, width, height, padding);
|
Daniel@0
|
9109 };
|
Daniel@0
|
9110
|
Daniel@0
|
9111 prototype.resize = function(width, height, padding) {
|
Daniel@0
|
9112 base.resize.call(this, width, height, padding);
|
Daniel@0
|
9113 Canvas.resize(this._canvas, this._width, this._height,
|
Daniel@0
|
9114 this._padding, CanvasRenderer.RETINA);
|
Daniel@0
|
9115 return this;
|
Daniel@0
|
9116 };
|
Daniel@0
|
9117
|
Daniel@0
|
9118 prototype.canvas = function() {
|
Daniel@0
|
9119 return this._canvas;
|
Daniel@0
|
9120 };
|
Daniel@0
|
9121
|
Daniel@0
|
9122 prototype.context = function() {
|
Daniel@0
|
9123 return this._canvas ? this._canvas.getContext('2d') : null;
|
Daniel@0
|
9124 };
|
Daniel@0
|
9125
|
Daniel@0
|
9126 prototype.pendingImages = function() {
|
Daniel@0
|
9127 return this._loader.pending();
|
Daniel@0
|
9128 };
|
Daniel@0
|
9129
|
Daniel@0
|
9130 function clipToBounds(g, items) {
|
Daniel@0
|
9131 if (!items) return null;
|
Daniel@0
|
9132
|
Daniel@0
|
9133 var b = new Bounds(), i, n, item, mark, group;
|
Daniel@0
|
9134 for (i=0, n=items.length; i<n; ++i) {
|
Daniel@0
|
9135 item = items[i];
|
Daniel@0
|
9136 mark = item.mark;
|
Daniel@0
|
9137 group = mark.group;
|
Daniel@0
|
9138 item = marks[mark.marktype].nested ? mark : item;
|
Daniel@0
|
9139 b.union(translate(item.bounds, group));
|
Daniel@0
|
9140 if (item['bounds:prev']) {
|
Daniel@0
|
9141 b.union(translate(item['bounds:prev'], group));
|
Daniel@0
|
9142 }
|
Daniel@0
|
9143 }
|
Daniel@0
|
9144 b.round();
|
Daniel@0
|
9145
|
Daniel@0
|
9146 g.beginPath();
|
Daniel@0
|
9147 g.rect(b.x1, b.y1, b.width(), b.height());
|
Daniel@0
|
9148 g.clip();
|
Daniel@0
|
9149
|
Daniel@0
|
9150 return b;
|
Daniel@0
|
9151 }
|
Daniel@0
|
9152
|
Daniel@0
|
9153 function translate(bounds, group) {
|
Daniel@0
|
9154 if (group == null) return bounds;
|
Daniel@0
|
9155 var b = bounds.clone();
|
Daniel@0
|
9156 for (; group != null; group = group.mark.group) {
|
Daniel@0
|
9157 b.translate(group.x || 0, group.y || 0);
|
Daniel@0
|
9158 }
|
Daniel@0
|
9159 return b;
|
Daniel@0
|
9160 }
|
Daniel@0
|
9161
|
Daniel@0
|
9162 prototype.render = function(scene, items) {
|
Daniel@0
|
9163 var g = this.context(),
|
Daniel@0
|
9164 p = this._padding,
|
Daniel@0
|
9165 w = this._width + p.left + p.right,
|
Daniel@0
|
9166 h = this._height + p.top + p.bottom,
|
Daniel@0
|
9167 b;
|
Daniel@0
|
9168
|
Daniel@0
|
9169 // setup
|
Daniel@0
|
9170 this._scene = scene; // cache scene for async redraw
|
Daniel@0
|
9171 g.save();
|
Daniel@0
|
9172 b = clipToBounds(g, items);
|
Daniel@0
|
9173 this.clear(-p.left, -p.top, w, h);
|
Daniel@0
|
9174
|
Daniel@0
|
9175 // render
|
Daniel@0
|
9176 this.draw(g, scene, b);
|
Daniel@0
|
9177
|
Daniel@0
|
9178 // takedown
|
Daniel@0
|
9179 g.restore();
|
Daniel@0
|
9180 this._scene = null; // clear scene cache
|
Daniel@0
|
9181
|
Daniel@0
|
9182 return this;
|
Daniel@0
|
9183 };
|
Daniel@0
|
9184
|
Daniel@0
|
9185 prototype.draw = function(ctx, scene, bounds) {
|
Daniel@0
|
9186 var mark = marks[scene.marktype];
|
Daniel@0
|
9187 mark.draw.call(this, ctx, scene, bounds);
|
Daniel@0
|
9188 };
|
Daniel@0
|
9189
|
Daniel@0
|
9190 prototype.clear = function(x, y, w, h) {
|
Daniel@0
|
9191 var g = this.context();
|
Daniel@0
|
9192 g.clearRect(x, y, w, h);
|
Daniel@0
|
9193 if (this._bgcolor != null) {
|
Daniel@0
|
9194 g.fillStyle = this._bgcolor;
|
Daniel@0
|
9195 g.fillRect(x, y, w, h);
|
Daniel@0
|
9196 }
|
Daniel@0
|
9197 };
|
Daniel@0
|
9198
|
Daniel@0
|
9199 prototype.loadImage = function(uri) {
|
Daniel@0
|
9200 var renderer = this,
|
Daniel@0
|
9201 scene = this._scene;
|
Daniel@0
|
9202 return this._loader.loadImage(uri, function() {
|
Daniel@0
|
9203 renderer.renderAsync(scene);
|
Daniel@0
|
9204 });
|
Daniel@0
|
9205 };
|
Daniel@0
|
9206
|
Daniel@0
|
9207 prototype.renderAsync = function(scene) {
|
Daniel@0
|
9208 // TODO make safe for multiple scene rendering?
|
Daniel@0
|
9209 var renderer = this;
|
Daniel@0
|
9210 if (renderer._async_id) {
|
Daniel@0
|
9211 clearTimeout(renderer._async_id);
|
Daniel@0
|
9212 }
|
Daniel@0
|
9213 renderer._async_id = setTimeout(function() {
|
Daniel@0
|
9214 renderer.render(scene);
|
Daniel@0
|
9215 delete renderer._async_id;
|
Daniel@0
|
9216 }, 10);
|
Daniel@0
|
9217 };
|
Daniel@0
|
9218
|
Daniel@0
|
9219 module.exports = CanvasRenderer;
|
Daniel@0
|
9220
|
Daniel@0
|
9221 },{"../../util/Bounds":74,"../../util/ImageLoader":77,"../../util/canvas":80,"../../util/dom":81,"../Renderer":52,"./marks":60}],55:[function(require,module,exports){
|
Daniel@0
|
9222 module.exports = {
|
Daniel@0
|
9223 Handler: require('./CanvasHandler'),
|
Daniel@0
|
9224 Renderer: require('./CanvasRenderer')
|
Daniel@0
|
9225 };
|
Daniel@0
|
9226 },{"./CanvasHandler":53,"./CanvasRenderer":54}],56:[function(require,module,exports){
|
Daniel@0
|
9227 var util = require('./util');
|
Daniel@0
|
9228 var halfpi = Math.PI / 2;
|
Daniel@0
|
9229
|
Daniel@0
|
9230 function path(g, o) {
|
Daniel@0
|
9231 var x = o.x || 0,
|
Daniel@0
|
9232 y = o.y || 0,
|
Daniel@0
|
9233 ir = o.innerRadius || 0,
|
Daniel@0
|
9234 or = o.outerRadius || 0,
|
Daniel@0
|
9235 sa = (o.startAngle || 0) - halfpi,
|
Daniel@0
|
9236 ea = (o.endAngle || 0) - halfpi;
|
Daniel@0
|
9237 g.beginPath();
|
Daniel@0
|
9238 if (ir === 0) g.moveTo(x, y);
|
Daniel@0
|
9239 else g.arc(x, y, ir, sa, ea, 0);
|
Daniel@0
|
9240 g.arc(x, y, or, ea, sa, 1);
|
Daniel@0
|
9241 g.closePath();
|
Daniel@0
|
9242 }
|
Daniel@0
|
9243
|
Daniel@0
|
9244 module.exports = {
|
Daniel@0
|
9245 draw: util.drawAll(path),
|
Daniel@0
|
9246 pick: util.pickPath(path)
|
Daniel@0
|
9247 };
|
Daniel@0
|
9248 },{"./util":67}],57:[function(require,module,exports){
|
Daniel@0
|
9249 var util = require('./util'),
|
Daniel@0
|
9250 parse = require('../../../path/parse'),
|
Daniel@0
|
9251 render = require('../../../path/render'),
|
Daniel@0
|
9252 areaPath = require('../../../util/svg').path.area;
|
Daniel@0
|
9253
|
Daniel@0
|
9254 function path(g, items) {
|
Daniel@0
|
9255 var o = items[0],
|
Daniel@0
|
9256 p = o.pathCache || (o.pathCache = parse(areaPath(items)));
|
Daniel@0
|
9257 render(g, p);
|
Daniel@0
|
9258 }
|
Daniel@0
|
9259
|
Daniel@0
|
9260 function pick(g, scene, x, y, gx, gy) {
|
Daniel@0
|
9261 var items = scene.items,
|
Daniel@0
|
9262 b = scene.bounds;
|
Daniel@0
|
9263
|
Daniel@0
|
9264 if (!items || !items.length || b && !b.contains(gx, gy)) {
|
Daniel@0
|
9265 return null;
|
Daniel@0
|
9266 }
|
Daniel@0
|
9267
|
Daniel@0
|
9268 if (g.pixelratio != null && g.pixelratio !== 1) {
|
Daniel@0
|
9269 x *= g.pixelratio;
|
Daniel@0
|
9270 y *= g.pixelratio;
|
Daniel@0
|
9271 }
|
Daniel@0
|
9272 return hit(g, items, x, y) ? items[0] : null;
|
Daniel@0
|
9273 }
|
Daniel@0
|
9274
|
Daniel@0
|
9275 var hit = util.testPath(path);
|
Daniel@0
|
9276
|
Daniel@0
|
9277 module.exports = {
|
Daniel@0
|
9278 draw: util.drawOne(path),
|
Daniel@0
|
9279 pick: pick,
|
Daniel@0
|
9280 nested: true
|
Daniel@0
|
9281 };
|
Daniel@0
|
9282
|
Daniel@0
|
9283 },{"../../../path/parse":49,"../../../path/render":50,"../../../util/svg":83,"./util":67}],58:[function(require,module,exports){
|
Daniel@0
|
9284 var util = require('./util'),
|
Daniel@0
|
9285 rect = require('./rect');
|
Daniel@0
|
9286
|
Daniel@0
|
9287 function draw(g, scene, bounds) {
|
Daniel@0
|
9288 if (!scene.items || !scene.items.length) return;
|
Daniel@0
|
9289
|
Daniel@0
|
9290 var groups = scene.items,
|
Daniel@0
|
9291 renderer = this,
|
Daniel@0
|
9292 group, items, axes, legends, gx, gy, i, n, j, m;
|
Daniel@0
|
9293
|
Daniel@0
|
9294 rect.draw.call(renderer, g, scene, bounds);
|
Daniel@0
|
9295
|
Daniel@0
|
9296 for (i=0, n=groups.length; i<n; ++i) {
|
Daniel@0
|
9297 group = groups[i];
|
Daniel@0
|
9298 axes = group.axisItems || [];
|
Daniel@0
|
9299 items = group.items || [];
|
Daniel@0
|
9300 legends = group.legendItems || [];
|
Daniel@0
|
9301 gx = group.x || 0;
|
Daniel@0
|
9302 gy = group.y || 0;
|
Daniel@0
|
9303
|
Daniel@0
|
9304 // render group contents
|
Daniel@0
|
9305 g.save();
|
Daniel@0
|
9306 g.translate(gx, gy);
|
Daniel@0
|
9307 if (group.clip) {
|
Daniel@0
|
9308 g.beginPath();
|
Daniel@0
|
9309 g.rect(0, 0, group.width || 0, group.height || 0);
|
Daniel@0
|
9310 g.clip();
|
Daniel@0
|
9311 }
|
Daniel@0
|
9312
|
Daniel@0
|
9313 if (bounds) bounds.translate(-gx, -gy);
|
Daniel@0
|
9314
|
Daniel@0
|
9315 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
9316 if (axes[j].layer === 'back') {
|
Daniel@0
|
9317 renderer.draw(g, axes[j], bounds);
|
Daniel@0
|
9318 }
|
Daniel@0
|
9319 }
|
Daniel@0
|
9320 for (j=0, m=items.length; j<m; ++j) {
|
Daniel@0
|
9321 renderer.draw(g, items[j], bounds);
|
Daniel@0
|
9322 }
|
Daniel@0
|
9323 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
9324 if (axes[j].layer !== 'back') {
|
Daniel@0
|
9325 renderer.draw(g, axes[j], bounds);
|
Daniel@0
|
9326 }
|
Daniel@0
|
9327 }
|
Daniel@0
|
9328 for (j=0, m=legends.length; j<m; ++j) {
|
Daniel@0
|
9329 renderer.draw(g, legends[j], bounds);
|
Daniel@0
|
9330 }
|
Daniel@0
|
9331
|
Daniel@0
|
9332 if (bounds) bounds.translate(gx, gy);
|
Daniel@0
|
9333 g.restore();
|
Daniel@0
|
9334 }
|
Daniel@0
|
9335 }
|
Daniel@0
|
9336
|
Daniel@0
|
9337 function hit(g, o) {
|
Daniel@0
|
9338 return o.fill || o.stroke;
|
Daniel@0
|
9339 }
|
Daniel@0
|
9340
|
Daniel@0
|
9341 function pick(g, scene, x, y, gx, gy) {
|
Daniel@0
|
9342 if (scene.bounds && !scene.bounds.contains(gx, gy)) {
|
Daniel@0
|
9343 return null;
|
Daniel@0
|
9344 }
|
Daniel@0
|
9345 var items = scene.items || [],
|
Daniel@0
|
9346 subscene, group, hits, dx, dy, i, j;
|
Daniel@0
|
9347
|
Daniel@0
|
9348 for (i=items.length; --i>=0;) {
|
Daniel@0
|
9349 group = items[i];
|
Daniel@0
|
9350 dx = group.x || 0;
|
Daniel@0
|
9351 dy = group.y || 0;
|
Daniel@0
|
9352
|
Daniel@0
|
9353 g.save();
|
Daniel@0
|
9354 g.translate(dx, dy);
|
Daniel@0
|
9355 for (j=group.items.length; --j >= 0;) {
|
Daniel@0
|
9356 subscene = group.items[j];
|
Daniel@0
|
9357 if (subscene.interactive === false) continue;
|
Daniel@0
|
9358 hits = this.pick(subscene, x, y, gx-dx, gy-dy);
|
Daniel@0
|
9359 if (hits) {
|
Daniel@0
|
9360 g.restore();
|
Daniel@0
|
9361 return hits;
|
Daniel@0
|
9362 }
|
Daniel@0
|
9363 }
|
Daniel@0
|
9364 g.restore();
|
Daniel@0
|
9365 }
|
Daniel@0
|
9366
|
Daniel@0
|
9367 return scene.interactive !== false ? pickSelf(g, scene, x, y, gx, gy) : null;
|
Daniel@0
|
9368 }
|
Daniel@0
|
9369
|
Daniel@0
|
9370 var pickSelf = util.pick(hit);
|
Daniel@0
|
9371
|
Daniel@0
|
9372 module.exports = {
|
Daniel@0
|
9373 draw: draw,
|
Daniel@0
|
9374 pick: pick
|
Daniel@0
|
9375 };
|
Daniel@0
|
9376
|
Daniel@0
|
9377 },{"./rect":63,"./util":67}],59:[function(require,module,exports){
|
Daniel@0
|
9378 var util = require('./util');
|
Daniel@0
|
9379
|
Daniel@0
|
9380 function draw(g, scene, bounds) {
|
Daniel@0
|
9381 if (!scene.items || !scene.items.length) return;
|
Daniel@0
|
9382
|
Daniel@0
|
9383 var renderer = this,
|
Daniel@0
|
9384 items = scene.items, o;
|
Daniel@0
|
9385
|
Daniel@0
|
9386 for (var i=0, len=items.length; i<len; ++i) {
|
Daniel@0
|
9387 o = items[i];
|
Daniel@0
|
9388 if (bounds && !bounds.intersects(o.bounds))
|
Daniel@0
|
9389 continue; // bounds check
|
Daniel@0
|
9390
|
Daniel@0
|
9391 if (!(o.image && o.image.url === o.url)) {
|
Daniel@0
|
9392 o.image = renderer.loadImage(o.url);
|
Daniel@0
|
9393 o.image.url = o.url;
|
Daniel@0
|
9394 }
|
Daniel@0
|
9395
|
Daniel@0
|
9396 var x = o.x || 0,
|
Daniel@0
|
9397 y = o.y || 0,
|
Daniel@0
|
9398 w = o.width || (o.image && o.image.width) || 0,
|
Daniel@0
|
9399 h = o.height || (o.image && o.image.height) || 0,
|
Daniel@0
|
9400 opac;
|
Daniel@0
|
9401 x = x - (o.align==='center' ? w/2 : o.align==='right' ? w : 0);
|
Daniel@0
|
9402 y = y - (o.baseline==='middle' ? h/2 : o.baseline==='bottom' ? h : 0);
|
Daniel@0
|
9403
|
Daniel@0
|
9404 if (o.image.loaded) {
|
Daniel@0
|
9405 g.globalAlpha = (opac = o.opacity) != null ? opac : 1;
|
Daniel@0
|
9406 g.drawImage(o.image, x, y, w, h);
|
Daniel@0
|
9407 }
|
Daniel@0
|
9408 }
|
Daniel@0
|
9409 }
|
Daniel@0
|
9410
|
Daniel@0
|
9411 module.exports = {
|
Daniel@0
|
9412 draw: draw,
|
Daniel@0
|
9413 pick: util.pick()
|
Daniel@0
|
9414 };
|
Daniel@0
|
9415 },{"./util":67}],60:[function(require,module,exports){
|
Daniel@0
|
9416 module.exports = {
|
Daniel@0
|
9417 arc: require('./arc'),
|
Daniel@0
|
9418 area: require('./area'),
|
Daniel@0
|
9419 group: require('./group'),
|
Daniel@0
|
9420 image: require('./image'),
|
Daniel@0
|
9421 line: require('./line'),
|
Daniel@0
|
9422 path: require('./path'),
|
Daniel@0
|
9423 rect: require('./rect'),
|
Daniel@0
|
9424 rule: require('./rule'),
|
Daniel@0
|
9425 symbol: require('./symbol'),
|
Daniel@0
|
9426 text: require('./text')
|
Daniel@0
|
9427 };
|
Daniel@0
|
9428
|
Daniel@0
|
9429 },{"./arc":56,"./area":57,"./group":58,"./image":59,"./line":61,"./path":62,"./rect":63,"./rule":64,"./symbol":65,"./text":66}],61:[function(require,module,exports){
|
Daniel@0
|
9430 var util = require('./util'),
|
Daniel@0
|
9431 parse = require('../../../path/parse'),
|
Daniel@0
|
9432 render = require('../../../path/render'),
|
Daniel@0
|
9433 linePath = require('../../../util/svg').path.line;
|
Daniel@0
|
9434
|
Daniel@0
|
9435 function path(g, items) {
|
Daniel@0
|
9436 var o = items[0],
|
Daniel@0
|
9437 p = o.pathCache || (o.pathCache = parse(linePath(items)));
|
Daniel@0
|
9438 render(g, p);
|
Daniel@0
|
9439 }
|
Daniel@0
|
9440
|
Daniel@0
|
9441 function pick(g, scene, x, y, gx, gy) {
|
Daniel@0
|
9442 var items = scene.items,
|
Daniel@0
|
9443 b = scene.bounds;
|
Daniel@0
|
9444
|
Daniel@0
|
9445 if (!items || !items.length || b && !b.contains(gx, gy)) {
|
Daniel@0
|
9446 return null;
|
Daniel@0
|
9447 }
|
Daniel@0
|
9448
|
Daniel@0
|
9449 if (g.pixelratio != null && g.pixelratio !== 1) {
|
Daniel@0
|
9450 x *= g.pixelratio;
|
Daniel@0
|
9451 y *= g.pixelratio;
|
Daniel@0
|
9452 }
|
Daniel@0
|
9453 return hit(g, items, x, y) ? items[0] : null;
|
Daniel@0
|
9454 }
|
Daniel@0
|
9455
|
Daniel@0
|
9456 var hit = util.testPath(path, false);
|
Daniel@0
|
9457
|
Daniel@0
|
9458 module.exports = {
|
Daniel@0
|
9459 draw: util.drawOne(path),
|
Daniel@0
|
9460 pick: pick,
|
Daniel@0
|
9461 nested: true
|
Daniel@0
|
9462 };
|
Daniel@0
|
9463
|
Daniel@0
|
9464 },{"../../../path/parse":49,"../../../path/render":50,"../../../util/svg":83,"./util":67}],62:[function(require,module,exports){
|
Daniel@0
|
9465 var util = require('./util'),
|
Daniel@0
|
9466 parse = require('../../../path/parse'),
|
Daniel@0
|
9467 render = require('../../../path/render');
|
Daniel@0
|
9468
|
Daniel@0
|
9469 function path(g, o) {
|
Daniel@0
|
9470 if (o.path == null) return true;
|
Daniel@0
|
9471 var p = o.pathCache || (o.pathCache = parse(o.path));
|
Daniel@0
|
9472 render(g, p, o.x, o.y);
|
Daniel@0
|
9473 }
|
Daniel@0
|
9474
|
Daniel@0
|
9475 module.exports = {
|
Daniel@0
|
9476 draw: util.drawAll(path),
|
Daniel@0
|
9477 pick: util.pickPath(path)
|
Daniel@0
|
9478 };
|
Daniel@0
|
9479
|
Daniel@0
|
9480 },{"../../../path/parse":49,"../../../path/render":50,"./util":67}],63:[function(require,module,exports){
|
Daniel@0
|
9481 var util = require('./util');
|
Daniel@0
|
9482
|
Daniel@0
|
9483 function draw(g, scene, bounds) {
|
Daniel@0
|
9484 if (!scene.items || !scene.items.length) return;
|
Daniel@0
|
9485
|
Daniel@0
|
9486 var items = scene.items,
|
Daniel@0
|
9487 o, opac, x, y, w, h;
|
Daniel@0
|
9488
|
Daniel@0
|
9489 for (var i=0, len=items.length; i<len; ++i) {
|
Daniel@0
|
9490 o = items[i];
|
Daniel@0
|
9491 if (bounds && !bounds.intersects(o.bounds))
|
Daniel@0
|
9492 continue; // bounds check
|
Daniel@0
|
9493
|
Daniel@0
|
9494 opac = o.opacity == null ? 1 : o.opacity;
|
Daniel@0
|
9495 if (opac === 0) continue;
|
Daniel@0
|
9496
|
Daniel@0
|
9497 x = o.x || 0;
|
Daniel@0
|
9498 y = o.y || 0;
|
Daniel@0
|
9499 w = o.width || 0;
|
Daniel@0
|
9500 h = o.height || 0;
|
Daniel@0
|
9501
|
Daniel@0
|
9502 if (o.fill && util.fill(g, o, opac)) {
|
Daniel@0
|
9503 g.fillRect(x, y, w, h);
|
Daniel@0
|
9504 }
|
Daniel@0
|
9505 if (o.stroke && util.stroke(g, o, opac)) {
|
Daniel@0
|
9506 g.strokeRect(x, y, w, h);
|
Daniel@0
|
9507 }
|
Daniel@0
|
9508 }
|
Daniel@0
|
9509 }
|
Daniel@0
|
9510
|
Daniel@0
|
9511 module.exports = {
|
Daniel@0
|
9512 draw: draw,
|
Daniel@0
|
9513 pick: util.pick()
|
Daniel@0
|
9514 };
|
Daniel@0
|
9515 },{"./util":67}],64:[function(require,module,exports){
|
Daniel@0
|
9516 var util = require('./util');
|
Daniel@0
|
9517
|
Daniel@0
|
9518 function draw(g, scene, bounds) {
|
Daniel@0
|
9519 if (!scene.items || !scene.items.length) return;
|
Daniel@0
|
9520
|
Daniel@0
|
9521 var items = scene.items,
|
Daniel@0
|
9522 o, opac, x1, y1, x2, y2;
|
Daniel@0
|
9523
|
Daniel@0
|
9524 for (var i=0, len=items.length; i<len; ++i) {
|
Daniel@0
|
9525 o = items[i];
|
Daniel@0
|
9526 if (bounds && !bounds.intersects(o.bounds))
|
Daniel@0
|
9527 continue; // bounds check
|
Daniel@0
|
9528
|
Daniel@0
|
9529 opac = o.opacity == null ? 1 : o.opacity;
|
Daniel@0
|
9530 if (opac === 0) continue;
|
Daniel@0
|
9531
|
Daniel@0
|
9532 x1 = o.x || 0;
|
Daniel@0
|
9533 y1 = o.y || 0;
|
Daniel@0
|
9534 x2 = o.x2 != null ? o.x2 : x1;
|
Daniel@0
|
9535 y2 = o.y2 != null ? o.y2 : y1;
|
Daniel@0
|
9536
|
Daniel@0
|
9537 if (o.stroke && util.stroke(g, o, opac)) {
|
Daniel@0
|
9538 g.beginPath();
|
Daniel@0
|
9539 g.moveTo(x1, y1);
|
Daniel@0
|
9540 g.lineTo(x2, y2);
|
Daniel@0
|
9541 g.stroke();
|
Daniel@0
|
9542 }
|
Daniel@0
|
9543 }
|
Daniel@0
|
9544 }
|
Daniel@0
|
9545
|
Daniel@0
|
9546 function stroke(g, o) {
|
Daniel@0
|
9547 var x1 = o.x || 0,
|
Daniel@0
|
9548 y1 = o.y || 0,
|
Daniel@0
|
9549 x2 = o.x2 != null ? o.x2 : x1,
|
Daniel@0
|
9550 y2 = o.y2 != null ? o.y2 : y1,
|
Daniel@0
|
9551 lw = o.strokeWidth,
|
Daniel@0
|
9552 lc = o.strokeCap;
|
Daniel@0
|
9553
|
Daniel@0
|
9554 g.lineWidth = lw != null ? lw : 1;
|
Daniel@0
|
9555 g.lineCap = lc != null ? lc : 'butt';
|
Daniel@0
|
9556 g.beginPath();
|
Daniel@0
|
9557 g.moveTo(x1, y1);
|
Daniel@0
|
9558 g.lineTo(x2, y2);
|
Daniel@0
|
9559 }
|
Daniel@0
|
9560
|
Daniel@0
|
9561 function hit(g, o, x, y) {
|
Daniel@0
|
9562 if (!g.isPointInStroke) return false;
|
Daniel@0
|
9563 stroke(g, o);
|
Daniel@0
|
9564 return g.isPointInStroke(x, y);
|
Daniel@0
|
9565 }
|
Daniel@0
|
9566
|
Daniel@0
|
9567 module.exports = {
|
Daniel@0
|
9568 draw: draw,
|
Daniel@0
|
9569 pick: util.pick(hit)
|
Daniel@0
|
9570 };
|
Daniel@0
|
9571
|
Daniel@0
|
9572 },{"./util":67}],65:[function(require,module,exports){
|
Daniel@0
|
9573 var util = require('./util');
|
Daniel@0
|
9574
|
Daniel@0
|
9575 var sqrt3 = Math.sqrt(3),
|
Daniel@0
|
9576 tan30 = Math.tan(30 * Math.PI / 180);
|
Daniel@0
|
9577
|
Daniel@0
|
9578 function path(g, o) {
|
Daniel@0
|
9579 var size = o.size != null ? o.size : 100,
|
Daniel@0
|
9580 x = o.x, y = o.y, r, t, rx, ry;
|
Daniel@0
|
9581
|
Daniel@0
|
9582 g.beginPath();
|
Daniel@0
|
9583
|
Daniel@0
|
9584 if (o.shape == null || o.shape === 'circle') {
|
Daniel@0
|
9585 r = Math.sqrt(size / Math.PI);
|
Daniel@0
|
9586 g.arc(x, y, r, 0, 2*Math.PI, 0);
|
Daniel@0
|
9587 g.closePath();
|
Daniel@0
|
9588 return;
|
Daniel@0
|
9589 }
|
Daniel@0
|
9590
|
Daniel@0
|
9591 switch (o.shape) {
|
Daniel@0
|
9592 case 'cross':
|
Daniel@0
|
9593 r = Math.sqrt(size / 5) / 2;
|
Daniel@0
|
9594 t = 3*r;
|
Daniel@0
|
9595 g.moveTo(x-t, y-r);
|
Daniel@0
|
9596 g.lineTo(x-r, y-r);
|
Daniel@0
|
9597 g.lineTo(x-r, y-t);
|
Daniel@0
|
9598 g.lineTo(x+r, y-t);
|
Daniel@0
|
9599 g.lineTo(x+r, y-r);
|
Daniel@0
|
9600 g.lineTo(x+t, y-r);
|
Daniel@0
|
9601 g.lineTo(x+t, y+r);
|
Daniel@0
|
9602 g.lineTo(x+r, y+r);
|
Daniel@0
|
9603 g.lineTo(x+r, y+t);
|
Daniel@0
|
9604 g.lineTo(x-r, y+t);
|
Daniel@0
|
9605 g.lineTo(x-r, y+r);
|
Daniel@0
|
9606 g.lineTo(x-t, y+r);
|
Daniel@0
|
9607 break;
|
Daniel@0
|
9608
|
Daniel@0
|
9609 case 'diamond':
|
Daniel@0
|
9610 ry = Math.sqrt(size / (2 * tan30));
|
Daniel@0
|
9611 rx = ry * tan30;
|
Daniel@0
|
9612 g.moveTo(x, y-ry);
|
Daniel@0
|
9613 g.lineTo(x+rx, y);
|
Daniel@0
|
9614 g.lineTo(x, y+ry);
|
Daniel@0
|
9615 g.lineTo(x-rx, y);
|
Daniel@0
|
9616 break;
|
Daniel@0
|
9617
|
Daniel@0
|
9618 case 'square':
|
Daniel@0
|
9619 t = Math.sqrt(size);
|
Daniel@0
|
9620 r = t / 2;
|
Daniel@0
|
9621 g.rect(x-r, y-r, t, t);
|
Daniel@0
|
9622 break;
|
Daniel@0
|
9623
|
Daniel@0
|
9624 case 'triangle-down':
|
Daniel@0
|
9625 rx = Math.sqrt(size / sqrt3);
|
Daniel@0
|
9626 ry = rx * sqrt3 / 2;
|
Daniel@0
|
9627 g.moveTo(x, y+ry);
|
Daniel@0
|
9628 g.lineTo(x+rx, y-ry);
|
Daniel@0
|
9629 g.lineTo(x-rx, y-ry);
|
Daniel@0
|
9630 break;
|
Daniel@0
|
9631
|
Daniel@0
|
9632 case 'triangle-up':
|
Daniel@0
|
9633 rx = Math.sqrt(size / sqrt3);
|
Daniel@0
|
9634 ry = rx * sqrt3 / 2;
|
Daniel@0
|
9635 g.moveTo(x, y-ry);
|
Daniel@0
|
9636 g.lineTo(x+rx, y+ry);
|
Daniel@0
|
9637 g.lineTo(x-rx, y+ry);
|
Daniel@0
|
9638 }
|
Daniel@0
|
9639 g.closePath();
|
Daniel@0
|
9640 }
|
Daniel@0
|
9641
|
Daniel@0
|
9642 module.exports = {
|
Daniel@0
|
9643 draw: util.drawAll(path),
|
Daniel@0
|
9644 pick: util.pickPath(path)
|
Daniel@0
|
9645 };
|
Daniel@0
|
9646 },{"./util":67}],66:[function(require,module,exports){
|
Daniel@0
|
9647 var Bounds = require('../../../util/Bounds'),
|
Daniel@0
|
9648 textBounds = require('../../../util/bound').text,
|
Daniel@0
|
9649 text = require('../../../util/text'),
|
Daniel@0
|
9650 util = require('./util'),
|
Daniel@0
|
9651 tempBounds = new Bounds();
|
Daniel@0
|
9652
|
Daniel@0
|
9653 function draw(g, scene, bounds) {
|
Daniel@0
|
9654 if (!scene.items || !scene.items.length) return;
|
Daniel@0
|
9655
|
Daniel@0
|
9656 var items = scene.items,
|
Daniel@0
|
9657 o, opac, x, y, r, t, str;
|
Daniel@0
|
9658
|
Daniel@0
|
9659 for (var i=0, len=items.length; i<len; ++i) {
|
Daniel@0
|
9660 o = items[i];
|
Daniel@0
|
9661 if (bounds && !bounds.intersects(o.bounds))
|
Daniel@0
|
9662 continue; // bounds check
|
Daniel@0
|
9663
|
Daniel@0
|
9664 str = text.value(o.text);
|
Daniel@0
|
9665 if (!str) continue;
|
Daniel@0
|
9666 opac = o.opacity == null ? 1 : o.opacity;
|
Daniel@0
|
9667 if (opac === 0) continue;
|
Daniel@0
|
9668
|
Daniel@0
|
9669 g.font = text.font(o);
|
Daniel@0
|
9670 g.textAlign = o.align || 'left';
|
Daniel@0
|
9671
|
Daniel@0
|
9672 x = (o.x || 0);
|
Daniel@0
|
9673 y = (o.y || 0);
|
Daniel@0
|
9674 if ((r = o.radius)) {
|
Daniel@0
|
9675 t = (o.theta || 0) - Math.PI/2;
|
Daniel@0
|
9676 x += r * Math.cos(t);
|
Daniel@0
|
9677 y += r * Math.sin(t);
|
Daniel@0
|
9678 }
|
Daniel@0
|
9679
|
Daniel@0
|
9680 if (o.angle) {
|
Daniel@0
|
9681 g.save();
|
Daniel@0
|
9682 g.translate(x, y);
|
Daniel@0
|
9683 g.rotate(o.angle * Math.PI/180);
|
Daniel@0
|
9684 x = y = 0; // reset x, y
|
Daniel@0
|
9685 }
|
Daniel@0
|
9686 x += (o.dx || 0);
|
Daniel@0
|
9687 y += (o.dy || 0) + text.offset(o);
|
Daniel@0
|
9688
|
Daniel@0
|
9689 if (o.fill && util.fill(g, o, opac)) {
|
Daniel@0
|
9690 g.fillText(str, x, y);
|
Daniel@0
|
9691 }
|
Daniel@0
|
9692 if (o.stroke && util.stroke(g, o, opac)) {
|
Daniel@0
|
9693 g.strokeText(str, x, y);
|
Daniel@0
|
9694 }
|
Daniel@0
|
9695 if (o.angle) g.restore();
|
Daniel@0
|
9696 }
|
Daniel@0
|
9697 }
|
Daniel@0
|
9698
|
Daniel@0
|
9699 function hit(g, o, x, y, gx, gy) {
|
Daniel@0
|
9700 if (o.fontSize <= 0) return false;
|
Daniel@0
|
9701 if (!o.angle) return true; // bounds sufficient if no rotation
|
Daniel@0
|
9702
|
Daniel@0
|
9703 // project point into space of unrotated bounds
|
Daniel@0
|
9704 var b = textBounds(o, tempBounds, true),
|
Daniel@0
|
9705 a = -o.angle * Math.PI / 180,
|
Daniel@0
|
9706 cos = Math.cos(a),
|
Daniel@0
|
9707 sin = Math.sin(a),
|
Daniel@0
|
9708 ox = o.x,
|
Daniel@0
|
9709 oy = o.y,
|
Daniel@0
|
9710 px = cos*gx - sin*gy + (ox - ox*cos + oy*sin),
|
Daniel@0
|
9711 py = sin*gx + cos*gy + (oy - ox*sin - oy*cos);
|
Daniel@0
|
9712
|
Daniel@0
|
9713 return b.contains(px, py);
|
Daniel@0
|
9714 }
|
Daniel@0
|
9715
|
Daniel@0
|
9716 module.exports = {
|
Daniel@0
|
9717 draw: draw,
|
Daniel@0
|
9718 pick: util.pick(hit)
|
Daniel@0
|
9719 };
|
Daniel@0
|
9720
|
Daniel@0
|
9721 },{"../../../util/Bounds":74,"../../../util/bound":79,"../../../util/text":84,"./util":67}],67:[function(require,module,exports){
|
Daniel@0
|
9722 function drawPathOne(path, g, o, items) {
|
Daniel@0
|
9723 if (path(g, items)) return;
|
Daniel@0
|
9724
|
Daniel@0
|
9725 var opac = o.opacity == null ? 1 : o.opacity;
|
Daniel@0
|
9726 if (opac===0) return;
|
Daniel@0
|
9727
|
Daniel@0
|
9728 if (o.fill && fill(g, o, opac)) { g.fill(); }
|
Daniel@0
|
9729 if (o.stroke && stroke(g, o, opac)) { g.stroke(); }
|
Daniel@0
|
9730 }
|
Daniel@0
|
9731
|
Daniel@0
|
9732 function drawPathAll(path, g, scene, bounds) {
|
Daniel@0
|
9733 var i, len, item;
|
Daniel@0
|
9734 for (i=0, len=scene.items.length; i<len; ++i) {
|
Daniel@0
|
9735 item = scene.items[i];
|
Daniel@0
|
9736 if (!bounds || bounds.intersects(item.bounds)) {
|
Daniel@0
|
9737 drawPathOne(path, g, item, item);
|
Daniel@0
|
9738 }
|
Daniel@0
|
9739 }
|
Daniel@0
|
9740 }
|
Daniel@0
|
9741
|
Daniel@0
|
9742 function drawAll(pathFunc) {
|
Daniel@0
|
9743 return function(g, scene, bounds) {
|
Daniel@0
|
9744 drawPathAll(pathFunc, g, scene, bounds);
|
Daniel@0
|
9745 };
|
Daniel@0
|
9746 }
|
Daniel@0
|
9747
|
Daniel@0
|
9748 function drawOne(pathFunc) {
|
Daniel@0
|
9749 return function(g, scene, bounds) {
|
Daniel@0
|
9750 if (!scene.items.length) return;
|
Daniel@0
|
9751 if (!bounds || bounds.intersects(scene.bounds)) {
|
Daniel@0
|
9752 drawPathOne(pathFunc, g, scene.items[0], scene.items);
|
Daniel@0
|
9753 }
|
Daniel@0
|
9754 };
|
Daniel@0
|
9755 }
|
Daniel@0
|
9756
|
Daniel@0
|
9757 var trueFunc = function() { return true; };
|
Daniel@0
|
9758
|
Daniel@0
|
9759 function pick(test) {
|
Daniel@0
|
9760 if (!test) test = trueFunc;
|
Daniel@0
|
9761
|
Daniel@0
|
9762 return function(g, scene, x, y, gx, gy) {
|
Daniel@0
|
9763 if (!scene.items.length) return null;
|
Daniel@0
|
9764
|
Daniel@0
|
9765 var o, b, i;
|
Daniel@0
|
9766
|
Daniel@0
|
9767 if (g.pixelratio != null && g.pixelratio !== 1) {
|
Daniel@0
|
9768 x *= g.pixelratio;
|
Daniel@0
|
9769 y *= g.pixelratio;
|
Daniel@0
|
9770 }
|
Daniel@0
|
9771
|
Daniel@0
|
9772 for (i=scene.items.length; --i >= 0;) {
|
Daniel@0
|
9773 o = scene.items[i]; b = o.bounds;
|
Daniel@0
|
9774 // first hit test against bounding box
|
Daniel@0
|
9775 if ((b && !b.contains(gx, gy)) || !b) continue;
|
Daniel@0
|
9776 // if in bounding box, perform more careful test
|
Daniel@0
|
9777 if (test(g, o, x, y, gx, gy)) return o;
|
Daniel@0
|
9778 }
|
Daniel@0
|
9779 return null;
|
Daniel@0
|
9780 };
|
Daniel@0
|
9781 }
|
Daniel@0
|
9782
|
Daniel@0
|
9783 function testPath(path, filled) {
|
Daniel@0
|
9784 return function(g, o, x, y) {
|
Daniel@0
|
9785 var item = Array.isArray(o) ? o[0] : o,
|
Daniel@0
|
9786 fill = (filled == null) ? item.fill : filled,
|
Daniel@0
|
9787 stroke = item.stroke && g.isPointInStroke, lw, lc;
|
Daniel@0
|
9788
|
Daniel@0
|
9789 if (stroke) {
|
Daniel@0
|
9790 lw = item.strokeWidth;
|
Daniel@0
|
9791 lc = item.strokeCap;
|
Daniel@0
|
9792 g.lineWidth = lw != null ? lw : 1;
|
Daniel@0
|
9793 g.lineCap = lc != null ? lc : 'butt';
|
Daniel@0
|
9794 }
|
Daniel@0
|
9795
|
Daniel@0
|
9796 return path(g, o) ? false :
|
Daniel@0
|
9797 (fill && g.isPointInPath(x, y)) ||
|
Daniel@0
|
9798 (stroke && g.isPointInStroke(x, y));
|
Daniel@0
|
9799 };
|
Daniel@0
|
9800 }
|
Daniel@0
|
9801
|
Daniel@0
|
9802 function pickPath(path) {
|
Daniel@0
|
9803 return pick(testPath(path));
|
Daniel@0
|
9804 }
|
Daniel@0
|
9805
|
Daniel@0
|
9806 function fill(g, o, opacity) {
|
Daniel@0
|
9807 opacity *= (o.fillOpacity==null ? 1 : o.fillOpacity);
|
Daniel@0
|
9808 if (opacity > 0) {
|
Daniel@0
|
9809 g.globalAlpha = opacity;
|
Daniel@0
|
9810 g.fillStyle = color(g, o, o.fill);
|
Daniel@0
|
9811 return true;
|
Daniel@0
|
9812 } else {
|
Daniel@0
|
9813 return false;
|
Daniel@0
|
9814 }
|
Daniel@0
|
9815 }
|
Daniel@0
|
9816
|
Daniel@0
|
9817 function stroke(g, o, opacity) {
|
Daniel@0
|
9818 var lw = (lw = o.strokeWidth) != null ? lw : 1, lc;
|
Daniel@0
|
9819 if (lw <= 0) return false;
|
Daniel@0
|
9820
|
Daniel@0
|
9821 opacity *= (o.strokeOpacity==null ? 1 : o.strokeOpacity);
|
Daniel@0
|
9822 if (opacity > 0) {
|
Daniel@0
|
9823 g.globalAlpha = opacity;
|
Daniel@0
|
9824 g.strokeStyle = color(g, o, o.stroke);
|
Daniel@0
|
9825 g.lineWidth = lw;
|
Daniel@0
|
9826 g.lineCap = (lc = o.strokeCap) != null ? lc : 'butt';
|
Daniel@0
|
9827 g.vgLineDash(o.strokeDash || null);
|
Daniel@0
|
9828 g.vgLineDashOffset(o.strokeDashOffset || 0);
|
Daniel@0
|
9829 return true;
|
Daniel@0
|
9830 } else {
|
Daniel@0
|
9831 return false;
|
Daniel@0
|
9832 }
|
Daniel@0
|
9833 }
|
Daniel@0
|
9834
|
Daniel@0
|
9835 function color(g, o, value) {
|
Daniel@0
|
9836 return (value.id) ?
|
Daniel@0
|
9837 gradient(g, value, o.bounds) :
|
Daniel@0
|
9838 value;
|
Daniel@0
|
9839 }
|
Daniel@0
|
9840
|
Daniel@0
|
9841 function gradient(g, p, b) {
|
Daniel@0
|
9842 var w = b.width(),
|
Daniel@0
|
9843 h = b.height(),
|
Daniel@0
|
9844 x1 = b.x1 + p.x1 * w,
|
Daniel@0
|
9845 y1 = b.y1 + p.y1 * h,
|
Daniel@0
|
9846 x2 = b.x1 + p.x2 * w,
|
Daniel@0
|
9847 y2 = b.y1 + p.y2 * h,
|
Daniel@0
|
9848 grad = g.createLinearGradient(x1, y1, x2, y2),
|
Daniel@0
|
9849 stop = p.stops,
|
Daniel@0
|
9850 i, n;
|
Daniel@0
|
9851
|
Daniel@0
|
9852 for (i=0, n=stop.length; i<n; ++i) {
|
Daniel@0
|
9853 grad.addColorStop(stop[i].offset, stop[i].color);
|
Daniel@0
|
9854 }
|
Daniel@0
|
9855 return grad;
|
Daniel@0
|
9856 }
|
Daniel@0
|
9857
|
Daniel@0
|
9858 module.exports = {
|
Daniel@0
|
9859 drawOne: drawOne,
|
Daniel@0
|
9860 drawAll: drawAll,
|
Daniel@0
|
9861 pick: pick,
|
Daniel@0
|
9862 pickPath: pickPath,
|
Daniel@0
|
9863 testPath: testPath,
|
Daniel@0
|
9864 stroke: stroke,
|
Daniel@0
|
9865 fill: fill,
|
Daniel@0
|
9866 color: color,
|
Daniel@0
|
9867 gradient: gradient
|
Daniel@0
|
9868 };
|
Daniel@0
|
9869
|
Daniel@0
|
9870 },{}],68:[function(require,module,exports){
|
Daniel@0
|
9871 module.exports = {
|
Daniel@0
|
9872 'canvas': require('./canvas'),
|
Daniel@0
|
9873 'svg': require('./svg')
|
Daniel@0
|
9874 };
|
Daniel@0
|
9875
|
Daniel@0
|
9876 },{"./canvas":55,"./svg":72}],69:[function(require,module,exports){
|
Daniel@0
|
9877 var DOM = require('../../util/dom'),
|
Daniel@0
|
9878 Handler = require('../Handler');
|
Daniel@0
|
9879
|
Daniel@0
|
9880 function SVGHandler() {
|
Daniel@0
|
9881 Handler.call(this);
|
Daniel@0
|
9882 }
|
Daniel@0
|
9883
|
Daniel@0
|
9884 var base = Handler.prototype;
|
Daniel@0
|
9885 var prototype = (SVGHandler.prototype = Object.create(base));
|
Daniel@0
|
9886 prototype.constructor = SVGHandler;
|
Daniel@0
|
9887
|
Daniel@0
|
9888 prototype.initialize = function(el, pad, obj) {
|
Daniel@0
|
9889 this._svg = DOM.find(el, 'svg');
|
Daniel@0
|
9890 return base.initialize.call(this, el, pad, obj);
|
Daniel@0
|
9891 };
|
Daniel@0
|
9892
|
Daniel@0
|
9893 prototype.svg = function() {
|
Daniel@0
|
9894 return this._svg;
|
Daniel@0
|
9895 };
|
Daniel@0
|
9896
|
Daniel@0
|
9897 // wrap an event listener for the SVG DOM
|
Daniel@0
|
9898 prototype.listener = function(handler) {
|
Daniel@0
|
9899 var that = this;
|
Daniel@0
|
9900 return function(evt) {
|
Daniel@0
|
9901 var target = evt.target,
|
Daniel@0
|
9902 item = target.__data__;
|
Daniel@0
|
9903 evt.vegaType = evt.type;
|
Daniel@0
|
9904 item = Array.isArray(item) ? item[0] : item;
|
Daniel@0
|
9905 handler.call(that._obj, evt, item);
|
Daniel@0
|
9906 };
|
Daniel@0
|
9907 };
|
Daniel@0
|
9908
|
Daniel@0
|
9909 // add an event handler
|
Daniel@0
|
9910 prototype.on = function(type, handler) {
|
Daniel@0
|
9911 var name = this.eventName(type),
|
Daniel@0
|
9912 svg = this._svg,
|
Daniel@0
|
9913 h = this._handlers,
|
Daniel@0
|
9914 x = {
|
Daniel@0
|
9915 type: type,
|
Daniel@0
|
9916 handler: handler,
|
Daniel@0
|
9917 listener: this.listener(handler)
|
Daniel@0
|
9918 };
|
Daniel@0
|
9919
|
Daniel@0
|
9920 (h[name] || (h[name] = [])).push(x);
|
Daniel@0
|
9921 svg.addEventListener(name, x.listener);
|
Daniel@0
|
9922 return this;
|
Daniel@0
|
9923 };
|
Daniel@0
|
9924
|
Daniel@0
|
9925 // remove an event handler
|
Daniel@0
|
9926 prototype.off = function(type, handler) {
|
Daniel@0
|
9927 var name = this.eventName(type),
|
Daniel@0
|
9928 svg = this._svg,
|
Daniel@0
|
9929 h = this._handlers[name], i;
|
Daniel@0
|
9930 if (!h) return;
|
Daniel@0
|
9931 for (i=h.length; --i>=0;) {
|
Daniel@0
|
9932 if (h[i].type === type && !handler || h[i].handler === handler) {
|
Daniel@0
|
9933 svg.removeEventListener(name, h[i].listener);
|
Daniel@0
|
9934 h.splice(i, 1);
|
Daniel@0
|
9935 }
|
Daniel@0
|
9936 }
|
Daniel@0
|
9937 return this;
|
Daniel@0
|
9938 };
|
Daniel@0
|
9939
|
Daniel@0
|
9940 module.exports = SVGHandler;
|
Daniel@0
|
9941
|
Daniel@0
|
9942 },{"../../util/dom":81,"../Handler":51}],70:[function(require,module,exports){
|
Daniel@0
|
9943 var ImageLoader = require('../../util/ImageLoader'),
|
Daniel@0
|
9944 Renderer = require('../Renderer'),
|
Daniel@0
|
9945 text = require('../../util/text'),
|
Daniel@0
|
9946 DOM = require('../../util/dom'),
|
Daniel@0
|
9947 SVG = require('../../util/svg'),
|
Daniel@0
|
9948 ns = SVG.metadata.xmlns,
|
Daniel@0
|
9949 marks = require('./marks');
|
Daniel@0
|
9950
|
Daniel@0
|
9951 function SVGRenderer(loadConfig) {
|
Daniel@0
|
9952 Renderer.call(this);
|
Daniel@0
|
9953 this._loader = new ImageLoader(loadConfig);
|
Daniel@0
|
9954 this._dirtyID = 0;
|
Daniel@0
|
9955 }
|
Daniel@0
|
9956
|
Daniel@0
|
9957 var base = Renderer.prototype;
|
Daniel@0
|
9958 var prototype = (SVGRenderer.prototype = Object.create(base));
|
Daniel@0
|
9959 prototype.constructor = SVGRenderer;
|
Daniel@0
|
9960
|
Daniel@0
|
9961 prototype.initialize = function(el, width, height, padding) {
|
Daniel@0
|
9962 if (el) {
|
Daniel@0
|
9963 this._svg = DOM.child(el, 0, 'svg', ns, 'marks');
|
Daniel@0
|
9964 DOM.clear(el, 1);
|
Daniel@0
|
9965 // set the svg root group
|
Daniel@0
|
9966 this._root = DOM.child(this._svg, 0, 'g', ns);
|
Daniel@0
|
9967 DOM.clear(this._svg, 1);
|
Daniel@0
|
9968 }
|
Daniel@0
|
9969
|
Daniel@0
|
9970 // create the svg definitions cache
|
Daniel@0
|
9971 this._defs = {
|
Daniel@0
|
9972 clip_id: 1,
|
Daniel@0
|
9973 gradient: {},
|
Daniel@0
|
9974 clipping: {}
|
Daniel@0
|
9975 };
|
Daniel@0
|
9976
|
Daniel@0
|
9977 // set background color if defined
|
Daniel@0
|
9978 this.background(this._bgcolor);
|
Daniel@0
|
9979
|
Daniel@0
|
9980 return base.initialize.call(this, el, width, height, padding);
|
Daniel@0
|
9981 };
|
Daniel@0
|
9982
|
Daniel@0
|
9983 prototype.background = function(bgcolor) {
|
Daniel@0
|
9984 if (arguments.length && this._svg) {
|
Daniel@0
|
9985 this._svg.style.setProperty('background-color', bgcolor);
|
Daniel@0
|
9986 }
|
Daniel@0
|
9987 return base.background.apply(this, arguments);
|
Daniel@0
|
9988 };
|
Daniel@0
|
9989
|
Daniel@0
|
9990 prototype.resize = function(width, height, padding) {
|
Daniel@0
|
9991 base.resize.call(this, width, height, padding);
|
Daniel@0
|
9992
|
Daniel@0
|
9993 if (this._svg) {
|
Daniel@0
|
9994 var w = this._width,
|
Daniel@0
|
9995 h = this._height,
|
Daniel@0
|
9996 p = this._padding;
|
Daniel@0
|
9997
|
Daniel@0
|
9998 this._svg.setAttribute('width', w + p.left + p.right);
|
Daniel@0
|
9999 this._svg.setAttribute('height', h + p.top + p.bottom);
|
Daniel@0
|
10000
|
Daniel@0
|
10001 this._root.setAttribute('transform', 'translate('+p.left+','+p.top+')');
|
Daniel@0
|
10002 }
|
Daniel@0
|
10003
|
Daniel@0
|
10004 return this;
|
Daniel@0
|
10005 };
|
Daniel@0
|
10006
|
Daniel@0
|
10007 prototype.svg = function() {
|
Daniel@0
|
10008 if (!this._svg) return null;
|
Daniel@0
|
10009
|
Daniel@0
|
10010 var attr = {
|
Daniel@0
|
10011 'class': 'marks',
|
Daniel@0
|
10012 'width': this._width + this._padding.left + this._padding.right,
|
Daniel@0
|
10013 'height': this._height + this._padding.top + this._padding.bottom,
|
Daniel@0
|
10014 };
|
Daniel@0
|
10015 for (var key in SVG.metadata) {
|
Daniel@0
|
10016 attr[key] = SVG.metadata[key];
|
Daniel@0
|
10017 }
|
Daniel@0
|
10018
|
Daniel@0
|
10019 return DOM.openTag('svg', attr) + this._svg.innerHTML + DOM.closeTag('svg');
|
Daniel@0
|
10020 };
|
Daniel@0
|
10021
|
Daniel@0
|
10022 prototype.imageURL = function(url) {
|
Daniel@0
|
10023 return this._loader.imageURL(url);
|
Daniel@0
|
10024 };
|
Daniel@0
|
10025
|
Daniel@0
|
10026
|
Daniel@0
|
10027 // -- Render entry point --
|
Daniel@0
|
10028
|
Daniel@0
|
10029 prototype.render = function(scene, items) {
|
Daniel@0
|
10030 if (this._dirtyCheck(items)) {
|
Daniel@0
|
10031 if (this._dirtyAll) this._resetDefs();
|
Daniel@0
|
10032 this.draw(this._root, scene, -1);
|
Daniel@0
|
10033 DOM.clear(this._root, 1);
|
Daniel@0
|
10034 }
|
Daniel@0
|
10035 this.updateDefs();
|
Daniel@0
|
10036 return this;
|
Daniel@0
|
10037 };
|
Daniel@0
|
10038
|
Daniel@0
|
10039 prototype.draw = function(el, scene, index) {
|
Daniel@0
|
10040 this.drawMark(el, scene, index, marks[scene.marktype]);
|
Daniel@0
|
10041 };
|
Daniel@0
|
10042
|
Daniel@0
|
10043
|
Daniel@0
|
10044 // -- Manage SVG definitions ('defs') block --
|
Daniel@0
|
10045
|
Daniel@0
|
10046 prototype.updateDefs = function() {
|
Daniel@0
|
10047 var svg = this._svg,
|
Daniel@0
|
10048 defs = this._defs,
|
Daniel@0
|
10049 el = defs.el,
|
Daniel@0
|
10050 index = 0, id;
|
Daniel@0
|
10051
|
Daniel@0
|
10052 for (id in defs.gradient) {
|
Daniel@0
|
10053 if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns));
|
Daniel@0
|
10054 updateGradient(el, defs.gradient[id], index++);
|
Daniel@0
|
10055 }
|
Daniel@0
|
10056
|
Daniel@0
|
10057 for (id in defs.clipping) {
|
Daniel@0
|
10058 if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns));
|
Daniel@0
|
10059 updateClipping(el, defs.clipping[id], index++);
|
Daniel@0
|
10060 }
|
Daniel@0
|
10061
|
Daniel@0
|
10062 // clean-up
|
Daniel@0
|
10063 if (el) {
|
Daniel@0
|
10064 if (index === 0) {
|
Daniel@0
|
10065 svg.removeChild(el);
|
Daniel@0
|
10066 defs.el = null;
|
Daniel@0
|
10067 } else {
|
Daniel@0
|
10068 DOM.clear(el, index);
|
Daniel@0
|
10069 }
|
Daniel@0
|
10070 }
|
Daniel@0
|
10071 };
|
Daniel@0
|
10072
|
Daniel@0
|
10073 function updateGradient(el, grad, index) {
|
Daniel@0
|
10074 var i, n, stop;
|
Daniel@0
|
10075
|
Daniel@0
|
10076 el = DOM.child(el, index, 'linearGradient', ns);
|
Daniel@0
|
10077 el.setAttribute('id', grad.id);
|
Daniel@0
|
10078 el.setAttribute('x1', grad.x1);
|
Daniel@0
|
10079 el.setAttribute('x2', grad.x2);
|
Daniel@0
|
10080 el.setAttribute('y1', grad.y1);
|
Daniel@0
|
10081 el.setAttribute('y2', grad.y2);
|
Daniel@0
|
10082
|
Daniel@0
|
10083 for (i=0, n=grad.stops.length; i<n; ++i) {
|
Daniel@0
|
10084 stop = DOM.child(el, i, 'stop', ns);
|
Daniel@0
|
10085 stop.setAttribute('offset', grad.stops[i].offset);
|
Daniel@0
|
10086 stop.setAttribute('stop-color', grad.stops[i].color);
|
Daniel@0
|
10087 }
|
Daniel@0
|
10088 DOM.clear(el, i);
|
Daniel@0
|
10089 }
|
Daniel@0
|
10090
|
Daniel@0
|
10091 function updateClipping(el, clip, index) {
|
Daniel@0
|
10092 var rect;
|
Daniel@0
|
10093
|
Daniel@0
|
10094 el = DOM.child(el, index, 'clipPath', ns);
|
Daniel@0
|
10095 el.setAttribute('id', clip.id);
|
Daniel@0
|
10096 rect = DOM.child(el, 0, 'rect', ns);
|
Daniel@0
|
10097 rect.setAttribute('x', 0);
|
Daniel@0
|
10098 rect.setAttribute('y', 0);
|
Daniel@0
|
10099 rect.setAttribute('width', clip.width);
|
Daniel@0
|
10100 rect.setAttribute('height', clip.height);
|
Daniel@0
|
10101 }
|
Daniel@0
|
10102
|
Daniel@0
|
10103 prototype._resetDefs = function() {
|
Daniel@0
|
10104 var def = this._defs;
|
Daniel@0
|
10105 def.clip_id = 1;
|
Daniel@0
|
10106 def.gradient = {};
|
Daniel@0
|
10107 def.clipping = {};
|
Daniel@0
|
10108 };
|
Daniel@0
|
10109
|
Daniel@0
|
10110
|
Daniel@0
|
10111 // -- Manage rendering of items marked as dirty --
|
Daniel@0
|
10112
|
Daniel@0
|
10113 prototype.isDirty = function(item) {
|
Daniel@0
|
10114 return this._dirtyAll || item.dirty === this._dirtyID;
|
Daniel@0
|
10115 };
|
Daniel@0
|
10116
|
Daniel@0
|
10117 prototype._dirtyCheck = function(items) {
|
Daniel@0
|
10118 this._dirtyAll = true;
|
Daniel@0
|
10119 if (!items) return true;
|
Daniel@0
|
10120
|
Daniel@0
|
10121 var id = ++this._dirtyID,
|
Daniel@0
|
10122 item, mark, type, mdef, i, n, o;
|
Daniel@0
|
10123
|
Daniel@0
|
10124 for (i=0, n=items.length; i<n; ++i) {
|
Daniel@0
|
10125 item = items[i];
|
Daniel@0
|
10126 mark = item.mark;
|
Daniel@0
|
10127 if (mark.marktype !== type) {
|
Daniel@0
|
10128 // memoize mark instance lookup
|
Daniel@0
|
10129 type = mark.marktype;
|
Daniel@0
|
10130 mdef = marks[type];
|
Daniel@0
|
10131 }
|
Daniel@0
|
10132
|
Daniel@0
|
10133 if (item.status === 'exit') { // EXIT
|
Daniel@0
|
10134 if (item._svg) {
|
Daniel@0
|
10135 if (mdef.nest && item.mark.items.length) {
|
Daniel@0
|
10136 // if nested mark with remaining points, update instead
|
Daniel@0
|
10137 this._update(mdef, item._svg, item.mark.items[0]);
|
Daniel@0
|
10138 o = item.mark.items[0];
|
Daniel@0
|
10139 o._svg = item._svg;
|
Daniel@0
|
10140 o._update = id;
|
Daniel@0
|
10141 } else {
|
Daniel@0
|
10142 // otherwise remove from DOM
|
Daniel@0
|
10143 DOM.remove(item._svg);
|
Daniel@0
|
10144 }
|
Daniel@0
|
10145 item._svg = null;
|
Daniel@0
|
10146 }
|
Daniel@0
|
10147 continue;
|
Daniel@0
|
10148 }
|
Daniel@0
|
10149
|
Daniel@0
|
10150 item = (mdef.nest ? mark.items[0] : item);
|
Daniel@0
|
10151 if (item._update === id) { // Already processed
|
Daniel@0
|
10152 continue;
|
Daniel@0
|
10153 } else if (item._svg) { // UPDATE
|
Daniel@0
|
10154 this._update(mdef, item._svg, item);
|
Daniel@0
|
10155 } else { // ENTER
|
Daniel@0
|
10156 this._dirtyAll = false;
|
Daniel@0
|
10157 dirtyParents(item, id);
|
Daniel@0
|
10158 }
|
Daniel@0
|
10159 item._update = id;
|
Daniel@0
|
10160 }
|
Daniel@0
|
10161 return !this._dirtyAll;
|
Daniel@0
|
10162 };
|
Daniel@0
|
10163
|
Daniel@0
|
10164 function dirtyParents(item, id) {
|
Daniel@0
|
10165 for (; item && item.dirty !== id; item=item.mark.group) {
|
Daniel@0
|
10166 item.dirty = id;
|
Daniel@0
|
10167 if (item.mark && item.mark.dirty !== id) {
|
Daniel@0
|
10168 item.mark.dirty = id;
|
Daniel@0
|
10169 } else return;
|
Daniel@0
|
10170 }
|
Daniel@0
|
10171 }
|
Daniel@0
|
10172
|
Daniel@0
|
10173
|
Daniel@0
|
10174 // -- Construct & maintain scenegraph to SVG mapping ---
|
Daniel@0
|
10175
|
Daniel@0
|
10176 // Draw a mark container.
|
Daniel@0
|
10177 prototype.drawMark = function(el, scene, index, mdef) {
|
Daniel@0
|
10178 if (!this.isDirty(scene)) return;
|
Daniel@0
|
10179
|
Daniel@0
|
10180 var items = mdef.nest ?
|
Daniel@0
|
10181 (scene.items && scene.items.length ? [scene.items[0]] : []) :
|
Daniel@0
|
10182 scene.items || [],
|
Daniel@0
|
10183 events = scene.interactive === false ? 'none' : null,
|
Daniel@0
|
10184 isGroup = (mdef.tag === 'g'),
|
Daniel@0
|
10185 className = DOM.cssClass(scene),
|
Daniel@0
|
10186 p, i, n, c, d, insert;
|
Daniel@0
|
10187
|
Daniel@0
|
10188 p = DOM.child(el, index+1, 'g', ns, className);
|
Daniel@0
|
10189 p.setAttribute('class', className);
|
Daniel@0
|
10190 scene._svg = p;
|
Daniel@0
|
10191 if (!isGroup && events) {
|
Daniel@0
|
10192 p.style.setProperty('pointer-events', events);
|
Daniel@0
|
10193 }
|
Daniel@0
|
10194
|
Daniel@0
|
10195 for (i=0, n=items.length; i<n; ++i) {
|
Daniel@0
|
10196 if (this.isDirty(d = items[i])) {
|
Daniel@0
|
10197 insert = !(this._dirtyAll || d._svg);
|
Daniel@0
|
10198 c = insert ? bind(p, mdef, d, i, true)
|
Daniel@0
|
10199 : (p.childNodes[i] || bind(p, mdef, d, i));
|
Daniel@0
|
10200 this._update(mdef, c, d);
|
Daniel@0
|
10201 if (isGroup) {
|
Daniel@0
|
10202 if (insert) this._dirtyAll = true;
|
Daniel@0
|
10203 this._recurse(c, d);
|
Daniel@0
|
10204 if (insert) this._dirtyAll = false;
|
Daniel@0
|
10205 }
|
Daniel@0
|
10206 }
|
Daniel@0
|
10207 }
|
Daniel@0
|
10208 DOM.clear(p, i);
|
Daniel@0
|
10209 return p;
|
Daniel@0
|
10210 };
|
Daniel@0
|
10211
|
Daniel@0
|
10212 // Recursively process group contents.
|
Daniel@0
|
10213 prototype._recurse = function(el, group) {
|
Daniel@0
|
10214 var items = group.items || [],
|
Daniel@0
|
10215 legends = group.legendItems || [],
|
Daniel@0
|
10216 axes = group.axisItems || [],
|
Daniel@0
|
10217 idx = 0, j, m;
|
Daniel@0
|
10218
|
Daniel@0
|
10219 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
10220 if (axes[j].layer === 'back') {
|
Daniel@0
|
10221 this.drawMark(el, axes[j], idx++, marks.group);
|
Daniel@0
|
10222 }
|
Daniel@0
|
10223 }
|
Daniel@0
|
10224 for (j=0, m=items.length; j<m; ++j) {
|
Daniel@0
|
10225 this.draw(el, items[j], idx++);
|
Daniel@0
|
10226 }
|
Daniel@0
|
10227 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
10228 if (axes[j].layer !== 'back') {
|
Daniel@0
|
10229 this.drawMark(el, axes[j], idx++, marks.group);
|
Daniel@0
|
10230 }
|
Daniel@0
|
10231 }
|
Daniel@0
|
10232 for (j=0, m=legends.length; j<m; ++j) {
|
Daniel@0
|
10233 this.drawMark(el, legends[j], idx++, marks.group);
|
Daniel@0
|
10234 }
|
Daniel@0
|
10235
|
Daniel@0
|
10236 // remove any extraneous DOM elements
|
Daniel@0
|
10237 DOM.clear(el, 1 + idx);
|
Daniel@0
|
10238 };
|
Daniel@0
|
10239
|
Daniel@0
|
10240 // Bind a scenegraph item to an SVG DOM element.
|
Daniel@0
|
10241 // Create new SVG elements as needed.
|
Daniel@0
|
10242 function bind(el, mdef, item, index, insert) {
|
Daniel@0
|
10243 // create svg element, bind item data for D3 compatibility
|
Daniel@0
|
10244 var node = DOM.child(el, index, mdef.tag, ns, null, insert);
|
Daniel@0
|
10245 node.__data__ = item;
|
Daniel@0
|
10246 node.__values__ = {fill: 'default'};
|
Daniel@0
|
10247
|
Daniel@0
|
10248 // create background rect
|
Daniel@0
|
10249 if (mdef.tag === 'g') {
|
Daniel@0
|
10250 var bg = DOM.child(node, 0, 'rect', ns, 'background');
|
Daniel@0
|
10251 bg.__data__ = item;
|
Daniel@0
|
10252 }
|
Daniel@0
|
10253
|
Daniel@0
|
10254 // add pointer from scenegraph item to svg element
|
Daniel@0
|
10255 return (item._svg = node);
|
Daniel@0
|
10256 }
|
Daniel@0
|
10257
|
Daniel@0
|
10258
|
Daniel@0
|
10259 // -- Set attributes & styles on SVG elements ---
|
Daniel@0
|
10260
|
Daniel@0
|
10261 var href = (typeof window !== 'undefined' ? window.location.href : ''),
|
Daniel@0
|
10262 element = null, // temp var for current SVG element
|
Daniel@0
|
10263 values = null; // temp var for current values hash
|
Daniel@0
|
10264
|
Daniel@0
|
10265 // Extra configuration for certain mark types
|
Daniel@0
|
10266 var mark_extras = {
|
Daniel@0
|
10267 group: function(mdef, el, item) {
|
Daniel@0
|
10268 element = el.childNodes[0];
|
Daniel@0
|
10269 values = el.__values__; // use parent's values hash
|
Daniel@0
|
10270 mdef.background(emit, item, this);
|
Daniel@0
|
10271
|
Daniel@0
|
10272 var value = item.mark.interactive === false ? 'none' : null;
|
Daniel@0
|
10273 if (value !== values.events) {
|
Daniel@0
|
10274 element.style.setProperty('pointer-events', value);
|
Daniel@0
|
10275 values.events = value;
|
Daniel@0
|
10276 }
|
Daniel@0
|
10277 },
|
Daniel@0
|
10278 text: function(mdef, el, item) {
|
Daniel@0
|
10279 var str = text.value(item.text);
|
Daniel@0
|
10280 if (str !== values.text) {
|
Daniel@0
|
10281 el.textContent = str;
|
Daniel@0
|
10282 values.text = str;
|
Daniel@0
|
10283 }
|
Daniel@0
|
10284 str = text.font(item);
|
Daniel@0
|
10285 if (str !== values.font) {
|
Daniel@0
|
10286 el.style.setProperty('font', str);
|
Daniel@0
|
10287 values.font = str;
|
Daniel@0
|
10288 }
|
Daniel@0
|
10289 }
|
Daniel@0
|
10290 };
|
Daniel@0
|
10291
|
Daniel@0
|
10292 prototype._update = function(mdef, el, item) {
|
Daniel@0
|
10293 // set dom element and values cache
|
Daniel@0
|
10294 // provides access to emit method
|
Daniel@0
|
10295 element = el;
|
Daniel@0
|
10296 values = el.__values__;
|
Daniel@0
|
10297
|
Daniel@0
|
10298 // apply svg attributes
|
Daniel@0
|
10299 mdef.attr(emit, item, this);
|
Daniel@0
|
10300
|
Daniel@0
|
10301 // some marks need special treatment
|
Daniel@0
|
10302 var extra = mark_extras[mdef.type];
|
Daniel@0
|
10303 if (extra) extra(mdef, el, item);
|
Daniel@0
|
10304
|
Daniel@0
|
10305 // apply svg css styles
|
Daniel@0
|
10306 // note: element may be modified by 'extra' method
|
Daniel@0
|
10307 this.style(element, item);
|
Daniel@0
|
10308 };
|
Daniel@0
|
10309
|
Daniel@0
|
10310 function emit(name, value, ns) {
|
Daniel@0
|
10311 // early exit if value is unchanged
|
Daniel@0
|
10312 if (value === values[name]) return;
|
Daniel@0
|
10313
|
Daniel@0
|
10314 if (value != null) {
|
Daniel@0
|
10315 // if value is provided, update DOM attribute
|
Daniel@0
|
10316 if (ns) {
|
Daniel@0
|
10317 element.setAttributeNS(ns, name, value);
|
Daniel@0
|
10318 } else {
|
Daniel@0
|
10319 element.setAttribute(name, value);
|
Daniel@0
|
10320 }
|
Daniel@0
|
10321 } else {
|
Daniel@0
|
10322 // else remove DOM attribute
|
Daniel@0
|
10323 if (ns) {
|
Daniel@0
|
10324 element.removeAttributeNS(ns, name);
|
Daniel@0
|
10325 } else {
|
Daniel@0
|
10326 element.removeAttribute(name);
|
Daniel@0
|
10327 }
|
Daniel@0
|
10328 }
|
Daniel@0
|
10329
|
Daniel@0
|
10330 // note current value for future comparison
|
Daniel@0
|
10331 values[name] = value;
|
Daniel@0
|
10332 }
|
Daniel@0
|
10333
|
Daniel@0
|
10334 prototype.style = function(el, o) {
|
Daniel@0
|
10335 if (o == null) return;
|
Daniel@0
|
10336 var i, n, prop, name, value;
|
Daniel@0
|
10337
|
Daniel@0
|
10338 for (i=0, n=SVG.styleProperties.length; i<n; ++i) {
|
Daniel@0
|
10339 prop = SVG.styleProperties[i];
|
Daniel@0
|
10340 value = o[prop];
|
Daniel@0
|
10341 if (value === values[prop]) continue;
|
Daniel@0
|
10342
|
Daniel@0
|
10343 name = SVG.styles[prop];
|
Daniel@0
|
10344 if (value == null) {
|
Daniel@0
|
10345 if (name === 'fill') {
|
Daniel@0
|
10346 el.style.setProperty(name, 'none');
|
Daniel@0
|
10347 } else {
|
Daniel@0
|
10348 el.style.removeProperty(name);
|
Daniel@0
|
10349 }
|
Daniel@0
|
10350 } else {
|
Daniel@0
|
10351 if (value.id) {
|
Daniel@0
|
10352 // ensure definition is included
|
Daniel@0
|
10353 this._defs.gradient[value.id] = value;
|
Daniel@0
|
10354 value = 'url(' + href + '#' + value.id + ')';
|
Daniel@0
|
10355 }
|
Daniel@0
|
10356 el.style.setProperty(name, value+'');
|
Daniel@0
|
10357 }
|
Daniel@0
|
10358
|
Daniel@0
|
10359 values[prop] = value;
|
Daniel@0
|
10360 }
|
Daniel@0
|
10361 };
|
Daniel@0
|
10362
|
Daniel@0
|
10363 module.exports = SVGRenderer;
|
Daniel@0
|
10364
|
Daniel@0
|
10365 },{"../../util/ImageLoader":77,"../../util/dom":81,"../../util/svg":83,"../../util/text":84,"../Renderer":52,"./marks":73}],71:[function(require,module,exports){
|
Daniel@0
|
10366 var Renderer = require('../Renderer'),
|
Daniel@0
|
10367 ImageLoader = require('../../util/ImageLoader'),
|
Daniel@0
|
10368 SVG = require('../../util/svg'),
|
Daniel@0
|
10369 text = require('../../util/text'),
|
Daniel@0
|
10370 DOM = require('../../util/dom'),
|
Daniel@0
|
10371 openTag = DOM.openTag,
|
Daniel@0
|
10372 closeTag = DOM.closeTag,
|
Daniel@0
|
10373 MARKS = require('./marks');
|
Daniel@0
|
10374
|
Daniel@0
|
10375 function SVGStringRenderer(loadConfig) {
|
Daniel@0
|
10376 Renderer.call(this);
|
Daniel@0
|
10377
|
Daniel@0
|
10378 this._loader = new ImageLoader(loadConfig);
|
Daniel@0
|
10379
|
Daniel@0
|
10380 this._text = {
|
Daniel@0
|
10381 head: '',
|
Daniel@0
|
10382 root: '',
|
Daniel@0
|
10383 foot: '',
|
Daniel@0
|
10384 defs: '',
|
Daniel@0
|
10385 body: ''
|
Daniel@0
|
10386 };
|
Daniel@0
|
10387
|
Daniel@0
|
10388 this._defs = {
|
Daniel@0
|
10389 clip_id: 1,
|
Daniel@0
|
10390 gradient: {},
|
Daniel@0
|
10391 clipping: {}
|
Daniel@0
|
10392 };
|
Daniel@0
|
10393 }
|
Daniel@0
|
10394
|
Daniel@0
|
10395 var base = Renderer.prototype;
|
Daniel@0
|
10396 var prototype = (SVGStringRenderer.prototype = Object.create(base));
|
Daniel@0
|
10397 prototype.constructor = SVGStringRenderer;
|
Daniel@0
|
10398
|
Daniel@0
|
10399 prototype.resize = function(width, height, padding) {
|
Daniel@0
|
10400 base.resize.call(this, width, height, padding);
|
Daniel@0
|
10401 var p = this._padding,
|
Daniel@0
|
10402 t = this._text;
|
Daniel@0
|
10403
|
Daniel@0
|
10404 var attr = {
|
Daniel@0
|
10405 'class': 'marks',
|
Daniel@0
|
10406 'width': this._width + p.left + p.right,
|
Daniel@0
|
10407 'height': this._height + p.top + p.bottom,
|
Daniel@0
|
10408 };
|
Daniel@0
|
10409 for (var key in SVG.metadata) {
|
Daniel@0
|
10410 attr[key] = SVG.metadata[key];
|
Daniel@0
|
10411 }
|
Daniel@0
|
10412
|
Daniel@0
|
10413 t.head = openTag('svg', attr);
|
Daniel@0
|
10414 t.root = openTag('g', {
|
Daniel@0
|
10415 transform: 'translate(' + p.left + ',' + p.top + ')'
|
Daniel@0
|
10416 });
|
Daniel@0
|
10417 t.foot = closeTag('g') + closeTag('svg');
|
Daniel@0
|
10418
|
Daniel@0
|
10419 return this;
|
Daniel@0
|
10420 };
|
Daniel@0
|
10421
|
Daniel@0
|
10422 prototype.svg = function() {
|
Daniel@0
|
10423 var t = this._text;
|
Daniel@0
|
10424 return t.head + t.defs + t.root + t.body + t.foot;
|
Daniel@0
|
10425 };
|
Daniel@0
|
10426
|
Daniel@0
|
10427 prototype.render = function(scene) {
|
Daniel@0
|
10428 this._text.body = this.mark(scene);
|
Daniel@0
|
10429 this._text.defs = this.buildDefs();
|
Daniel@0
|
10430 return this;
|
Daniel@0
|
10431 };
|
Daniel@0
|
10432
|
Daniel@0
|
10433 prototype.reset = function() {
|
Daniel@0
|
10434 this._defs.clip_id = 0;
|
Daniel@0
|
10435 return this;
|
Daniel@0
|
10436 };
|
Daniel@0
|
10437
|
Daniel@0
|
10438 prototype.buildDefs = function() {
|
Daniel@0
|
10439 var all = this._defs,
|
Daniel@0
|
10440 defs = '',
|
Daniel@0
|
10441 i, id, def, stops;
|
Daniel@0
|
10442
|
Daniel@0
|
10443 for (id in all.gradient) {
|
Daniel@0
|
10444 def = all.gradient[id];
|
Daniel@0
|
10445 stops = def.stops;
|
Daniel@0
|
10446
|
Daniel@0
|
10447 defs += openTag('linearGradient', {
|
Daniel@0
|
10448 id: id,
|
Daniel@0
|
10449 x1: def.x1,
|
Daniel@0
|
10450 x2: def.x2,
|
Daniel@0
|
10451 y1: def.y1,
|
Daniel@0
|
10452 y2: def.y2
|
Daniel@0
|
10453 });
|
Daniel@0
|
10454
|
Daniel@0
|
10455 for (i=0; i<stops.length; ++i) {
|
Daniel@0
|
10456 defs += openTag('stop', {
|
Daniel@0
|
10457 offset: stops[i].offset,
|
Daniel@0
|
10458 'stop-color': stops[i].color
|
Daniel@0
|
10459 }) + closeTag('stop');
|
Daniel@0
|
10460 }
|
Daniel@0
|
10461
|
Daniel@0
|
10462 defs += closeTag('linearGradient');
|
Daniel@0
|
10463 }
|
Daniel@0
|
10464
|
Daniel@0
|
10465 for (id in all.clipping) {
|
Daniel@0
|
10466 def = all.clipping[id];
|
Daniel@0
|
10467
|
Daniel@0
|
10468 defs += openTag('clipPath', {id: id});
|
Daniel@0
|
10469
|
Daniel@0
|
10470 defs += openTag('rect', {
|
Daniel@0
|
10471 x: 0,
|
Daniel@0
|
10472 y: 0,
|
Daniel@0
|
10473 width: def.width,
|
Daniel@0
|
10474 height: def.height
|
Daniel@0
|
10475 }) + closeTag('rect');
|
Daniel@0
|
10476
|
Daniel@0
|
10477 defs += closeTag('clipPath');
|
Daniel@0
|
10478 }
|
Daniel@0
|
10479
|
Daniel@0
|
10480 return (defs.length > 0) ? openTag('defs') + defs + closeTag('defs') : '';
|
Daniel@0
|
10481 };
|
Daniel@0
|
10482
|
Daniel@0
|
10483 prototype.imageURL = function(url) {
|
Daniel@0
|
10484 return this._loader.imageURL(url);
|
Daniel@0
|
10485 };
|
Daniel@0
|
10486
|
Daniel@0
|
10487 var object;
|
Daniel@0
|
10488
|
Daniel@0
|
10489 function emit(name, value, ns, prefixed) {
|
Daniel@0
|
10490 object[prefixed || name] = value;
|
Daniel@0
|
10491 }
|
Daniel@0
|
10492
|
Daniel@0
|
10493 prototype.attributes = function(attr, item) {
|
Daniel@0
|
10494 object = {};
|
Daniel@0
|
10495 attr(emit, item, this);
|
Daniel@0
|
10496 return object;
|
Daniel@0
|
10497 };
|
Daniel@0
|
10498
|
Daniel@0
|
10499 prototype.mark = function(scene) {
|
Daniel@0
|
10500 var mdef = MARKS[scene.marktype],
|
Daniel@0
|
10501 tag = mdef.tag,
|
Daniel@0
|
10502 attr = mdef.attr,
|
Daniel@0
|
10503 nest = mdef.nest || false,
|
Daniel@0
|
10504 data = nest ?
|
Daniel@0
|
10505 (scene.items && scene.items.length ? [scene.items[0]] : []) :
|
Daniel@0
|
10506 (scene.items || []),
|
Daniel@0
|
10507 defs = this._defs,
|
Daniel@0
|
10508 str = '',
|
Daniel@0
|
10509 style, i, item;
|
Daniel@0
|
10510
|
Daniel@0
|
10511 if (tag !== 'g' && scene.interactive === false) {
|
Daniel@0
|
10512 style = 'style="pointer-events: none;"';
|
Daniel@0
|
10513 }
|
Daniel@0
|
10514
|
Daniel@0
|
10515 // render opening group tag
|
Daniel@0
|
10516 str += openTag('g', {
|
Daniel@0
|
10517 'class': DOM.cssClass(scene)
|
Daniel@0
|
10518 }, style);
|
Daniel@0
|
10519
|
Daniel@0
|
10520 // render contained elements
|
Daniel@0
|
10521 for (i=0; i<data.length; ++i) {
|
Daniel@0
|
10522 item = data[i];
|
Daniel@0
|
10523 style = (tag !== 'g') ? styles(item, scene, tag, defs) : null;
|
Daniel@0
|
10524 str += openTag(tag, this.attributes(attr, item), style);
|
Daniel@0
|
10525 if (tag === 'text') {
|
Daniel@0
|
10526 str += escape_text(text.value(item.text));
|
Daniel@0
|
10527 } else if (tag === 'g') {
|
Daniel@0
|
10528 str += openTag('rect',
|
Daniel@0
|
10529 this.attributes(mdef.background, item),
|
Daniel@0
|
10530 styles(item, scene, 'bgrect', defs)) + closeTag('rect');
|
Daniel@0
|
10531 str += this.markGroup(item);
|
Daniel@0
|
10532 }
|
Daniel@0
|
10533 str += closeTag(tag);
|
Daniel@0
|
10534 }
|
Daniel@0
|
10535
|
Daniel@0
|
10536 // render closing group tag
|
Daniel@0
|
10537 return str + closeTag('g');
|
Daniel@0
|
10538 };
|
Daniel@0
|
10539
|
Daniel@0
|
10540 prototype.markGroup = function(scene) {
|
Daniel@0
|
10541 var str = '',
|
Daniel@0
|
10542 axes = scene.axisItems || [],
|
Daniel@0
|
10543 items = scene.items || [],
|
Daniel@0
|
10544 legends = scene.legendItems || [],
|
Daniel@0
|
10545 j, m;
|
Daniel@0
|
10546
|
Daniel@0
|
10547 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
10548 if (axes[j].layer === 'back') {
|
Daniel@0
|
10549 str += this.mark(axes[j]);
|
Daniel@0
|
10550 }
|
Daniel@0
|
10551 }
|
Daniel@0
|
10552 for (j=0, m=items.length; j<m; ++j) {
|
Daniel@0
|
10553 str += this.mark(items[j]);
|
Daniel@0
|
10554 }
|
Daniel@0
|
10555 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
10556 if (axes[j].layer !== 'back') {
|
Daniel@0
|
10557 str += this.mark(axes[j]);
|
Daniel@0
|
10558 }
|
Daniel@0
|
10559 }
|
Daniel@0
|
10560 for (j=0, m=legends.length; j<m; ++j) {
|
Daniel@0
|
10561 str += this.mark(legends[j]);
|
Daniel@0
|
10562 }
|
Daniel@0
|
10563
|
Daniel@0
|
10564 return str;
|
Daniel@0
|
10565 };
|
Daniel@0
|
10566
|
Daniel@0
|
10567 function styles(o, mark, tag, defs) {
|
Daniel@0
|
10568 if (o == null) return '';
|
Daniel@0
|
10569 var i, n, prop, name, value, s = '';
|
Daniel@0
|
10570
|
Daniel@0
|
10571 if (tag === 'bgrect' && mark.interactive === false) {
|
Daniel@0
|
10572 s += 'pointer-events: none;';
|
Daniel@0
|
10573 }
|
Daniel@0
|
10574
|
Daniel@0
|
10575 if (tag === 'text') {
|
Daniel@0
|
10576 s += 'font: ' + text.font(o) + ';';
|
Daniel@0
|
10577 }
|
Daniel@0
|
10578
|
Daniel@0
|
10579 for (i=0, n=SVG.styleProperties.length; i<n; ++i) {
|
Daniel@0
|
10580 prop = SVG.styleProperties[i];
|
Daniel@0
|
10581 name = SVG.styles[prop];
|
Daniel@0
|
10582 value = o[prop];
|
Daniel@0
|
10583
|
Daniel@0
|
10584 if (value == null) {
|
Daniel@0
|
10585 if (name === 'fill') {
|
Daniel@0
|
10586 s += (s.length ? ' ' : '') + 'fill: none;';
|
Daniel@0
|
10587 }
|
Daniel@0
|
10588 } else {
|
Daniel@0
|
10589 if (value.id) {
|
Daniel@0
|
10590 // ensure definition is included
|
Daniel@0
|
10591 defs.gradient[value.id] = value;
|
Daniel@0
|
10592 value = 'url(#' + value.id + ')';
|
Daniel@0
|
10593 }
|
Daniel@0
|
10594 s += (s.length ? ' ' : '') + name + ': ' + value + ';';
|
Daniel@0
|
10595 }
|
Daniel@0
|
10596 }
|
Daniel@0
|
10597
|
Daniel@0
|
10598 return s ? 'style="' + s + '"' : null;
|
Daniel@0
|
10599 }
|
Daniel@0
|
10600
|
Daniel@0
|
10601 function escape_text(s) {
|
Daniel@0
|
10602 return s.replace(/&/g, '&')
|
Daniel@0
|
10603 .replace(/</g, '<')
|
Daniel@0
|
10604 .replace(/>/g, '>');
|
Daniel@0
|
10605 }
|
Daniel@0
|
10606
|
Daniel@0
|
10607 module.exports = SVGStringRenderer;
|
Daniel@0
|
10608
|
Daniel@0
|
10609 },{"../../util/ImageLoader":77,"../../util/dom":81,"../../util/svg":83,"../../util/text":84,"../Renderer":52,"./marks":73}],72:[function(require,module,exports){
|
Daniel@0
|
10610 module.exports = {
|
Daniel@0
|
10611 Handler: require('./SVGHandler'),
|
Daniel@0
|
10612 Renderer: require('./SVGRenderer'),
|
Daniel@0
|
10613 string: {
|
Daniel@0
|
10614 Renderer : require('./SVGStringRenderer')
|
Daniel@0
|
10615 }
|
Daniel@0
|
10616 };
|
Daniel@0
|
10617 },{"./SVGHandler":69,"./SVGRenderer":70,"./SVGStringRenderer":71}],73:[function(require,module,exports){
|
Daniel@0
|
10618 var text = require('../../util/text'),
|
Daniel@0
|
10619 SVG = require('../../util/svg'),
|
Daniel@0
|
10620 textAlign = SVG.textAlign,
|
Daniel@0
|
10621 path = SVG.path;
|
Daniel@0
|
10622
|
Daniel@0
|
10623 function translateItem(o) {
|
Daniel@0
|
10624 return translate(o.x || 0, o.y || 0);
|
Daniel@0
|
10625 }
|
Daniel@0
|
10626
|
Daniel@0
|
10627 function translate(x, y) {
|
Daniel@0
|
10628 return 'translate(' + x + ',' + y + ')';
|
Daniel@0
|
10629 }
|
Daniel@0
|
10630
|
Daniel@0
|
10631 module.exports = {
|
Daniel@0
|
10632 arc: {
|
Daniel@0
|
10633 tag: 'path',
|
Daniel@0
|
10634 type: 'arc',
|
Daniel@0
|
10635 attr: function(emit, o) {
|
Daniel@0
|
10636 emit('transform', translateItem(o));
|
Daniel@0
|
10637 emit('d', path.arc(o));
|
Daniel@0
|
10638 }
|
Daniel@0
|
10639 },
|
Daniel@0
|
10640 area: {
|
Daniel@0
|
10641 tag: 'path',
|
Daniel@0
|
10642 type: 'area',
|
Daniel@0
|
10643 nest: true,
|
Daniel@0
|
10644 attr: function(emit, o) {
|
Daniel@0
|
10645 var items = o.mark.items;
|
Daniel@0
|
10646 if (items.length) emit('d', path.area(items));
|
Daniel@0
|
10647 }
|
Daniel@0
|
10648 },
|
Daniel@0
|
10649 group: {
|
Daniel@0
|
10650 tag: 'g',
|
Daniel@0
|
10651 type: 'group',
|
Daniel@0
|
10652 attr: function(emit, o, renderer) {
|
Daniel@0
|
10653 var id = null, defs, c;
|
Daniel@0
|
10654 emit('transform', translateItem(o));
|
Daniel@0
|
10655 if (o.clip) {
|
Daniel@0
|
10656 defs = renderer._defs;
|
Daniel@0
|
10657 id = o.clip_id || (o.clip_id = 'clip' + defs.clip_id++);
|
Daniel@0
|
10658 c = defs.clipping[id] || (defs.clipping[id] = {id: id});
|
Daniel@0
|
10659 c.width = o.width || 0;
|
Daniel@0
|
10660 c.height = o.height || 0;
|
Daniel@0
|
10661 }
|
Daniel@0
|
10662 emit('clip-path', id ? ('url(#' + id + ')') : null);
|
Daniel@0
|
10663 },
|
Daniel@0
|
10664 background: function(emit, o) {
|
Daniel@0
|
10665 emit('class', 'background');
|
Daniel@0
|
10666 emit('width', o.width || 0);
|
Daniel@0
|
10667 emit('height', o.height || 0);
|
Daniel@0
|
10668 }
|
Daniel@0
|
10669 },
|
Daniel@0
|
10670 image: {
|
Daniel@0
|
10671 tag: 'image',
|
Daniel@0
|
10672 type: 'image',
|
Daniel@0
|
10673 attr: function(emit, o, renderer) {
|
Daniel@0
|
10674 var x = o.x || 0,
|
Daniel@0
|
10675 y = o.y || 0,
|
Daniel@0
|
10676 w = o.width || 0,
|
Daniel@0
|
10677 h = o.height || 0,
|
Daniel@0
|
10678 url = renderer.imageURL(o.url);
|
Daniel@0
|
10679
|
Daniel@0
|
10680 x = x - (o.align === 'center' ? w/2 : o.align === 'right' ? w : 0);
|
Daniel@0
|
10681 y = y - (o.baseline === 'middle' ? h/2 : o.baseline === 'bottom' ? h : 0);
|
Daniel@0
|
10682
|
Daniel@0
|
10683 emit('href', url, 'http://www.w3.org/1999/xlink', 'xlink:href');
|
Daniel@0
|
10684 emit('transform', translate(x, y));
|
Daniel@0
|
10685 emit('width', w);
|
Daniel@0
|
10686 emit('height', h);
|
Daniel@0
|
10687 }
|
Daniel@0
|
10688 },
|
Daniel@0
|
10689 line: {
|
Daniel@0
|
10690 tag: 'path',
|
Daniel@0
|
10691 type: 'line',
|
Daniel@0
|
10692 nest: true,
|
Daniel@0
|
10693 attr: function(emit, o) {
|
Daniel@0
|
10694 var items = o.mark.items;
|
Daniel@0
|
10695 if (items.length) emit('d', path.line(items));
|
Daniel@0
|
10696 }
|
Daniel@0
|
10697 },
|
Daniel@0
|
10698 path: {
|
Daniel@0
|
10699 tag: 'path',
|
Daniel@0
|
10700 type: 'path',
|
Daniel@0
|
10701 attr: function(emit, o) {
|
Daniel@0
|
10702 emit('transform', translateItem(o));
|
Daniel@0
|
10703 emit('d', o.path);
|
Daniel@0
|
10704 }
|
Daniel@0
|
10705 },
|
Daniel@0
|
10706 rect: {
|
Daniel@0
|
10707 tag: 'rect',
|
Daniel@0
|
10708 type: 'rect',
|
Daniel@0
|
10709 nest: false,
|
Daniel@0
|
10710 attr: function(emit, o) {
|
Daniel@0
|
10711 emit('transform', translateItem(o));
|
Daniel@0
|
10712 emit('width', o.width || 0);
|
Daniel@0
|
10713 emit('height', o.height || 0);
|
Daniel@0
|
10714 }
|
Daniel@0
|
10715 },
|
Daniel@0
|
10716 rule: {
|
Daniel@0
|
10717 tag: 'line',
|
Daniel@0
|
10718 type: 'rule',
|
Daniel@0
|
10719 attr: function(emit, o) {
|
Daniel@0
|
10720 emit('transform', translateItem(o));
|
Daniel@0
|
10721 emit('x2', o.x2 != null ? o.x2 - (o.x||0) : 0);
|
Daniel@0
|
10722 emit('y2', o.y2 != null ? o.y2 - (o.y||0) : 0);
|
Daniel@0
|
10723 }
|
Daniel@0
|
10724 },
|
Daniel@0
|
10725 symbol: {
|
Daniel@0
|
10726 tag: 'path',
|
Daniel@0
|
10727 type: 'symbol',
|
Daniel@0
|
10728 attr: function(emit, o) {
|
Daniel@0
|
10729 emit('transform', translateItem(o));
|
Daniel@0
|
10730 emit('d', path.symbol(o));
|
Daniel@0
|
10731 }
|
Daniel@0
|
10732 },
|
Daniel@0
|
10733 text: {
|
Daniel@0
|
10734 tag: 'text',
|
Daniel@0
|
10735 type: 'text',
|
Daniel@0
|
10736 nest: false,
|
Daniel@0
|
10737 attr: function(emit, o) {
|
Daniel@0
|
10738 var dx = (o.dx || 0),
|
Daniel@0
|
10739 dy = (o.dy || 0) + text.offset(o),
|
Daniel@0
|
10740 x = (o.x || 0),
|
Daniel@0
|
10741 y = (o.y || 0),
|
Daniel@0
|
10742 a = o.angle || 0,
|
Daniel@0
|
10743 r = o.radius || 0, t;
|
Daniel@0
|
10744
|
Daniel@0
|
10745 if (r) {
|
Daniel@0
|
10746 t = (o.theta || 0) - Math.PI/2;
|
Daniel@0
|
10747 x += r * Math.cos(t);
|
Daniel@0
|
10748 y += r * Math.sin(t);
|
Daniel@0
|
10749 }
|
Daniel@0
|
10750
|
Daniel@0
|
10751 emit('text-anchor', textAlign[o.align] || 'start');
|
Daniel@0
|
10752
|
Daniel@0
|
10753 if (a) {
|
Daniel@0
|
10754 t = translate(x, y) + ' rotate('+a+')';
|
Daniel@0
|
10755 if (dx || dy) t += ' ' + translate(dx, dy);
|
Daniel@0
|
10756 } else {
|
Daniel@0
|
10757 t = translate(x+dx, y+dy);
|
Daniel@0
|
10758 }
|
Daniel@0
|
10759 emit('transform', t);
|
Daniel@0
|
10760 }
|
Daniel@0
|
10761 }
|
Daniel@0
|
10762 };
|
Daniel@0
|
10763
|
Daniel@0
|
10764 },{"../../util/svg":83,"../../util/text":84}],74:[function(require,module,exports){
|
Daniel@0
|
10765 function Bounds(b) {
|
Daniel@0
|
10766 this.clear();
|
Daniel@0
|
10767 if (b) this.union(b);
|
Daniel@0
|
10768 }
|
Daniel@0
|
10769
|
Daniel@0
|
10770 var prototype = Bounds.prototype;
|
Daniel@0
|
10771
|
Daniel@0
|
10772 prototype.clone = function() {
|
Daniel@0
|
10773 return new Bounds(this);
|
Daniel@0
|
10774 };
|
Daniel@0
|
10775
|
Daniel@0
|
10776 prototype.clear = function() {
|
Daniel@0
|
10777 this.x1 = +Number.MAX_VALUE;
|
Daniel@0
|
10778 this.y1 = +Number.MAX_VALUE;
|
Daniel@0
|
10779 this.x2 = -Number.MAX_VALUE;
|
Daniel@0
|
10780 this.y2 = -Number.MAX_VALUE;
|
Daniel@0
|
10781 return this;
|
Daniel@0
|
10782 };
|
Daniel@0
|
10783
|
Daniel@0
|
10784 prototype.set = function(x1, y1, x2, y2) {
|
Daniel@0
|
10785 this.x1 = x1;
|
Daniel@0
|
10786 this.y1 = y1;
|
Daniel@0
|
10787 this.x2 = x2;
|
Daniel@0
|
10788 this.y2 = y2;
|
Daniel@0
|
10789 return this;
|
Daniel@0
|
10790 };
|
Daniel@0
|
10791
|
Daniel@0
|
10792 prototype.add = function(x, y) {
|
Daniel@0
|
10793 if (x < this.x1) this.x1 = x;
|
Daniel@0
|
10794 if (y < this.y1) this.y1 = y;
|
Daniel@0
|
10795 if (x > this.x2) this.x2 = x;
|
Daniel@0
|
10796 if (y > this.y2) this.y2 = y;
|
Daniel@0
|
10797 return this;
|
Daniel@0
|
10798 };
|
Daniel@0
|
10799
|
Daniel@0
|
10800 prototype.expand = function(d) {
|
Daniel@0
|
10801 this.x1 -= d;
|
Daniel@0
|
10802 this.y1 -= d;
|
Daniel@0
|
10803 this.x2 += d;
|
Daniel@0
|
10804 this.y2 += d;
|
Daniel@0
|
10805 return this;
|
Daniel@0
|
10806 };
|
Daniel@0
|
10807
|
Daniel@0
|
10808 prototype.round = function() {
|
Daniel@0
|
10809 this.x1 = Math.floor(this.x1);
|
Daniel@0
|
10810 this.y1 = Math.floor(this.y1);
|
Daniel@0
|
10811 this.x2 = Math.ceil(this.x2);
|
Daniel@0
|
10812 this.y2 = Math.ceil(this.y2);
|
Daniel@0
|
10813 return this;
|
Daniel@0
|
10814 };
|
Daniel@0
|
10815
|
Daniel@0
|
10816 prototype.translate = function(dx, dy) {
|
Daniel@0
|
10817 this.x1 += dx;
|
Daniel@0
|
10818 this.x2 += dx;
|
Daniel@0
|
10819 this.y1 += dy;
|
Daniel@0
|
10820 this.y2 += dy;
|
Daniel@0
|
10821 return this;
|
Daniel@0
|
10822 };
|
Daniel@0
|
10823
|
Daniel@0
|
10824 prototype.rotate = function(angle, x, y) {
|
Daniel@0
|
10825 var cos = Math.cos(angle),
|
Daniel@0
|
10826 sin = Math.sin(angle),
|
Daniel@0
|
10827 cx = x - x*cos + y*sin,
|
Daniel@0
|
10828 cy = y - x*sin - y*cos,
|
Daniel@0
|
10829 x1 = this.x1, x2 = this.x2,
|
Daniel@0
|
10830 y1 = this.y1, y2 = this.y2;
|
Daniel@0
|
10831
|
Daniel@0
|
10832 return this.clear()
|
Daniel@0
|
10833 .add(cos*x1 - sin*y1 + cx, sin*x1 + cos*y1 + cy)
|
Daniel@0
|
10834 .add(cos*x1 - sin*y2 + cx, sin*x1 + cos*y2 + cy)
|
Daniel@0
|
10835 .add(cos*x2 - sin*y1 + cx, sin*x2 + cos*y1 + cy)
|
Daniel@0
|
10836 .add(cos*x2 - sin*y2 + cx, sin*x2 + cos*y2 + cy);
|
Daniel@0
|
10837 };
|
Daniel@0
|
10838
|
Daniel@0
|
10839 prototype.union = function(b) {
|
Daniel@0
|
10840 if (b.x1 < this.x1) this.x1 = b.x1;
|
Daniel@0
|
10841 if (b.y1 < this.y1) this.y1 = b.y1;
|
Daniel@0
|
10842 if (b.x2 > this.x2) this.x2 = b.x2;
|
Daniel@0
|
10843 if (b.y2 > this.y2) this.y2 = b.y2;
|
Daniel@0
|
10844 return this;
|
Daniel@0
|
10845 };
|
Daniel@0
|
10846
|
Daniel@0
|
10847 prototype.encloses = function(b) {
|
Daniel@0
|
10848 return b && (
|
Daniel@0
|
10849 this.x1 <= b.x1 &&
|
Daniel@0
|
10850 this.x2 >= b.x2 &&
|
Daniel@0
|
10851 this.y1 <= b.y1 &&
|
Daniel@0
|
10852 this.y2 >= b.y2
|
Daniel@0
|
10853 );
|
Daniel@0
|
10854 };
|
Daniel@0
|
10855
|
Daniel@0
|
10856 prototype.intersects = function(b) {
|
Daniel@0
|
10857 return b && !(
|
Daniel@0
|
10858 this.x2 < b.x1 ||
|
Daniel@0
|
10859 this.x1 > b.x2 ||
|
Daniel@0
|
10860 this.y2 < b.y1 ||
|
Daniel@0
|
10861 this.y1 > b.y2
|
Daniel@0
|
10862 );
|
Daniel@0
|
10863 };
|
Daniel@0
|
10864
|
Daniel@0
|
10865 prototype.contains = function(x, y) {
|
Daniel@0
|
10866 return !(
|
Daniel@0
|
10867 x < this.x1 ||
|
Daniel@0
|
10868 x > this.x2 ||
|
Daniel@0
|
10869 y < this.y1 ||
|
Daniel@0
|
10870 y > this.y2
|
Daniel@0
|
10871 );
|
Daniel@0
|
10872 };
|
Daniel@0
|
10873
|
Daniel@0
|
10874 prototype.width = function() {
|
Daniel@0
|
10875 return this.x2 - this.x1;
|
Daniel@0
|
10876 };
|
Daniel@0
|
10877
|
Daniel@0
|
10878 prototype.height = function() {
|
Daniel@0
|
10879 return this.y2 - this.y1;
|
Daniel@0
|
10880 };
|
Daniel@0
|
10881
|
Daniel@0
|
10882 module.exports = Bounds;
|
Daniel@0
|
10883
|
Daniel@0
|
10884 },{}],75:[function(require,module,exports){
|
Daniel@0
|
10885 module.exports = function(b) {
|
Daniel@0
|
10886 function noop() { }
|
Daniel@0
|
10887 function add(x,y) { b.add(x, y); }
|
Daniel@0
|
10888
|
Daniel@0
|
10889 return {
|
Daniel@0
|
10890 bounds: function(_) {
|
Daniel@0
|
10891 if (!arguments.length) return b;
|
Daniel@0
|
10892 return (b = _, this);
|
Daniel@0
|
10893 },
|
Daniel@0
|
10894 beginPath: noop,
|
Daniel@0
|
10895 closePath: noop,
|
Daniel@0
|
10896 moveTo: add,
|
Daniel@0
|
10897 lineTo: add,
|
Daniel@0
|
10898 quadraticCurveTo: function(x1, y1, x2, y2) {
|
Daniel@0
|
10899 b.add(x1, y1);
|
Daniel@0
|
10900 b.add(x2, y2);
|
Daniel@0
|
10901 },
|
Daniel@0
|
10902 bezierCurveTo: function(x1, y1, x2, y2, x3, y3) {
|
Daniel@0
|
10903 b.add(x1, y1);
|
Daniel@0
|
10904 b.add(x2, y2);
|
Daniel@0
|
10905 b.add(x3, y3);
|
Daniel@0
|
10906 }
|
Daniel@0
|
10907 };
|
Daniel@0
|
10908 };
|
Daniel@0
|
10909
|
Daniel@0
|
10910 },{}],76:[function(require,module,exports){
|
Daniel@0
|
10911 var gradient_id = 0;
|
Daniel@0
|
10912
|
Daniel@0
|
10913 function Gradient(type) {
|
Daniel@0
|
10914 this.id = 'gradient_' + (gradient_id++);
|
Daniel@0
|
10915 this.type = type || 'linear';
|
Daniel@0
|
10916 this.stops = [];
|
Daniel@0
|
10917 this.x1 = 0;
|
Daniel@0
|
10918 this.x2 = 1;
|
Daniel@0
|
10919 this.y1 = 0;
|
Daniel@0
|
10920 this.y2 = 0;
|
Daniel@0
|
10921 }
|
Daniel@0
|
10922
|
Daniel@0
|
10923 var prototype = Gradient.prototype;
|
Daniel@0
|
10924
|
Daniel@0
|
10925 prototype.stop = function(offset, color) {
|
Daniel@0
|
10926 this.stops.push({
|
Daniel@0
|
10927 offset: offset,
|
Daniel@0
|
10928 color: color
|
Daniel@0
|
10929 });
|
Daniel@0
|
10930 return this;
|
Daniel@0
|
10931 };
|
Daniel@0
|
10932
|
Daniel@0
|
10933 module.exports = Gradient;
|
Daniel@0
|
10934 },{}],77:[function(require,module,exports){
|
Daniel@0
|
10935 (function (global){
|
Daniel@0
|
10936 var load = require('datalib/src/import/load');
|
Daniel@0
|
10937
|
Daniel@0
|
10938 function ImageLoader(loadConfig) {
|
Daniel@0
|
10939 this._pending = 0;
|
Daniel@0
|
10940 this._config = loadConfig || ImageLoader.Config;
|
Daniel@0
|
10941 }
|
Daniel@0
|
10942
|
Daniel@0
|
10943 // Overridable global default load configuration
|
Daniel@0
|
10944 ImageLoader.Config = null;
|
Daniel@0
|
10945
|
Daniel@0
|
10946 var prototype = ImageLoader.prototype;
|
Daniel@0
|
10947
|
Daniel@0
|
10948 prototype.pending = function() {
|
Daniel@0
|
10949 return this._pending;
|
Daniel@0
|
10950 };
|
Daniel@0
|
10951
|
Daniel@0
|
10952 prototype.params = function(uri) {
|
Daniel@0
|
10953 var p = {url: uri}, k;
|
Daniel@0
|
10954 for (k in this._config) { p[k] = this._config[k]; }
|
Daniel@0
|
10955 return p;
|
Daniel@0
|
10956 };
|
Daniel@0
|
10957
|
Daniel@0
|
10958 prototype.imageURL = function(uri) {
|
Daniel@0
|
10959 return load.sanitizeUrl(this.params(uri));
|
Daniel@0
|
10960 };
|
Daniel@0
|
10961
|
Daniel@0
|
10962 function browser(uri, callback) {
|
Daniel@0
|
10963 var url = load.sanitizeUrl(this.params(uri));
|
Daniel@0
|
10964 if (!url) { // error
|
Daniel@0
|
10965 if (callback) callback(uri, null);
|
Daniel@0
|
10966 return null;
|
Daniel@0
|
10967 }
|
Daniel@0
|
10968
|
Daniel@0
|
10969 var loader = this,
|
Daniel@0
|
10970 image = new Image();
|
Daniel@0
|
10971
|
Daniel@0
|
10972 loader._pending += 1;
|
Daniel@0
|
10973
|
Daniel@0
|
10974 image.onload = function() {
|
Daniel@0
|
10975 loader._pending -= 1;
|
Daniel@0
|
10976 image.loaded = true;
|
Daniel@0
|
10977 if (callback) callback(null, image);
|
Daniel@0
|
10978 };
|
Daniel@0
|
10979 image.src = url;
|
Daniel@0
|
10980
|
Daniel@0
|
10981 return image;
|
Daniel@0
|
10982 }
|
Daniel@0
|
10983
|
Daniel@0
|
10984 function server(uri, callback) {
|
Daniel@0
|
10985 var loader = this,
|
Daniel@0
|
10986 image = new ((typeof window !== "undefined" ? window['canvas'] : typeof global !== "undefined" ? global['canvas'] : null).Image)();
|
Daniel@0
|
10987
|
Daniel@0
|
10988 loader._pending += 1;
|
Daniel@0
|
10989
|
Daniel@0
|
10990 load(this.params(uri), function(err, data) {
|
Daniel@0
|
10991 loader._pending -= 1;
|
Daniel@0
|
10992 if (err) {
|
Daniel@0
|
10993 if (callback) callback(err, null);
|
Daniel@0
|
10994 return null;
|
Daniel@0
|
10995 }
|
Daniel@0
|
10996 image.src = data;
|
Daniel@0
|
10997 image.loaded = true;
|
Daniel@0
|
10998 if (callback) callback(null, image);
|
Daniel@0
|
10999 });
|
Daniel@0
|
11000
|
Daniel@0
|
11001 return image;
|
Daniel@0
|
11002 }
|
Daniel@0
|
11003
|
Daniel@0
|
11004 prototype.loadImage = function(uri, callback) {
|
Daniel@0
|
11005 return load.useXHR ?
|
Daniel@0
|
11006 browser.call(this, uri, callback) :
|
Daniel@0
|
11007 server.call(this, uri, callback);
|
Daniel@0
|
11008 };
|
Daniel@0
|
11009
|
Daniel@0
|
11010 module.exports = ImageLoader;
|
Daniel@0
|
11011
|
Daniel@0
|
11012 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
11013
|
Daniel@0
|
11014 },{"datalib/src/import/load":20}],78:[function(require,module,exports){
|
Daniel@0
|
11015 function Item(mark) {
|
Daniel@0
|
11016 this.mark = mark;
|
Daniel@0
|
11017 }
|
Daniel@0
|
11018
|
Daniel@0
|
11019 var prototype = Item.prototype;
|
Daniel@0
|
11020
|
Daniel@0
|
11021 prototype.hasPropertySet = function(name) {
|
Daniel@0
|
11022 var props = this.mark.def.properties;
|
Daniel@0
|
11023 return props && props[name] != null;
|
Daniel@0
|
11024 };
|
Daniel@0
|
11025
|
Daniel@0
|
11026 prototype.cousin = function(offset, index) {
|
Daniel@0
|
11027 if (offset === 0) return this;
|
Daniel@0
|
11028 offset = offset || -1;
|
Daniel@0
|
11029 var mark = this.mark,
|
Daniel@0
|
11030 group = mark.group,
|
Daniel@0
|
11031 iidx = index==null ? mark.items.indexOf(this) : index,
|
Daniel@0
|
11032 midx = group.items.indexOf(mark) + offset;
|
Daniel@0
|
11033 return group.items[midx].items[iidx];
|
Daniel@0
|
11034 };
|
Daniel@0
|
11035
|
Daniel@0
|
11036 prototype.sibling = function(offset) {
|
Daniel@0
|
11037 if (offset === 0) return this;
|
Daniel@0
|
11038 offset = offset || -1;
|
Daniel@0
|
11039 var mark = this.mark,
|
Daniel@0
|
11040 iidx = mark.items.indexOf(this) + offset;
|
Daniel@0
|
11041 return mark.items[iidx];
|
Daniel@0
|
11042 };
|
Daniel@0
|
11043
|
Daniel@0
|
11044 prototype.remove = function() {
|
Daniel@0
|
11045 var item = this,
|
Daniel@0
|
11046 list = item.mark.items,
|
Daniel@0
|
11047 i = list.indexOf(item);
|
Daniel@0
|
11048 if (i >= 0) {
|
Daniel@0
|
11049 if (i===list.length-1) {
|
Daniel@0
|
11050 list.pop();
|
Daniel@0
|
11051 } else {
|
Daniel@0
|
11052 list.splice(i, 1);
|
Daniel@0
|
11053 }
|
Daniel@0
|
11054 }
|
Daniel@0
|
11055 return item;
|
Daniel@0
|
11056 };
|
Daniel@0
|
11057
|
Daniel@0
|
11058 prototype.touch = function() {
|
Daniel@0
|
11059 if (this.pathCache) this.pathCache = null;
|
Daniel@0
|
11060 };
|
Daniel@0
|
11061
|
Daniel@0
|
11062 module.exports = Item;
|
Daniel@0
|
11063 },{}],79:[function(require,module,exports){
|
Daniel@0
|
11064 var BoundsContext = require('./BoundsContext'),
|
Daniel@0
|
11065 Bounds = require('./Bounds'),
|
Daniel@0
|
11066 canvas = require('./canvas'),
|
Daniel@0
|
11067 svg = require('./svg'),
|
Daniel@0
|
11068 text = require('./text'),
|
Daniel@0
|
11069 paths = require('../path'),
|
Daniel@0
|
11070 parse = paths.parse,
|
Daniel@0
|
11071 drawPath = paths.render,
|
Daniel@0
|
11072 areaPath = svg.path.area,
|
Daniel@0
|
11073 linePath = svg.path.line,
|
Daniel@0
|
11074 halfpi = Math.PI / 2,
|
Daniel@0
|
11075 sqrt3 = Math.sqrt(3),
|
Daniel@0
|
11076 tan30 = Math.tan(30 * Math.PI / 180),
|
Daniel@0
|
11077 g2D = null,
|
Daniel@0
|
11078 bc = BoundsContext();
|
Daniel@0
|
11079
|
Daniel@0
|
11080 function context() {
|
Daniel@0
|
11081 return g2D || (g2D = canvas.instance(1,1).getContext('2d'));
|
Daniel@0
|
11082 }
|
Daniel@0
|
11083
|
Daniel@0
|
11084 function strokeBounds(o, bounds) {
|
Daniel@0
|
11085 if (o.stroke && o.opacity !== 0 && o.stokeOpacity !== 0) {
|
Daniel@0
|
11086 bounds.expand(o.strokeWidth != null ? o.strokeWidth : 1);
|
Daniel@0
|
11087 }
|
Daniel@0
|
11088 return bounds;
|
Daniel@0
|
11089 }
|
Daniel@0
|
11090
|
Daniel@0
|
11091 function pathBounds(o, path, bounds, x, y) {
|
Daniel@0
|
11092 if (path == null) {
|
Daniel@0
|
11093 bounds.set(0, 0, 0, 0);
|
Daniel@0
|
11094 } else {
|
Daniel@0
|
11095 drawPath(bc.bounds(bounds), path, x, y);
|
Daniel@0
|
11096 strokeBounds(o, bounds);
|
Daniel@0
|
11097 }
|
Daniel@0
|
11098 return bounds;
|
Daniel@0
|
11099 }
|
Daniel@0
|
11100
|
Daniel@0
|
11101 function path(o, bounds) {
|
Daniel@0
|
11102 var p = o.path ? o.pathCache || (o.pathCache = parse(o.path)) : null;
|
Daniel@0
|
11103 return pathBounds(o, p, bounds, o.x, o.y);
|
Daniel@0
|
11104 }
|
Daniel@0
|
11105
|
Daniel@0
|
11106 function area(mark, bounds) {
|
Daniel@0
|
11107 if (mark.items.length === 0) return bounds;
|
Daniel@0
|
11108 var items = mark.items,
|
Daniel@0
|
11109 item = items[0],
|
Daniel@0
|
11110 p = item.pathCache || (item.pathCache = parse(areaPath(items)));
|
Daniel@0
|
11111 return pathBounds(item, p, bounds);
|
Daniel@0
|
11112 }
|
Daniel@0
|
11113
|
Daniel@0
|
11114 function line(mark, bounds) {
|
Daniel@0
|
11115 if (mark.items.length === 0) return bounds;
|
Daniel@0
|
11116 var items = mark.items,
|
Daniel@0
|
11117 item = items[0],
|
Daniel@0
|
11118 p = item.pathCache || (item.pathCache = parse(linePath(items)));
|
Daniel@0
|
11119 return pathBounds(item, p, bounds);
|
Daniel@0
|
11120 }
|
Daniel@0
|
11121
|
Daniel@0
|
11122 function rect(o, bounds) {
|
Daniel@0
|
11123 var x, y;
|
Daniel@0
|
11124 return strokeBounds(o, bounds.set(
|
Daniel@0
|
11125 x = o.x || 0,
|
Daniel@0
|
11126 y = o.y || 0,
|
Daniel@0
|
11127 (x + o.width) || 0,
|
Daniel@0
|
11128 (y + o.height) || 0
|
Daniel@0
|
11129 ));
|
Daniel@0
|
11130 }
|
Daniel@0
|
11131
|
Daniel@0
|
11132 function image(o, bounds) {
|
Daniel@0
|
11133 var x = o.x || 0,
|
Daniel@0
|
11134 y = o.y || 0,
|
Daniel@0
|
11135 w = o.width || 0,
|
Daniel@0
|
11136 h = o.height || 0;
|
Daniel@0
|
11137 x = x - (o.align === 'center' ? w/2 : (o.align === 'right' ? w : 0));
|
Daniel@0
|
11138 y = y - (o.baseline === 'middle' ? h/2 : (o.baseline === 'bottom' ? h : 0));
|
Daniel@0
|
11139 return bounds.set(x, y, x+w, y+h);
|
Daniel@0
|
11140 }
|
Daniel@0
|
11141
|
Daniel@0
|
11142 function rule(o, bounds) {
|
Daniel@0
|
11143 var x1, y1;
|
Daniel@0
|
11144 return strokeBounds(o, bounds.set(
|
Daniel@0
|
11145 x1 = o.x || 0,
|
Daniel@0
|
11146 y1 = o.y || 0,
|
Daniel@0
|
11147 o.x2 != null ? o.x2 : x1,
|
Daniel@0
|
11148 o.y2 != null ? o.y2 : y1
|
Daniel@0
|
11149 ));
|
Daniel@0
|
11150 }
|
Daniel@0
|
11151
|
Daniel@0
|
11152 function arc(o, bounds) {
|
Daniel@0
|
11153 var cx = o.x || 0,
|
Daniel@0
|
11154 cy = o.y || 0,
|
Daniel@0
|
11155 ir = o.innerRadius || 0,
|
Daniel@0
|
11156 or = o.outerRadius || 0,
|
Daniel@0
|
11157 sa = (o.startAngle || 0) - halfpi,
|
Daniel@0
|
11158 ea = (o.endAngle || 0) - halfpi,
|
Daniel@0
|
11159 xmin = Infinity, xmax = -Infinity,
|
Daniel@0
|
11160 ymin = Infinity, ymax = -Infinity,
|
Daniel@0
|
11161 a, i, n, x, y, ix, iy, ox, oy;
|
Daniel@0
|
11162
|
Daniel@0
|
11163 var angles = [sa, ea],
|
Daniel@0
|
11164 s = sa - (sa % halfpi);
|
Daniel@0
|
11165 for (i=0; i<4 && s<ea; ++i, s+=halfpi) {
|
Daniel@0
|
11166 angles.push(s);
|
Daniel@0
|
11167 }
|
Daniel@0
|
11168
|
Daniel@0
|
11169 for (i=0, n=angles.length; i<n; ++i) {
|
Daniel@0
|
11170 a = angles[i];
|
Daniel@0
|
11171 x = Math.cos(a); ix = ir*x; ox = or*x;
|
Daniel@0
|
11172 y = Math.sin(a); iy = ir*y; oy = or*y;
|
Daniel@0
|
11173 xmin = Math.min(xmin, ix, ox);
|
Daniel@0
|
11174 xmax = Math.max(xmax, ix, ox);
|
Daniel@0
|
11175 ymin = Math.min(ymin, iy, oy);
|
Daniel@0
|
11176 ymax = Math.max(ymax, iy, oy);
|
Daniel@0
|
11177 }
|
Daniel@0
|
11178
|
Daniel@0
|
11179 return strokeBounds(o, bounds.set(
|
Daniel@0
|
11180 cx + xmin,
|
Daniel@0
|
11181 cy + ymin,
|
Daniel@0
|
11182 cx + xmax,
|
Daniel@0
|
11183 cy + ymax
|
Daniel@0
|
11184 ));
|
Daniel@0
|
11185 }
|
Daniel@0
|
11186
|
Daniel@0
|
11187 function symbol(o, bounds) {
|
Daniel@0
|
11188 var size = o.size != null ? o.size : 100,
|
Daniel@0
|
11189 x = o.x || 0,
|
Daniel@0
|
11190 y = o.y || 0,
|
Daniel@0
|
11191 r, t, rx, ry;
|
Daniel@0
|
11192
|
Daniel@0
|
11193 switch (o.shape) {
|
Daniel@0
|
11194 case 'cross':
|
Daniel@0
|
11195 t = 3 * Math.sqrt(size / 5) / 2;
|
Daniel@0
|
11196 bounds.set(x-t, y-t, x+t, y+t);
|
Daniel@0
|
11197 break;
|
Daniel@0
|
11198
|
Daniel@0
|
11199 case 'diamond':
|
Daniel@0
|
11200 ry = Math.sqrt(size / (2 * tan30));
|
Daniel@0
|
11201 rx = ry * tan30;
|
Daniel@0
|
11202 bounds.set(x-rx, y-ry, x+rx, y+ry);
|
Daniel@0
|
11203 break;
|
Daniel@0
|
11204
|
Daniel@0
|
11205 case 'square':
|
Daniel@0
|
11206 t = Math.sqrt(size);
|
Daniel@0
|
11207 r = t / 2;
|
Daniel@0
|
11208 bounds.set(x-r, y-r, x+r, y+r);
|
Daniel@0
|
11209 break;
|
Daniel@0
|
11210
|
Daniel@0
|
11211 case 'triangle-down':
|
Daniel@0
|
11212 rx = Math.sqrt(size / sqrt3);
|
Daniel@0
|
11213 ry = rx * sqrt3 / 2;
|
Daniel@0
|
11214 bounds.set(x-rx, y-ry, x+rx, y+ry);
|
Daniel@0
|
11215 break;
|
Daniel@0
|
11216
|
Daniel@0
|
11217 case 'triangle-up':
|
Daniel@0
|
11218 rx = Math.sqrt(size / sqrt3);
|
Daniel@0
|
11219 ry = rx * sqrt3 / 2;
|
Daniel@0
|
11220 bounds.set(x-rx, y-ry, x+rx, y+ry);
|
Daniel@0
|
11221 break;
|
Daniel@0
|
11222
|
Daniel@0
|
11223 default:
|
Daniel@0
|
11224 r = Math.sqrt(size/Math.PI);
|
Daniel@0
|
11225 bounds.set(x-r, y-r, x+r, y+r);
|
Daniel@0
|
11226 }
|
Daniel@0
|
11227
|
Daniel@0
|
11228 return strokeBounds(o, bounds);
|
Daniel@0
|
11229 }
|
Daniel@0
|
11230
|
Daniel@0
|
11231 function textMark(o, bounds, noRotate) {
|
Daniel@0
|
11232 var g = context(),
|
Daniel@0
|
11233 h = text.size(o),
|
Daniel@0
|
11234 a = o.align,
|
Daniel@0
|
11235 r = o.radius || 0,
|
Daniel@0
|
11236 x = (o.x || 0),
|
Daniel@0
|
11237 y = (o.y || 0),
|
Daniel@0
|
11238 dx = (o.dx || 0),
|
Daniel@0
|
11239 dy = (o.dy || 0) + text.offset(o) - Math.round(0.8*h), // use 4/5 offset
|
Daniel@0
|
11240 w, t;
|
Daniel@0
|
11241
|
Daniel@0
|
11242 if (r) {
|
Daniel@0
|
11243 t = (o.theta || 0) - Math.PI/2;
|
Daniel@0
|
11244 x += r * Math.cos(t);
|
Daniel@0
|
11245 y += r * Math.sin(t);
|
Daniel@0
|
11246 }
|
Daniel@0
|
11247
|
Daniel@0
|
11248 // horizontal alignment
|
Daniel@0
|
11249 g.font = text.font(o);
|
Daniel@0
|
11250 w = g.measureText(text.value(o.text)).width;
|
Daniel@0
|
11251 if (a === 'center') {
|
Daniel@0
|
11252 dx -= (w / 2);
|
Daniel@0
|
11253 } else if (a === 'right') {
|
Daniel@0
|
11254 dx -= w;
|
Daniel@0
|
11255 } else {
|
Daniel@0
|
11256 // left by default, do nothing
|
Daniel@0
|
11257 }
|
Daniel@0
|
11258
|
Daniel@0
|
11259 bounds.set(dx+=x, dy+=y, dx+w, dy+h);
|
Daniel@0
|
11260 if (o.angle && !noRotate) {
|
Daniel@0
|
11261 bounds.rotate(o.angle*Math.PI/180, x, y);
|
Daniel@0
|
11262 }
|
Daniel@0
|
11263 return bounds.expand(noRotate ? 0 : 1);
|
Daniel@0
|
11264 }
|
Daniel@0
|
11265
|
Daniel@0
|
11266 function group(g, bounds, includeLegends) {
|
Daniel@0
|
11267 var axes = g.axisItems || [],
|
Daniel@0
|
11268 items = g.items || [],
|
Daniel@0
|
11269 legends = g.legendItems || [],
|
Daniel@0
|
11270 j, m;
|
Daniel@0
|
11271
|
Daniel@0
|
11272 for (j=0, m=axes.length; j<m; ++j) {
|
Daniel@0
|
11273 bounds.union(axes[j].bounds);
|
Daniel@0
|
11274 }
|
Daniel@0
|
11275 for (j=0, m=items.length; j<m; ++j) {
|
Daniel@0
|
11276 bounds.union(items[j].bounds);
|
Daniel@0
|
11277 }
|
Daniel@0
|
11278 if (includeLegends) {
|
Daniel@0
|
11279 for (j=0, m=legends.length; j<m; ++j) {
|
Daniel@0
|
11280 bounds.union(legends[j].bounds);
|
Daniel@0
|
11281 }
|
Daniel@0
|
11282 }
|
Daniel@0
|
11283 if (g.width || g.height) {
|
Daniel@0
|
11284 strokeBounds(g, bounds
|
Daniel@0
|
11285 .add(0, 0)
|
Daniel@0
|
11286 .add(g.width || 0, g.height || 0));
|
Daniel@0
|
11287 }
|
Daniel@0
|
11288 return bounds.translate(g.x || 0, g.y || 0);
|
Daniel@0
|
11289 }
|
Daniel@0
|
11290
|
Daniel@0
|
11291 var methods = {
|
Daniel@0
|
11292 group: group,
|
Daniel@0
|
11293 symbol: symbol,
|
Daniel@0
|
11294 image: image,
|
Daniel@0
|
11295 rect: rect,
|
Daniel@0
|
11296 rule: rule,
|
Daniel@0
|
11297 arc: arc,
|
Daniel@0
|
11298 text: textMark,
|
Daniel@0
|
11299 path: path,
|
Daniel@0
|
11300 area: area,
|
Daniel@0
|
11301 line: line
|
Daniel@0
|
11302 };
|
Daniel@0
|
11303 methods.area.nest = true;
|
Daniel@0
|
11304 methods.line.nest = true;
|
Daniel@0
|
11305
|
Daniel@0
|
11306 function itemBounds(item, func, opt) {
|
Daniel@0
|
11307 var type = item.mark.marktype;
|
Daniel@0
|
11308 func = func || methods[type];
|
Daniel@0
|
11309 if (func.nest) item = item.mark;
|
Daniel@0
|
11310
|
Daniel@0
|
11311 var curr = item.bounds,
|
Daniel@0
|
11312 prev = item['bounds:prev'] || (item['bounds:prev'] = new Bounds());
|
Daniel@0
|
11313
|
Daniel@0
|
11314 if (curr) {
|
Daniel@0
|
11315 prev.clear().union(curr);
|
Daniel@0
|
11316 curr.clear();
|
Daniel@0
|
11317 } else {
|
Daniel@0
|
11318 item.bounds = new Bounds();
|
Daniel@0
|
11319 }
|
Daniel@0
|
11320 func(item, item.bounds, opt);
|
Daniel@0
|
11321 if (!curr) prev.clear().union(item.bounds);
|
Daniel@0
|
11322 return item.bounds;
|
Daniel@0
|
11323 }
|
Daniel@0
|
11324
|
Daniel@0
|
11325 var DUMMY_ITEM = {mark: null};
|
Daniel@0
|
11326
|
Daniel@0
|
11327 function markBounds(mark, bounds, opt) {
|
Daniel@0
|
11328 var type = mark.marktype,
|
Daniel@0
|
11329 func = methods[type],
|
Daniel@0
|
11330 items = mark.items,
|
Daniel@0
|
11331 hasi = items && items.length,
|
Daniel@0
|
11332 i, n, o, b;
|
Daniel@0
|
11333
|
Daniel@0
|
11334 if (func.nest) {
|
Daniel@0
|
11335 o = hasi ? items[0]
|
Daniel@0
|
11336 : (DUMMY_ITEM.mark = mark, DUMMY_ITEM); // no items, so fake it
|
Daniel@0
|
11337 b = itemBounds(o, func, opt);
|
Daniel@0
|
11338 bounds = bounds && bounds.union(b) || b;
|
Daniel@0
|
11339 return bounds;
|
Daniel@0
|
11340 }
|
Daniel@0
|
11341
|
Daniel@0
|
11342 bounds = bounds || mark.bounds && mark.bounds.clear() || new Bounds();
|
Daniel@0
|
11343 if (hasi) {
|
Daniel@0
|
11344 for (i=0, n=items.length; i<n; ++i) {
|
Daniel@0
|
11345 bounds.union(itemBounds(items[i], func, opt));
|
Daniel@0
|
11346 }
|
Daniel@0
|
11347 }
|
Daniel@0
|
11348 return (mark.bounds = bounds);
|
Daniel@0
|
11349 }
|
Daniel@0
|
11350
|
Daniel@0
|
11351 module.exports = {
|
Daniel@0
|
11352 mark: markBounds,
|
Daniel@0
|
11353 item: itemBounds,
|
Daniel@0
|
11354 text: textMark,
|
Daniel@0
|
11355 group: group
|
Daniel@0
|
11356 };
|
Daniel@0
|
11357
|
Daniel@0
|
11358 },{"../path":48,"./Bounds":74,"./BoundsContext":75,"./canvas":80,"./svg":83,"./text":84}],80:[function(require,module,exports){
|
Daniel@0
|
11359 (function (global){
|
Daniel@0
|
11360 function instance(w, h) {
|
Daniel@0
|
11361 w = w || 1;
|
Daniel@0
|
11362 h = h || 1;
|
Daniel@0
|
11363 var canvas;
|
Daniel@0
|
11364
|
Daniel@0
|
11365 if (typeof document !== 'undefined' && document.createElement) {
|
Daniel@0
|
11366 canvas = document.createElement('canvas');
|
Daniel@0
|
11367 canvas.width = w;
|
Daniel@0
|
11368 canvas.height = h;
|
Daniel@0
|
11369 } else {
|
Daniel@0
|
11370 var Canvas = (typeof window !== "undefined" ? window['canvas'] : typeof global !== "undefined" ? global['canvas'] : null);
|
Daniel@0
|
11371 if (!Canvas.prototype) return null;
|
Daniel@0
|
11372 canvas = new Canvas(w, h);
|
Daniel@0
|
11373 }
|
Daniel@0
|
11374 return lineDash(canvas);
|
Daniel@0
|
11375 }
|
Daniel@0
|
11376
|
Daniel@0
|
11377 function resize(canvas, w, h, p, retina) {
|
Daniel@0
|
11378 var g = this._ctx = canvas.getContext('2d'),
|
Daniel@0
|
11379 s = 1;
|
Daniel@0
|
11380
|
Daniel@0
|
11381 canvas.width = w + p.left + p.right;
|
Daniel@0
|
11382 canvas.height = h + p.top + p.bottom;
|
Daniel@0
|
11383
|
Daniel@0
|
11384 // if browser canvas, attempt to modify for retina display
|
Daniel@0
|
11385 if (retina && typeof HTMLElement !== 'undefined' &&
|
Daniel@0
|
11386 canvas instanceof HTMLElement)
|
Daniel@0
|
11387 {
|
Daniel@0
|
11388 g.pixelratio = (s = pixelRatio(canvas) || 1);
|
Daniel@0
|
11389 }
|
Daniel@0
|
11390
|
Daniel@0
|
11391 g.setTransform(s, 0, 0, s, s*p.left, s*p.top);
|
Daniel@0
|
11392 return canvas;
|
Daniel@0
|
11393 }
|
Daniel@0
|
11394
|
Daniel@0
|
11395 function pixelRatio(canvas) {
|
Daniel@0
|
11396 var g = canvas.getContext('2d');
|
Daniel@0
|
11397
|
Daniel@0
|
11398 // get canvas pixel data
|
Daniel@0
|
11399 var devicePixelRatio = window && window.devicePixelRatio || 1,
|
Daniel@0
|
11400 backingStoreRatio = (
|
Daniel@0
|
11401 g.webkitBackingStorePixelRatio ||
|
Daniel@0
|
11402 g.mozBackingStorePixelRatio ||
|
Daniel@0
|
11403 g.msBackingStorePixelRatio ||
|
Daniel@0
|
11404 g.oBackingStorePixelRatio ||
|
Daniel@0
|
11405 g.backingStorePixelRatio) || 1,
|
Daniel@0
|
11406 ratio = devicePixelRatio / backingStoreRatio;
|
Daniel@0
|
11407
|
Daniel@0
|
11408 if (devicePixelRatio !== backingStoreRatio) {
|
Daniel@0
|
11409 // set actual and visible canvas size
|
Daniel@0
|
11410 var w = canvas.width,
|
Daniel@0
|
11411 h = canvas.height;
|
Daniel@0
|
11412 canvas.width = w * ratio;
|
Daniel@0
|
11413 canvas.height = h * ratio;
|
Daniel@0
|
11414 canvas.style.width = w + 'px';
|
Daniel@0
|
11415 canvas.style.height = h + 'px';
|
Daniel@0
|
11416 }
|
Daniel@0
|
11417
|
Daniel@0
|
11418 return ratio;
|
Daniel@0
|
11419 }
|
Daniel@0
|
11420
|
Daniel@0
|
11421 function lineDash(canvas) {
|
Daniel@0
|
11422 var g = canvas.getContext('2d');
|
Daniel@0
|
11423 if (g.vgLineDash) return; // already initialized!
|
Daniel@0
|
11424
|
Daniel@0
|
11425 var NOOP = function() {},
|
Daniel@0
|
11426 NODASH = [];
|
Daniel@0
|
11427
|
Daniel@0
|
11428 if (g.setLineDash) {
|
Daniel@0
|
11429 g.vgLineDash = function(dash) { this.setLineDash(dash || NODASH); };
|
Daniel@0
|
11430 g.vgLineDashOffset = function(off) { this.lineDashOffset = off; };
|
Daniel@0
|
11431 } else if (g.webkitLineDash !== undefined) {
|
Daniel@0
|
11432 g.vgLineDash = function(dash) { this.webkitLineDash = dash || NODASH; };
|
Daniel@0
|
11433 g.vgLineDashOffset = function(off) { this.webkitLineDashOffset = off; };
|
Daniel@0
|
11434 } else if (g.mozDash !== undefined) {
|
Daniel@0
|
11435 g.vgLineDash = function(dash) { this.mozDash = dash; };
|
Daniel@0
|
11436 g.vgLineDashOffset = NOOP;
|
Daniel@0
|
11437 } else {
|
Daniel@0
|
11438 g.vgLineDash = NOOP;
|
Daniel@0
|
11439 g.vgLineDashOffset = NOOP;
|
Daniel@0
|
11440 }
|
Daniel@0
|
11441 return canvas;
|
Daniel@0
|
11442 }
|
Daniel@0
|
11443
|
Daniel@0
|
11444 module.exports = {
|
Daniel@0
|
11445 instance: instance,
|
Daniel@0
|
11446 resize: resize,
|
Daniel@0
|
11447 lineDash: lineDash
|
Daniel@0
|
11448 };
|
Daniel@0
|
11449
|
Daniel@0
|
11450 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
11451
|
Daniel@0
|
11452 },{}],81:[function(require,module,exports){
|
Daniel@0
|
11453 // create a new DOM element
|
Daniel@0
|
11454 function create(doc, tag, ns) {
|
Daniel@0
|
11455 return ns ? doc.createElementNS(ns, tag) : doc.createElement(tag);
|
Daniel@0
|
11456 }
|
Daniel@0
|
11457
|
Daniel@0
|
11458 // remove element from DOM
|
Daniel@0
|
11459 // recursively remove parent elements if empty
|
Daniel@0
|
11460 function remove(el) {
|
Daniel@0
|
11461 if (!el) return;
|
Daniel@0
|
11462 var p = el.parentNode;
|
Daniel@0
|
11463 if (p) {
|
Daniel@0
|
11464 p.removeChild(el);
|
Daniel@0
|
11465 if (!p.childNodes || !p.childNodes.length) remove(p);
|
Daniel@0
|
11466 }
|
Daniel@0
|
11467 }
|
Daniel@0
|
11468
|
Daniel@0
|
11469 module.exports = {
|
Daniel@0
|
11470 // find first child element with matching tag
|
Daniel@0
|
11471 find: function(el, tag) {
|
Daniel@0
|
11472 tag = tag.toLowerCase();
|
Daniel@0
|
11473 for (var i=0, n=el.childNodes.length; i<n; ++i) {
|
Daniel@0
|
11474 if (el.childNodes[i].tagName.toLowerCase() === tag) {
|
Daniel@0
|
11475 return el.childNodes[i];
|
Daniel@0
|
11476 }
|
Daniel@0
|
11477 }
|
Daniel@0
|
11478 },
|
Daniel@0
|
11479 // retrieve child element at given index
|
Daniel@0
|
11480 // create & insert if doesn't exist or if tag/className do not match
|
Daniel@0
|
11481 child: function(el, index, tag, ns, className, insert) {
|
Daniel@0
|
11482 var a, b;
|
Daniel@0
|
11483 a = b = el.childNodes[index];
|
Daniel@0
|
11484 if (!a || insert ||
|
Daniel@0
|
11485 a.tagName.toLowerCase() !== tag.toLowerCase() ||
|
Daniel@0
|
11486 className && a.getAttribute('class') != className) {
|
Daniel@0
|
11487 a = create(el.ownerDocument, tag, ns);
|
Daniel@0
|
11488 el.insertBefore(a, b);
|
Daniel@0
|
11489 if (className) a.setAttribute('class', className);
|
Daniel@0
|
11490 }
|
Daniel@0
|
11491 return a;
|
Daniel@0
|
11492 },
|
Daniel@0
|
11493 // remove all child elements at or above the given index
|
Daniel@0
|
11494 clear: function(el, index) {
|
Daniel@0
|
11495 var curr = el.childNodes.length;
|
Daniel@0
|
11496 while (curr > index) {
|
Daniel@0
|
11497 el.removeChild(el.childNodes[--curr]);
|
Daniel@0
|
11498 }
|
Daniel@0
|
11499 return el;
|
Daniel@0
|
11500 },
|
Daniel@0
|
11501 remove: remove,
|
Daniel@0
|
11502 // generate css class name for mark
|
Daniel@0
|
11503 cssClass: function(mark) {
|
Daniel@0
|
11504 return 'mark-' + mark.marktype + (mark.name ? ' '+mark.name : '');
|
Daniel@0
|
11505 },
|
Daniel@0
|
11506 // generate string for an opening xml tag
|
Daniel@0
|
11507 // tag: the name of the xml tag
|
Daniel@0
|
11508 // attr: hash of attribute name-value pairs to include
|
Daniel@0
|
11509 // raw: additional raw string to include in tag markup
|
Daniel@0
|
11510 openTag: function(tag, attr, raw) {
|
Daniel@0
|
11511 var s = '<' + tag, key, val;
|
Daniel@0
|
11512 if (attr) {
|
Daniel@0
|
11513 for (key in attr) {
|
Daniel@0
|
11514 val = attr[key];
|
Daniel@0
|
11515 if (val != null) {
|
Daniel@0
|
11516 s += ' ' + key + '="' + val + '"';
|
Daniel@0
|
11517 }
|
Daniel@0
|
11518 }
|
Daniel@0
|
11519 }
|
Daniel@0
|
11520 if (raw) s += ' ' + raw;
|
Daniel@0
|
11521 return s + '>';
|
Daniel@0
|
11522 },
|
Daniel@0
|
11523 // generate string for closing xml tag
|
Daniel@0
|
11524 // tag: the name of the xml tag
|
Daniel@0
|
11525 closeTag: function(tag) {
|
Daniel@0
|
11526 return '</' + tag + '>';
|
Daniel@0
|
11527 }
|
Daniel@0
|
11528 };
|
Daniel@0
|
11529
|
Daniel@0
|
11530 },{}],82:[function(require,module,exports){
|
Daniel@0
|
11531 var bound = require('../util/bound');
|
Daniel@0
|
11532
|
Daniel@0
|
11533 var sets = [
|
Daniel@0
|
11534 'items',
|
Daniel@0
|
11535 'axisItems',
|
Daniel@0
|
11536 'legendItems'
|
Daniel@0
|
11537 ];
|
Daniel@0
|
11538
|
Daniel@0
|
11539 var keys = [
|
Daniel@0
|
11540 'marktype', 'name', 'interactive', 'clip',
|
Daniel@0
|
11541 'items', 'axisItems', 'legendItems', 'layer',
|
Daniel@0
|
11542 'x', 'y', 'width', 'height', 'align', 'baseline', // layout
|
Daniel@0
|
11543 'fill', 'fillOpacity', 'opacity', // fill
|
Daniel@0
|
11544 'stroke', 'strokeOpacity', 'strokeWidth', 'strokeCap', // stroke
|
Daniel@0
|
11545 'strokeDash', 'strokeDashOffset', // stroke dash
|
Daniel@0
|
11546 'startAngle', 'endAngle', 'innerRadius', 'outerRadius', // arc
|
Daniel@0
|
11547 'interpolate', 'tension', 'orient', // area, line
|
Daniel@0
|
11548 'url', // image
|
Daniel@0
|
11549 'path', // path
|
Daniel@0
|
11550 'x2', 'y2', // rule
|
Daniel@0
|
11551 'size', 'shape', // symbol
|
Daniel@0
|
11552 'text', 'angle', 'theta', 'radius', 'dx', 'dy', // text
|
Daniel@0
|
11553 'font', 'fontSize', 'fontWeight', 'fontStyle', 'fontVariant' // font
|
Daniel@0
|
11554 ];
|
Daniel@0
|
11555
|
Daniel@0
|
11556 function toJSON(scene, indent) {
|
Daniel@0
|
11557 return JSON.stringify(scene, keys, indent);
|
Daniel@0
|
11558 }
|
Daniel@0
|
11559
|
Daniel@0
|
11560 function fromJSON(json) {
|
Daniel@0
|
11561 var scene = (typeof json === 'string' ? JSON.parse(json) : json);
|
Daniel@0
|
11562 return initialize(scene);
|
Daniel@0
|
11563 }
|
Daniel@0
|
11564
|
Daniel@0
|
11565 function initialize(scene) {
|
Daniel@0
|
11566 var type = scene.marktype,
|
Daniel@0
|
11567 i, n, s, m, items;
|
Daniel@0
|
11568
|
Daniel@0
|
11569 for (s=0, m=sets.length; s<m; ++s) {
|
Daniel@0
|
11570 if ((items = scene[sets[s]])) {
|
Daniel@0
|
11571 for (i=0, n=items.length; i<n; ++i) {
|
Daniel@0
|
11572 items[i][type ? 'mark' : 'group'] = scene;
|
Daniel@0
|
11573 if (!type || type === 'group') {
|
Daniel@0
|
11574 initialize(items[i]);
|
Daniel@0
|
11575 }
|
Daniel@0
|
11576 }
|
Daniel@0
|
11577 }
|
Daniel@0
|
11578 }
|
Daniel@0
|
11579
|
Daniel@0
|
11580 if (type) bound.mark(scene);
|
Daniel@0
|
11581 return scene;
|
Daniel@0
|
11582 }
|
Daniel@0
|
11583
|
Daniel@0
|
11584 module.exports = {
|
Daniel@0
|
11585 toJSON: toJSON,
|
Daniel@0
|
11586 fromJSON: fromJSON
|
Daniel@0
|
11587 };
|
Daniel@0
|
11588 },{"../util/bound":79}],83:[function(require,module,exports){
|
Daniel@0
|
11589 (function (global){
|
Daniel@0
|
11590 var d3_svg = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null).svg;
|
Daniel@0
|
11591
|
Daniel@0
|
11592 function x(o) { return o.x || 0; }
|
Daniel@0
|
11593 function y(o) { return o.y || 0; }
|
Daniel@0
|
11594 function xw(o) { return (o.x || 0) + (o.width || 0); }
|
Daniel@0
|
11595 function yh(o) { return (o.y || 0) + (o.height || 0); }
|
Daniel@0
|
11596 function size(o) { return o.size == null ? 100 : o.size; }
|
Daniel@0
|
11597 function shape(o) { return o.shape || 'circle'; }
|
Daniel@0
|
11598
|
Daniel@0
|
11599 var areav = d3_svg.area().x(x).y1(y).y0(yh),
|
Daniel@0
|
11600 areah = d3_svg.area().y(y).x1(x).x0(xw),
|
Daniel@0
|
11601 line = d3_svg.line().x(x).y(y);
|
Daniel@0
|
11602
|
Daniel@0
|
11603 module.exports = {
|
Daniel@0
|
11604 metadata: {
|
Daniel@0
|
11605 'version': '1.1',
|
Daniel@0
|
11606 'xmlns': 'http://www.w3.org/2000/svg',
|
Daniel@0
|
11607 'xmlns:xlink': 'http://www.w3.org/1999/xlink'
|
Daniel@0
|
11608 },
|
Daniel@0
|
11609 path: {
|
Daniel@0
|
11610 arc: d3_svg.arc(),
|
Daniel@0
|
11611 symbol: d3_svg.symbol().type(shape).size(size),
|
Daniel@0
|
11612 area: function(items) {
|
Daniel@0
|
11613 var o = items[0];
|
Daniel@0
|
11614 return (o.orient === 'horizontal' ? areah : areav)
|
Daniel@0
|
11615 .interpolate(o.interpolate || 'linear')
|
Daniel@0
|
11616 .tension(o.tension || 0.7)
|
Daniel@0
|
11617 (items);
|
Daniel@0
|
11618 },
|
Daniel@0
|
11619 line: function(items) {
|
Daniel@0
|
11620 var o = items[0];
|
Daniel@0
|
11621 return line
|
Daniel@0
|
11622 .interpolate(o.interpolate || 'linear')
|
Daniel@0
|
11623 .tension(o.tension || 0.7)
|
Daniel@0
|
11624 (items);
|
Daniel@0
|
11625 }
|
Daniel@0
|
11626 },
|
Daniel@0
|
11627 textAlign: {
|
Daniel@0
|
11628 'left': 'start',
|
Daniel@0
|
11629 'center': 'middle',
|
Daniel@0
|
11630 'right': 'end'
|
Daniel@0
|
11631 },
|
Daniel@0
|
11632 textBaseline: {
|
Daniel@0
|
11633 'top': 'before-edge',
|
Daniel@0
|
11634 'bottom': 'after-edge',
|
Daniel@0
|
11635 'middle': 'central'
|
Daniel@0
|
11636 },
|
Daniel@0
|
11637 styles: {
|
Daniel@0
|
11638 'fill': 'fill',
|
Daniel@0
|
11639 'fillOpacity': 'fill-opacity',
|
Daniel@0
|
11640 'stroke': 'stroke',
|
Daniel@0
|
11641 'strokeWidth': 'stroke-width',
|
Daniel@0
|
11642 'strokeOpacity': 'stroke-opacity',
|
Daniel@0
|
11643 'strokeCap': 'stroke-linecap',
|
Daniel@0
|
11644 'strokeDash': 'stroke-dasharray',
|
Daniel@0
|
11645 'strokeDashOffset': 'stroke-dashoffset',
|
Daniel@0
|
11646 'opacity': 'opacity'
|
Daniel@0
|
11647 },
|
Daniel@0
|
11648 styleProperties: [
|
Daniel@0
|
11649 'fill',
|
Daniel@0
|
11650 'fillOpacity',
|
Daniel@0
|
11651 'stroke',
|
Daniel@0
|
11652 'strokeWidth',
|
Daniel@0
|
11653 'strokeOpacity',
|
Daniel@0
|
11654 'strokeCap',
|
Daniel@0
|
11655 'strokeDash',
|
Daniel@0
|
11656 'strokeDashOffset',
|
Daniel@0
|
11657 'opacity'
|
Daniel@0
|
11658 ]
|
Daniel@0
|
11659 };
|
Daniel@0
|
11660
|
Daniel@0
|
11661 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
11662
|
Daniel@0
|
11663 },{}],84:[function(require,module,exports){
|
Daniel@0
|
11664 function size(item) {
|
Daniel@0
|
11665 return item.fontSize != null ? item.fontSize : 11;
|
Daniel@0
|
11666 }
|
Daniel@0
|
11667
|
Daniel@0
|
11668 module.exports = {
|
Daniel@0
|
11669 size: size,
|
Daniel@0
|
11670 value: function(s) {
|
Daniel@0
|
11671 return s != null ? String(s) : '';
|
Daniel@0
|
11672 },
|
Daniel@0
|
11673 font: function(item, quote) {
|
Daniel@0
|
11674 var font = item.font;
|
Daniel@0
|
11675 if (quote && font) {
|
Daniel@0
|
11676 font = String(font).replace(/\"/g, '\'');
|
Daniel@0
|
11677 }
|
Daniel@0
|
11678 return '' +
|
Daniel@0
|
11679 (item.fontStyle ? item.fontStyle + ' ' : '') +
|
Daniel@0
|
11680 (item.fontVariant ? item.fontVariant + ' ' : '') +
|
Daniel@0
|
11681 (item.fontWeight ? item.fontWeight + ' ' : '') +
|
Daniel@0
|
11682 size(item) + 'px ' +
|
Daniel@0
|
11683 (font || 'sans-serif');
|
Daniel@0
|
11684 },
|
Daniel@0
|
11685 offset: function(item) {
|
Daniel@0
|
11686 // perform our own font baseline calculation
|
Daniel@0
|
11687 // why? not all browsers support SVG 1.1 'alignment-baseline' :(
|
Daniel@0
|
11688 var baseline = item.baseline,
|
Daniel@0
|
11689 h = size(item);
|
Daniel@0
|
11690 return Math.round(
|
Daniel@0
|
11691 baseline === 'top' ? 0.93*h :
|
Daniel@0
|
11692 baseline === 'middle' ? 0.30*h :
|
Daniel@0
|
11693 baseline === 'bottom' ? -0.21*h : 0
|
Daniel@0
|
11694 );
|
Daniel@0
|
11695 }
|
Daniel@0
|
11696 };
|
Daniel@0
|
11697
|
Daniel@0
|
11698 },{}],85:[function(require,module,exports){
|
Daniel@0
|
11699 var sg = require('vega-scenegraph').render,
|
Daniel@0
|
11700 canvas = sg.canvas,
|
Daniel@0
|
11701 svg = sg.svg.string,
|
Daniel@0
|
11702 View = require('./View');
|
Daniel@0
|
11703
|
Daniel@0
|
11704 function HeadlessView(width, height, model) {
|
Daniel@0
|
11705 View.call(null, width, height, model);
|
Daniel@0
|
11706 this._type = 'canvas';
|
Daniel@0
|
11707 this._renderers = {canvas: canvas, svg: svg};
|
Daniel@0
|
11708 }
|
Daniel@0
|
11709
|
Daniel@0
|
11710 var prototype = (HeadlessView.prototype = new View());
|
Daniel@0
|
11711
|
Daniel@0
|
11712 prototype.renderer = function(type) {
|
Daniel@0
|
11713 if(type) this._type = type;
|
Daniel@0
|
11714 return View.prototype.renderer.apply(this, arguments);
|
Daniel@0
|
11715 };
|
Daniel@0
|
11716
|
Daniel@0
|
11717 prototype.canvas = function() {
|
Daniel@0
|
11718 return (this._type === 'canvas') ? this._renderer.canvas() : null;
|
Daniel@0
|
11719 };
|
Daniel@0
|
11720
|
Daniel@0
|
11721 prototype.canvasAsync = function(callback) {
|
Daniel@0
|
11722 var r = this._renderer, view = this;
|
Daniel@0
|
11723
|
Daniel@0
|
11724 function wait() {
|
Daniel@0
|
11725 if (r.pendingImages() === 0) {
|
Daniel@0
|
11726 view.render(); // re-render with all images
|
Daniel@0
|
11727 callback(view.canvas());
|
Daniel@0
|
11728 } else {
|
Daniel@0
|
11729 setTimeout(wait, 10);
|
Daniel@0
|
11730 }
|
Daniel@0
|
11731 }
|
Daniel@0
|
11732
|
Daniel@0
|
11733 // if images loading, poll until ready
|
Daniel@0
|
11734 if (this._type !== 'canvas') return null;
|
Daniel@0
|
11735 if (r.pendingImages() > 0) { wait(); } else { callback(this.canvas()); }
|
Daniel@0
|
11736 };
|
Daniel@0
|
11737
|
Daniel@0
|
11738 prototype.svg = function() {
|
Daniel@0
|
11739 return (this._type === 'svg') ? this._renderer.svg() : null;
|
Daniel@0
|
11740 };
|
Daniel@0
|
11741
|
Daniel@0
|
11742 prototype.initialize = function() {
|
Daniel@0
|
11743 var w = this._width,
|
Daniel@0
|
11744 h = this._height,
|
Daniel@0
|
11745 bg = this._bgcolor,
|
Daniel@0
|
11746 pad = this._padding,
|
Daniel@0
|
11747 config = this.model().config();
|
Daniel@0
|
11748
|
Daniel@0
|
11749 if (this._viewport) {
|
Daniel@0
|
11750 w = this._viewport[0] - (pad ? pad.left + pad.right : 0);
|
Daniel@0
|
11751 h = this._viewport[1] - (pad ? pad.top + pad.bottom : 0);
|
Daniel@0
|
11752 }
|
Daniel@0
|
11753
|
Daniel@0
|
11754 this._renderer = (this._renderer || new this._io.Renderer(config.load))
|
Daniel@0
|
11755 .initialize(null, w, h, pad)
|
Daniel@0
|
11756 .background(bg);
|
Daniel@0
|
11757
|
Daniel@0
|
11758 return this;
|
Daniel@0
|
11759 };
|
Daniel@0
|
11760
|
Daniel@0
|
11761 module.exports = HeadlessView;
|
Daniel@0
|
11762 },{"./View":87,"vega-scenegraph":46}],86:[function(require,module,exports){
|
Daniel@0
|
11763 var dl = require('datalib'),
|
Daniel@0
|
11764 df = require('vega-dataflow'),
|
Daniel@0
|
11765 ChangeSet = df.ChangeSet,
|
Daniel@0
|
11766 Base = df.Graph.prototype,
|
Daniel@0
|
11767 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
11768 GroupBuilder = require('../scene/GroupBuilder'),
|
Daniel@0
|
11769 visit = require('../scene/visit'),
|
Daniel@0
|
11770 config = require('./config');
|
Daniel@0
|
11771
|
Daniel@0
|
11772 function Model(cfg) {
|
Daniel@0
|
11773 this._defs = {};
|
Daniel@0
|
11774 this._predicates = {};
|
Daniel@0
|
11775 this._scene = null;
|
Daniel@0
|
11776
|
Daniel@0
|
11777 this._node = null;
|
Daniel@0
|
11778 this._builder = null; // Top-level scenegraph builder
|
Daniel@0
|
11779
|
Daniel@0
|
11780 this._reset = {axes: false, legends: false};
|
Daniel@0
|
11781
|
Daniel@0
|
11782 this.config(cfg);
|
Daniel@0
|
11783 Base.init.call(this);
|
Daniel@0
|
11784 }
|
Daniel@0
|
11785
|
Daniel@0
|
11786 var prototype = (Model.prototype = Object.create(Base));
|
Daniel@0
|
11787 prototype.constructor = Model;
|
Daniel@0
|
11788
|
Daniel@0
|
11789 prototype.defs = function(defs) {
|
Daniel@0
|
11790 if (!arguments.length) return this._defs;
|
Daniel@0
|
11791 this._defs = defs;
|
Daniel@0
|
11792 return this;
|
Daniel@0
|
11793 };
|
Daniel@0
|
11794
|
Daniel@0
|
11795 prototype.config = function(cfg) {
|
Daniel@0
|
11796 if (!arguments.length) return this._config;
|
Daniel@0
|
11797 this._config = Object.create(config);
|
Daniel@0
|
11798 for (var name in cfg) {
|
Daniel@0
|
11799 var x = cfg[name], y = this._config[name];
|
Daniel@0
|
11800 if (dl.isObject(x) && dl.isObject(y)) {
|
Daniel@0
|
11801 dl.extend(y, x);
|
Daniel@0
|
11802 } else {
|
Daniel@0
|
11803 this._config[name] = x;
|
Daniel@0
|
11804 }
|
Daniel@0
|
11805 }
|
Daniel@0
|
11806
|
Daniel@0
|
11807 return this;
|
Daniel@0
|
11808 };
|
Daniel@0
|
11809
|
Daniel@0
|
11810 prototype.width = function(width) {
|
Daniel@0
|
11811 if (this._defs) this._defs.width = width;
|
Daniel@0
|
11812 if (this._defs && this._defs.marks) this._defs.marks.width = width;
|
Daniel@0
|
11813 if (this._scene) {
|
Daniel@0
|
11814 this._scene.items[0].width = width;
|
Daniel@0
|
11815 this._scene.items[0]._dirty = true;
|
Daniel@0
|
11816 }
|
Daniel@0
|
11817 this._reset.axes = true;
|
Daniel@0
|
11818 return this;
|
Daniel@0
|
11819 };
|
Daniel@0
|
11820
|
Daniel@0
|
11821 prototype.height = function(height) {
|
Daniel@0
|
11822 if (this._defs) this._defs.height = height;
|
Daniel@0
|
11823 if (this._defs && this._defs.marks) this._defs.marks.height = height;
|
Daniel@0
|
11824 if (this._scene) {
|
Daniel@0
|
11825 this._scene.items[0].height = height;
|
Daniel@0
|
11826 this._scene.items[0]._dirty = true;
|
Daniel@0
|
11827 }
|
Daniel@0
|
11828 this._reset.axes = true;
|
Daniel@0
|
11829 return this;
|
Daniel@0
|
11830 };
|
Daniel@0
|
11831
|
Daniel@0
|
11832 prototype.node = function() {
|
Daniel@0
|
11833 return this._node || (this._node = new Node(this));
|
Daniel@0
|
11834 };
|
Daniel@0
|
11835
|
Daniel@0
|
11836 prototype.data = function() {
|
Daniel@0
|
11837 var data = Base.data.apply(this, arguments);
|
Daniel@0
|
11838 if (arguments.length > 1) { // new Datasource
|
Daniel@0
|
11839 this.node().addListener(data.pipeline()[0]);
|
Daniel@0
|
11840 }
|
Daniel@0
|
11841 return data;
|
Daniel@0
|
11842 };
|
Daniel@0
|
11843
|
Daniel@0
|
11844 function predicates(name) {
|
Daniel@0
|
11845 var m = this, pred = {};
|
Daniel@0
|
11846 if (!dl.isArray(name)) return this._predicates[name];
|
Daniel@0
|
11847 name.forEach(function(n) { pred[n] = m._predicates[n]; });
|
Daniel@0
|
11848 return pred;
|
Daniel@0
|
11849 }
|
Daniel@0
|
11850
|
Daniel@0
|
11851 prototype.predicate = function(name, predicate) {
|
Daniel@0
|
11852 if (arguments.length === 1) return predicates.call(this, name);
|
Daniel@0
|
11853 return (this._predicates[name] = predicate);
|
Daniel@0
|
11854 };
|
Daniel@0
|
11855
|
Daniel@0
|
11856 prototype.predicates = function() { return this._predicates; };
|
Daniel@0
|
11857
|
Daniel@0
|
11858 prototype.scene = function(renderer) {
|
Daniel@0
|
11859 if (!arguments.length) return this._scene;
|
Daniel@0
|
11860 if (this._builder) this.node().removeListener(this._builder.disconnect());
|
Daniel@0
|
11861 this._builder = new GroupBuilder(this, this._defs.marks, this._scene={});
|
Daniel@0
|
11862 this.node().addListener(this._builder.connect());
|
Daniel@0
|
11863 var p = this._builder.pipeline();
|
Daniel@0
|
11864 p[p.length-1].addListener(renderer);
|
Daniel@0
|
11865 return this;
|
Daniel@0
|
11866 };
|
Daniel@0
|
11867
|
Daniel@0
|
11868 prototype.reset = function() {
|
Daniel@0
|
11869 if (this._scene && this._reset.axes) {
|
Daniel@0
|
11870 visit(this._scene, function(item) {
|
Daniel@0
|
11871 if (item.axes) item.axes.forEach(function(axis) { axis.reset(); });
|
Daniel@0
|
11872 });
|
Daniel@0
|
11873 this._reset.axes = false;
|
Daniel@0
|
11874 }
|
Daniel@0
|
11875 if (this._scene && this._reset.legends) {
|
Daniel@0
|
11876 visit(this._scene, function(item) {
|
Daniel@0
|
11877 if (item.legends) item.legends.forEach(function(l) { l.reset(); });
|
Daniel@0
|
11878 });
|
Daniel@0
|
11879 this._reset.legends = false;
|
Daniel@0
|
11880 }
|
Daniel@0
|
11881 return this;
|
Daniel@0
|
11882 };
|
Daniel@0
|
11883
|
Daniel@0
|
11884 prototype.addListener = function(l) {
|
Daniel@0
|
11885 this.node().addListener(l);
|
Daniel@0
|
11886 };
|
Daniel@0
|
11887
|
Daniel@0
|
11888 prototype.removeListener = function(l) {
|
Daniel@0
|
11889 this.node().removeListener(l);
|
Daniel@0
|
11890 };
|
Daniel@0
|
11891
|
Daniel@0
|
11892 prototype.fire = function(cs) {
|
Daniel@0
|
11893 if (!cs) cs = ChangeSet.create();
|
Daniel@0
|
11894 this.propagate(cs, this.node());
|
Daniel@0
|
11895 };
|
Daniel@0
|
11896
|
Daniel@0
|
11897 module.exports = Model;
|
Daniel@0
|
11898 },{"../scene/GroupBuilder":110,"../scene/visit":115,"./config":88,"datalib":24,"vega-dataflow":39}],87:[function(require,module,exports){
|
Daniel@0
|
11899 (function (global){
|
Daniel@0
|
11900 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
11901 dl = require('datalib'),
|
Daniel@0
|
11902 df = require('vega-dataflow'),
|
Daniel@0
|
11903 sg = require('vega-scenegraph').render,
|
Daniel@0
|
11904 log = require('vega-logging'),
|
Daniel@0
|
11905 Deps = df.Dependencies,
|
Daniel@0
|
11906 parseStreams = require('../parse/streams'),
|
Daniel@0
|
11907 Encoder = require('../scene/Encoder'),
|
Daniel@0
|
11908 Transition = require('../scene/Transition');
|
Daniel@0
|
11909
|
Daniel@0
|
11910 function View(el, width, height) {
|
Daniel@0
|
11911 this._el = null;
|
Daniel@0
|
11912 this._model = null;
|
Daniel@0
|
11913 this._width = this.__width = width || 500;
|
Daniel@0
|
11914 this._height = this.__height = height || 300;
|
Daniel@0
|
11915 this._bgcolor = null;
|
Daniel@0
|
11916 this._autopad = 1;
|
Daniel@0
|
11917 this._padding = {top:0, left:0, bottom:0, right:0};
|
Daniel@0
|
11918 this._viewport = null;
|
Daniel@0
|
11919 this._renderer = null;
|
Daniel@0
|
11920 this._handler = null;
|
Daniel@0
|
11921 this._streamer = null; // Targeted update for streaming changes
|
Daniel@0
|
11922 this._changeset = null;
|
Daniel@0
|
11923 this._repaint = true; // Full re-render on every re-init
|
Daniel@0
|
11924 this._renderers = sg;
|
Daniel@0
|
11925 this._io = null;
|
Daniel@0
|
11926 this._api = {}; // Stash streaming data API sandboxes.
|
Daniel@0
|
11927 }
|
Daniel@0
|
11928
|
Daniel@0
|
11929 var prototype = View.prototype;
|
Daniel@0
|
11930
|
Daniel@0
|
11931 prototype.model = function(model) {
|
Daniel@0
|
11932 if (!arguments.length) return this._model;
|
Daniel@0
|
11933 if (this._model !== model) {
|
Daniel@0
|
11934 this._model = model;
|
Daniel@0
|
11935 this._streamer = new df.Node(model);
|
Daniel@0
|
11936 this._streamer._rank = -1; // HACK: To reduce re-ranking churn.
|
Daniel@0
|
11937 this._changeset = df.ChangeSet.create();
|
Daniel@0
|
11938 if (this._handler) this._handler.model(model);
|
Daniel@0
|
11939 }
|
Daniel@0
|
11940 return this;
|
Daniel@0
|
11941 };
|
Daniel@0
|
11942
|
Daniel@0
|
11943 // Sandboxed streaming data API
|
Daniel@0
|
11944 function streaming(src) {
|
Daniel@0
|
11945 var view = this,
|
Daniel@0
|
11946 ds = this._model.data(src),
|
Daniel@0
|
11947 name = ds.name(),
|
Daniel@0
|
11948 listener = ds.pipeline()[0],
|
Daniel@0
|
11949 streamer = this._streamer,
|
Daniel@0
|
11950 api = {};
|
Daniel@0
|
11951
|
Daniel@0
|
11952 // If we have it stashed, don't create a new closure.
|
Daniel@0
|
11953 if (this._api[src]) return this._api[src];
|
Daniel@0
|
11954
|
Daniel@0
|
11955 api.insert = function(vals) {
|
Daniel@0
|
11956 ds.insert(dl.duplicate(vals)); // Don't pollute the environment
|
Daniel@0
|
11957 streamer.addListener(listener);
|
Daniel@0
|
11958 view._changeset.data[name] = 1;
|
Daniel@0
|
11959 return api;
|
Daniel@0
|
11960 };
|
Daniel@0
|
11961
|
Daniel@0
|
11962 api.update = function() {
|
Daniel@0
|
11963 streamer.addListener(listener);
|
Daniel@0
|
11964 view._changeset.data[name] = 1;
|
Daniel@0
|
11965 return (ds.update.apply(ds, arguments), api);
|
Daniel@0
|
11966 };
|
Daniel@0
|
11967
|
Daniel@0
|
11968 api.remove = function() {
|
Daniel@0
|
11969 streamer.addListener(listener);
|
Daniel@0
|
11970 view._changeset.data[name] = 1;
|
Daniel@0
|
11971 return (ds.remove.apply(ds, arguments), api);
|
Daniel@0
|
11972 };
|
Daniel@0
|
11973
|
Daniel@0
|
11974 api.values = function() { return ds.values(); };
|
Daniel@0
|
11975
|
Daniel@0
|
11976 return (this._api[src] = api);
|
Daniel@0
|
11977 }
|
Daniel@0
|
11978
|
Daniel@0
|
11979 prototype.data = function(data) {
|
Daniel@0
|
11980 var v = this;
|
Daniel@0
|
11981 if (!arguments.length) return v._model.values();
|
Daniel@0
|
11982 else if (dl.isString(data)) return streaming.call(v, data);
|
Daniel@0
|
11983 else if (dl.isObject(data)) {
|
Daniel@0
|
11984 dl.keys(data).forEach(function(k) {
|
Daniel@0
|
11985 var api = streaming.call(v, k);
|
Daniel@0
|
11986 data[k](api);
|
Daniel@0
|
11987 });
|
Daniel@0
|
11988 }
|
Daniel@0
|
11989 return this;
|
Daniel@0
|
11990 };
|
Daniel@0
|
11991
|
Daniel@0
|
11992 prototype.signal = function(name, value) {
|
Daniel@0
|
11993 var m = this._model,
|
Daniel@0
|
11994 cs = this._changeset,
|
Daniel@0
|
11995 streamer = this._streamer,
|
Daniel@0
|
11996 setter = name;
|
Daniel@0
|
11997
|
Daniel@0
|
11998 if (!arguments.length) {
|
Daniel@0
|
11999 return m.values(Deps.SIGNALS);
|
Daniel@0
|
12000 } else if (arguments.length == 1 && dl.isString(name)) {
|
Daniel@0
|
12001 return m.values(Deps.SIGNALS, name);
|
Daniel@0
|
12002 }
|
Daniel@0
|
12003
|
Daniel@0
|
12004 if (arguments.length == 2) {
|
Daniel@0
|
12005 setter = {};
|
Daniel@0
|
12006 setter[name] = value;
|
Daniel@0
|
12007 }
|
Daniel@0
|
12008
|
Daniel@0
|
12009 dl.keys(setter).forEach(function(k) {
|
Daniel@0
|
12010 streamer.addListener(m.signal(k).value(setter[k]));
|
Daniel@0
|
12011 cs.signals[k] = 1;
|
Daniel@0
|
12012 cs.reflow = true;
|
Daniel@0
|
12013 });
|
Daniel@0
|
12014
|
Daniel@0
|
12015 return this;
|
Daniel@0
|
12016 };
|
Daniel@0
|
12017
|
Daniel@0
|
12018 prototype.width = function(width) {
|
Daniel@0
|
12019 if (!arguments.length) return this.__width;
|
Daniel@0
|
12020 if (this.__width !== width) {
|
Daniel@0
|
12021 this._width = this.__width = width;
|
Daniel@0
|
12022 this.model().width(width);
|
Daniel@0
|
12023 this.initialize();
|
Daniel@0
|
12024 if (this._strict) this._autopad = 1;
|
Daniel@0
|
12025 }
|
Daniel@0
|
12026 return this;
|
Daniel@0
|
12027 };
|
Daniel@0
|
12028
|
Daniel@0
|
12029 prototype.height = function(height) {
|
Daniel@0
|
12030 if (!arguments.length) return this.__height;
|
Daniel@0
|
12031 if (this.__height !== height) {
|
Daniel@0
|
12032 this._height = this.__height = height;
|
Daniel@0
|
12033 this.model().height(height);
|
Daniel@0
|
12034 this.initialize();
|
Daniel@0
|
12035 if (this._strict) this._autopad = 1;
|
Daniel@0
|
12036 }
|
Daniel@0
|
12037 return this;
|
Daniel@0
|
12038 };
|
Daniel@0
|
12039
|
Daniel@0
|
12040 prototype.background = function(bgcolor) {
|
Daniel@0
|
12041 if (!arguments.length) return this._bgcolor;
|
Daniel@0
|
12042 if (this._bgcolor !== bgcolor) {
|
Daniel@0
|
12043 this._bgcolor = bgcolor;
|
Daniel@0
|
12044 this.initialize();
|
Daniel@0
|
12045 }
|
Daniel@0
|
12046 return this;
|
Daniel@0
|
12047 };
|
Daniel@0
|
12048
|
Daniel@0
|
12049 prototype.padding = function(pad) {
|
Daniel@0
|
12050 if (!arguments.length) return this._padding;
|
Daniel@0
|
12051 if (this._padding !== pad) {
|
Daniel@0
|
12052 if (dl.isString(pad)) {
|
Daniel@0
|
12053 this._autopad = 1;
|
Daniel@0
|
12054 this._padding = {top:0, left:0, bottom:0, right:0};
|
Daniel@0
|
12055 this._strict = (pad === 'strict');
|
Daniel@0
|
12056 } else {
|
Daniel@0
|
12057 this._autopad = 0;
|
Daniel@0
|
12058 this._padding = pad;
|
Daniel@0
|
12059 this._strict = false;
|
Daniel@0
|
12060 }
|
Daniel@0
|
12061 if (this._renderer) this._renderer.resize(this._width, this._height, pad);
|
Daniel@0
|
12062 if (this._handler) this._handler.padding(pad);
|
Daniel@0
|
12063 }
|
Daniel@0
|
12064 return (this._repaint = true, this);
|
Daniel@0
|
12065 };
|
Daniel@0
|
12066
|
Daniel@0
|
12067 prototype.autopad = function(opt) {
|
Daniel@0
|
12068 if (this._autopad < 1) return this;
|
Daniel@0
|
12069 else this._autopad = 0;
|
Daniel@0
|
12070
|
Daniel@0
|
12071 var b = this.model().scene().bounds,
|
Daniel@0
|
12072 pad = this._padding,
|
Daniel@0
|
12073 config = this.model().config(),
|
Daniel@0
|
12074 inset = config.autopadInset,
|
Daniel@0
|
12075 l = b.x1 < 0 ? Math.ceil(-b.x1) + inset : 0,
|
Daniel@0
|
12076 t = b.y1 < 0 ? Math.ceil(-b.y1) + inset : 0,
|
Daniel@0
|
12077 r = b.x2 > this._width ? Math.ceil(+b.x2 - this._width) + inset : 0;
|
Daniel@0
|
12078 b = b.y2 > this._height ? Math.ceil(+b.y2 - this._height) + inset : 0;
|
Daniel@0
|
12079 pad = {left:l, top:t, right:r, bottom:b};
|
Daniel@0
|
12080
|
Daniel@0
|
12081 if (this._strict) {
|
Daniel@0
|
12082 this._autopad = 0;
|
Daniel@0
|
12083 this._padding = pad;
|
Daniel@0
|
12084 this._width = Math.max(0, this.__width - (l+r));
|
Daniel@0
|
12085 this._height = Math.max(0, this.__height - (t+b));
|
Daniel@0
|
12086
|
Daniel@0
|
12087 this._model.width(this._width)
|
Daniel@0
|
12088 .height(this._height).reset();
|
Daniel@0
|
12089
|
Daniel@0
|
12090 this.initialize()
|
Daniel@0
|
12091 .update({props:'enter'}).update({props:'update'});
|
Daniel@0
|
12092 } else {
|
Daniel@0
|
12093 this.padding(pad).update(opt);
|
Daniel@0
|
12094 }
|
Daniel@0
|
12095 return this;
|
Daniel@0
|
12096 };
|
Daniel@0
|
12097
|
Daniel@0
|
12098 prototype.viewport = function(size) {
|
Daniel@0
|
12099 if (!arguments.length) return this._viewport;
|
Daniel@0
|
12100 if (this._viewport !== size) {
|
Daniel@0
|
12101 this._viewport = size;
|
Daniel@0
|
12102 this.initialize();
|
Daniel@0
|
12103 }
|
Daniel@0
|
12104 return this;
|
Daniel@0
|
12105 };
|
Daniel@0
|
12106
|
Daniel@0
|
12107 prototype.renderer = function(type) {
|
Daniel@0
|
12108 if (!arguments.length) return this._renderer;
|
Daniel@0
|
12109 if (this._renderers[type]) type = this._renderers[type];
|
Daniel@0
|
12110 else if (dl.isString(type)) throw new Error('Unknown renderer: ' + type);
|
Daniel@0
|
12111 else if (!type) throw new Error('No renderer specified');
|
Daniel@0
|
12112
|
Daniel@0
|
12113 if (this._io !== type) {
|
Daniel@0
|
12114 this._io = type;
|
Daniel@0
|
12115 this._renderer = null;
|
Daniel@0
|
12116 this.initialize();
|
Daniel@0
|
12117 if (this._build) this.render();
|
Daniel@0
|
12118 }
|
Daniel@0
|
12119 return this;
|
Daniel@0
|
12120 };
|
Daniel@0
|
12121
|
Daniel@0
|
12122 prototype.initialize = function(el) {
|
Daniel@0
|
12123 var v = this, prevHandler,
|
Daniel@0
|
12124 w = v._width, h = v._height, pad = v._padding, bg = v._bgcolor,
|
Daniel@0
|
12125 config = this.model().config();
|
Daniel@0
|
12126
|
Daniel@0
|
12127 if (!arguments.length || el === null) {
|
Daniel@0
|
12128 el = this._el ? this._el.parentNode : null;
|
Daniel@0
|
12129 if (!el) return this; // This View cannot init w/o an
|
Daniel@0
|
12130 }
|
Daniel@0
|
12131
|
Daniel@0
|
12132 // clear pre-existing container
|
Daniel@0
|
12133 d3.select(el).select('div.vega').remove();
|
Daniel@0
|
12134
|
Daniel@0
|
12135 // add div container
|
Daniel@0
|
12136 this._el = el = d3.select(el)
|
Daniel@0
|
12137 .append('div')
|
Daniel@0
|
12138 .attr('class', 'vega')
|
Daniel@0
|
12139 .style('position', 'relative')
|
Daniel@0
|
12140 .node();
|
Daniel@0
|
12141 if (v._viewport) {
|
Daniel@0
|
12142 d3.select(el)
|
Daniel@0
|
12143 .style('width', (v._viewport[0] || w)+'px')
|
Daniel@0
|
12144 .style('height', (v._viewport[1] || h)+'px')
|
Daniel@0
|
12145 .style('overflow', 'auto');
|
Daniel@0
|
12146 }
|
Daniel@0
|
12147
|
Daniel@0
|
12148 // renderer
|
Daniel@0
|
12149 sg.canvas.Renderer.RETINA = config.render.retina;
|
Daniel@0
|
12150 v._renderer = (v._renderer || new this._io.Renderer(config.load))
|
Daniel@0
|
12151 .initialize(el, w, h, pad)
|
Daniel@0
|
12152 .background(bg);
|
Daniel@0
|
12153
|
Daniel@0
|
12154 // input handler
|
Daniel@0
|
12155 prevHandler = v._handler;
|
Daniel@0
|
12156 v._handler = new this._io.Handler()
|
Daniel@0
|
12157 .initialize(el, pad, v);
|
Daniel@0
|
12158
|
Daniel@0
|
12159 if (prevHandler) {
|
Daniel@0
|
12160 prevHandler.handlers().forEach(function(h) {
|
Daniel@0
|
12161 v._handler.on(h.type, h.handler);
|
Daniel@0
|
12162 });
|
Daniel@0
|
12163 } else {
|
Daniel@0
|
12164 // Register event listeners for signal stream definitions.
|
Daniel@0
|
12165 v._detach = parseStreams(this);
|
Daniel@0
|
12166 }
|
Daniel@0
|
12167
|
Daniel@0
|
12168 return (this._repaint = true, this);
|
Daniel@0
|
12169 };
|
Daniel@0
|
12170
|
Daniel@0
|
12171 prototype.destroy = function() {
|
Daniel@0
|
12172 if (this._detach) this._detach();
|
Daniel@0
|
12173 };
|
Daniel@0
|
12174
|
Daniel@0
|
12175 function build() {
|
Daniel@0
|
12176 var v = this;
|
Daniel@0
|
12177 v._renderNode = new df.Node(v._model)
|
Daniel@0
|
12178 .router(true);
|
Daniel@0
|
12179
|
Daniel@0
|
12180 v._renderNode.evaluate = function(input) {
|
Daniel@0
|
12181 log.debug(input, ['rendering']);
|
Daniel@0
|
12182
|
Daniel@0
|
12183 var s = v._model.scene(),
|
Daniel@0
|
12184 h = v._handler;
|
Daniel@0
|
12185
|
Daniel@0
|
12186 if (h && h.scene) h.scene(s);
|
Daniel@0
|
12187
|
Daniel@0
|
12188 if (input.trans) {
|
Daniel@0
|
12189 input.trans.start(function(items) { v._renderer.render(s, items); });
|
Daniel@0
|
12190 } else if (v._repaint) {
|
Daniel@0
|
12191 v._renderer.render(s);
|
Daniel@0
|
12192 v._repaint = false;
|
Daniel@0
|
12193 } else if (input.dirty.length) {
|
Daniel@0
|
12194 v._renderer.render(s, input.dirty);
|
Daniel@0
|
12195 }
|
Daniel@0
|
12196
|
Daniel@0
|
12197 if (input.dirty.length) {
|
Daniel@0
|
12198 input.dirty.forEach(function(i) { i._dirty = false; });
|
Daniel@0
|
12199 s.items[0]._dirty = false;
|
Daniel@0
|
12200 }
|
Daniel@0
|
12201
|
Daniel@0
|
12202 // For all updated datasources, clear their previous values.
|
Daniel@0
|
12203 for (var d in input.data) { v._model.data(d).synchronize(); }
|
Daniel@0
|
12204 return input;
|
Daniel@0
|
12205 };
|
Daniel@0
|
12206
|
Daniel@0
|
12207 return (v._model.scene(v._renderNode), true);
|
Daniel@0
|
12208 }
|
Daniel@0
|
12209
|
Daniel@0
|
12210 prototype.update = function(opt) {
|
Daniel@0
|
12211 opt = opt || {};
|
Daniel@0
|
12212 var v = this,
|
Daniel@0
|
12213 trans = opt.duration ? new Transition(opt.duration, opt.ease) : null;
|
Daniel@0
|
12214
|
Daniel@0
|
12215 var cs = v._changeset;
|
Daniel@0
|
12216 if (trans) cs.trans = trans;
|
Daniel@0
|
12217 if (opt.props !== undefined) {
|
Daniel@0
|
12218 if (dl.keys(cs.data).length > 0) {
|
Daniel@0
|
12219 throw Error(
|
Daniel@0
|
12220 'New data values are not reflected in the visualization.' +
|
Daniel@0
|
12221 ' Please call view.update() before updating a specified property set.'
|
Daniel@0
|
12222 );
|
Daniel@0
|
12223 }
|
Daniel@0
|
12224
|
Daniel@0
|
12225 cs.reflow = true;
|
Daniel@0
|
12226 cs.request = opt.props;
|
Daniel@0
|
12227 }
|
Daniel@0
|
12228
|
Daniel@0
|
12229 var built = v._build;
|
Daniel@0
|
12230 v._build = v._build || build.call(this);
|
Daniel@0
|
12231
|
Daniel@0
|
12232 // If specific items are specified, short-circuit dataflow graph.
|
Daniel@0
|
12233 // Else-If there are streaming updates, perform a targeted propagation.
|
Daniel@0
|
12234 // Otherwise, reevaluate the entire model (datasources + scene).
|
Daniel@0
|
12235 if (opt.items && built) {
|
Daniel@0
|
12236 Encoder.update(this._model, opt.trans, opt.props, opt.items, cs.dirty);
|
Daniel@0
|
12237 v._renderNode.evaluate(cs);
|
Daniel@0
|
12238 } else if (v._streamer.listeners().length && built) {
|
Daniel@0
|
12239 v._model.propagate(cs, v._streamer);
|
Daniel@0
|
12240 v._streamer.disconnect();
|
Daniel@0
|
12241 } else {
|
Daniel@0
|
12242 v._model.fire(cs);
|
Daniel@0
|
12243 }
|
Daniel@0
|
12244
|
Daniel@0
|
12245 v._changeset = df.ChangeSet.create();
|
Daniel@0
|
12246
|
Daniel@0
|
12247 return v.autopad(opt);
|
Daniel@0
|
12248 };
|
Daniel@0
|
12249
|
Daniel@0
|
12250 prototype.toImageURL = function(type) {
|
Daniel@0
|
12251 var v = this, Renderer;
|
Daniel@0
|
12252
|
Daniel@0
|
12253 // lookup appropriate renderer
|
Daniel@0
|
12254 switch (type || 'png') {
|
Daniel@0
|
12255 case 'canvas':
|
Daniel@0
|
12256 case 'png':
|
Daniel@0
|
12257 Renderer = sg.canvas.Renderer; break;
|
Daniel@0
|
12258 case 'svg':
|
Daniel@0
|
12259 Renderer = sg.svg.string.Renderer; break;
|
Daniel@0
|
12260 default: throw Error('Unrecognized renderer type: ' + type);
|
Daniel@0
|
12261 }
|
Daniel@0
|
12262
|
Daniel@0
|
12263 var retina = sg.canvas.Renderer.RETINA;
|
Daniel@0
|
12264 sg.canvas.Renderer.RETINA = false; // ignore retina screen
|
Daniel@0
|
12265
|
Daniel@0
|
12266 // render the scenegraph
|
Daniel@0
|
12267 var ren = new Renderer(v._model.config.load)
|
Daniel@0
|
12268 .initialize(null, v._width, v._height, v._padding)
|
Daniel@0
|
12269 .render(v._model.scene());
|
Daniel@0
|
12270
|
Daniel@0
|
12271 sg.canvas.Renderer.RETINA = retina; // restore retina settings
|
Daniel@0
|
12272
|
Daniel@0
|
12273 // return data url
|
Daniel@0
|
12274 if (type === 'svg') {
|
Daniel@0
|
12275 var blob = new Blob([ren.svg()], {type: 'image/svg+xml'});
|
Daniel@0
|
12276 return window.URL.createObjectURL(blob);
|
Daniel@0
|
12277 } else {
|
Daniel@0
|
12278 return ren.canvas().toDataURL('image/png');
|
Daniel@0
|
12279 }
|
Daniel@0
|
12280 };
|
Daniel@0
|
12281
|
Daniel@0
|
12282 prototype.render = function(items) {
|
Daniel@0
|
12283 this._renderer.render(this._model.scene(), items);
|
Daniel@0
|
12284 return this;
|
Daniel@0
|
12285 };
|
Daniel@0
|
12286
|
Daniel@0
|
12287 prototype.on = function() {
|
Daniel@0
|
12288 this._handler.on.apply(this._handler, arguments);
|
Daniel@0
|
12289 return this;
|
Daniel@0
|
12290 };
|
Daniel@0
|
12291
|
Daniel@0
|
12292 prototype.onSignal = function(name, handler) {
|
Daniel@0
|
12293 this._model.signal(name).on(handler);
|
Daniel@0
|
12294 return this;
|
Daniel@0
|
12295 };
|
Daniel@0
|
12296
|
Daniel@0
|
12297 prototype.off = function() {
|
Daniel@0
|
12298 this._handler.off.apply(this._handler, arguments);
|
Daniel@0
|
12299 return this;
|
Daniel@0
|
12300 };
|
Daniel@0
|
12301
|
Daniel@0
|
12302 prototype.offSignal = function(name, handler) {
|
Daniel@0
|
12303 this._model.signal(name).off(handler);
|
Daniel@0
|
12304 return this;
|
Daniel@0
|
12305 };
|
Daniel@0
|
12306
|
Daniel@0
|
12307 View.factory = function(model) {
|
Daniel@0
|
12308 var HeadlessView = require('./HeadlessView');
|
Daniel@0
|
12309 return function(opt) {
|
Daniel@0
|
12310 opt = opt || {};
|
Daniel@0
|
12311 var defs = model.defs();
|
Daniel@0
|
12312 var v = (opt.el ? new View() : new HeadlessView())
|
Daniel@0
|
12313 .model(model)
|
Daniel@0
|
12314 .renderer(opt.renderer || 'canvas')
|
Daniel@0
|
12315 .width(defs.width)
|
Daniel@0
|
12316 .height(defs.height)
|
Daniel@0
|
12317 .background(defs.background)
|
Daniel@0
|
12318 .padding(defs.padding)
|
Daniel@0
|
12319 .viewport(defs.viewport)
|
Daniel@0
|
12320 .initialize(opt.el);
|
Daniel@0
|
12321
|
Daniel@0
|
12322 if (opt.data) v.data(opt.data);
|
Daniel@0
|
12323
|
Daniel@0
|
12324 if (opt.hover !== false && opt.el) {
|
Daniel@0
|
12325 v.on('mouseover', function(evt, item) {
|
Daniel@0
|
12326 if (item && item.hasPropertySet('hover')) {
|
Daniel@0
|
12327 this.update({props:'hover', items:item});
|
Daniel@0
|
12328 }
|
Daniel@0
|
12329 })
|
Daniel@0
|
12330 .on('mouseout', function(evt, item) {
|
Daniel@0
|
12331 if (item && item.hasPropertySet('hover')) {
|
Daniel@0
|
12332 this.update({props:'update', items:item});
|
Daniel@0
|
12333 }
|
Daniel@0
|
12334 });
|
Daniel@0
|
12335 }
|
Daniel@0
|
12336
|
Daniel@0
|
12337 return v;
|
Daniel@0
|
12338 };
|
Daniel@0
|
12339 };
|
Daniel@0
|
12340
|
Daniel@0
|
12341 module.exports = View;
|
Daniel@0
|
12342 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
12343
|
Daniel@0
|
12344 },{"../parse/streams":105,"../scene/Encoder":109,"../scene/Transition":112,"./HeadlessView":85,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],88:[function(require,module,exports){
|
Daniel@0
|
12345 (function (global){
|
Daniel@0
|
12346 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
12347 config = {};
|
Daniel@0
|
12348
|
Daniel@0
|
12349 config.load = {
|
Daniel@0
|
12350 // base url for loading external data files
|
Daniel@0
|
12351 // used only for server-side operation
|
Daniel@0
|
12352 baseURL: '',
|
Daniel@0
|
12353 // Allows domain restriction when using data loading via XHR.
|
Daniel@0
|
12354 // To enable, set it to a list of allowed domains
|
Daniel@0
|
12355 // e.g., ['wikipedia.org', 'eff.org']
|
Daniel@0
|
12356 domainWhiteList: false
|
Daniel@0
|
12357 };
|
Daniel@0
|
12358
|
Daniel@0
|
12359 // inset padding for automatic padding calculation
|
Daniel@0
|
12360 config.autopadInset = 5;
|
Daniel@0
|
12361
|
Daniel@0
|
12362 // extensible scale lookup table
|
Daniel@0
|
12363 // all d3.scale.* instances also supported
|
Daniel@0
|
12364 config.scale = {
|
Daniel@0
|
12365 time: d3.time.scale,
|
Daniel@0
|
12366 utc: d3.time.scale.utc
|
Daniel@0
|
12367 };
|
Daniel@0
|
12368
|
Daniel@0
|
12369 // default rendering settings
|
Daniel@0
|
12370 config.render = {
|
Daniel@0
|
12371 retina: true
|
Daniel@0
|
12372 };
|
Daniel@0
|
12373
|
Daniel@0
|
12374 // default axis properties
|
Daniel@0
|
12375 config.axis = {
|
Daniel@0
|
12376 orient: 'bottom',
|
Daniel@0
|
12377 ticks: 10,
|
Daniel@0
|
12378 padding: 3,
|
Daniel@0
|
12379 axisColor: '#000',
|
Daniel@0
|
12380 gridColor: '#000',
|
Daniel@0
|
12381 gridOpacity: 0.15,
|
Daniel@0
|
12382 tickColor: '#000',
|
Daniel@0
|
12383 tickLabelColor: '#000',
|
Daniel@0
|
12384 axisWidth: 1,
|
Daniel@0
|
12385 tickWidth: 1,
|
Daniel@0
|
12386 tickSize: 6,
|
Daniel@0
|
12387 tickLabelFontSize: 11,
|
Daniel@0
|
12388 tickLabelFont: 'sans-serif',
|
Daniel@0
|
12389 titleColor: '#000',
|
Daniel@0
|
12390 titleFont: 'sans-serif',
|
Daniel@0
|
12391 titleFontSize: 11,
|
Daniel@0
|
12392 titleFontWeight: 'bold',
|
Daniel@0
|
12393 titleOffset: 35
|
Daniel@0
|
12394 };
|
Daniel@0
|
12395
|
Daniel@0
|
12396 // default legend properties
|
Daniel@0
|
12397 config.legend = {
|
Daniel@0
|
12398 orient: 'right',
|
Daniel@0
|
12399 offset: 20,
|
Daniel@0
|
12400 padding: 3,
|
Daniel@0
|
12401 gradientStrokeColor: '#888',
|
Daniel@0
|
12402 gradientStrokeWidth: 1,
|
Daniel@0
|
12403 gradientHeight: 16,
|
Daniel@0
|
12404 gradientWidth: 100,
|
Daniel@0
|
12405 labelColor: '#000',
|
Daniel@0
|
12406 labelFontSize: 10,
|
Daniel@0
|
12407 labelFont: 'sans-serif',
|
Daniel@0
|
12408 labelAlign: 'left',
|
Daniel@0
|
12409 labelBaseline: 'middle',
|
Daniel@0
|
12410 labelOffset: 8,
|
Daniel@0
|
12411 symbolShape: 'circle',
|
Daniel@0
|
12412 symbolSize: 50,
|
Daniel@0
|
12413 symbolColor: '#888',
|
Daniel@0
|
12414 symbolStrokeWidth: 1,
|
Daniel@0
|
12415 titleColor: '#000',
|
Daniel@0
|
12416 titleFont: 'sans-serif',
|
Daniel@0
|
12417 titleFontSize: 11,
|
Daniel@0
|
12418 titleFontWeight: 'bold'
|
Daniel@0
|
12419 };
|
Daniel@0
|
12420
|
Daniel@0
|
12421 // default color values
|
Daniel@0
|
12422 config.color = {
|
Daniel@0
|
12423 rgb: [128, 128, 128],
|
Daniel@0
|
12424 lab: [50, 0, 0],
|
Daniel@0
|
12425 hcl: [0, 0, 50],
|
Daniel@0
|
12426 hsl: [0, 0, 0.5]
|
Daniel@0
|
12427 };
|
Daniel@0
|
12428
|
Daniel@0
|
12429 // default scale ranges
|
Daniel@0
|
12430 config.range = {
|
Daniel@0
|
12431 category10: d3.scale.category10().range(),
|
Daniel@0
|
12432 category20: d3.scale.category20().range(),
|
Daniel@0
|
12433 category20b: d3.scale.category20b().range(),
|
Daniel@0
|
12434 category20c: d3.scale.category20c().range(),
|
Daniel@0
|
12435 shapes: [
|
Daniel@0
|
12436 'circle',
|
Daniel@0
|
12437 'cross',
|
Daniel@0
|
12438 'diamond',
|
Daniel@0
|
12439 'square',
|
Daniel@0
|
12440 'triangle-down',
|
Daniel@0
|
12441 'triangle-up'
|
Daniel@0
|
12442 ]
|
Daniel@0
|
12443 };
|
Daniel@0
|
12444
|
Daniel@0
|
12445 module.exports = config;
|
Daniel@0
|
12446 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
12447
|
Daniel@0
|
12448 },{}],89:[function(require,module,exports){
|
Daniel@0
|
12449 var dl = require('datalib'),
|
Daniel@0
|
12450 parse = require('../parse'),
|
Daniel@0
|
12451 Scale = require('../scene/Scale'),
|
Daniel@0
|
12452 config = require('./config');
|
Daniel@0
|
12453
|
Daniel@0
|
12454 function compile(module, opt, schema) {
|
Daniel@0
|
12455 var s = module.schema;
|
Daniel@0
|
12456 if (!s) return;
|
Daniel@0
|
12457 if (s.refs) dl.extend(schema.refs, s.refs);
|
Daniel@0
|
12458 if (s.defs) dl.extend(schema.defs, s.defs);
|
Daniel@0
|
12459 }
|
Daniel@0
|
12460
|
Daniel@0
|
12461 module.exports = function(opt) {
|
Daniel@0
|
12462 var schema = null;
|
Daniel@0
|
12463 opt = opt || {};
|
Daniel@0
|
12464
|
Daniel@0
|
12465 // Compile if we're not loading the schema from a URL.
|
Daniel@0
|
12466 // Load from a URL to extend the existing base schema.
|
Daniel@0
|
12467 if (opt.url) {
|
Daniel@0
|
12468 schema = dl.json(dl.extend({url: opt.url}, config.load));
|
Daniel@0
|
12469 } else {
|
Daniel@0
|
12470 schema = {
|
Daniel@0
|
12471 "$schema": "http://json-schema.org/draft-04/schema#",
|
Daniel@0
|
12472 "title": "Vega Visualization Specification Language",
|
Daniel@0
|
12473 "defs": {},
|
Daniel@0
|
12474 "refs": {},
|
Daniel@0
|
12475 "$ref": "#/defs/spec"
|
Daniel@0
|
12476 };
|
Daniel@0
|
12477
|
Daniel@0
|
12478 dl.keys(parse).forEach(function(k) { compile(parse[k], opt, schema); });
|
Daniel@0
|
12479
|
Daniel@0
|
12480 // Scales aren't in the parser, add schema manually
|
Daniel@0
|
12481 compile(Scale, opt, schema);
|
Daniel@0
|
12482 }
|
Daniel@0
|
12483
|
Daniel@0
|
12484 // Extend schema to support custom mark properties or property sets.
|
Daniel@0
|
12485 if (opt.properties) dl.keys(opt.properties).forEach(function(k) {
|
Daniel@0
|
12486 schema.defs.propset.properties[k] = {"$ref": "#/refs/"+opt.properties[k]+"Value"};
|
Daniel@0
|
12487 });
|
Daniel@0
|
12488
|
Daniel@0
|
12489 if (opt.propertySets) dl.keys(opt.propertySets).forEach(function(k) {
|
Daniel@0
|
12490 schema.defs.mark.properties.properties.properties[k] = {"$ref": "#/defs/propset"};
|
Daniel@0
|
12491 });
|
Daniel@0
|
12492
|
Daniel@0
|
12493 return schema;
|
Daniel@0
|
12494 };
|
Daniel@0
|
12495 },{"../parse":95,"../scene/Scale":111,"./config":88,"datalib":24}],90:[function(require,module,exports){
|
Daniel@0
|
12496 var dl = require('datalib'),
|
Daniel@0
|
12497 axs = require('../scene/axis');
|
Daniel@0
|
12498
|
Daniel@0
|
12499 var ORIENT = {
|
Daniel@0
|
12500 "x": "bottom",
|
Daniel@0
|
12501 "y": "left",
|
Daniel@0
|
12502 "top": "top",
|
Daniel@0
|
12503 "bottom": "bottom",
|
Daniel@0
|
12504 "left": "left",
|
Daniel@0
|
12505 "right": "right"
|
Daniel@0
|
12506 };
|
Daniel@0
|
12507
|
Daniel@0
|
12508 function parseAxes(model, spec, axes, group) {
|
Daniel@0
|
12509 var config = model.config();
|
Daniel@0
|
12510 (spec || []).forEach(function(def, index) {
|
Daniel@0
|
12511 axes[index] = axes[index] || axs(model);
|
Daniel@0
|
12512 parseAxis(config, def, index, axes[index], group);
|
Daniel@0
|
12513 });
|
Daniel@0
|
12514 }
|
Daniel@0
|
12515
|
Daniel@0
|
12516 function parseAxis(config, def, index, axis, group) {
|
Daniel@0
|
12517 // axis scale
|
Daniel@0
|
12518 if (def.scale !== undefined) {
|
Daniel@0
|
12519 axis.scale(group.scale(def.scale));
|
Daniel@0
|
12520 }
|
Daniel@0
|
12521
|
Daniel@0
|
12522 // axis orientation
|
Daniel@0
|
12523 axis.orient(def.orient || ORIENT[def.type]);
|
Daniel@0
|
12524 // axis offset
|
Daniel@0
|
12525 axis.offset(def.offset || 0);
|
Daniel@0
|
12526 // axis layer
|
Daniel@0
|
12527 axis.layer(def.layer || "front");
|
Daniel@0
|
12528 // axis grid lines
|
Daniel@0
|
12529 axis.grid(def.grid || false);
|
Daniel@0
|
12530 // axis title
|
Daniel@0
|
12531 axis.title(def.title || null);
|
Daniel@0
|
12532 // axis title offset
|
Daniel@0
|
12533 axis.titleOffset(def.titleOffset != null ?
|
Daniel@0
|
12534 def.titleOffset : config.axis.titleOffset);
|
Daniel@0
|
12535 // axis values
|
Daniel@0
|
12536 axis.tickValues(def.values || null);
|
Daniel@0
|
12537 // axis label formatting
|
Daniel@0
|
12538 axis.tickFormat(def.format || null);
|
Daniel@0
|
12539 axis.tickFormatType(def.formatType || null);
|
Daniel@0
|
12540 // axis tick subdivision
|
Daniel@0
|
12541 axis.tickSubdivide(def.subdivide || 0);
|
Daniel@0
|
12542 // axis tick padding
|
Daniel@0
|
12543 axis.tickPadding(def.tickPadding || config.axis.padding);
|
Daniel@0
|
12544
|
Daniel@0
|
12545 // axis tick size(s)
|
Daniel@0
|
12546 var size = [];
|
Daniel@0
|
12547 if (def.tickSize !== undefined) {
|
Daniel@0
|
12548 for (var i=0; i<3; ++i) size.push(def.tickSize);
|
Daniel@0
|
12549 } else {
|
Daniel@0
|
12550 var ts = config.axis.tickSize;
|
Daniel@0
|
12551 size = [ts, ts, ts];
|
Daniel@0
|
12552 }
|
Daniel@0
|
12553 if (def.tickSizeMajor != null) size[0] = def.tickSizeMajor;
|
Daniel@0
|
12554 if (def.tickSizeMinor != null) size[1] = def.tickSizeMinor;
|
Daniel@0
|
12555 if (def.tickSizeEnd != null) size[2] = def.tickSizeEnd;
|
Daniel@0
|
12556 if (size.length) {
|
Daniel@0
|
12557 axis.tickSize.apply(axis, size);
|
Daniel@0
|
12558 }
|
Daniel@0
|
12559
|
Daniel@0
|
12560 // axis tick count
|
Daniel@0
|
12561 axis.tickCount(def.ticks || config.axis.ticks);
|
Daniel@0
|
12562
|
Daniel@0
|
12563 // style properties
|
Daniel@0
|
12564 var p = def.properties;
|
Daniel@0
|
12565 if (p && p.ticks) {
|
Daniel@0
|
12566 axis.majorTickProperties(p.majorTicks ?
|
Daniel@0
|
12567 dl.extend({}, p.ticks, p.majorTicks) : p.ticks);
|
Daniel@0
|
12568 axis.minorTickProperties(p.minorTicks ?
|
Daniel@0
|
12569 dl.extend({}, p.ticks, p.minorTicks) : p.ticks);
|
Daniel@0
|
12570 } else {
|
Daniel@0
|
12571 axis.majorTickProperties(p && p.majorTicks || {});
|
Daniel@0
|
12572 axis.minorTickProperties(p && p.minorTicks || {});
|
Daniel@0
|
12573 }
|
Daniel@0
|
12574 axis.tickLabelProperties(p && p.labels || {});
|
Daniel@0
|
12575 axis.titleProperties(p && p.title || {});
|
Daniel@0
|
12576 axis.gridLineProperties(p && p.grid || {});
|
Daniel@0
|
12577 axis.domainProperties(p && p.axis || {});
|
Daniel@0
|
12578 }
|
Daniel@0
|
12579
|
Daniel@0
|
12580 module.exports = parseAxes;
|
Daniel@0
|
12581 },{"../scene/axis":113,"datalib":24}],91:[function(require,module,exports){
|
Daniel@0
|
12582 (function (global){
|
Daniel@0
|
12583 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null);
|
Daniel@0
|
12584
|
Daniel@0
|
12585 function parseBg(bg) {
|
Daniel@0
|
12586 // return null if input is null or undefined
|
Daniel@0
|
12587 if (bg == null) return null;
|
Daniel@0
|
12588 // run through d3 rgb to sanity check
|
Daniel@0
|
12589 return d3.rgb(bg) + "";
|
Daniel@0
|
12590 }
|
Daniel@0
|
12591
|
Daniel@0
|
12592 module.exports = parseBg;
|
Daniel@0
|
12593 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
12594
|
Daniel@0
|
12595 },{}],92:[function(require,module,exports){
|
Daniel@0
|
12596 var dl = require('datalib'),
|
Daniel@0
|
12597 log = require('vega-logging'),
|
Daniel@0
|
12598 parseTransforms = require('./transforms'),
|
Daniel@0
|
12599 parseModify = require('./modify');
|
Daniel@0
|
12600
|
Daniel@0
|
12601 function parseData(model, spec, callback) {
|
Daniel@0
|
12602 var config = model.config(),
|
Daniel@0
|
12603 count = 0;
|
Daniel@0
|
12604
|
Daniel@0
|
12605 function loaded(d) {
|
Daniel@0
|
12606 return function(error, data) {
|
Daniel@0
|
12607 if (error) {
|
Daniel@0
|
12608 log.error('LOADING FAILED: ' + d.url + ' ' + error);
|
Daniel@0
|
12609 } else {
|
Daniel@0
|
12610 model.data(d.name).values(dl.read(data, d.format));
|
Daniel@0
|
12611 }
|
Daniel@0
|
12612 if (--count === 0) callback();
|
Daniel@0
|
12613 };
|
Daniel@0
|
12614 }
|
Daniel@0
|
12615
|
Daniel@0
|
12616 // process each data set definition
|
Daniel@0
|
12617 (spec || []).forEach(function(d) {
|
Daniel@0
|
12618 if (d.url) {
|
Daniel@0
|
12619 count += 1;
|
Daniel@0
|
12620 dl.load(dl.extend({url: d.url}, config.load), loaded(d));
|
Daniel@0
|
12621 }
|
Daniel@0
|
12622 parseData.datasource(model, d);
|
Daniel@0
|
12623 });
|
Daniel@0
|
12624
|
Daniel@0
|
12625 if (count === 0) setTimeout(callback, 1);
|
Daniel@0
|
12626 return spec;
|
Daniel@0
|
12627 }
|
Daniel@0
|
12628
|
Daniel@0
|
12629 parseData.datasource = function(model, d) {
|
Daniel@0
|
12630 var transform = (d.transform || []).map(function(t) {
|
Daniel@0
|
12631 return parseTransforms(model, t);
|
Daniel@0
|
12632 }),
|
Daniel@0
|
12633 mod = (d.modify || []).map(function(m) {
|
Daniel@0
|
12634 return parseModify(model, m, d);
|
Daniel@0
|
12635 }),
|
Daniel@0
|
12636 ds = model.data(d.name, mod.concat(transform));
|
Daniel@0
|
12637
|
Daniel@0
|
12638 if (d.values) {
|
Daniel@0
|
12639 ds.values(dl.read(d.values, d.format));
|
Daniel@0
|
12640 } else if (d.source) {
|
Daniel@0
|
12641 // Derived ds will be pulsed by its src rather than the model.
|
Daniel@0
|
12642 ds.source(d.source).addListener(ds);
|
Daniel@0
|
12643 model.removeListener(ds.pipeline()[0]);
|
Daniel@0
|
12644 }
|
Daniel@0
|
12645
|
Daniel@0
|
12646 return ds;
|
Daniel@0
|
12647 };
|
Daniel@0
|
12648
|
Daniel@0
|
12649 module.exports = parseData;
|
Daniel@0
|
12650 },{"./modify":99,"./transforms":106,"datalib":24,"vega-logging":45}],93:[function(require,module,exports){
|
Daniel@0
|
12651 module.exports = (function() {
|
Daniel@0
|
12652 /*
|
Daniel@0
|
12653 * Generated by PEG.js 0.8.0.
|
Daniel@0
|
12654 *
|
Daniel@0
|
12655 * http://pegjs.majda.cz/
|
Daniel@0
|
12656 */
|
Daniel@0
|
12657
|
Daniel@0
|
12658 function peg$subclass(child, parent) {
|
Daniel@0
|
12659 function ctor() { this.constructor = child; }
|
Daniel@0
|
12660 ctor.prototype = parent.prototype;
|
Daniel@0
|
12661 child.prototype = new ctor();
|
Daniel@0
|
12662 }
|
Daniel@0
|
12663
|
Daniel@0
|
12664 function SyntaxError(message, expected, found, offset, line, column) {
|
Daniel@0
|
12665 this.message = message;
|
Daniel@0
|
12666 this.expected = expected;
|
Daniel@0
|
12667 this.found = found;
|
Daniel@0
|
12668 this.offset = offset;
|
Daniel@0
|
12669 this.line = line;
|
Daniel@0
|
12670 this.column = column;
|
Daniel@0
|
12671
|
Daniel@0
|
12672 this.name = "SyntaxError";
|
Daniel@0
|
12673 }
|
Daniel@0
|
12674
|
Daniel@0
|
12675 peg$subclass(SyntaxError, Error);
|
Daniel@0
|
12676
|
Daniel@0
|
12677 function parse(input) {
|
Daniel@0
|
12678 var options = arguments.length > 1 ? arguments[1] : {},
|
Daniel@0
|
12679
|
Daniel@0
|
12680 peg$FAILED = {},
|
Daniel@0
|
12681
|
Daniel@0
|
12682 peg$startRuleFunctions = { start: peg$parsestart },
|
Daniel@0
|
12683 peg$startRuleFunction = peg$parsestart,
|
Daniel@0
|
12684
|
Daniel@0
|
12685 peg$c0 = peg$FAILED,
|
Daniel@0
|
12686 peg$c1 = ",",
|
Daniel@0
|
12687 peg$c2 = { type: "literal", value: ",", description: "\",\"" },
|
Daniel@0
|
12688 peg$c3 = function(o, m) { return [o].concat(m); },
|
Daniel@0
|
12689 peg$c4 = function(o) { return [o]; },
|
Daniel@0
|
12690 peg$c5 = "[",
|
Daniel@0
|
12691 peg$c6 = { type: "literal", value: "[", description: "\"[\"" },
|
Daniel@0
|
12692 peg$c7 = "]",
|
Daniel@0
|
12693 peg$c8 = { type: "literal", value: "]", description: "\"]\"" },
|
Daniel@0
|
12694 peg$c9 = ">",
|
Daniel@0
|
12695 peg$c10 = { type: "literal", value: ">", description: "\">\"" },
|
Daniel@0
|
12696 peg$c11 = function(f1, f2, o) { return {start: f1, end: f2, middle: o}; },
|
Daniel@0
|
12697 peg$c12 = [],
|
Daniel@0
|
12698 peg$c13 = function(s, f) { return (s.filters = f, s); },
|
Daniel@0
|
12699 peg$c14 = function(s) { return s; },
|
Daniel@0
|
12700 peg$c15 = "(",
|
Daniel@0
|
12701 peg$c16 = { type: "literal", value: "(", description: "\"(\"" },
|
Daniel@0
|
12702 peg$c17 = ")",
|
Daniel@0
|
12703 peg$c18 = { type: "literal", value: ")", description: "\")\"" },
|
Daniel@0
|
12704 peg$c19 = function(m) { return {stream: m}; },
|
Daniel@0
|
12705 peg$c20 = "@",
|
Daniel@0
|
12706 peg$c21 = { type: "literal", value: "@", description: "\"@\"" },
|
Daniel@0
|
12707 peg$c22 = ":",
|
Daniel@0
|
12708 peg$c23 = { type: "literal", value: ":", description: "\":\"" },
|
Daniel@0
|
12709 peg$c24 = function(n, e) { return {event: e, name: n}; },
|
Daniel@0
|
12710 peg$c25 = function(m, e) { return {event: e, mark: m}; },
|
Daniel@0
|
12711 peg$c26 = function(t, e) { return {event: e, target: t}; },
|
Daniel@0
|
12712 peg$c27 = function(e) { return {event: e}; },
|
Daniel@0
|
12713 peg$c28 = function(s) { return {signal: s}; },
|
Daniel@0
|
12714 peg$c29 = "rect",
|
Daniel@0
|
12715 peg$c30 = { type: "literal", value: "rect", description: "\"rect\"" },
|
Daniel@0
|
12716 peg$c31 = "symbol",
|
Daniel@0
|
12717 peg$c32 = { type: "literal", value: "symbol", description: "\"symbol\"" },
|
Daniel@0
|
12718 peg$c33 = "path",
|
Daniel@0
|
12719 peg$c34 = { type: "literal", value: "path", description: "\"path\"" },
|
Daniel@0
|
12720 peg$c35 = "arc",
|
Daniel@0
|
12721 peg$c36 = { type: "literal", value: "arc", description: "\"arc\"" },
|
Daniel@0
|
12722 peg$c37 = "area",
|
Daniel@0
|
12723 peg$c38 = { type: "literal", value: "area", description: "\"area\"" },
|
Daniel@0
|
12724 peg$c39 = "line",
|
Daniel@0
|
12725 peg$c40 = { type: "literal", value: "line", description: "\"line\"" },
|
Daniel@0
|
12726 peg$c41 = "rule",
|
Daniel@0
|
12727 peg$c42 = { type: "literal", value: "rule", description: "\"rule\"" },
|
Daniel@0
|
12728 peg$c43 = "image",
|
Daniel@0
|
12729 peg$c44 = { type: "literal", value: "image", description: "\"image\"" },
|
Daniel@0
|
12730 peg$c45 = "text",
|
Daniel@0
|
12731 peg$c46 = { type: "literal", value: "text", description: "\"text\"" },
|
Daniel@0
|
12732 peg$c47 = "group",
|
Daniel@0
|
12733 peg$c48 = { type: "literal", value: "group", description: "\"group\"" },
|
Daniel@0
|
12734 peg$c49 = "mousedown",
|
Daniel@0
|
12735 peg$c50 = { type: "literal", value: "mousedown", description: "\"mousedown\"" },
|
Daniel@0
|
12736 peg$c51 = "mouseup",
|
Daniel@0
|
12737 peg$c52 = { type: "literal", value: "mouseup", description: "\"mouseup\"" },
|
Daniel@0
|
12738 peg$c53 = "click",
|
Daniel@0
|
12739 peg$c54 = { type: "literal", value: "click", description: "\"click\"" },
|
Daniel@0
|
12740 peg$c55 = "dblclick",
|
Daniel@0
|
12741 peg$c56 = { type: "literal", value: "dblclick", description: "\"dblclick\"" },
|
Daniel@0
|
12742 peg$c57 = "wheel",
|
Daniel@0
|
12743 peg$c58 = { type: "literal", value: "wheel", description: "\"wheel\"" },
|
Daniel@0
|
12744 peg$c59 = "keydown",
|
Daniel@0
|
12745 peg$c60 = { type: "literal", value: "keydown", description: "\"keydown\"" },
|
Daniel@0
|
12746 peg$c61 = "keypress",
|
Daniel@0
|
12747 peg$c62 = { type: "literal", value: "keypress", description: "\"keypress\"" },
|
Daniel@0
|
12748 peg$c63 = "keyup",
|
Daniel@0
|
12749 peg$c64 = { type: "literal", value: "keyup", description: "\"keyup\"" },
|
Daniel@0
|
12750 peg$c65 = "mousewheel",
|
Daniel@0
|
12751 peg$c66 = { type: "literal", value: "mousewheel", description: "\"mousewheel\"" },
|
Daniel@0
|
12752 peg$c67 = "mousemove",
|
Daniel@0
|
12753 peg$c68 = { type: "literal", value: "mousemove", description: "\"mousemove\"" },
|
Daniel@0
|
12754 peg$c69 = "mouseout",
|
Daniel@0
|
12755 peg$c70 = { type: "literal", value: "mouseout", description: "\"mouseout\"" },
|
Daniel@0
|
12756 peg$c71 = "mouseover",
|
Daniel@0
|
12757 peg$c72 = { type: "literal", value: "mouseover", description: "\"mouseover\"" },
|
Daniel@0
|
12758 peg$c73 = "mouseenter",
|
Daniel@0
|
12759 peg$c74 = { type: "literal", value: "mouseenter", description: "\"mouseenter\"" },
|
Daniel@0
|
12760 peg$c75 = "touchstart",
|
Daniel@0
|
12761 peg$c76 = { type: "literal", value: "touchstart", description: "\"touchstart\"" },
|
Daniel@0
|
12762 peg$c77 = "touchmove",
|
Daniel@0
|
12763 peg$c78 = { type: "literal", value: "touchmove", description: "\"touchmove\"" },
|
Daniel@0
|
12764 peg$c79 = "touchend",
|
Daniel@0
|
12765 peg$c80 = { type: "literal", value: "touchend", description: "\"touchend\"" },
|
Daniel@0
|
12766 peg$c81 = function(e) { return e; },
|
Daniel@0
|
12767 peg$c82 = /^[a-zA-Z0-9_\-]/,
|
Daniel@0
|
12768 peg$c83 = { type: "class", value: "[a-zA-Z0-9_\\-]", description: "[a-zA-Z0-9_\\-]" },
|
Daniel@0
|
12769 peg$c84 = function(n) { return n.join(""); },
|
Daniel@0
|
12770 peg$c85 = /^[a-zA-Z0-9\-_ #.>+~[\]=|\^$*]/,
|
Daniel@0
|
12771 peg$c86 = { type: "class", value: "[a-zA-Z0-9\\-_ #.>+~[\\]=|\\^$*]", description: "[a-zA-Z0-9\\-_ #.>+~[\\]=|\\^$*]" },
|
Daniel@0
|
12772 peg$c87 = function(c) { return c.join(""); },
|
Daniel@0
|
12773 peg$c88 = /^['"a-zA-Z0-9_().><=! \t-&|~]/,
|
Daniel@0
|
12774 peg$c89 = { type: "class", value: "['\"a-zA-Z0-9_().><=! \\t-&|~]", description: "['\"a-zA-Z0-9_().><=! \\t-&|~]" },
|
Daniel@0
|
12775 peg$c90 = function(v) { return v.join(""); },
|
Daniel@0
|
12776 peg$c91 = /^[ \t\r\n]/,
|
Daniel@0
|
12777 peg$c92 = { type: "class", value: "[ \\t\\r\\n]", description: "[ \\t\\r\\n]" },
|
Daniel@0
|
12778
|
Daniel@0
|
12779 peg$currPos = 0,
|
Daniel@0
|
12780 peg$reportedPos = 0,
|
Daniel@0
|
12781 peg$cachedPos = 0,
|
Daniel@0
|
12782 peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
|
Daniel@0
|
12783 peg$maxFailPos = 0,
|
Daniel@0
|
12784 peg$maxFailExpected = [],
|
Daniel@0
|
12785 peg$silentFails = 0,
|
Daniel@0
|
12786
|
Daniel@0
|
12787 peg$result;
|
Daniel@0
|
12788
|
Daniel@0
|
12789 if ("startRule" in options) {
|
Daniel@0
|
12790 if (!(options.startRule in peg$startRuleFunctions)) {
|
Daniel@0
|
12791 throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
Daniel@0
|
12792 }
|
Daniel@0
|
12793
|
Daniel@0
|
12794 peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
Daniel@0
|
12795 }
|
Daniel@0
|
12796
|
Daniel@0
|
12797 function text() {
|
Daniel@0
|
12798 return input.substring(peg$reportedPos, peg$currPos);
|
Daniel@0
|
12799 }
|
Daniel@0
|
12800
|
Daniel@0
|
12801 function offset() {
|
Daniel@0
|
12802 return peg$reportedPos;
|
Daniel@0
|
12803 }
|
Daniel@0
|
12804
|
Daniel@0
|
12805 function line() {
|
Daniel@0
|
12806 return peg$computePosDetails(peg$reportedPos).line;
|
Daniel@0
|
12807 }
|
Daniel@0
|
12808
|
Daniel@0
|
12809 function column() {
|
Daniel@0
|
12810 return peg$computePosDetails(peg$reportedPos).column;
|
Daniel@0
|
12811 }
|
Daniel@0
|
12812
|
Daniel@0
|
12813 function expected(description) {
|
Daniel@0
|
12814 throw peg$buildException(
|
Daniel@0
|
12815 null,
|
Daniel@0
|
12816 [{ type: "other", description: description }],
|
Daniel@0
|
12817 peg$reportedPos
|
Daniel@0
|
12818 );
|
Daniel@0
|
12819 }
|
Daniel@0
|
12820
|
Daniel@0
|
12821 function error(message) {
|
Daniel@0
|
12822 throw peg$buildException(message, null, peg$reportedPos);
|
Daniel@0
|
12823 }
|
Daniel@0
|
12824
|
Daniel@0
|
12825 function peg$computePosDetails(pos) {
|
Daniel@0
|
12826 function advance(details, startPos, endPos) {
|
Daniel@0
|
12827 var p, ch;
|
Daniel@0
|
12828
|
Daniel@0
|
12829 for (p = startPos; p < endPos; p++) {
|
Daniel@0
|
12830 ch = input.charAt(p);
|
Daniel@0
|
12831 if (ch === "\n") {
|
Daniel@0
|
12832 if (!details.seenCR) { details.line++; }
|
Daniel@0
|
12833 details.column = 1;
|
Daniel@0
|
12834 details.seenCR = false;
|
Daniel@0
|
12835 } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
|
Daniel@0
|
12836 details.line++;
|
Daniel@0
|
12837 details.column = 1;
|
Daniel@0
|
12838 details.seenCR = true;
|
Daniel@0
|
12839 } else {
|
Daniel@0
|
12840 details.column++;
|
Daniel@0
|
12841 details.seenCR = false;
|
Daniel@0
|
12842 }
|
Daniel@0
|
12843 }
|
Daniel@0
|
12844 }
|
Daniel@0
|
12845
|
Daniel@0
|
12846 if (peg$cachedPos !== pos) {
|
Daniel@0
|
12847 if (peg$cachedPos > pos) {
|
Daniel@0
|
12848 peg$cachedPos = 0;
|
Daniel@0
|
12849 peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
|
Daniel@0
|
12850 }
|
Daniel@0
|
12851 advance(peg$cachedPosDetails, peg$cachedPos, pos);
|
Daniel@0
|
12852 peg$cachedPos = pos;
|
Daniel@0
|
12853 }
|
Daniel@0
|
12854
|
Daniel@0
|
12855 return peg$cachedPosDetails;
|
Daniel@0
|
12856 }
|
Daniel@0
|
12857
|
Daniel@0
|
12858 function peg$fail(expected) {
|
Daniel@0
|
12859 if (peg$currPos < peg$maxFailPos) { return; }
|
Daniel@0
|
12860
|
Daniel@0
|
12861 if (peg$currPos > peg$maxFailPos) {
|
Daniel@0
|
12862 peg$maxFailPos = peg$currPos;
|
Daniel@0
|
12863 peg$maxFailExpected = [];
|
Daniel@0
|
12864 }
|
Daniel@0
|
12865
|
Daniel@0
|
12866 peg$maxFailExpected.push(expected);
|
Daniel@0
|
12867 }
|
Daniel@0
|
12868
|
Daniel@0
|
12869 function peg$buildException(message, expected, pos) {
|
Daniel@0
|
12870 function cleanupExpected(expected) {
|
Daniel@0
|
12871 var i = 1;
|
Daniel@0
|
12872
|
Daniel@0
|
12873 expected.sort(function(a, b) {
|
Daniel@0
|
12874 if (a.description < b.description) {
|
Daniel@0
|
12875 return -1;
|
Daniel@0
|
12876 } else if (a.description > b.description) {
|
Daniel@0
|
12877 return 1;
|
Daniel@0
|
12878 } else {
|
Daniel@0
|
12879 return 0;
|
Daniel@0
|
12880 }
|
Daniel@0
|
12881 });
|
Daniel@0
|
12882
|
Daniel@0
|
12883 while (i < expected.length) {
|
Daniel@0
|
12884 if (expected[i - 1] === expected[i]) {
|
Daniel@0
|
12885 expected.splice(i, 1);
|
Daniel@0
|
12886 } else {
|
Daniel@0
|
12887 i++;
|
Daniel@0
|
12888 }
|
Daniel@0
|
12889 }
|
Daniel@0
|
12890 }
|
Daniel@0
|
12891
|
Daniel@0
|
12892 function buildMessage(expected, found) {
|
Daniel@0
|
12893 function stringEscape(s) {
|
Daniel@0
|
12894 function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
|
Daniel@0
|
12895
|
Daniel@0
|
12896 return s
|
Daniel@0
|
12897 .replace(/\\/g, '\\\\')
|
Daniel@0
|
12898 .replace(/"/g, '\\"')
|
Daniel@0
|
12899 .replace(/\x08/g, '\\b')
|
Daniel@0
|
12900 .replace(/\t/g, '\\t')
|
Daniel@0
|
12901 .replace(/\n/g, '\\n')
|
Daniel@0
|
12902 .replace(/\f/g, '\\f')
|
Daniel@0
|
12903 .replace(/\r/g, '\\r')
|
Daniel@0
|
12904 .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
Daniel@0
|
12905 .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
|
Daniel@0
|
12906 .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
|
Daniel@0
|
12907 .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
|
Daniel@0
|
12908 }
|
Daniel@0
|
12909
|
Daniel@0
|
12910 var expectedDescs = new Array(expected.length),
|
Daniel@0
|
12911 expectedDesc, foundDesc, i;
|
Daniel@0
|
12912
|
Daniel@0
|
12913 for (i = 0; i < expected.length; i++) {
|
Daniel@0
|
12914 expectedDescs[i] = expected[i].description;
|
Daniel@0
|
12915 }
|
Daniel@0
|
12916
|
Daniel@0
|
12917 expectedDesc = expected.length > 1
|
Daniel@0
|
12918 ? expectedDescs.slice(0, -1).join(", ")
|
Daniel@0
|
12919 + " or "
|
Daniel@0
|
12920 + expectedDescs[expected.length - 1]
|
Daniel@0
|
12921 : expectedDescs[0];
|
Daniel@0
|
12922
|
Daniel@0
|
12923 foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
|
Daniel@0
|
12924
|
Daniel@0
|
12925 return "Expected " + expectedDesc + " but " + foundDesc + " found.";
|
Daniel@0
|
12926 }
|
Daniel@0
|
12927
|
Daniel@0
|
12928 var posDetails = peg$computePosDetails(pos),
|
Daniel@0
|
12929 found = pos < input.length ? input.charAt(pos) : null;
|
Daniel@0
|
12930
|
Daniel@0
|
12931 if (expected !== null) {
|
Daniel@0
|
12932 cleanupExpected(expected);
|
Daniel@0
|
12933 }
|
Daniel@0
|
12934
|
Daniel@0
|
12935 return new SyntaxError(
|
Daniel@0
|
12936 message !== null ? message : buildMessage(expected, found),
|
Daniel@0
|
12937 expected,
|
Daniel@0
|
12938 found,
|
Daniel@0
|
12939 pos,
|
Daniel@0
|
12940 posDetails.line,
|
Daniel@0
|
12941 posDetails.column
|
Daniel@0
|
12942 );
|
Daniel@0
|
12943 }
|
Daniel@0
|
12944
|
Daniel@0
|
12945 function peg$parsestart() {
|
Daniel@0
|
12946 var s0;
|
Daniel@0
|
12947
|
Daniel@0
|
12948 s0 = peg$parsemerged();
|
Daniel@0
|
12949
|
Daniel@0
|
12950 return s0;
|
Daniel@0
|
12951 }
|
Daniel@0
|
12952
|
Daniel@0
|
12953 function peg$parsemerged() {
|
Daniel@0
|
12954 var s0, s1, s2, s3, s4, s5;
|
Daniel@0
|
12955
|
Daniel@0
|
12956 s0 = peg$currPos;
|
Daniel@0
|
12957 s1 = peg$parseordered();
|
Daniel@0
|
12958 if (s1 !== peg$FAILED) {
|
Daniel@0
|
12959 s2 = peg$parsesep();
|
Daniel@0
|
12960 if (s2 !== peg$FAILED) {
|
Daniel@0
|
12961 if (input.charCodeAt(peg$currPos) === 44) {
|
Daniel@0
|
12962 s3 = peg$c1;
|
Daniel@0
|
12963 peg$currPos++;
|
Daniel@0
|
12964 } else {
|
Daniel@0
|
12965 s3 = peg$FAILED;
|
Daniel@0
|
12966 if (peg$silentFails === 0) { peg$fail(peg$c2); }
|
Daniel@0
|
12967 }
|
Daniel@0
|
12968 if (s3 !== peg$FAILED) {
|
Daniel@0
|
12969 s4 = peg$parsesep();
|
Daniel@0
|
12970 if (s4 !== peg$FAILED) {
|
Daniel@0
|
12971 s5 = peg$parsemerged();
|
Daniel@0
|
12972 if (s5 !== peg$FAILED) {
|
Daniel@0
|
12973 peg$reportedPos = s0;
|
Daniel@0
|
12974 s1 = peg$c3(s1, s5);
|
Daniel@0
|
12975 s0 = s1;
|
Daniel@0
|
12976 } else {
|
Daniel@0
|
12977 peg$currPos = s0;
|
Daniel@0
|
12978 s0 = peg$c0;
|
Daniel@0
|
12979 }
|
Daniel@0
|
12980 } else {
|
Daniel@0
|
12981 peg$currPos = s0;
|
Daniel@0
|
12982 s0 = peg$c0;
|
Daniel@0
|
12983 }
|
Daniel@0
|
12984 } else {
|
Daniel@0
|
12985 peg$currPos = s0;
|
Daniel@0
|
12986 s0 = peg$c0;
|
Daniel@0
|
12987 }
|
Daniel@0
|
12988 } else {
|
Daniel@0
|
12989 peg$currPos = s0;
|
Daniel@0
|
12990 s0 = peg$c0;
|
Daniel@0
|
12991 }
|
Daniel@0
|
12992 } else {
|
Daniel@0
|
12993 peg$currPos = s0;
|
Daniel@0
|
12994 s0 = peg$c0;
|
Daniel@0
|
12995 }
|
Daniel@0
|
12996 if (s0 === peg$FAILED) {
|
Daniel@0
|
12997 s0 = peg$currPos;
|
Daniel@0
|
12998 s1 = peg$parseordered();
|
Daniel@0
|
12999 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13000 peg$reportedPos = s0;
|
Daniel@0
|
13001 s1 = peg$c4(s1);
|
Daniel@0
|
13002 }
|
Daniel@0
|
13003 s0 = s1;
|
Daniel@0
|
13004 }
|
Daniel@0
|
13005
|
Daniel@0
|
13006 return s0;
|
Daniel@0
|
13007 }
|
Daniel@0
|
13008
|
Daniel@0
|
13009 function peg$parseordered() {
|
Daniel@0
|
13010 var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
|
Daniel@0
|
13011
|
Daniel@0
|
13012 s0 = peg$currPos;
|
Daniel@0
|
13013 if (input.charCodeAt(peg$currPos) === 91) {
|
Daniel@0
|
13014 s1 = peg$c5;
|
Daniel@0
|
13015 peg$currPos++;
|
Daniel@0
|
13016 } else {
|
Daniel@0
|
13017 s1 = peg$FAILED;
|
Daniel@0
|
13018 if (peg$silentFails === 0) { peg$fail(peg$c6); }
|
Daniel@0
|
13019 }
|
Daniel@0
|
13020 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13021 s2 = peg$parsesep();
|
Daniel@0
|
13022 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13023 s3 = peg$parsefiltered();
|
Daniel@0
|
13024 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13025 s4 = peg$parsesep();
|
Daniel@0
|
13026 if (s4 !== peg$FAILED) {
|
Daniel@0
|
13027 if (input.charCodeAt(peg$currPos) === 44) {
|
Daniel@0
|
13028 s5 = peg$c1;
|
Daniel@0
|
13029 peg$currPos++;
|
Daniel@0
|
13030 } else {
|
Daniel@0
|
13031 s5 = peg$FAILED;
|
Daniel@0
|
13032 if (peg$silentFails === 0) { peg$fail(peg$c2); }
|
Daniel@0
|
13033 }
|
Daniel@0
|
13034 if (s5 !== peg$FAILED) {
|
Daniel@0
|
13035 s6 = peg$parsesep();
|
Daniel@0
|
13036 if (s6 !== peg$FAILED) {
|
Daniel@0
|
13037 s7 = peg$parsefiltered();
|
Daniel@0
|
13038 if (s7 !== peg$FAILED) {
|
Daniel@0
|
13039 s8 = peg$parsesep();
|
Daniel@0
|
13040 if (s8 !== peg$FAILED) {
|
Daniel@0
|
13041 if (input.charCodeAt(peg$currPos) === 93) {
|
Daniel@0
|
13042 s9 = peg$c7;
|
Daniel@0
|
13043 peg$currPos++;
|
Daniel@0
|
13044 } else {
|
Daniel@0
|
13045 s9 = peg$FAILED;
|
Daniel@0
|
13046 if (peg$silentFails === 0) { peg$fail(peg$c8); }
|
Daniel@0
|
13047 }
|
Daniel@0
|
13048 if (s9 !== peg$FAILED) {
|
Daniel@0
|
13049 s10 = peg$parsesep();
|
Daniel@0
|
13050 if (s10 !== peg$FAILED) {
|
Daniel@0
|
13051 if (input.charCodeAt(peg$currPos) === 62) {
|
Daniel@0
|
13052 s11 = peg$c9;
|
Daniel@0
|
13053 peg$currPos++;
|
Daniel@0
|
13054 } else {
|
Daniel@0
|
13055 s11 = peg$FAILED;
|
Daniel@0
|
13056 if (peg$silentFails === 0) { peg$fail(peg$c10); }
|
Daniel@0
|
13057 }
|
Daniel@0
|
13058 if (s11 !== peg$FAILED) {
|
Daniel@0
|
13059 s12 = peg$parsesep();
|
Daniel@0
|
13060 if (s12 !== peg$FAILED) {
|
Daniel@0
|
13061 s13 = peg$parseordered();
|
Daniel@0
|
13062 if (s13 !== peg$FAILED) {
|
Daniel@0
|
13063 peg$reportedPos = s0;
|
Daniel@0
|
13064 s1 = peg$c11(s3, s7, s13);
|
Daniel@0
|
13065 s0 = s1;
|
Daniel@0
|
13066 } else {
|
Daniel@0
|
13067 peg$currPos = s0;
|
Daniel@0
|
13068 s0 = peg$c0;
|
Daniel@0
|
13069 }
|
Daniel@0
|
13070 } else {
|
Daniel@0
|
13071 peg$currPos = s0;
|
Daniel@0
|
13072 s0 = peg$c0;
|
Daniel@0
|
13073 }
|
Daniel@0
|
13074 } else {
|
Daniel@0
|
13075 peg$currPos = s0;
|
Daniel@0
|
13076 s0 = peg$c0;
|
Daniel@0
|
13077 }
|
Daniel@0
|
13078 } else {
|
Daniel@0
|
13079 peg$currPos = s0;
|
Daniel@0
|
13080 s0 = peg$c0;
|
Daniel@0
|
13081 }
|
Daniel@0
|
13082 } else {
|
Daniel@0
|
13083 peg$currPos = s0;
|
Daniel@0
|
13084 s0 = peg$c0;
|
Daniel@0
|
13085 }
|
Daniel@0
|
13086 } else {
|
Daniel@0
|
13087 peg$currPos = s0;
|
Daniel@0
|
13088 s0 = peg$c0;
|
Daniel@0
|
13089 }
|
Daniel@0
|
13090 } else {
|
Daniel@0
|
13091 peg$currPos = s0;
|
Daniel@0
|
13092 s0 = peg$c0;
|
Daniel@0
|
13093 }
|
Daniel@0
|
13094 } else {
|
Daniel@0
|
13095 peg$currPos = s0;
|
Daniel@0
|
13096 s0 = peg$c0;
|
Daniel@0
|
13097 }
|
Daniel@0
|
13098 } else {
|
Daniel@0
|
13099 peg$currPos = s0;
|
Daniel@0
|
13100 s0 = peg$c0;
|
Daniel@0
|
13101 }
|
Daniel@0
|
13102 } else {
|
Daniel@0
|
13103 peg$currPos = s0;
|
Daniel@0
|
13104 s0 = peg$c0;
|
Daniel@0
|
13105 }
|
Daniel@0
|
13106 } else {
|
Daniel@0
|
13107 peg$currPos = s0;
|
Daniel@0
|
13108 s0 = peg$c0;
|
Daniel@0
|
13109 }
|
Daniel@0
|
13110 } else {
|
Daniel@0
|
13111 peg$currPos = s0;
|
Daniel@0
|
13112 s0 = peg$c0;
|
Daniel@0
|
13113 }
|
Daniel@0
|
13114 } else {
|
Daniel@0
|
13115 peg$currPos = s0;
|
Daniel@0
|
13116 s0 = peg$c0;
|
Daniel@0
|
13117 }
|
Daniel@0
|
13118 if (s0 === peg$FAILED) {
|
Daniel@0
|
13119 s0 = peg$parsefiltered();
|
Daniel@0
|
13120 }
|
Daniel@0
|
13121
|
Daniel@0
|
13122 return s0;
|
Daniel@0
|
13123 }
|
Daniel@0
|
13124
|
Daniel@0
|
13125 function peg$parsefiltered() {
|
Daniel@0
|
13126 var s0, s1, s2, s3;
|
Daniel@0
|
13127
|
Daniel@0
|
13128 s0 = peg$currPos;
|
Daniel@0
|
13129 s1 = peg$parsestream();
|
Daniel@0
|
13130 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13131 s2 = [];
|
Daniel@0
|
13132 s3 = peg$parsefilter();
|
Daniel@0
|
13133 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13134 while (s3 !== peg$FAILED) {
|
Daniel@0
|
13135 s2.push(s3);
|
Daniel@0
|
13136 s3 = peg$parsefilter();
|
Daniel@0
|
13137 }
|
Daniel@0
|
13138 } else {
|
Daniel@0
|
13139 s2 = peg$c0;
|
Daniel@0
|
13140 }
|
Daniel@0
|
13141 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13142 peg$reportedPos = s0;
|
Daniel@0
|
13143 s1 = peg$c13(s1, s2);
|
Daniel@0
|
13144 s0 = s1;
|
Daniel@0
|
13145 } else {
|
Daniel@0
|
13146 peg$currPos = s0;
|
Daniel@0
|
13147 s0 = peg$c0;
|
Daniel@0
|
13148 }
|
Daniel@0
|
13149 } else {
|
Daniel@0
|
13150 peg$currPos = s0;
|
Daniel@0
|
13151 s0 = peg$c0;
|
Daniel@0
|
13152 }
|
Daniel@0
|
13153 if (s0 === peg$FAILED) {
|
Daniel@0
|
13154 s0 = peg$currPos;
|
Daniel@0
|
13155 s1 = peg$parsestream();
|
Daniel@0
|
13156 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13157 peg$reportedPos = s0;
|
Daniel@0
|
13158 s1 = peg$c14(s1);
|
Daniel@0
|
13159 }
|
Daniel@0
|
13160 s0 = s1;
|
Daniel@0
|
13161 }
|
Daniel@0
|
13162
|
Daniel@0
|
13163 return s0;
|
Daniel@0
|
13164 }
|
Daniel@0
|
13165
|
Daniel@0
|
13166 function peg$parsestream() {
|
Daniel@0
|
13167 var s0, s1, s2, s3, s4;
|
Daniel@0
|
13168
|
Daniel@0
|
13169 s0 = peg$currPos;
|
Daniel@0
|
13170 if (input.charCodeAt(peg$currPos) === 40) {
|
Daniel@0
|
13171 s1 = peg$c15;
|
Daniel@0
|
13172 peg$currPos++;
|
Daniel@0
|
13173 } else {
|
Daniel@0
|
13174 s1 = peg$FAILED;
|
Daniel@0
|
13175 if (peg$silentFails === 0) { peg$fail(peg$c16); }
|
Daniel@0
|
13176 }
|
Daniel@0
|
13177 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13178 s2 = peg$parsemerged();
|
Daniel@0
|
13179 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13180 if (input.charCodeAt(peg$currPos) === 41) {
|
Daniel@0
|
13181 s3 = peg$c17;
|
Daniel@0
|
13182 peg$currPos++;
|
Daniel@0
|
13183 } else {
|
Daniel@0
|
13184 s3 = peg$FAILED;
|
Daniel@0
|
13185 if (peg$silentFails === 0) { peg$fail(peg$c18); }
|
Daniel@0
|
13186 }
|
Daniel@0
|
13187 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13188 peg$reportedPos = s0;
|
Daniel@0
|
13189 s1 = peg$c19(s2);
|
Daniel@0
|
13190 s0 = s1;
|
Daniel@0
|
13191 } else {
|
Daniel@0
|
13192 peg$currPos = s0;
|
Daniel@0
|
13193 s0 = peg$c0;
|
Daniel@0
|
13194 }
|
Daniel@0
|
13195 } else {
|
Daniel@0
|
13196 peg$currPos = s0;
|
Daniel@0
|
13197 s0 = peg$c0;
|
Daniel@0
|
13198 }
|
Daniel@0
|
13199 } else {
|
Daniel@0
|
13200 peg$currPos = s0;
|
Daniel@0
|
13201 s0 = peg$c0;
|
Daniel@0
|
13202 }
|
Daniel@0
|
13203 if (s0 === peg$FAILED) {
|
Daniel@0
|
13204 s0 = peg$currPos;
|
Daniel@0
|
13205 if (input.charCodeAt(peg$currPos) === 64) {
|
Daniel@0
|
13206 s1 = peg$c20;
|
Daniel@0
|
13207 peg$currPos++;
|
Daniel@0
|
13208 } else {
|
Daniel@0
|
13209 s1 = peg$FAILED;
|
Daniel@0
|
13210 if (peg$silentFails === 0) { peg$fail(peg$c21); }
|
Daniel@0
|
13211 }
|
Daniel@0
|
13212 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13213 s2 = peg$parsename();
|
Daniel@0
|
13214 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13215 if (input.charCodeAt(peg$currPos) === 58) {
|
Daniel@0
|
13216 s3 = peg$c22;
|
Daniel@0
|
13217 peg$currPos++;
|
Daniel@0
|
13218 } else {
|
Daniel@0
|
13219 s3 = peg$FAILED;
|
Daniel@0
|
13220 if (peg$silentFails === 0) { peg$fail(peg$c23); }
|
Daniel@0
|
13221 }
|
Daniel@0
|
13222 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13223 s4 = peg$parseeventType();
|
Daniel@0
|
13224 if (s4 !== peg$FAILED) {
|
Daniel@0
|
13225 peg$reportedPos = s0;
|
Daniel@0
|
13226 s1 = peg$c24(s2, s4);
|
Daniel@0
|
13227 s0 = s1;
|
Daniel@0
|
13228 } else {
|
Daniel@0
|
13229 peg$currPos = s0;
|
Daniel@0
|
13230 s0 = peg$c0;
|
Daniel@0
|
13231 }
|
Daniel@0
|
13232 } else {
|
Daniel@0
|
13233 peg$currPos = s0;
|
Daniel@0
|
13234 s0 = peg$c0;
|
Daniel@0
|
13235 }
|
Daniel@0
|
13236 } else {
|
Daniel@0
|
13237 peg$currPos = s0;
|
Daniel@0
|
13238 s0 = peg$c0;
|
Daniel@0
|
13239 }
|
Daniel@0
|
13240 } else {
|
Daniel@0
|
13241 peg$currPos = s0;
|
Daniel@0
|
13242 s0 = peg$c0;
|
Daniel@0
|
13243 }
|
Daniel@0
|
13244 if (s0 === peg$FAILED) {
|
Daniel@0
|
13245 s0 = peg$currPos;
|
Daniel@0
|
13246 s1 = peg$parsemarkType();
|
Daniel@0
|
13247 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13248 if (input.charCodeAt(peg$currPos) === 58) {
|
Daniel@0
|
13249 s2 = peg$c22;
|
Daniel@0
|
13250 peg$currPos++;
|
Daniel@0
|
13251 } else {
|
Daniel@0
|
13252 s2 = peg$FAILED;
|
Daniel@0
|
13253 if (peg$silentFails === 0) { peg$fail(peg$c23); }
|
Daniel@0
|
13254 }
|
Daniel@0
|
13255 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13256 s3 = peg$parseeventType();
|
Daniel@0
|
13257 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13258 peg$reportedPos = s0;
|
Daniel@0
|
13259 s1 = peg$c25(s1, s3);
|
Daniel@0
|
13260 s0 = s1;
|
Daniel@0
|
13261 } else {
|
Daniel@0
|
13262 peg$currPos = s0;
|
Daniel@0
|
13263 s0 = peg$c0;
|
Daniel@0
|
13264 }
|
Daniel@0
|
13265 } else {
|
Daniel@0
|
13266 peg$currPos = s0;
|
Daniel@0
|
13267 s0 = peg$c0;
|
Daniel@0
|
13268 }
|
Daniel@0
|
13269 } else {
|
Daniel@0
|
13270 peg$currPos = s0;
|
Daniel@0
|
13271 s0 = peg$c0;
|
Daniel@0
|
13272 }
|
Daniel@0
|
13273 if (s0 === peg$FAILED) {
|
Daniel@0
|
13274 s0 = peg$currPos;
|
Daniel@0
|
13275 s1 = peg$parsecss();
|
Daniel@0
|
13276 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13277 if (input.charCodeAt(peg$currPos) === 58) {
|
Daniel@0
|
13278 s2 = peg$c22;
|
Daniel@0
|
13279 peg$currPos++;
|
Daniel@0
|
13280 } else {
|
Daniel@0
|
13281 s2 = peg$FAILED;
|
Daniel@0
|
13282 if (peg$silentFails === 0) { peg$fail(peg$c23); }
|
Daniel@0
|
13283 }
|
Daniel@0
|
13284 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13285 s3 = peg$parseeventType();
|
Daniel@0
|
13286 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13287 peg$reportedPos = s0;
|
Daniel@0
|
13288 s1 = peg$c26(s1, s3);
|
Daniel@0
|
13289 s0 = s1;
|
Daniel@0
|
13290 } else {
|
Daniel@0
|
13291 peg$currPos = s0;
|
Daniel@0
|
13292 s0 = peg$c0;
|
Daniel@0
|
13293 }
|
Daniel@0
|
13294 } else {
|
Daniel@0
|
13295 peg$currPos = s0;
|
Daniel@0
|
13296 s0 = peg$c0;
|
Daniel@0
|
13297 }
|
Daniel@0
|
13298 } else {
|
Daniel@0
|
13299 peg$currPos = s0;
|
Daniel@0
|
13300 s0 = peg$c0;
|
Daniel@0
|
13301 }
|
Daniel@0
|
13302 if (s0 === peg$FAILED) {
|
Daniel@0
|
13303 s0 = peg$currPos;
|
Daniel@0
|
13304 s1 = peg$parseeventType();
|
Daniel@0
|
13305 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13306 peg$reportedPos = s0;
|
Daniel@0
|
13307 s1 = peg$c27(s1);
|
Daniel@0
|
13308 }
|
Daniel@0
|
13309 s0 = s1;
|
Daniel@0
|
13310 if (s0 === peg$FAILED) {
|
Daniel@0
|
13311 s0 = peg$currPos;
|
Daniel@0
|
13312 s1 = peg$parsename();
|
Daniel@0
|
13313 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13314 peg$reportedPos = s0;
|
Daniel@0
|
13315 s1 = peg$c28(s1);
|
Daniel@0
|
13316 }
|
Daniel@0
|
13317 s0 = s1;
|
Daniel@0
|
13318 }
|
Daniel@0
|
13319 }
|
Daniel@0
|
13320 }
|
Daniel@0
|
13321 }
|
Daniel@0
|
13322 }
|
Daniel@0
|
13323
|
Daniel@0
|
13324 return s0;
|
Daniel@0
|
13325 }
|
Daniel@0
|
13326
|
Daniel@0
|
13327 function peg$parsemarkType() {
|
Daniel@0
|
13328 var s0;
|
Daniel@0
|
13329
|
Daniel@0
|
13330 if (input.substr(peg$currPos, 4) === peg$c29) {
|
Daniel@0
|
13331 s0 = peg$c29;
|
Daniel@0
|
13332 peg$currPos += 4;
|
Daniel@0
|
13333 } else {
|
Daniel@0
|
13334 s0 = peg$FAILED;
|
Daniel@0
|
13335 if (peg$silentFails === 0) { peg$fail(peg$c30); }
|
Daniel@0
|
13336 }
|
Daniel@0
|
13337 if (s0 === peg$FAILED) {
|
Daniel@0
|
13338 if (input.substr(peg$currPos, 6) === peg$c31) {
|
Daniel@0
|
13339 s0 = peg$c31;
|
Daniel@0
|
13340 peg$currPos += 6;
|
Daniel@0
|
13341 } else {
|
Daniel@0
|
13342 s0 = peg$FAILED;
|
Daniel@0
|
13343 if (peg$silentFails === 0) { peg$fail(peg$c32); }
|
Daniel@0
|
13344 }
|
Daniel@0
|
13345 if (s0 === peg$FAILED) {
|
Daniel@0
|
13346 if (input.substr(peg$currPos, 4) === peg$c33) {
|
Daniel@0
|
13347 s0 = peg$c33;
|
Daniel@0
|
13348 peg$currPos += 4;
|
Daniel@0
|
13349 } else {
|
Daniel@0
|
13350 s0 = peg$FAILED;
|
Daniel@0
|
13351 if (peg$silentFails === 0) { peg$fail(peg$c34); }
|
Daniel@0
|
13352 }
|
Daniel@0
|
13353 if (s0 === peg$FAILED) {
|
Daniel@0
|
13354 if (input.substr(peg$currPos, 3) === peg$c35) {
|
Daniel@0
|
13355 s0 = peg$c35;
|
Daniel@0
|
13356 peg$currPos += 3;
|
Daniel@0
|
13357 } else {
|
Daniel@0
|
13358 s0 = peg$FAILED;
|
Daniel@0
|
13359 if (peg$silentFails === 0) { peg$fail(peg$c36); }
|
Daniel@0
|
13360 }
|
Daniel@0
|
13361 if (s0 === peg$FAILED) {
|
Daniel@0
|
13362 if (input.substr(peg$currPos, 4) === peg$c37) {
|
Daniel@0
|
13363 s0 = peg$c37;
|
Daniel@0
|
13364 peg$currPos += 4;
|
Daniel@0
|
13365 } else {
|
Daniel@0
|
13366 s0 = peg$FAILED;
|
Daniel@0
|
13367 if (peg$silentFails === 0) { peg$fail(peg$c38); }
|
Daniel@0
|
13368 }
|
Daniel@0
|
13369 if (s0 === peg$FAILED) {
|
Daniel@0
|
13370 if (input.substr(peg$currPos, 4) === peg$c39) {
|
Daniel@0
|
13371 s0 = peg$c39;
|
Daniel@0
|
13372 peg$currPos += 4;
|
Daniel@0
|
13373 } else {
|
Daniel@0
|
13374 s0 = peg$FAILED;
|
Daniel@0
|
13375 if (peg$silentFails === 0) { peg$fail(peg$c40); }
|
Daniel@0
|
13376 }
|
Daniel@0
|
13377 if (s0 === peg$FAILED) {
|
Daniel@0
|
13378 if (input.substr(peg$currPos, 4) === peg$c41) {
|
Daniel@0
|
13379 s0 = peg$c41;
|
Daniel@0
|
13380 peg$currPos += 4;
|
Daniel@0
|
13381 } else {
|
Daniel@0
|
13382 s0 = peg$FAILED;
|
Daniel@0
|
13383 if (peg$silentFails === 0) { peg$fail(peg$c42); }
|
Daniel@0
|
13384 }
|
Daniel@0
|
13385 if (s0 === peg$FAILED) {
|
Daniel@0
|
13386 if (input.substr(peg$currPos, 5) === peg$c43) {
|
Daniel@0
|
13387 s0 = peg$c43;
|
Daniel@0
|
13388 peg$currPos += 5;
|
Daniel@0
|
13389 } else {
|
Daniel@0
|
13390 s0 = peg$FAILED;
|
Daniel@0
|
13391 if (peg$silentFails === 0) { peg$fail(peg$c44); }
|
Daniel@0
|
13392 }
|
Daniel@0
|
13393 if (s0 === peg$FAILED) {
|
Daniel@0
|
13394 if (input.substr(peg$currPos, 4) === peg$c45) {
|
Daniel@0
|
13395 s0 = peg$c45;
|
Daniel@0
|
13396 peg$currPos += 4;
|
Daniel@0
|
13397 } else {
|
Daniel@0
|
13398 s0 = peg$FAILED;
|
Daniel@0
|
13399 if (peg$silentFails === 0) { peg$fail(peg$c46); }
|
Daniel@0
|
13400 }
|
Daniel@0
|
13401 if (s0 === peg$FAILED) {
|
Daniel@0
|
13402 if (input.substr(peg$currPos, 5) === peg$c47) {
|
Daniel@0
|
13403 s0 = peg$c47;
|
Daniel@0
|
13404 peg$currPos += 5;
|
Daniel@0
|
13405 } else {
|
Daniel@0
|
13406 s0 = peg$FAILED;
|
Daniel@0
|
13407 if (peg$silentFails === 0) { peg$fail(peg$c48); }
|
Daniel@0
|
13408 }
|
Daniel@0
|
13409 }
|
Daniel@0
|
13410 }
|
Daniel@0
|
13411 }
|
Daniel@0
|
13412 }
|
Daniel@0
|
13413 }
|
Daniel@0
|
13414 }
|
Daniel@0
|
13415 }
|
Daniel@0
|
13416 }
|
Daniel@0
|
13417 }
|
Daniel@0
|
13418
|
Daniel@0
|
13419 return s0;
|
Daniel@0
|
13420 }
|
Daniel@0
|
13421
|
Daniel@0
|
13422 function peg$parseeventType() {
|
Daniel@0
|
13423 var s0;
|
Daniel@0
|
13424
|
Daniel@0
|
13425 if (input.substr(peg$currPos, 9) === peg$c49) {
|
Daniel@0
|
13426 s0 = peg$c49;
|
Daniel@0
|
13427 peg$currPos += 9;
|
Daniel@0
|
13428 } else {
|
Daniel@0
|
13429 s0 = peg$FAILED;
|
Daniel@0
|
13430 if (peg$silentFails === 0) { peg$fail(peg$c50); }
|
Daniel@0
|
13431 }
|
Daniel@0
|
13432 if (s0 === peg$FAILED) {
|
Daniel@0
|
13433 if (input.substr(peg$currPos, 7) === peg$c51) {
|
Daniel@0
|
13434 s0 = peg$c51;
|
Daniel@0
|
13435 peg$currPos += 7;
|
Daniel@0
|
13436 } else {
|
Daniel@0
|
13437 s0 = peg$FAILED;
|
Daniel@0
|
13438 if (peg$silentFails === 0) { peg$fail(peg$c52); }
|
Daniel@0
|
13439 }
|
Daniel@0
|
13440 if (s0 === peg$FAILED) {
|
Daniel@0
|
13441 if (input.substr(peg$currPos, 5) === peg$c53) {
|
Daniel@0
|
13442 s0 = peg$c53;
|
Daniel@0
|
13443 peg$currPos += 5;
|
Daniel@0
|
13444 } else {
|
Daniel@0
|
13445 s0 = peg$FAILED;
|
Daniel@0
|
13446 if (peg$silentFails === 0) { peg$fail(peg$c54); }
|
Daniel@0
|
13447 }
|
Daniel@0
|
13448 if (s0 === peg$FAILED) {
|
Daniel@0
|
13449 if (input.substr(peg$currPos, 8) === peg$c55) {
|
Daniel@0
|
13450 s0 = peg$c55;
|
Daniel@0
|
13451 peg$currPos += 8;
|
Daniel@0
|
13452 } else {
|
Daniel@0
|
13453 s0 = peg$FAILED;
|
Daniel@0
|
13454 if (peg$silentFails === 0) { peg$fail(peg$c56); }
|
Daniel@0
|
13455 }
|
Daniel@0
|
13456 if (s0 === peg$FAILED) {
|
Daniel@0
|
13457 if (input.substr(peg$currPos, 5) === peg$c57) {
|
Daniel@0
|
13458 s0 = peg$c57;
|
Daniel@0
|
13459 peg$currPos += 5;
|
Daniel@0
|
13460 } else {
|
Daniel@0
|
13461 s0 = peg$FAILED;
|
Daniel@0
|
13462 if (peg$silentFails === 0) { peg$fail(peg$c58); }
|
Daniel@0
|
13463 }
|
Daniel@0
|
13464 if (s0 === peg$FAILED) {
|
Daniel@0
|
13465 if (input.substr(peg$currPos, 7) === peg$c59) {
|
Daniel@0
|
13466 s0 = peg$c59;
|
Daniel@0
|
13467 peg$currPos += 7;
|
Daniel@0
|
13468 } else {
|
Daniel@0
|
13469 s0 = peg$FAILED;
|
Daniel@0
|
13470 if (peg$silentFails === 0) { peg$fail(peg$c60); }
|
Daniel@0
|
13471 }
|
Daniel@0
|
13472 if (s0 === peg$FAILED) {
|
Daniel@0
|
13473 if (input.substr(peg$currPos, 8) === peg$c61) {
|
Daniel@0
|
13474 s0 = peg$c61;
|
Daniel@0
|
13475 peg$currPos += 8;
|
Daniel@0
|
13476 } else {
|
Daniel@0
|
13477 s0 = peg$FAILED;
|
Daniel@0
|
13478 if (peg$silentFails === 0) { peg$fail(peg$c62); }
|
Daniel@0
|
13479 }
|
Daniel@0
|
13480 if (s0 === peg$FAILED) {
|
Daniel@0
|
13481 if (input.substr(peg$currPos, 5) === peg$c63) {
|
Daniel@0
|
13482 s0 = peg$c63;
|
Daniel@0
|
13483 peg$currPos += 5;
|
Daniel@0
|
13484 } else {
|
Daniel@0
|
13485 s0 = peg$FAILED;
|
Daniel@0
|
13486 if (peg$silentFails === 0) { peg$fail(peg$c64); }
|
Daniel@0
|
13487 }
|
Daniel@0
|
13488 if (s0 === peg$FAILED) {
|
Daniel@0
|
13489 if (input.substr(peg$currPos, 10) === peg$c65) {
|
Daniel@0
|
13490 s0 = peg$c65;
|
Daniel@0
|
13491 peg$currPos += 10;
|
Daniel@0
|
13492 } else {
|
Daniel@0
|
13493 s0 = peg$FAILED;
|
Daniel@0
|
13494 if (peg$silentFails === 0) { peg$fail(peg$c66); }
|
Daniel@0
|
13495 }
|
Daniel@0
|
13496 if (s0 === peg$FAILED) {
|
Daniel@0
|
13497 if (input.substr(peg$currPos, 9) === peg$c67) {
|
Daniel@0
|
13498 s0 = peg$c67;
|
Daniel@0
|
13499 peg$currPos += 9;
|
Daniel@0
|
13500 } else {
|
Daniel@0
|
13501 s0 = peg$FAILED;
|
Daniel@0
|
13502 if (peg$silentFails === 0) { peg$fail(peg$c68); }
|
Daniel@0
|
13503 }
|
Daniel@0
|
13504 if (s0 === peg$FAILED) {
|
Daniel@0
|
13505 if (input.substr(peg$currPos, 8) === peg$c69) {
|
Daniel@0
|
13506 s0 = peg$c69;
|
Daniel@0
|
13507 peg$currPos += 8;
|
Daniel@0
|
13508 } else {
|
Daniel@0
|
13509 s0 = peg$FAILED;
|
Daniel@0
|
13510 if (peg$silentFails === 0) { peg$fail(peg$c70); }
|
Daniel@0
|
13511 }
|
Daniel@0
|
13512 if (s0 === peg$FAILED) {
|
Daniel@0
|
13513 if (input.substr(peg$currPos, 9) === peg$c71) {
|
Daniel@0
|
13514 s0 = peg$c71;
|
Daniel@0
|
13515 peg$currPos += 9;
|
Daniel@0
|
13516 } else {
|
Daniel@0
|
13517 s0 = peg$FAILED;
|
Daniel@0
|
13518 if (peg$silentFails === 0) { peg$fail(peg$c72); }
|
Daniel@0
|
13519 }
|
Daniel@0
|
13520 if (s0 === peg$FAILED) {
|
Daniel@0
|
13521 if (input.substr(peg$currPos, 10) === peg$c73) {
|
Daniel@0
|
13522 s0 = peg$c73;
|
Daniel@0
|
13523 peg$currPos += 10;
|
Daniel@0
|
13524 } else {
|
Daniel@0
|
13525 s0 = peg$FAILED;
|
Daniel@0
|
13526 if (peg$silentFails === 0) { peg$fail(peg$c74); }
|
Daniel@0
|
13527 }
|
Daniel@0
|
13528 if (s0 === peg$FAILED) {
|
Daniel@0
|
13529 if (input.substr(peg$currPos, 10) === peg$c75) {
|
Daniel@0
|
13530 s0 = peg$c75;
|
Daniel@0
|
13531 peg$currPos += 10;
|
Daniel@0
|
13532 } else {
|
Daniel@0
|
13533 s0 = peg$FAILED;
|
Daniel@0
|
13534 if (peg$silentFails === 0) { peg$fail(peg$c76); }
|
Daniel@0
|
13535 }
|
Daniel@0
|
13536 if (s0 === peg$FAILED) {
|
Daniel@0
|
13537 if (input.substr(peg$currPos, 9) === peg$c77) {
|
Daniel@0
|
13538 s0 = peg$c77;
|
Daniel@0
|
13539 peg$currPos += 9;
|
Daniel@0
|
13540 } else {
|
Daniel@0
|
13541 s0 = peg$FAILED;
|
Daniel@0
|
13542 if (peg$silentFails === 0) { peg$fail(peg$c78); }
|
Daniel@0
|
13543 }
|
Daniel@0
|
13544 if (s0 === peg$FAILED) {
|
Daniel@0
|
13545 if (input.substr(peg$currPos, 8) === peg$c79) {
|
Daniel@0
|
13546 s0 = peg$c79;
|
Daniel@0
|
13547 peg$currPos += 8;
|
Daniel@0
|
13548 } else {
|
Daniel@0
|
13549 s0 = peg$FAILED;
|
Daniel@0
|
13550 if (peg$silentFails === 0) { peg$fail(peg$c80); }
|
Daniel@0
|
13551 }
|
Daniel@0
|
13552 }
|
Daniel@0
|
13553 }
|
Daniel@0
|
13554 }
|
Daniel@0
|
13555 }
|
Daniel@0
|
13556 }
|
Daniel@0
|
13557 }
|
Daniel@0
|
13558 }
|
Daniel@0
|
13559 }
|
Daniel@0
|
13560 }
|
Daniel@0
|
13561 }
|
Daniel@0
|
13562 }
|
Daniel@0
|
13563 }
|
Daniel@0
|
13564 }
|
Daniel@0
|
13565 }
|
Daniel@0
|
13566 }
|
Daniel@0
|
13567
|
Daniel@0
|
13568 return s0;
|
Daniel@0
|
13569 }
|
Daniel@0
|
13570
|
Daniel@0
|
13571 function peg$parsefilter() {
|
Daniel@0
|
13572 var s0, s1, s2, s3;
|
Daniel@0
|
13573
|
Daniel@0
|
13574 s0 = peg$currPos;
|
Daniel@0
|
13575 if (input.charCodeAt(peg$currPos) === 91) {
|
Daniel@0
|
13576 s1 = peg$c5;
|
Daniel@0
|
13577 peg$currPos++;
|
Daniel@0
|
13578 } else {
|
Daniel@0
|
13579 s1 = peg$FAILED;
|
Daniel@0
|
13580 if (peg$silentFails === 0) { peg$fail(peg$c6); }
|
Daniel@0
|
13581 }
|
Daniel@0
|
13582 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13583 s2 = peg$parseexpr();
|
Daniel@0
|
13584 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13585 if (input.charCodeAt(peg$currPos) === 93) {
|
Daniel@0
|
13586 s3 = peg$c7;
|
Daniel@0
|
13587 peg$currPos++;
|
Daniel@0
|
13588 } else {
|
Daniel@0
|
13589 s3 = peg$FAILED;
|
Daniel@0
|
13590 if (peg$silentFails === 0) { peg$fail(peg$c8); }
|
Daniel@0
|
13591 }
|
Daniel@0
|
13592 if (s3 !== peg$FAILED) {
|
Daniel@0
|
13593 peg$reportedPos = s0;
|
Daniel@0
|
13594 s1 = peg$c81(s2);
|
Daniel@0
|
13595 s0 = s1;
|
Daniel@0
|
13596 } else {
|
Daniel@0
|
13597 peg$currPos = s0;
|
Daniel@0
|
13598 s0 = peg$c0;
|
Daniel@0
|
13599 }
|
Daniel@0
|
13600 } else {
|
Daniel@0
|
13601 peg$currPos = s0;
|
Daniel@0
|
13602 s0 = peg$c0;
|
Daniel@0
|
13603 }
|
Daniel@0
|
13604 } else {
|
Daniel@0
|
13605 peg$currPos = s0;
|
Daniel@0
|
13606 s0 = peg$c0;
|
Daniel@0
|
13607 }
|
Daniel@0
|
13608
|
Daniel@0
|
13609 return s0;
|
Daniel@0
|
13610 }
|
Daniel@0
|
13611
|
Daniel@0
|
13612 function peg$parsename() {
|
Daniel@0
|
13613 var s0, s1, s2;
|
Daniel@0
|
13614
|
Daniel@0
|
13615 s0 = peg$currPos;
|
Daniel@0
|
13616 s1 = [];
|
Daniel@0
|
13617 if (peg$c82.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13618 s2 = input.charAt(peg$currPos);
|
Daniel@0
|
13619 peg$currPos++;
|
Daniel@0
|
13620 } else {
|
Daniel@0
|
13621 s2 = peg$FAILED;
|
Daniel@0
|
13622 if (peg$silentFails === 0) { peg$fail(peg$c83); }
|
Daniel@0
|
13623 }
|
Daniel@0
|
13624 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13625 while (s2 !== peg$FAILED) {
|
Daniel@0
|
13626 s1.push(s2);
|
Daniel@0
|
13627 if (peg$c82.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13628 s2 = input.charAt(peg$currPos);
|
Daniel@0
|
13629 peg$currPos++;
|
Daniel@0
|
13630 } else {
|
Daniel@0
|
13631 s2 = peg$FAILED;
|
Daniel@0
|
13632 if (peg$silentFails === 0) { peg$fail(peg$c83); }
|
Daniel@0
|
13633 }
|
Daniel@0
|
13634 }
|
Daniel@0
|
13635 } else {
|
Daniel@0
|
13636 s1 = peg$c0;
|
Daniel@0
|
13637 }
|
Daniel@0
|
13638 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13639 peg$reportedPos = s0;
|
Daniel@0
|
13640 s1 = peg$c84(s1);
|
Daniel@0
|
13641 }
|
Daniel@0
|
13642 s0 = s1;
|
Daniel@0
|
13643
|
Daniel@0
|
13644 return s0;
|
Daniel@0
|
13645 }
|
Daniel@0
|
13646
|
Daniel@0
|
13647 function peg$parsecss() {
|
Daniel@0
|
13648 var s0, s1, s2;
|
Daniel@0
|
13649
|
Daniel@0
|
13650 s0 = peg$currPos;
|
Daniel@0
|
13651 s1 = [];
|
Daniel@0
|
13652 if (peg$c85.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13653 s2 = input.charAt(peg$currPos);
|
Daniel@0
|
13654 peg$currPos++;
|
Daniel@0
|
13655 } else {
|
Daniel@0
|
13656 s2 = peg$FAILED;
|
Daniel@0
|
13657 if (peg$silentFails === 0) { peg$fail(peg$c86); }
|
Daniel@0
|
13658 }
|
Daniel@0
|
13659 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13660 while (s2 !== peg$FAILED) {
|
Daniel@0
|
13661 s1.push(s2);
|
Daniel@0
|
13662 if (peg$c85.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13663 s2 = input.charAt(peg$currPos);
|
Daniel@0
|
13664 peg$currPos++;
|
Daniel@0
|
13665 } else {
|
Daniel@0
|
13666 s2 = peg$FAILED;
|
Daniel@0
|
13667 if (peg$silentFails === 0) { peg$fail(peg$c86); }
|
Daniel@0
|
13668 }
|
Daniel@0
|
13669 }
|
Daniel@0
|
13670 } else {
|
Daniel@0
|
13671 s1 = peg$c0;
|
Daniel@0
|
13672 }
|
Daniel@0
|
13673 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13674 peg$reportedPos = s0;
|
Daniel@0
|
13675 s1 = peg$c87(s1);
|
Daniel@0
|
13676 }
|
Daniel@0
|
13677 s0 = s1;
|
Daniel@0
|
13678
|
Daniel@0
|
13679 return s0;
|
Daniel@0
|
13680 }
|
Daniel@0
|
13681
|
Daniel@0
|
13682 function peg$parseexpr() {
|
Daniel@0
|
13683 var s0, s1, s2;
|
Daniel@0
|
13684
|
Daniel@0
|
13685 s0 = peg$currPos;
|
Daniel@0
|
13686 s1 = [];
|
Daniel@0
|
13687 if (peg$c88.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13688 s2 = input.charAt(peg$currPos);
|
Daniel@0
|
13689 peg$currPos++;
|
Daniel@0
|
13690 } else {
|
Daniel@0
|
13691 s2 = peg$FAILED;
|
Daniel@0
|
13692 if (peg$silentFails === 0) { peg$fail(peg$c89); }
|
Daniel@0
|
13693 }
|
Daniel@0
|
13694 if (s2 !== peg$FAILED) {
|
Daniel@0
|
13695 while (s2 !== peg$FAILED) {
|
Daniel@0
|
13696 s1.push(s2);
|
Daniel@0
|
13697 if (peg$c88.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13698 s2 = input.charAt(peg$currPos);
|
Daniel@0
|
13699 peg$currPos++;
|
Daniel@0
|
13700 } else {
|
Daniel@0
|
13701 s2 = peg$FAILED;
|
Daniel@0
|
13702 if (peg$silentFails === 0) { peg$fail(peg$c89); }
|
Daniel@0
|
13703 }
|
Daniel@0
|
13704 }
|
Daniel@0
|
13705 } else {
|
Daniel@0
|
13706 s1 = peg$c0;
|
Daniel@0
|
13707 }
|
Daniel@0
|
13708 if (s1 !== peg$FAILED) {
|
Daniel@0
|
13709 peg$reportedPos = s0;
|
Daniel@0
|
13710 s1 = peg$c90(s1);
|
Daniel@0
|
13711 }
|
Daniel@0
|
13712 s0 = s1;
|
Daniel@0
|
13713
|
Daniel@0
|
13714 return s0;
|
Daniel@0
|
13715 }
|
Daniel@0
|
13716
|
Daniel@0
|
13717 function peg$parsesep() {
|
Daniel@0
|
13718 var s0, s1;
|
Daniel@0
|
13719
|
Daniel@0
|
13720 s0 = [];
|
Daniel@0
|
13721 if (peg$c91.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13722 s1 = input.charAt(peg$currPos);
|
Daniel@0
|
13723 peg$currPos++;
|
Daniel@0
|
13724 } else {
|
Daniel@0
|
13725 s1 = peg$FAILED;
|
Daniel@0
|
13726 if (peg$silentFails === 0) { peg$fail(peg$c92); }
|
Daniel@0
|
13727 }
|
Daniel@0
|
13728 while (s1 !== peg$FAILED) {
|
Daniel@0
|
13729 s0.push(s1);
|
Daniel@0
|
13730 if (peg$c91.test(input.charAt(peg$currPos))) {
|
Daniel@0
|
13731 s1 = input.charAt(peg$currPos);
|
Daniel@0
|
13732 peg$currPos++;
|
Daniel@0
|
13733 } else {
|
Daniel@0
|
13734 s1 = peg$FAILED;
|
Daniel@0
|
13735 if (peg$silentFails === 0) { peg$fail(peg$c92); }
|
Daniel@0
|
13736 }
|
Daniel@0
|
13737 }
|
Daniel@0
|
13738
|
Daniel@0
|
13739 return s0;
|
Daniel@0
|
13740 }
|
Daniel@0
|
13741
|
Daniel@0
|
13742 peg$result = peg$startRuleFunction();
|
Daniel@0
|
13743
|
Daniel@0
|
13744 if (peg$result !== peg$FAILED && peg$currPos === input.length) {
|
Daniel@0
|
13745 return peg$result;
|
Daniel@0
|
13746 } else {
|
Daniel@0
|
13747 if (peg$result !== peg$FAILED && peg$currPos < input.length) {
|
Daniel@0
|
13748 peg$fail({ type: "end", description: "end of input" });
|
Daniel@0
|
13749 }
|
Daniel@0
|
13750
|
Daniel@0
|
13751 throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
|
Daniel@0
|
13752 }
|
Daniel@0
|
13753 }
|
Daniel@0
|
13754
|
Daniel@0
|
13755 return {
|
Daniel@0
|
13756 SyntaxError: SyntaxError,
|
Daniel@0
|
13757 parse: parse
|
Daniel@0
|
13758 };
|
Daniel@0
|
13759 })();
|
Daniel@0
|
13760 },{}],94:[function(require,module,exports){
|
Daniel@0
|
13761 var expr = require('vega-expression'),
|
Daniel@0
|
13762 args = ['datum', 'event', 'signals'];
|
Daniel@0
|
13763
|
Daniel@0
|
13764 module.exports = expr.compiler(args, {
|
Daniel@0
|
13765 idWhiteList: args,
|
Daniel@0
|
13766 fieldVar: args[0],
|
Daniel@0
|
13767 globalVar: args[2],
|
Daniel@0
|
13768 functions: function(codegen) {
|
Daniel@0
|
13769 var fn = expr.functions(codegen);
|
Daniel@0
|
13770 fn.eventItem = function() { return 'event.vg.item'; };
|
Daniel@0
|
13771 fn.eventGroup = 'event.vg.getGroup';
|
Daniel@0
|
13772 fn.eventX = 'event.vg.getX';
|
Daniel@0
|
13773 fn.eventY = 'event.vg.getY';
|
Daniel@0
|
13774 fn.open = 'window.open';
|
Daniel@0
|
13775 return fn;
|
Daniel@0
|
13776 }
|
Daniel@0
|
13777 });
|
Daniel@0
|
13778 },{"vega-expression":43}],95:[function(require,module,exports){
|
Daniel@0
|
13779 module.exports = {
|
Daniel@0
|
13780 axes: require('./axes'),
|
Daniel@0
|
13781 background: require('./background'),
|
Daniel@0
|
13782 data: require('./data'),
|
Daniel@0
|
13783 events: require('./events'),
|
Daniel@0
|
13784 expr: require('./expr'),
|
Daniel@0
|
13785 legends: require('./legends'),
|
Daniel@0
|
13786 mark: require('./mark'),
|
Daniel@0
|
13787 marks: require('./marks'),
|
Daniel@0
|
13788 modify: require('./modify'),
|
Daniel@0
|
13789 padding: require('./padding'),
|
Daniel@0
|
13790 predicates: require('./predicates'),
|
Daniel@0
|
13791 properties: require('./properties'),
|
Daniel@0
|
13792 signals: require('./signals'),
|
Daniel@0
|
13793 spec: require('./spec'),
|
Daniel@0
|
13794 streams: require('./streams'),
|
Daniel@0
|
13795 transforms: require('./transforms')
|
Daniel@0
|
13796 };
|
Daniel@0
|
13797 },{"./axes":90,"./background":91,"./data":92,"./events":93,"./expr":94,"./legends":96,"./mark":97,"./marks":98,"./modify":99,"./padding":100,"./predicates":101,"./properties":102,"./signals":103,"./spec":104,"./streams":105,"./transforms":106}],96:[function(require,module,exports){
|
Daniel@0
|
13798 var lgnd = require('../scene/legend');
|
Daniel@0
|
13799
|
Daniel@0
|
13800 function parseLegends(model, spec, legends, group) {
|
Daniel@0
|
13801 (spec || []).forEach(function(def, index) {
|
Daniel@0
|
13802 legends[index] = legends[index] || lgnd(model);
|
Daniel@0
|
13803 parseLegend(def, index, legends[index], group);
|
Daniel@0
|
13804 });
|
Daniel@0
|
13805 }
|
Daniel@0
|
13806
|
Daniel@0
|
13807 function parseLegend(def, index, legend, group) {
|
Daniel@0
|
13808 // legend scales
|
Daniel@0
|
13809 legend.size (def.size ? group.scale(def.size) : null);
|
Daniel@0
|
13810 legend.shape (def.shape ? group.scale(def.shape) : null);
|
Daniel@0
|
13811 legend.fill (def.fill ? group.scale(def.fill) : null);
|
Daniel@0
|
13812 legend.stroke(def.stroke ? group.scale(def.stroke) : null);
|
Daniel@0
|
13813
|
Daniel@0
|
13814 // legend orientation
|
Daniel@0
|
13815 if (def.orient) legend.orient(def.orient);
|
Daniel@0
|
13816
|
Daniel@0
|
13817 // legend offset
|
Daniel@0
|
13818 if (def.offset != null) legend.offset(def.offset);
|
Daniel@0
|
13819
|
Daniel@0
|
13820 // legend title
|
Daniel@0
|
13821 legend.title(def.title || null);
|
Daniel@0
|
13822
|
Daniel@0
|
13823 // legend values
|
Daniel@0
|
13824 legend.values(def.values || null);
|
Daniel@0
|
13825
|
Daniel@0
|
13826 // legend label formatting
|
Daniel@0
|
13827 legend.format(def.format !== undefined ? def.format : null);
|
Daniel@0
|
13828
|
Daniel@0
|
13829 // style properties
|
Daniel@0
|
13830 var p = def.properties;
|
Daniel@0
|
13831 legend.titleProperties(p && p.title || {});
|
Daniel@0
|
13832 legend.labelProperties(p && p.labels || {});
|
Daniel@0
|
13833 legend.legendProperties(p && p.legend || {});
|
Daniel@0
|
13834 legend.symbolProperties(p && p.symbols || {});
|
Daniel@0
|
13835 legend.gradientProperties(p && p.gradient || {});
|
Daniel@0
|
13836 }
|
Daniel@0
|
13837
|
Daniel@0
|
13838 module.exports = parseLegends;
|
Daniel@0
|
13839 },{"../scene/legend":114}],97:[function(require,module,exports){
|
Daniel@0
|
13840 var dl = require('datalib'),
|
Daniel@0
|
13841 parseProperties = require('./properties');
|
Daniel@0
|
13842
|
Daniel@0
|
13843 function parseMark(model, mark) {
|
Daniel@0
|
13844 var props = mark.properties,
|
Daniel@0
|
13845 group = mark.marks;
|
Daniel@0
|
13846
|
Daniel@0
|
13847 // parse mark property definitions
|
Daniel@0
|
13848 dl.keys(props).forEach(function(k) {
|
Daniel@0
|
13849 props[k] = parseProperties(model, mark.type, props[k]);
|
Daniel@0
|
13850 });
|
Daniel@0
|
13851
|
Daniel@0
|
13852 // parse delay function
|
Daniel@0
|
13853 if (mark.delay) {
|
Daniel@0
|
13854 mark.delay = parseProperties(model, mark.type, {delay: mark.delay});
|
Daniel@0
|
13855 }
|
Daniel@0
|
13856
|
Daniel@0
|
13857 // recurse if group type
|
Daniel@0
|
13858 if (group) {
|
Daniel@0
|
13859 mark.marks = group.map(function(g) { return parseMark(model, g); });
|
Daniel@0
|
13860 }
|
Daniel@0
|
13861
|
Daniel@0
|
13862 return mark;
|
Daniel@0
|
13863 }
|
Daniel@0
|
13864
|
Daniel@0
|
13865 module.exports = parseMark;
|
Daniel@0
|
13866 },{"./properties":102,"datalib":24}],98:[function(require,module,exports){
|
Daniel@0
|
13867 var parseMark = require('./mark');
|
Daniel@0
|
13868
|
Daniel@0
|
13869 function parseRootMark(model, spec, width, height) {
|
Daniel@0
|
13870 return {
|
Daniel@0
|
13871 type: "group",
|
Daniel@0
|
13872 width: width,
|
Daniel@0
|
13873 height: height,
|
Daniel@0
|
13874 scales: spec.scales || [],
|
Daniel@0
|
13875 axes: spec.axes || [],
|
Daniel@0
|
13876 legends: spec.legends || [],
|
Daniel@0
|
13877 marks: (spec.marks || []).map(function(m) { return parseMark(model, m); })
|
Daniel@0
|
13878 };
|
Daniel@0
|
13879 }
|
Daniel@0
|
13880
|
Daniel@0
|
13881 module.exports = parseRootMark;
|
Daniel@0
|
13882 },{"./mark":97}],99:[function(require,module,exports){
|
Daniel@0
|
13883 var dl = require('datalib'),
|
Daniel@0
|
13884 log = require('vega-logging'),
|
Daniel@0
|
13885 df = require('vega-dataflow'),
|
Daniel@0
|
13886 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
13887 Tuple = df.Tuple,
|
Daniel@0
|
13888 Deps = df.Dependencies;
|
Daniel@0
|
13889
|
Daniel@0
|
13890 var Types = {
|
Daniel@0
|
13891 INSERT: "insert",
|
Daniel@0
|
13892 REMOVE: "remove",
|
Daniel@0
|
13893 TOGGLE: "toggle",
|
Daniel@0
|
13894 CLEAR: "clear"
|
Daniel@0
|
13895 };
|
Daniel@0
|
13896
|
Daniel@0
|
13897 var EMPTY = [];
|
Daniel@0
|
13898
|
Daniel@0
|
13899 var filter = function(field, value, src, dest) {
|
Daniel@0
|
13900 for(var i = src.length-1; i >= 0; --i) {
|
Daniel@0
|
13901 if (src[i][field] == value)
|
Daniel@0
|
13902 dest.push.apply(dest, src.splice(i, 1));
|
Daniel@0
|
13903 }
|
Daniel@0
|
13904 };
|
Daniel@0
|
13905
|
Daniel@0
|
13906 function parseModify(model, def, ds) {
|
Daniel@0
|
13907 var signal = def.signal ? dl.field(def.signal) : null,
|
Daniel@0
|
13908 signalName = signal ? signal[0] : null,
|
Daniel@0
|
13909 predicate = def.predicate ? model.predicate(def.predicate.name || def.predicate) : null,
|
Daniel@0
|
13910 reeval = (predicate === null),
|
Daniel@0
|
13911 node = new Node(model).router(def.type === Types.CLEAR);
|
Daniel@0
|
13912
|
Daniel@0
|
13913 node.evaluate = function(input) {
|
Daniel@0
|
13914 if (predicate !== null) { // TODO: predicate args
|
Daniel@0
|
13915 var db = model.values(Deps.DATA, predicate.data || EMPTY),
|
Daniel@0
|
13916 sg = model.values(Deps.SIGNALS, predicate.signals || EMPTY);
|
Daniel@0
|
13917 reeval = predicate.call(predicate, {}, db, sg, model._predicates);
|
Daniel@0
|
13918 }
|
Daniel@0
|
13919
|
Daniel@0
|
13920 log.debug(input, [def.type+"ing", reeval]);
|
Daniel@0
|
13921 if (!reeval) return input;
|
Daniel@0
|
13922
|
Daniel@0
|
13923 var datum = {},
|
Daniel@0
|
13924 value = signal ? model.signalRef(def.signal) : null,
|
Daniel@0
|
13925 d = model.data(ds.name),
|
Daniel@0
|
13926 t = null;
|
Daniel@0
|
13927
|
Daniel@0
|
13928 datum[def.field] = value;
|
Daniel@0
|
13929
|
Daniel@0
|
13930 // We have to modify ds._data so that subsequent pulses contain
|
Daniel@0
|
13931 // our dynamic data. W/o modifying ds._data, only the output
|
Daniel@0
|
13932 // collector will contain dynamic tuples.
|
Daniel@0
|
13933 if (def.type === Types.INSERT) {
|
Daniel@0
|
13934 t = Tuple.ingest(datum);
|
Daniel@0
|
13935 input.add.push(t);
|
Daniel@0
|
13936 d._data.push(t);
|
Daniel@0
|
13937 } else if (def.type === Types.REMOVE) {
|
Daniel@0
|
13938 filter(def.field, value, input.add, input.rem);
|
Daniel@0
|
13939 filter(def.field, value, input.mod, input.rem);
|
Daniel@0
|
13940 d._data = d._data.filter(function(x) { return x[def.field] !== value; });
|
Daniel@0
|
13941 } else if (def.type === Types.TOGGLE) {
|
Daniel@0
|
13942 var add = [], rem = [];
|
Daniel@0
|
13943 filter(def.field, value, input.rem, add);
|
Daniel@0
|
13944 filter(def.field, value, input.add, rem);
|
Daniel@0
|
13945 filter(def.field, value, input.mod, rem);
|
Daniel@0
|
13946 if (!(add.length || rem.length)) add.push(Tuple.ingest(datum));
|
Daniel@0
|
13947
|
Daniel@0
|
13948 input.add.push.apply(input.add, add);
|
Daniel@0
|
13949 d._data.push.apply(d._data, add);
|
Daniel@0
|
13950 input.rem.push.apply(input.rem, rem);
|
Daniel@0
|
13951 d._data = d._data.filter(function(x) { return rem.indexOf(x) === -1; });
|
Daniel@0
|
13952 } else if (def.type === Types.CLEAR) {
|
Daniel@0
|
13953 input.rem.push.apply(input.rem, input.add);
|
Daniel@0
|
13954 input.rem.push.apply(input.rem, input.mod);
|
Daniel@0
|
13955 input.add = [];
|
Daniel@0
|
13956 input.mod = [];
|
Daniel@0
|
13957 d._data = [];
|
Daniel@0
|
13958 }
|
Daniel@0
|
13959
|
Daniel@0
|
13960 input.fields[def.field] = 1;
|
Daniel@0
|
13961 return input;
|
Daniel@0
|
13962 };
|
Daniel@0
|
13963
|
Daniel@0
|
13964 if (signalName) node.dependency(Deps.SIGNALS, signalName);
|
Daniel@0
|
13965
|
Daniel@0
|
13966 if (predicate) {
|
Daniel@0
|
13967 node.dependency(Deps.DATA, predicate.data);
|
Daniel@0
|
13968 node.dependency(Deps.SIGNALS, predicate.signals);
|
Daniel@0
|
13969 }
|
Daniel@0
|
13970
|
Daniel@0
|
13971 return node;
|
Daniel@0
|
13972 }
|
Daniel@0
|
13973
|
Daniel@0
|
13974 module.exports = parseModify;
|
Daniel@0
|
13975 },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],100:[function(require,module,exports){
|
Daniel@0
|
13976 var dl = require('datalib');
|
Daniel@0
|
13977
|
Daniel@0
|
13978 function parsePadding(pad) {
|
Daniel@0
|
13979 if (pad == null) return "auto";
|
Daniel@0
|
13980 else if (dl.isString(pad)) return pad==="strict" ? "strict" : "auto";
|
Daniel@0
|
13981 else if (dl.isObject(pad)) return pad;
|
Daniel@0
|
13982 var p = dl.isNumber(pad) ? pad : 20;
|
Daniel@0
|
13983 return {top:p, left:p, right:p, bottom:p};
|
Daniel@0
|
13984 }
|
Daniel@0
|
13985
|
Daniel@0
|
13986 module.exports = parsePadding;
|
Daniel@0
|
13987 },{"datalib":24}],101:[function(require,module,exports){
|
Daniel@0
|
13988 var dl = require('datalib');
|
Daniel@0
|
13989
|
Daniel@0
|
13990 var types = {
|
Daniel@0
|
13991 '=': parseComparator,
|
Daniel@0
|
13992 '==': parseComparator,
|
Daniel@0
|
13993 '!=': parseComparator,
|
Daniel@0
|
13994 '>': parseComparator,
|
Daniel@0
|
13995 '>=': parseComparator,
|
Daniel@0
|
13996 '<': parseComparator,
|
Daniel@0
|
13997 '<=': parseComparator,
|
Daniel@0
|
13998 'and': parseLogical,
|
Daniel@0
|
13999 '&&': parseLogical,
|
Daniel@0
|
14000 'or': parseLogical,
|
Daniel@0
|
14001 '||': parseLogical,
|
Daniel@0
|
14002 'in': parseIn
|
Daniel@0
|
14003 };
|
Daniel@0
|
14004
|
Daniel@0
|
14005 var nullScale = function() { return 0; };
|
Daniel@0
|
14006 nullScale.invert = nullScale;
|
Daniel@0
|
14007
|
Daniel@0
|
14008 function parsePredicates(model, spec) {
|
Daniel@0
|
14009 (spec || []).forEach(function(s) {
|
Daniel@0
|
14010 var parse = types[s.type](model, s);
|
Daniel@0
|
14011
|
Daniel@0
|
14012 /* jshint evil:true */
|
Daniel@0
|
14013 var pred = Function("args", "db", "signals", "predicates", parse.code);
|
Daniel@0
|
14014 pred.root = function() { return model.scene().items[0]; }; // For global scales
|
Daniel@0
|
14015 pred.nullScale = nullScale;
|
Daniel@0
|
14016 pred.isFunction = dl.isFunction;
|
Daniel@0
|
14017 pred.signals = parse.signals;
|
Daniel@0
|
14018 pred.data = parse.data;
|
Daniel@0
|
14019
|
Daniel@0
|
14020 model.predicate(s.name, pred);
|
Daniel@0
|
14021 });
|
Daniel@0
|
14022
|
Daniel@0
|
14023 return spec;
|
Daniel@0
|
14024 }
|
Daniel@0
|
14025
|
Daniel@0
|
14026 function parseSignal(signal, signals) {
|
Daniel@0
|
14027 var s = dl.field(signal),
|
Daniel@0
|
14028 code = "signals["+s.map(dl.str).join("][")+"]";
|
Daniel@0
|
14029 signals[s[0]] = 1;
|
Daniel@0
|
14030 return code;
|
Daniel@0
|
14031 }
|
Daniel@0
|
14032
|
Daniel@0
|
14033 function parseOperands(model, operands) {
|
Daniel@0
|
14034 var decl = [], defs = [],
|
Daniel@0
|
14035 signals = {}, db = {};
|
Daniel@0
|
14036
|
Daniel@0
|
14037 function setSignal(s) { signals[s] = 1; }
|
Daniel@0
|
14038 function setData(d) { db[d] = 1; }
|
Daniel@0
|
14039
|
Daniel@0
|
14040 dl.array(operands).forEach(function(o, i) {
|
Daniel@0
|
14041 var name = "o" + i,
|
Daniel@0
|
14042 def = "";
|
Daniel@0
|
14043
|
Daniel@0
|
14044 if (o.value !== undefined) {
|
Daniel@0
|
14045 def = dl.str(o.value);
|
Daniel@0
|
14046 } else if (o.arg) {
|
Daniel@0
|
14047 def = "args["+dl.str(o.arg)+"]";
|
Daniel@0
|
14048 } else if (o.signal) {
|
Daniel@0
|
14049 def = parseSignal(o.signal, signals);
|
Daniel@0
|
14050 } else if (o.predicate) {
|
Daniel@0
|
14051 var ref = o.predicate,
|
Daniel@0
|
14052 predName = ref && (ref.name || ref),
|
Daniel@0
|
14053 pred = model.predicate(predName),
|
Daniel@0
|
14054 p = "predicates["+dl.str(predName)+"]";
|
Daniel@0
|
14055
|
Daniel@0
|
14056 pred.signals.forEach(setSignal);
|
Daniel@0
|
14057 pred.data.forEach(setData);
|
Daniel@0
|
14058
|
Daniel@0
|
14059 if (dl.isObject(ref)) {
|
Daniel@0
|
14060 dl.keys(ref).forEach(function(k) {
|
Daniel@0
|
14061 if (k === "name") return;
|
Daniel@0
|
14062 var i = ref[k];
|
Daniel@0
|
14063 def += "args["+dl.str(k)+"] = ";
|
Daniel@0
|
14064 if (i.signal) {
|
Daniel@0
|
14065 def += parseSignal(i.signal, signals);
|
Daniel@0
|
14066 } else if (i.arg) {
|
Daniel@0
|
14067 def += "args["+dl.str(i.arg)+"]";
|
Daniel@0
|
14068 }
|
Daniel@0
|
14069 def += ", ";
|
Daniel@0
|
14070 });
|
Daniel@0
|
14071 }
|
Daniel@0
|
14072
|
Daniel@0
|
14073 def += p+".call("+p+", args, db, signals, predicates)";
|
Daniel@0
|
14074 }
|
Daniel@0
|
14075
|
Daniel@0
|
14076 decl.push(name);
|
Daniel@0
|
14077 defs.push(name+"=("+def+")");
|
Daniel@0
|
14078 });
|
Daniel@0
|
14079
|
Daniel@0
|
14080 return {
|
Daniel@0
|
14081 code: "var " + decl.join(", ") + ";\n" + defs.join(";\n") + ";\n",
|
Daniel@0
|
14082 signals: dl.keys(signals),
|
Daniel@0
|
14083 data: dl.keys(db)
|
Daniel@0
|
14084 };
|
Daniel@0
|
14085 }
|
Daniel@0
|
14086
|
Daniel@0
|
14087 function parseComparator(model, spec) {
|
Daniel@0
|
14088 var ops = parseOperands(model, spec.operands);
|
Daniel@0
|
14089 if (spec.type === '=') spec.type = '==';
|
Daniel@0
|
14090
|
Daniel@0
|
14091 ops.code += "o0 = o0 instanceof Date ? o0.getTime() : o0;\n" +
|
Daniel@0
|
14092 "o1 = o1 instanceof Date ? o1.getTime() : o1;\n";
|
Daniel@0
|
14093
|
Daniel@0
|
14094 return {
|
Daniel@0
|
14095 code: ops.code + "return " + ["o0", "o1"].join(spec.type) + ";",
|
Daniel@0
|
14096 signals: ops.signals,
|
Daniel@0
|
14097 data: ops.data
|
Daniel@0
|
14098 };
|
Daniel@0
|
14099 }
|
Daniel@0
|
14100
|
Daniel@0
|
14101 function parseLogical(model, spec) {
|
Daniel@0
|
14102 var ops = parseOperands(model, spec.operands),
|
Daniel@0
|
14103 o = [], i = 0, len = spec.operands.length;
|
Daniel@0
|
14104
|
Daniel@0
|
14105 while (o.push("o"+i++) < len);
|
Daniel@0
|
14106 if (spec.type === 'and') spec.type = '&&';
|
Daniel@0
|
14107 else if (spec.type === 'or') spec.type = '||';
|
Daniel@0
|
14108
|
Daniel@0
|
14109 return {
|
Daniel@0
|
14110 code: ops.code + "return " + o.join(spec.type) + ";",
|
Daniel@0
|
14111 signals: ops.signals,
|
Daniel@0
|
14112 data: ops.data
|
Daniel@0
|
14113 };
|
Daniel@0
|
14114 }
|
Daniel@0
|
14115
|
Daniel@0
|
14116 function parseIn(model, spec) {
|
Daniel@0
|
14117 var o = [spec.item], code = "";
|
Daniel@0
|
14118 if (spec.range) o.push.apply(o, spec.range);
|
Daniel@0
|
14119 if (spec.scale) {
|
Daniel@0
|
14120 code = parseScale(spec.scale, o);
|
Daniel@0
|
14121 }
|
Daniel@0
|
14122
|
Daniel@0
|
14123 var ops = parseOperands(model, o);
|
Daniel@0
|
14124 code = ops.code + code + "\n var ordSet = null;\n";
|
Daniel@0
|
14125
|
Daniel@0
|
14126 if (spec.data) {
|
Daniel@0
|
14127 var field = dl.field(spec.field).map(dl.str);
|
Daniel@0
|
14128 code += "var where = function(d) { return d["+field.join("][")+"] == o0 };\n";
|
Daniel@0
|
14129 code += "return db["+dl.str(spec.data)+"].filter(where).length > 0;";
|
Daniel@0
|
14130 } else if (spec.range) {
|
Daniel@0
|
14131 // TODO: inclusive/exclusive range?
|
Daniel@0
|
14132 if (spec.scale) {
|
Daniel@0
|
14133 code += "if (scale.length == 2) {\n" + // inverting ordinal scales
|
Daniel@0
|
14134 " ordSet = scale(o1, o2);\n" +
|
Daniel@0
|
14135 "} else {\n" +
|
Daniel@0
|
14136 " o1 = scale(o1);\no2 = scale(o2);\n" +
|
Daniel@0
|
14137 "}";
|
Daniel@0
|
14138 }
|
Daniel@0
|
14139
|
Daniel@0
|
14140 code += "return ordSet !== null ? ordSet.indexOf(o0) !== -1 :\n" +
|
Daniel@0
|
14141 " o1 < o2 ? o1 <= o0 && o0 <= o2 : o2 <= o0 && o0 <= o1;";
|
Daniel@0
|
14142 }
|
Daniel@0
|
14143
|
Daniel@0
|
14144 return {
|
Daniel@0
|
14145 code: code,
|
Daniel@0
|
14146 signals: ops.signals,
|
Daniel@0
|
14147 data: ops.data.concat(spec.data ? [spec.data] : [])
|
Daniel@0
|
14148 };
|
Daniel@0
|
14149 }
|
Daniel@0
|
14150
|
Daniel@0
|
14151 // Populate ops such that ultimate scale/inversion function will be in `scale` var.
|
Daniel@0
|
14152 function parseScale(spec, ops) {
|
Daniel@0
|
14153 var code = "var scale = ",
|
Daniel@0
|
14154 idx = ops.length;
|
Daniel@0
|
14155
|
Daniel@0
|
14156 if (dl.isString(spec)) {
|
Daniel@0
|
14157 ops.push({ value: spec });
|
Daniel@0
|
14158 code += "this.root().scale(o"+idx+")";
|
Daniel@0
|
14159 } else if (spec.arg) { // Scale function is being passed as an arg
|
Daniel@0
|
14160 ops.push(spec);
|
Daniel@0
|
14161 code += "o"+idx;
|
Daniel@0
|
14162 } else if (spec.name) { // Full scale parameter {name: ..}
|
Daniel@0
|
14163 ops.push(dl.isString(spec.name) ? {value: spec.name} : spec.name);
|
Daniel@0
|
14164 code += "(this.isFunction(o"+idx+") ? o"+idx+" : ";
|
Daniel@0
|
14165 if (spec.scope) {
|
Daniel@0
|
14166 ops.push(spec.scope);
|
Daniel@0
|
14167 code += "((o"+(idx+1)+".scale || this.root().scale)(o"+idx+") || this.nullScale)";
|
Daniel@0
|
14168 } else {
|
Daniel@0
|
14169 code += "this.root().scale(o"+idx+")";
|
Daniel@0
|
14170 }
|
Daniel@0
|
14171 code += ")";
|
Daniel@0
|
14172 }
|
Daniel@0
|
14173
|
Daniel@0
|
14174 if (spec.invert === true) { // Allow spec.invert.arg?
|
Daniel@0
|
14175 code += ".invert";
|
Daniel@0
|
14176 }
|
Daniel@0
|
14177
|
Daniel@0
|
14178 return code+";\n";
|
Daniel@0
|
14179 }
|
Daniel@0
|
14180
|
Daniel@0
|
14181 module.exports = parsePredicates;
|
Daniel@0
|
14182 },{"datalib":24}],102:[function(require,module,exports){
|
Daniel@0
|
14183 (function (global){
|
Daniel@0
|
14184 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
14185 dl = require('datalib'),
|
Daniel@0
|
14186 log = require('vega-logging'),
|
Daniel@0
|
14187 Tuple = require('vega-dataflow').Tuple;
|
Daniel@0
|
14188
|
Daniel@0
|
14189 var DEPS = ["signals", "scales", "data", "fields"];
|
Daniel@0
|
14190
|
Daniel@0
|
14191 function properties(model, mark, spec) {
|
Daniel@0
|
14192 var config = model.config(),
|
Daniel@0
|
14193 code = "",
|
Daniel@0
|
14194 names = dl.keys(spec),
|
Daniel@0
|
14195 i, len, name, ref, vars = {},
|
Daniel@0
|
14196 deps = {
|
Daniel@0
|
14197 signals: {},
|
Daniel@0
|
14198 scales: {},
|
Daniel@0
|
14199 data: {},
|
Daniel@0
|
14200 fields: {},
|
Daniel@0
|
14201 nested: [],
|
Daniel@0
|
14202 _nRefs: {}, // Temp stash to de-dupe nested refs.
|
Daniel@0
|
14203 reflow: false
|
Daniel@0
|
14204 };
|
Daniel@0
|
14205
|
Daniel@0
|
14206 code += "var o = trans ? {} : item, d=0, set=this.tpl.set, tmpl=signals||{}, t;\n" +
|
Daniel@0
|
14207 // Stash for dl.template
|
Daniel@0
|
14208 "tmpl.datum = item.datum;\n" +
|
Daniel@0
|
14209 "tmpl.group = group;\n" +
|
Daniel@0
|
14210 "tmpl.parent = group.datum;\n";
|
Daniel@0
|
14211
|
Daniel@0
|
14212 function handleDep(p) {
|
Daniel@0
|
14213 if (ref[p] == null) return;
|
Daniel@0
|
14214 var k = dl.array(ref[p]), i, n;
|
Daniel@0
|
14215 for (i=0, n=k.length; i<n; ++i) {
|
Daniel@0
|
14216 deps[p][k[i]] = 1;
|
Daniel@0
|
14217 }
|
Daniel@0
|
14218 }
|
Daniel@0
|
14219
|
Daniel@0
|
14220 function handleNestedRefs(r) {
|
Daniel@0
|
14221 var k = (r.parent ? "parent_" : "group_")+r.level;
|
Daniel@0
|
14222 deps._nRefs[k] = r;
|
Daniel@0
|
14223 }
|
Daniel@0
|
14224
|
Daniel@0
|
14225 for (i=0, len=names.length; i<len; ++i) {
|
Daniel@0
|
14226 ref = spec[name = names[i]];
|
Daniel@0
|
14227 code += (i > 0) ? "\n " : " ";
|
Daniel@0
|
14228 if (ref.rule) {
|
Daniel@0
|
14229 ref = rule(model, name, ref.rule);
|
Daniel@0
|
14230 code += "\n " + ref.code;
|
Daniel@0
|
14231 } else {
|
Daniel@0
|
14232 ref = valueRef(config, name, ref);
|
Daniel@0
|
14233 code += "d += set(o, "+dl.str(name)+", "+ref.val+");";
|
Daniel@0
|
14234 }
|
Daniel@0
|
14235
|
Daniel@0
|
14236 vars[name] = true;
|
Daniel@0
|
14237 DEPS.forEach(handleDep);
|
Daniel@0
|
14238 deps.reflow = deps.reflow || ref.reflow;
|
Daniel@0
|
14239 if (ref.nested.length) ref.nested.forEach(handleNestedRefs);
|
Daniel@0
|
14240 }
|
Daniel@0
|
14241
|
Daniel@0
|
14242 // If nested references are present, sort them based on their level
|
Daniel@0
|
14243 // to speed up determination of whether encoders should be reeval'd.
|
Daniel@0
|
14244 dl.keys(deps._nRefs).forEach(function(k) { deps.nested.push(deps._nRefs[k]); });
|
Daniel@0
|
14245 deps.nested.sort(function(a, b) {
|
Daniel@0
|
14246 a = a.level;
|
Daniel@0
|
14247 b = b.level;
|
Daniel@0
|
14248 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
Daniel@0
|
14249 });
|
Daniel@0
|
14250
|
Daniel@0
|
14251 if (vars.x2) {
|
Daniel@0
|
14252 if (vars.x) {
|
Daniel@0
|
14253 code += "\n if (o.x > o.x2) { " +
|
Daniel@0
|
14254 "\n t = o.x;" +
|
Daniel@0
|
14255 "\n d += set(o, 'x', o.x2);" +
|
Daniel@0
|
14256 "\n d += set(o, 'x2', t); " +
|
Daniel@0
|
14257 "\n };";
|
Daniel@0
|
14258 code += "\n d += set(o, 'width', (o.x2 - o.x));";
|
Daniel@0
|
14259 } else if (vars.width) {
|
Daniel@0
|
14260 code += "\n d += set(o, 'x', (o.x2 - o.width));";
|
Daniel@0
|
14261 } else {
|
Daniel@0
|
14262 code += "\n d += set(o, 'x', o.x2);";
|
Daniel@0
|
14263 }
|
Daniel@0
|
14264 }
|
Daniel@0
|
14265
|
Daniel@0
|
14266 if (vars.xc) {
|
Daniel@0
|
14267 if (vars.width) {
|
Daniel@0
|
14268 code += "\n d += set(o, 'x', (o.xc - o.width/2));" ;
|
Daniel@0
|
14269 } else {
|
Daniel@0
|
14270 code += "\n d += set(o, 'x', o.xc);" ;
|
Daniel@0
|
14271 }
|
Daniel@0
|
14272 }
|
Daniel@0
|
14273
|
Daniel@0
|
14274 if (vars.y2) {
|
Daniel@0
|
14275 if (vars.y) {
|
Daniel@0
|
14276 code += "\n if (o.y > o.y2) { " +
|
Daniel@0
|
14277 "\n t = o.y;" +
|
Daniel@0
|
14278 "\n d += set(o, 'y', o.y2);" +
|
Daniel@0
|
14279 "\n d += set(o, 'y2', t);" +
|
Daniel@0
|
14280 "\n };";
|
Daniel@0
|
14281 code += "\n d += set(o, 'height', (o.y2 - o.y));";
|
Daniel@0
|
14282 } else if (vars.height) {
|
Daniel@0
|
14283 code += "\n d += set(o, 'y', (o.y2 - o.height));";
|
Daniel@0
|
14284 } else {
|
Daniel@0
|
14285 code += "\n d += set(o, 'y', o.y2);";
|
Daniel@0
|
14286 }
|
Daniel@0
|
14287 }
|
Daniel@0
|
14288
|
Daniel@0
|
14289 if (vars.yc) {
|
Daniel@0
|
14290 if (vars.height) {
|
Daniel@0
|
14291 code += "\n d += set(o, 'y', (o.yc - o.height/2));" ;
|
Daniel@0
|
14292 } else {
|
Daniel@0
|
14293 code += "\n d += set(o, 'y', o.yc);" ;
|
Daniel@0
|
14294 }
|
Daniel@0
|
14295 }
|
Daniel@0
|
14296
|
Daniel@0
|
14297 if (hasPath(mark, vars)) code += "\n d += (item.touch(), 1);";
|
Daniel@0
|
14298 code += "\n if (trans) trans.interpolate(item, o);";
|
Daniel@0
|
14299 code += "\n return d > 0;";
|
Daniel@0
|
14300
|
Daniel@0
|
14301 try {
|
Daniel@0
|
14302 /* jshint evil:true */
|
Daniel@0
|
14303 var encoder = Function('item', 'group', 'trans', 'db',
|
Daniel@0
|
14304 'signals', 'predicates', code);
|
Daniel@0
|
14305 encoder.tpl = Tuple;
|
Daniel@0
|
14306 encoder.util = dl;
|
Daniel@0
|
14307 encoder.d3 = d3; // For color spaces
|
Daniel@0
|
14308 dl.extend(encoder, dl.template.context);
|
Daniel@0
|
14309 return {
|
Daniel@0
|
14310 encode: encoder,
|
Daniel@0
|
14311 signals: dl.keys(deps.signals),
|
Daniel@0
|
14312 scales: dl.keys(deps.scales),
|
Daniel@0
|
14313 data: dl.keys(deps.data),
|
Daniel@0
|
14314 fields: dl.keys(deps.fields),
|
Daniel@0
|
14315 nested: deps.nested,
|
Daniel@0
|
14316 reflow: deps.reflow
|
Daniel@0
|
14317 };
|
Daniel@0
|
14318 } catch (e) {
|
Daniel@0
|
14319 log.error(e);
|
Daniel@0
|
14320 log.log(code);
|
Daniel@0
|
14321 }
|
Daniel@0
|
14322 }
|
Daniel@0
|
14323
|
Daniel@0
|
14324 function dependencies(a, b) {
|
Daniel@0
|
14325 if (!dl.isObject(a)) {
|
Daniel@0
|
14326 a = {reflow: false, nested: []};
|
Daniel@0
|
14327 DEPS.forEach(function(d) { a[d] = []; });
|
Daniel@0
|
14328 }
|
Daniel@0
|
14329
|
Daniel@0
|
14330 if (dl.isObject(b)) {
|
Daniel@0
|
14331 a.reflow = a.reflow || b.reflow;
|
Daniel@0
|
14332 a.nested.push.apply(a.nested, b.nested);
|
Daniel@0
|
14333 DEPS.forEach(function(d) { a[d].push.apply(a[d], b[d]); });
|
Daniel@0
|
14334 }
|
Daniel@0
|
14335
|
Daniel@0
|
14336 return a;
|
Daniel@0
|
14337 }
|
Daniel@0
|
14338
|
Daniel@0
|
14339 function hasPath(mark, vars) {
|
Daniel@0
|
14340 return vars.path ||
|
Daniel@0
|
14341 ((mark==='area' || mark==='line') &&
|
Daniel@0
|
14342 (vars.x || vars.x2 || vars.width ||
|
Daniel@0
|
14343 vars.y || vars.y2 || vars.height ||
|
Daniel@0
|
14344 vars.tension || vars.interpolate));
|
Daniel@0
|
14345 }
|
Daniel@0
|
14346
|
Daniel@0
|
14347 function rule(model, name, rules) {
|
Daniel@0
|
14348 var config = model.config(),
|
Daniel@0
|
14349 deps = dependencies(),
|
Daniel@0
|
14350 inputs = [], code = '';
|
Daniel@0
|
14351
|
Daniel@0
|
14352 (rules||[]).forEach(function(r, i) {
|
Daniel@0
|
14353 var def = r.predicate,
|
Daniel@0
|
14354 predName = def && (def.name || def),
|
Daniel@0
|
14355 pred = model.predicate(predName),
|
Daniel@0
|
14356 p = 'predicates['+dl.str(predName)+']',
|
Daniel@0
|
14357 input = [], args = name+'_arg'+i,
|
Daniel@0
|
14358 ref;
|
Daniel@0
|
14359
|
Daniel@0
|
14360 if (dl.isObject(def)) {
|
Daniel@0
|
14361 dl.keys(def).forEach(function(k) {
|
Daniel@0
|
14362 if (k === 'name') return;
|
Daniel@0
|
14363 var ref = valueRef(config, i, def[k]);
|
Daniel@0
|
14364 input.push(dl.str(k)+': '+ref.val);
|
Daniel@0
|
14365 dependencies(deps, ref);
|
Daniel@0
|
14366 });
|
Daniel@0
|
14367 }
|
Daniel@0
|
14368
|
Daniel@0
|
14369 ref = valueRef(config, name, r);
|
Daniel@0
|
14370 dependencies(deps, ref);
|
Daniel@0
|
14371
|
Daniel@0
|
14372 if (predName) {
|
Daniel@0
|
14373 deps.signals.push.apply(deps.signals, pred.signals);
|
Daniel@0
|
14374 deps.data.push.apply(deps.data, pred.data);
|
Daniel@0
|
14375 inputs.push(args+" = {\n "+input.join(",\n ")+"\n }");
|
Daniel@0
|
14376 code += "if ("+p+".call("+p+","+args+", db, signals, predicates)) {" +
|
Daniel@0
|
14377 "\n d += set(o, "+dl.str(name)+", "+ref.val+");";
|
Daniel@0
|
14378 code += rules[i+1] ? "\n } else " : " }";
|
Daniel@0
|
14379 } else {
|
Daniel@0
|
14380 code += "{" +
|
Daniel@0
|
14381 "\n d += set(o, "+dl.str(name)+", "+ref.val+");"+
|
Daniel@0
|
14382 "\n }\n";
|
Daniel@0
|
14383 }
|
Daniel@0
|
14384 });
|
Daniel@0
|
14385
|
Daniel@0
|
14386 code = "var " + inputs.join(",\n ") + ";\n " + code;
|
Daniel@0
|
14387 return (deps.code = code, deps);
|
Daniel@0
|
14388 }
|
Daniel@0
|
14389
|
Daniel@0
|
14390 function valueRef(config, name, ref) {
|
Daniel@0
|
14391 if (ref == null) return null;
|
Daniel@0
|
14392
|
Daniel@0
|
14393 if (name==='fill' || name==='stroke') {
|
Daniel@0
|
14394 if (ref.c) {
|
Daniel@0
|
14395 return colorRef(config, 'hcl', ref.h, ref.c, ref.l);
|
Daniel@0
|
14396 } else if (ref.h || ref.s) {
|
Daniel@0
|
14397 return colorRef(config, 'hsl', ref.h, ref.s, ref.l);
|
Daniel@0
|
14398 } else if (ref.l || ref.a) {
|
Daniel@0
|
14399 return colorRef(config, 'lab', ref.l, ref.a, ref.b);
|
Daniel@0
|
14400 } else if (ref.r || ref.g || ref.b) {
|
Daniel@0
|
14401 return colorRef(config, 'rgb', ref.r, ref.g, ref.b);
|
Daniel@0
|
14402 }
|
Daniel@0
|
14403 }
|
Daniel@0
|
14404
|
Daniel@0
|
14405 // initialize value
|
Daniel@0
|
14406 var val = null, scale = null,
|
Daniel@0
|
14407 deps = dependencies(),
|
Daniel@0
|
14408 sgRef = null, fRef = null, sRef = null, tmpl = {};
|
Daniel@0
|
14409
|
Daniel@0
|
14410 if (ref.template !== undefined) {
|
Daniel@0
|
14411 val = dl.template.source(ref.template, 'tmpl', tmpl);
|
Daniel@0
|
14412 dl.keys(tmpl).forEach(function(k) {
|
Daniel@0
|
14413 var f = dl.field(k),
|
Daniel@0
|
14414 a = f.shift();
|
Daniel@0
|
14415 if (a === 'parent' || a === 'group') {
|
Daniel@0
|
14416 deps.nested.push({
|
Daniel@0
|
14417 parent: a === 'parent',
|
Daniel@0
|
14418 group: a === 'group',
|
Daniel@0
|
14419 level: 1
|
Daniel@0
|
14420 });
|
Daniel@0
|
14421 } else if (a === 'datum') {
|
Daniel@0
|
14422 deps.fields.push(f[0]);
|
Daniel@0
|
14423 } else {
|
Daniel@0
|
14424 deps.signals.push(a);
|
Daniel@0
|
14425 }
|
Daniel@0
|
14426 });
|
Daniel@0
|
14427 }
|
Daniel@0
|
14428
|
Daniel@0
|
14429 if (ref.value !== undefined) {
|
Daniel@0
|
14430 val = dl.str(ref.value);
|
Daniel@0
|
14431 }
|
Daniel@0
|
14432
|
Daniel@0
|
14433 if (ref.signal !== undefined) {
|
Daniel@0
|
14434 sgRef = dl.field(ref.signal);
|
Daniel@0
|
14435 val = 'signals['+sgRef.map(dl.str).join('][')+']';
|
Daniel@0
|
14436 deps.signals.push(sgRef.shift());
|
Daniel@0
|
14437 }
|
Daniel@0
|
14438
|
Daniel@0
|
14439 if (ref.field !== undefined) {
|
Daniel@0
|
14440 ref.field = dl.isString(ref.field) ? {datum: ref.field} : ref.field;
|
Daniel@0
|
14441 fRef = fieldRef(ref.field);
|
Daniel@0
|
14442 val = fRef.val;
|
Daniel@0
|
14443 dependencies(deps, fRef);
|
Daniel@0
|
14444 }
|
Daniel@0
|
14445
|
Daniel@0
|
14446 if (ref.scale !== undefined) {
|
Daniel@0
|
14447 sRef = scaleRef(ref.scale);
|
Daniel@0
|
14448 scale = sRef.val;
|
Daniel@0
|
14449 dependencies(deps, sRef);
|
Daniel@0
|
14450 deps.scales.push(ref.scale.name || ref.scale);
|
Daniel@0
|
14451
|
Daniel@0
|
14452 // run through scale function if val specified.
|
Daniel@0
|
14453 // if no val, scale function is predicate arg.
|
Daniel@0
|
14454 if (val !== null || ref.band || ref.mult || ref.offset) {
|
Daniel@0
|
14455 val = scale + (ref.band ? '.rangeBand()' :
|
Daniel@0
|
14456 '('+(val !== null ? val : 'item.datum.data')+')');
|
Daniel@0
|
14457 } else {
|
Daniel@0
|
14458 val = scale;
|
Daniel@0
|
14459 }
|
Daniel@0
|
14460 }
|
Daniel@0
|
14461
|
Daniel@0
|
14462 // multiply, offset, return value
|
Daniel@0
|
14463 val = '(' + (ref.mult?(dl.number(ref.mult)+' * '):'') + val + ')' +
|
Daniel@0
|
14464 (ref.offset ? ' + ' + dl.number(ref.offset) : '');
|
Daniel@0
|
14465
|
Daniel@0
|
14466 // Collate dependencies
|
Daniel@0
|
14467 return (deps.val = val, deps);
|
Daniel@0
|
14468 }
|
Daniel@0
|
14469
|
Daniel@0
|
14470 function colorRef(config, type, x, y, z) {
|
Daniel@0
|
14471 var xx = x ? valueRef(config, '', x) : config.color[type][0],
|
Daniel@0
|
14472 yy = y ? valueRef(config, '', y) : config.color[type][1],
|
Daniel@0
|
14473 zz = z ? valueRef(config, '', z) : config.color[type][2],
|
Daniel@0
|
14474 deps = dependencies();
|
Daniel@0
|
14475
|
Daniel@0
|
14476 [xx, yy, zz].forEach(function(v) {
|
Daniel@0
|
14477 if (dl.isArray) return;
|
Daniel@0
|
14478 dependencies(deps, v);
|
Daniel@0
|
14479 });
|
Daniel@0
|
14480
|
Daniel@0
|
14481 var val = '(this.d3.' + type + '(' + [xx.val, yy.val, zz.val].join(',') + ') + "")';
|
Daniel@0
|
14482 return (deps.val = val, deps);
|
Daniel@0
|
14483 }
|
Daniel@0
|
14484
|
Daniel@0
|
14485 // {field: {datum: "foo"} } -> item.datum.foo
|
Daniel@0
|
14486 // {field: {group: "foo"} } -> group.foo
|
Daniel@0
|
14487 // {field: {parent: "foo"} } -> group.datum.foo
|
Daniel@0
|
14488 function fieldRef(ref) {
|
Daniel@0
|
14489 if (dl.isString(ref)) {
|
Daniel@0
|
14490 return {val: dl.field(ref).map(dl.str).join('][')};
|
Daniel@0
|
14491 }
|
Daniel@0
|
14492
|
Daniel@0
|
14493 // Resolve nesting/parent lookups
|
Daniel@0
|
14494 var l = ref.level || 1,
|
Daniel@0
|
14495 nested = (ref.group || ref.parent) && l,
|
Daniel@0
|
14496 scope = nested ? Array(l).join('group.mark.') : '',
|
Daniel@0
|
14497 r = fieldRef(ref.datum || ref.group || ref.parent || ref.signal),
|
Daniel@0
|
14498 val = r.val,
|
Daniel@0
|
14499 deps = dependencies(null, r);
|
Daniel@0
|
14500
|
Daniel@0
|
14501 if (ref.datum) {
|
Daniel@0
|
14502 val = 'item.datum['+val+']';
|
Daniel@0
|
14503 deps.fields.push(ref.datum);
|
Daniel@0
|
14504 } else if (ref.group) {
|
Daniel@0
|
14505 val = scope+'group['+val+']';
|
Daniel@0
|
14506 deps.nested.push({ level: l, group: true });
|
Daniel@0
|
14507 } else if (ref.parent) {
|
Daniel@0
|
14508 val = scope+'group.datum['+val+']';
|
Daniel@0
|
14509 deps.nested.push({ level: l, parent: true });
|
Daniel@0
|
14510 } else if (ref.signal) {
|
Daniel@0
|
14511 val = 'signals['+val+']';
|
Daniel@0
|
14512 deps.signals.push(dl.field(ref.signal)[0]);
|
Daniel@0
|
14513 deps.reflow = true;
|
Daniel@0
|
14514 }
|
Daniel@0
|
14515
|
Daniel@0
|
14516 return (deps.val = val, deps);
|
Daniel@0
|
14517 }
|
Daniel@0
|
14518
|
Daniel@0
|
14519 // {scale: "x"}
|
Daniel@0
|
14520 // {scale: {name: "x"}},
|
Daniel@0
|
14521 // {scale: fieldRef}
|
Daniel@0
|
14522 function scaleRef(ref) {
|
Daniel@0
|
14523 var scale = null,
|
Daniel@0
|
14524 fr = null,
|
Daniel@0
|
14525 deps = dependencies();
|
Daniel@0
|
14526
|
Daniel@0
|
14527 if (dl.isString(ref)) {
|
Daniel@0
|
14528 scale = dl.str(ref);
|
Daniel@0
|
14529 } else if (ref.name) {
|
Daniel@0
|
14530 scale = dl.isString(ref.name) ? dl.str(ref.name) : (fr = fieldRef(ref.name)).val;
|
Daniel@0
|
14531 } else {
|
Daniel@0
|
14532 scale = (fr = fieldRef(ref)).val;
|
Daniel@0
|
14533 }
|
Daniel@0
|
14534
|
Daniel@0
|
14535 scale = '(item.mark._scaleRefs['+scale+'] = 1, group.scale('+scale+'))';
|
Daniel@0
|
14536 if (ref.invert) scale += '.invert';
|
Daniel@0
|
14537
|
Daniel@0
|
14538 // Mark scale refs as they're dealt with separately in mark._scaleRefs.
|
Daniel@0
|
14539 if (fr) fr.nested.forEach(function(g) { g.scale = true; });
|
Daniel@0
|
14540 return fr ? (fr.val = scale, fr) : (deps.val = scale, deps);
|
Daniel@0
|
14541 }
|
Daniel@0
|
14542
|
Daniel@0
|
14543 module.exports = properties;
|
Daniel@0
|
14544 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
14545
|
Daniel@0
|
14546 },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],103:[function(require,module,exports){
|
Daniel@0
|
14547 var dl = require('datalib'),
|
Daniel@0
|
14548 SIGNALS = require('vega-dataflow').Dependencies.SIGNALS,
|
Daniel@0
|
14549 expr = require('./expr');
|
Daniel@0
|
14550
|
Daniel@0
|
14551 var RESERVED = ['datum', 'event', 'signals']
|
Daniel@0
|
14552 .concat(dl.keys(expr.codegen.functions));
|
Daniel@0
|
14553
|
Daniel@0
|
14554 function parseSignals(model, spec) {
|
Daniel@0
|
14555 // process each signal definition
|
Daniel@0
|
14556 (spec || []).forEach(function(s) {
|
Daniel@0
|
14557 if (RESERVED.indexOf(s.name) !== -1) {
|
Daniel@0
|
14558 throw Error('Signal name "'+s.name+'" is a '+
|
Daniel@0
|
14559 'reserved keyword ('+RESERVED.join(', ')+').');
|
Daniel@0
|
14560 }
|
Daniel@0
|
14561
|
Daniel@0
|
14562 var signal = model.signal(s.name, s.init)
|
Daniel@0
|
14563 .verbose(s.verbose);
|
Daniel@0
|
14564
|
Daniel@0
|
14565 if (s.init && s.init.expr) {
|
Daniel@0
|
14566 s.init.expr = expr(s.init.expr);
|
Daniel@0
|
14567 signal.value(exprVal(model, s.init));
|
Daniel@0
|
14568 }
|
Daniel@0
|
14569
|
Daniel@0
|
14570 if (s.expr) {
|
Daniel@0
|
14571 s.expr = expr(s.expr);
|
Daniel@0
|
14572 signal.evaluate = function(input) {
|
Daniel@0
|
14573 var val = exprVal(model, s);
|
Daniel@0
|
14574 if (val !== signal.value() || signal.verbose()) {
|
Daniel@0
|
14575 signal.value(val);
|
Daniel@0
|
14576 input.signals[s.name] = 1;
|
Daniel@0
|
14577 return input;
|
Daniel@0
|
14578 }
|
Daniel@0
|
14579 return model.doNotPropagate;
|
Daniel@0
|
14580 };
|
Daniel@0
|
14581 signal.dependency(SIGNALS, s.expr.globals);
|
Daniel@0
|
14582 s.expr.globals.forEach(function(dep) {
|
Daniel@0
|
14583 model.signal(dep).addListener(signal);
|
Daniel@0
|
14584 });
|
Daniel@0
|
14585 }
|
Daniel@0
|
14586 });
|
Daniel@0
|
14587
|
Daniel@0
|
14588 return spec;
|
Daniel@0
|
14589 }
|
Daniel@0
|
14590
|
Daniel@0
|
14591 function exprVal(model, spec) {
|
Daniel@0
|
14592 var e = spec.expr,
|
Daniel@0
|
14593 val = e.fn(null, null, model.values(SIGNALS, e.globals));
|
Daniel@0
|
14594 return spec.scale ? parseSignals.scale(model, spec, val) : val;
|
Daniel@0
|
14595 }
|
Daniel@0
|
14596
|
Daniel@0
|
14597 parseSignals.scale = function scale(model, spec, value, datum, evt) {
|
Daniel@0
|
14598 var def = spec.scale,
|
Daniel@0
|
14599 name = def.name || def.signal || def,
|
Daniel@0
|
14600 scope = def.scope, e;
|
Daniel@0
|
14601
|
Daniel@0
|
14602 if (scope) {
|
Daniel@0
|
14603 if (scope.signal) {
|
Daniel@0
|
14604 scope = model.signalRef(scope.signal);
|
Daniel@0
|
14605 } else if (dl.isString(scope)) { // Scope is an expression
|
Daniel@0
|
14606 e = def._expr = (def._expr || expr(scope));
|
Daniel@0
|
14607 scope = e.fn(datum, evt, model.values(SIGNALS, e.globals));
|
Daniel@0
|
14608 }
|
Daniel@0
|
14609 }
|
Daniel@0
|
14610
|
Daniel@0
|
14611 if (!scope || !scope.scale) {
|
Daniel@0
|
14612 scope = (scope && scope.mark) ? scope.mark.group : model.scene().items[0];
|
Daniel@0
|
14613 }
|
Daniel@0
|
14614
|
Daniel@0
|
14615 var s = scope.scale(name);
|
Daniel@0
|
14616 return !s ? value : (def.invert ? s.invert(value) : s(value));
|
Daniel@0
|
14617 };
|
Daniel@0
|
14618
|
Daniel@0
|
14619 module.exports = parseSignals;
|
Daniel@0
|
14620 },{"./expr":94,"datalib":24,"vega-dataflow":39}],104:[function(require,module,exports){
|
Daniel@0
|
14621 var dl = require('datalib'),
|
Daniel@0
|
14622 log = require('vega-logging'),
|
Daniel@0
|
14623 Model = require('../core/Model'),
|
Daniel@0
|
14624 View = require('../core/View');
|
Daniel@0
|
14625
|
Daniel@0
|
14626 function parseSpec(spec, callback) {
|
Daniel@0
|
14627 var vf = arguments[arguments.length-1],
|
Daniel@0
|
14628 viewFactory = arguments.length > 2 && dl.isFunction(vf) ? vf : View.factory,
|
Daniel@0
|
14629 config = arguments[2] !== viewFactory ? arguments[2] : {},
|
Daniel@0
|
14630 model = new Model(config);
|
Daniel@0
|
14631
|
Daniel@0
|
14632 function parse(spec) {
|
Daniel@0
|
14633 // protect against subsequent spec modification
|
Daniel@0
|
14634 spec = dl.duplicate(spec);
|
Daniel@0
|
14635
|
Daniel@0
|
14636 var parsers = require('./'),
|
Daniel@0
|
14637 width = spec.width || 500,
|
Daniel@0
|
14638 height = spec.height || 500,
|
Daniel@0
|
14639 viewport = spec.viewport || null;
|
Daniel@0
|
14640
|
Daniel@0
|
14641 model.defs({
|
Daniel@0
|
14642 width: width,
|
Daniel@0
|
14643 height: height,
|
Daniel@0
|
14644 viewport: viewport,
|
Daniel@0
|
14645 background: parsers.background(spec.background),
|
Daniel@0
|
14646 padding: parsers.padding(spec.padding),
|
Daniel@0
|
14647 signals: parsers.signals(model, spec.signals),
|
Daniel@0
|
14648 predicates: parsers.predicates(model, spec.predicates),
|
Daniel@0
|
14649 marks: parsers.marks(model, spec, width, height),
|
Daniel@0
|
14650 data: parsers.data(model, spec.data, function() {
|
Daniel@0
|
14651 callback(viewFactory(model));
|
Daniel@0
|
14652 })
|
Daniel@0
|
14653 });
|
Daniel@0
|
14654 }
|
Daniel@0
|
14655
|
Daniel@0
|
14656 if (dl.isObject(spec)) {
|
Daniel@0
|
14657 parse(spec);
|
Daniel@0
|
14658 } else if (dl.isString(spec)) {
|
Daniel@0
|
14659 var opts = dl.extend({url: spec}, model.config().load);
|
Daniel@0
|
14660 dl.load(opts, function(err, data) {
|
Daniel@0
|
14661 if (err) {
|
Daniel@0
|
14662 log.error('LOADING SPECIFICATION FAILED: ' + err.statusText);
|
Daniel@0
|
14663 } else {
|
Daniel@0
|
14664 try {
|
Daniel@0
|
14665 parse(JSON.parse(data));
|
Daniel@0
|
14666 } catch (e) {
|
Daniel@0
|
14667 log.error('INVALID SPECIFICATION: Must be a valid JSON object. '+e);
|
Daniel@0
|
14668 }
|
Daniel@0
|
14669 }
|
Daniel@0
|
14670 });
|
Daniel@0
|
14671 } else {
|
Daniel@0
|
14672 log.error('INVALID SPECIFICATION: Must be a valid JSON object or URL.');
|
Daniel@0
|
14673 }
|
Daniel@0
|
14674 }
|
Daniel@0
|
14675
|
Daniel@0
|
14676 module.exports = parseSpec;
|
Daniel@0
|
14677 },{"../core/Model":86,"../core/View":87,"./":95,"datalib":24,"vega-logging":45}],105:[function(require,module,exports){
|
Daniel@0
|
14678 (function (global){
|
Daniel@0
|
14679 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
14680 dl = require('datalib'),
|
Daniel@0
|
14681 df = require('vega-dataflow'),
|
Daniel@0
|
14682 SIGNALS = df.Dependencies.SIGNALS,
|
Daniel@0
|
14683 parseSignals = require('./signals'),
|
Daniel@0
|
14684 selector = require('./events'),
|
Daniel@0
|
14685 expr = require('./expr');
|
Daniel@0
|
14686
|
Daniel@0
|
14687 var GATEKEEPER = '_vgGATEKEEPER';
|
Daniel@0
|
14688
|
Daniel@0
|
14689 var vgEvent = {
|
Daniel@0
|
14690 getGroup: function(name) { return name ? this.name[name] : this.group; },
|
Daniel@0
|
14691 getXY: function(item) {
|
Daniel@0
|
14692 var p = {x: this.x, y: this.y};
|
Daniel@0
|
14693 if (typeof item === 'string') {
|
Daniel@0
|
14694 item = this.name[item];
|
Daniel@0
|
14695 }
|
Daniel@0
|
14696 for (; item; item = item.mark && item.mark.group) {
|
Daniel@0
|
14697 p.x -= item.x || 0;
|
Daniel@0
|
14698 p.y -= item.y || 0;
|
Daniel@0
|
14699 }
|
Daniel@0
|
14700 return p;
|
Daniel@0
|
14701 },
|
Daniel@0
|
14702 getX: function(item) { return this.getXY(item).x; },
|
Daniel@0
|
14703 getY: function(item) { return this.getXY(item).y; }
|
Daniel@0
|
14704 };
|
Daniel@0
|
14705
|
Daniel@0
|
14706 function parseStreams(view) {
|
Daniel@0
|
14707 var model = view.model(),
|
Daniel@0
|
14708 spec = model.defs().signals,
|
Daniel@0
|
14709 registry = {handlers: {}, nodes: {}},
|
Daniel@0
|
14710 internal = dl.duplicate(registry), // Internal event processing
|
Daniel@0
|
14711 external = dl.duplicate(registry); // External event processing
|
Daniel@0
|
14712
|
Daniel@0
|
14713 (spec || []).forEach(function(sig) {
|
Daniel@0
|
14714 var signal = model.signal(sig.name);
|
Daniel@0
|
14715 if (sig.expr) return; // Cannot have an expr and stream definition.
|
Daniel@0
|
14716
|
Daniel@0
|
14717 (sig.streams || []).forEach(function(stream) {
|
Daniel@0
|
14718 var sel = selector.parse(stream.type),
|
Daniel@0
|
14719 exp = expr(stream.expr);
|
Daniel@0
|
14720 mergedStream(signal, sel, exp, stream);
|
Daniel@0
|
14721 });
|
Daniel@0
|
14722 });
|
Daniel@0
|
14723
|
Daniel@0
|
14724 // We register the event listeners all together so that if multiple
|
Daniel@0
|
14725 // signals are registered on the same event, they will receive the
|
Daniel@0
|
14726 // new value on the same pulse.
|
Daniel@0
|
14727 dl.keys(internal.handlers).forEach(function(type) {
|
Daniel@0
|
14728 view.on(type, function(evt, item) {
|
Daniel@0
|
14729 evt.preventDefault(); // stop text selection
|
Daniel@0
|
14730 extendEvent(evt, item);
|
Daniel@0
|
14731 fire(internal, type, (item && item.datum) || {}, evt);
|
Daniel@0
|
14732 });
|
Daniel@0
|
14733 });
|
Daniel@0
|
14734
|
Daniel@0
|
14735 // add external event listeners
|
Daniel@0
|
14736 dl.keys(external.handlers).forEach(function(type) {
|
Daniel@0
|
14737 if (typeof window === 'undefined') return; // No external support
|
Daniel@0
|
14738
|
Daniel@0
|
14739 var h = external.handlers[type],
|
Daniel@0
|
14740 t = type.split(':'), // --> no element pseudo-selectors
|
Daniel@0
|
14741 elt = (t[0] === 'window') ? [window] :
|
Daniel@0
|
14742 window.document.querySelectorAll(t[0]);
|
Daniel@0
|
14743
|
Daniel@0
|
14744 function handler(evt) {
|
Daniel@0
|
14745 extendEvent(evt);
|
Daniel@0
|
14746 fire(external, type, d3.select(this).datum(), evt);
|
Daniel@0
|
14747 }
|
Daniel@0
|
14748
|
Daniel@0
|
14749 for (var i=0; i<elt.length; ++i) {
|
Daniel@0
|
14750 elt[i].addEventListener(t[1], handler);
|
Daniel@0
|
14751 }
|
Daniel@0
|
14752
|
Daniel@0
|
14753 h.elements = elt;
|
Daniel@0
|
14754 h.listener = handler;
|
Daniel@0
|
14755 });
|
Daniel@0
|
14756
|
Daniel@0
|
14757 // remove external event listeners
|
Daniel@0
|
14758 external.detach = function() {
|
Daniel@0
|
14759 dl.keys(external.handlers).forEach(function(type) {
|
Daniel@0
|
14760 var h = external.handlers[type],
|
Daniel@0
|
14761 t = type.split(':'),
|
Daniel@0
|
14762 elt = h.elements || [];
|
Daniel@0
|
14763
|
Daniel@0
|
14764 for (var i=0; i<elt.length; ++i) {
|
Daniel@0
|
14765 elt[i].removeEventListener(t[1], h.listener);
|
Daniel@0
|
14766 }
|
Daniel@0
|
14767 });
|
Daniel@0
|
14768 };
|
Daniel@0
|
14769
|
Daniel@0
|
14770 // export detach method
|
Daniel@0
|
14771 return external.detach;
|
Daniel@0
|
14772
|
Daniel@0
|
14773 // -- helper functions -----
|
Daniel@0
|
14774
|
Daniel@0
|
14775 function extendEvent(evt, item) {
|
Daniel@0
|
14776 var mouse = d3.mouse((d3.event=evt, view.renderer().scene())),
|
Daniel@0
|
14777 pad = view.padding(),
|
Daniel@0
|
14778 names = {}, mark, group, i;
|
Daniel@0
|
14779
|
Daniel@0
|
14780 if (item) {
|
Daniel@0
|
14781 mark = item.mark;
|
Daniel@0
|
14782 group = mark.marktype === 'group' ? item : mark.group;
|
Daniel@0
|
14783 for (i=item; i!=null; i=i.mark.group) {
|
Daniel@0
|
14784 if (i.mark.def.name) {
|
Daniel@0
|
14785 names[i.mark.def.name] = i;
|
Daniel@0
|
14786 }
|
Daniel@0
|
14787 }
|
Daniel@0
|
14788 }
|
Daniel@0
|
14789 names.root = view.model().scene().items[0];
|
Daniel@0
|
14790
|
Daniel@0
|
14791 evt.vg = Object.create(vgEvent);
|
Daniel@0
|
14792 evt.vg.group = group;
|
Daniel@0
|
14793 evt.vg.item = item || {};
|
Daniel@0
|
14794 evt.vg.name = names;
|
Daniel@0
|
14795 evt.vg.x = mouse[0] - pad.left;
|
Daniel@0
|
14796 evt.vg.y = mouse[1] - pad.top;
|
Daniel@0
|
14797 }
|
Daniel@0
|
14798
|
Daniel@0
|
14799 function fire(registry, type, datum, evt) {
|
Daniel@0
|
14800 var handlers = registry.handlers[type],
|
Daniel@0
|
14801 node = registry.nodes[type],
|
Daniel@0
|
14802 cs = df.ChangeSet.create(null, true),
|
Daniel@0
|
14803 filtered = false,
|
Daniel@0
|
14804 val, i, n, h;
|
Daniel@0
|
14805
|
Daniel@0
|
14806 function invoke(f) {
|
Daniel@0
|
14807 return !f.fn(datum, evt, model.values(SIGNALS, f.globals));
|
Daniel@0
|
14808 }
|
Daniel@0
|
14809
|
Daniel@0
|
14810 for (i=0, n=handlers.length; i<n; ++i) {
|
Daniel@0
|
14811 h = handlers[i];
|
Daniel@0
|
14812 filtered = h.filters.some(invoke);
|
Daniel@0
|
14813 if (filtered) continue;
|
Daniel@0
|
14814
|
Daniel@0
|
14815 val = h.exp.fn(datum, evt, model.values(SIGNALS, h.exp.globals));
|
Daniel@0
|
14816 if (h.spec.scale) {
|
Daniel@0
|
14817 val = parseSignals.scale(model, h.spec, val, datum, evt);
|
Daniel@0
|
14818 }
|
Daniel@0
|
14819
|
Daniel@0
|
14820 if (val !== h.signal.value() || h.signal.verbose()) {
|
Daniel@0
|
14821 h.signal.value(val);
|
Daniel@0
|
14822 cs.signals[h.signal.name()] = 1;
|
Daniel@0
|
14823 }
|
Daniel@0
|
14824 }
|
Daniel@0
|
14825
|
Daniel@0
|
14826 model.propagate(cs, node);
|
Daniel@0
|
14827 }
|
Daniel@0
|
14828
|
Daniel@0
|
14829 function mergedStream(sig, selector, exp, spec) {
|
Daniel@0
|
14830 selector.forEach(function(s) {
|
Daniel@0
|
14831 if (s.event) domEvent(sig, s, exp, spec);
|
Daniel@0
|
14832 else if (s.signal) signal(sig, s, exp, spec);
|
Daniel@0
|
14833 else if (s.start) orderedStream(sig, s, exp, spec);
|
Daniel@0
|
14834 else if (s.stream) mergedStream(sig, s.stream, exp, spec);
|
Daniel@0
|
14835 });
|
Daniel@0
|
14836 }
|
Daniel@0
|
14837
|
Daniel@0
|
14838 function domEvent(sig, selector, exp, spec) {
|
Daniel@0
|
14839 var evt = selector.event,
|
Daniel@0
|
14840 name = selector.name,
|
Daniel@0
|
14841 mark = selector.mark,
|
Daniel@0
|
14842 target = selector.target,
|
Daniel@0
|
14843 filters = selector.filters || [],
|
Daniel@0
|
14844 registry = target ? external : internal,
|
Daniel@0
|
14845 type = target ? target+':'+evt : evt,
|
Daniel@0
|
14846 node = registry.nodes[type] || (registry.nodes[type] = new df.Node(model)),
|
Daniel@0
|
14847 handlers = registry.handlers[type] || (registry.handlers[type] = []);
|
Daniel@0
|
14848
|
Daniel@0
|
14849 if (name) {
|
Daniel@0
|
14850 filters.push('!!event.vg.name["' + name + '"]'); // Mimic event bubbling
|
Daniel@0
|
14851 } else if (mark) {
|
Daniel@0
|
14852 filters.push('event.vg.item.mark && event.vg.item.mark.marktype==='+dl.str(mark));
|
Daniel@0
|
14853 }
|
Daniel@0
|
14854
|
Daniel@0
|
14855 handlers.push({
|
Daniel@0
|
14856 signal: sig,
|
Daniel@0
|
14857 exp: exp,
|
Daniel@0
|
14858 spec: spec,
|
Daniel@0
|
14859 filters: filters.map(function(f) { return expr(f); })
|
Daniel@0
|
14860 });
|
Daniel@0
|
14861
|
Daniel@0
|
14862 node.addListener(sig);
|
Daniel@0
|
14863 }
|
Daniel@0
|
14864
|
Daniel@0
|
14865 function signal(sig, selector, exp, spec) {
|
Daniel@0
|
14866 var n = new df.Node(model);
|
Daniel@0
|
14867 n.evaluate = function(input) {
|
Daniel@0
|
14868 if (!input.signals[selector.signal]) return model.doNotPropagate;
|
Daniel@0
|
14869 var val = exp.fn(null, null, model.values(SIGNALS, exp.globals));
|
Daniel@0
|
14870 if (spec.scale) {
|
Daniel@0
|
14871 val = parseSignals.scale(model, spec, val);
|
Daniel@0
|
14872 }
|
Daniel@0
|
14873
|
Daniel@0
|
14874 if (val !== sig.value() || sig.verbose()) {
|
Daniel@0
|
14875 sig.value(val);
|
Daniel@0
|
14876 input.signals[sig.name()] = 1;
|
Daniel@0
|
14877 input.reflow = true;
|
Daniel@0
|
14878 }
|
Daniel@0
|
14879
|
Daniel@0
|
14880 return input;
|
Daniel@0
|
14881 };
|
Daniel@0
|
14882 n.dependency(df.Dependencies.SIGNALS, selector.signal);
|
Daniel@0
|
14883 n.addListener(sig);
|
Daniel@0
|
14884 model.signal(selector.signal).addListener(n);
|
Daniel@0
|
14885 }
|
Daniel@0
|
14886
|
Daniel@0
|
14887 function orderedStream(sig, selector, exp, spec) {
|
Daniel@0
|
14888 var name = sig.name(),
|
Daniel@0
|
14889 gk = name + GATEKEEPER,
|
Daniel@0
|
14890 trueFn = expr('true'),
|
Daniel@0
|
14891 falseFn = expr('false'),
|
Daniel@0
|
14892 middle = selector.middle,
|
Daniel@0
|
14893 filters = middle.filters || (middle.filters = []),
|
Daniel@0
|
14894 gatekeeper = model.signal(gk) || model.signal(gk, false);
|
Daniel@0
|
14895
|
Daniel@0
|
14896 // Register an anonymous signal to act as a gatekeeper. Its value is
|
Daniel@0
|
14897 // true or false depending on whether the start or end streams occur.
|
Daniel@0
|
14898 // The middle signal then simply filters for the gatekeeper's value.
|
Daniel@0
|
14899 mergedStream(gatekeeper, [selector.start], trueFn, {});
|
Daniel@0
|
14900 mergedStream(gatekeeper, [selector.end], falseFn, {});
|
Daniel@0
|
14901
|
Daniel@0
|
14902 filters.push(gatekeeper.name());
|
Daniel@0
|
14903 mergedStream(sig, [selector.middle], exp, spec);
|
Daniel@0
|
14904 }
|
Daniel@0
|
14905 }
|
Daniel@0
|
14906
|
Daniel@0
|
14907 module.exports = parseStreams;
|
Daniel@0
|
14908 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
14909
|
Daniel@0
|
14910 },{"./events":93,"./expr":94,"./signals":103,"datalib":24,"vega-dataflow":39}],106:[function(require,module,exports){
|
Daniel@0
|
14911 var dl = require('datalib'),
|
Daniel@0
|
14912 transforms = require('../transforms/index');
|
Daniel@0
|
14913
|
Daniel@0
|
14914 function parseTransforms(model, def) {
|
Daniel@0
|
14915 var tx = new transforms[def.type](model);
|
Daniel@0
|
14916
|
Daniel@0
|
14917 // We want to rename output fields before setting any other properties,
|
Daniel@0
|
14918 // as subsequent properties may require output to be set (e.g. group by).
|
Daniel@0
|
14919 if(def.output) tx.output(def.output);
|
Daniel@0
|
14920
|
Daniel@0
|
14921 dl.keys(def).forEach(function(k) {
|
Daniel@0
|
14922 if(k === 'type' || k === 'output') return;
|
Daniel@0
|
14923 tx.param(k, def[k]);
|
Daniel@0
|
14924 });
|
Daniel@0
|
14925
|
Daniel@0
|
14926 return tx;
|
Daniel@0
|
14927 }
|
Daniel@0
|
14928
|
Daniel@0
|
14929 module.exports = parseTransforms;
|
Daniel@0
|
14930 },{"../transforms/index":139,"datalib":24}],107:[function(require,module,exports){
|
Daniel@0
|
14931 var dl = require('datalib'),
|
Daniel@0
|
14932 df = require('vega-dataflow'),
|
Daniel@0
|
14933 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
14934 log = require('vega-logging'),
|
Daniel@0
|
14935 bound = require('vega-scenegraph').bound,
|
Daniel@0
|
14936 Encoder = require('./Encoder');
|
Daniel@0
|
14937
|
Daniel@0
|
14938 function Bounder(graph, mark) {
|
Daniel@0
|
14939 this._mark = mark;
|
Daniel@0
|
14940 return Node.prototype.init.call(this, graph)
|
Daniel@0
|
14941 .router(true)
|
Daniel@0
|
14942 .reflows(true)
|
Daniel@0
|
14943 .mutates(true);
|
Daniel@0
|
14944 }
|
Daniel@0
|
14945
|
Daniel@0
|
14946 var proto = (Bounder.prototype = new Node());
|
Daniel@0
|
14947
|
Daniel@0
|
14948 proto.evaluate = function(input) {
|
Daniel@0
|
14949 log.debug(input, ['bounds', this._mark.marktype]);
|
Daniel@0
|
14950
|
Daniel@0
|
14951 var type = this._mark.marktype,
|
Daniel@0
|
14952 isGrp = type === 'group',
|
Daniel@0
|
14953 items = this._mark.items,
|
Daniel@0
|
14954 hasLegends = dl.array(this._mark.def.legends).length > 0,
|
Daniel@0
|
14955 i, ilen, j, jlen, group, legend;
|
Daniel@0
|
14956
|
Daniel@0
|
14957 if (input.add.length || input.rem.length || !items.length ||
|
Daniel@0
|
14958 input.mod.length === items.length ||
|
Daniel@0
|
14959 type === 'area' || type === 'line') {
|
Daniel@0
|
14960 bound.mark(this._mark, null, isGrp && !hasLegends);
|
Daniel@0
|
14961 } else {
|
Daniel@0
|
14962 input.mod.forEach(function(item) { bound.item(item); });
|
Daniel@0
|
14963 }
|
Daniel@0
|
14964
|
Daniel@0
|
14965 if (isGrp && hasLegends) {
|
Daniel@0
|
14966 for (i=0, ilen=items.length; i<ilen; ++i) {
|
Daniel@0
|
14967 group = items[i];
|
Daniel@0
|
14968 group._legendPositions = null;
|
Daniel@0
|
14969 for (j=0, jlen=group.legendItems.length; j<jlen; ++j) {
|
Daniel@0
|
14970 legend = group.legendItems[j];
|
Daniel@0
|
14971 Encoder.update(this._graph, input.trans, 'vg_legendPosition', legend.items, input.dirty);
|
Daniel@0
|
14972 bound.mark(legend, null, false);
|
Daniel@0
|
14973 }
|
Daniel@0
|
14974 }
|
Daniel@0
|
14975
|
Daniel@0
|
14976 bound.mark(this._mark, null, true);
|
Daniel@0
|
14977 }
|
Daniel@0
|
14978
|
Daniel@0
|
14979 return df.ChangeSet.create(input, true);
|
Daniel@0
|
14980 };
|
Daniel@0
|
14981
|
Daniel@0
|
14982 module.exports = Bounder;
|
Daniel@0
|
14983 },{"./Encoder":109,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],108:[function(require,module,exports){
|
Daniel@0
|
14984 var dl = require('datalib'),
|
Daniel@0
|
14985 log = require('vega-logging'),
|
Daniel@0
|
14986 Item = require('vega-scenegraph').Item,
|
Daniel@0
|
14987 df = require('vega-dataflow'),
|
Daniel@0
|
14988 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
14989 Deps = df.Dependencies,
|
Daniel@0
|
14990 Tuple = df.Tuple,
|
Daniel@0
|
14991 ChangeSet = df.ChangeSet,
|
Daniel@0
|
14992 Sentinel = {},
|
Daniel@0
|
14993 Encoder = require('./Encoder'),
|
Daniel@0
|
14994 Bounder = require('./Bounder'),
|
Daniel@0
|
14995 parseData = require('../parse/data');
|
Daniel@0
|
14996
|
Daniel@0
|
14997 function Builder() {
|
Daniel@0
|
14998 return arguments.length ? this.init.apply(this, arguments) : this;
|
Daniel@0
|
14999 }
|
Daniel@0
|
15000
|
Daniel@0
|
15001 var Status = Builder.STATUS = {
|
Daniel@0
|
15002 ENTER: 'enter',
|
Daniel@0
|
15003 UPDATE: 'update',
|
Daniel@0
|
15004 EXIT: 'exit'
|
Daniel@0
|
15005 };
|
Daniel@0
|
15006
|
Daniel@0
|
15007 var CONNECTED = 1, DISCONNECTED = 2;
|
Daniel@0
|
15008
|
Daniel@0
|
15009 var proto = (Builder.prototype = new Node());
|
Daniel@0
|
15010
|
Daniel@0
|
15011 proto.init = function(graph, def, mark, parent, parent_id, inheritFrom) {
|
Daniel@0
|
15012 Node.prototype.init.call(this, graph)
|
Daniel@0
|
15013 .router(true)
|
Daniel@0
|
15014 .collector(true);
|
Daniel@0
|
15015
|
Daniel@0
|
15016 this._def = def;
|
Daniel@0
|
15017 this._mark = mark;
|
Daniel@0
|
15018 this._from = (def.from ? def.from.data : null) || inheritFrom;
|
Daniel@0
|
15019 this._ds = dl.isString(this._from) ? graph.data(this._from) : null;
|
Daniel@0
|
15020 this._map = {};
|
Daniel@0
|
15021 this._status = null; // Connected or disconnected?
|
Daniel@0
|
15022
|
Daniel@0
|
15023 mark.def = def;
|
Daniel@0
|
15024 mark.marktype = def.type;
|
Daniel@0
|
15025 mark.interactive = (def.interactive !== false);
|
Daniel@0
|
15026 mark.items = [];
|
Daniel@0
|
15027 if (dl.isValid(def.name)) mark.name = def.name;
|
Daniel@0
|
15028
|
Daniel@0
|
15029 this._parent = parent;
|
Daniel@0
|
15030 this._parent_id = parent_id;
|
Daniel@0
|
15031
|
Daniel@0
|
15032 if (def.from && (def.from.mark || def.from.transform || def.from.modify)) {
|
Daniel@0
|
15033 inlineDs.call(this);
|
Daniel@0
|
15034 }
|
Daniel@0
|
15035
|
Daniel@0
|
15036 // Non-group mark builders are super nodes. Encoder and Bounder remain
|
Daniel@0
|
15037 // separate operators but are embedded and called by Builder.evaluate.
|
Daniel@0
|
15038 this._isSuper = (this._def.type !== 'group');
|
Daniel@0
|
15039 this._encoder = new Encoder(this._graph, this._mark, this);
|
Daniel@0
|
15040 this._bounder = new Bounder(this._graph, this._mark);
|
Daniel@0
|
15041 this._output = null; // Output changeset for reactive geom as Bounder reflows
|
Daniel@0
|
15042
|
Daniel@0
|
15043 if (this._ds) { this._encoder.dependency(Deps.DATA, this._from); }
|
Daniel@0
|
15044
|
Daniel@0
|
15045 // Since Builders are super nodes, copy over encoder dependencies
|
Daniel@0
|
15046 // (bounder has no registered dependencies).
|
Daniel@0
|
15047 this.dependency(Deps.DATA, this._encoder.dependency(Deps.DATA));
|
Daniel@0
|
15048 this.dependency(Deps.SCALES, this._encoder.dependency(Deps.SCALES));
|
Daniel@0
|
15049 this.dependency(Deps.SIGNALS, this._encoder.dependency(Deps.SIGNALS));
|
Daniel@0
|
15050
|
Daniel@0
|
15051 return this;
|
Daniel@0
|
15052 };
|
Daniel@0
|
15053
|
Daniel@0
|
15054 // Reactive geometry and mark-level transformations are handled here
|
Daniel@0
|
15055 // because they need their group's data-joined context.
|
Daniel@0
|
15056 function inlineDs() {
|
Daniel@0
|
15057 var from = this._def.from,
|
Daniel@0
|
15058 geom = from.mark,
|
Daniel@0
|
15059 src, name, spec, sibling, output, input;
|
Daniel@0
|
15060
|
Daniel@0
|
15061 if (geom) {
|
Daniel@0
|
15062 name = ['vg', this._parent_id, geom].join('_');
|
Daniel@0
|
15063 spec = {
|
Daniel@0
|
15064 name: name,
|
Daniel@0
|
15065 transform: from.transform,
|
Daniel@0
|
15066 modify: from.modify
|
Daniel@0
|
15067 };
|
Daniel@0
|
15068 } else {
|
Daniel@0
|
15069 src = this._graph.data(this._from);
|
Daniel@0
|
15070 name = ['vg', this._from, this._def.type, src.listeners(true).length].join('_');
|
Daniel@0
|
15071 spec = {
|
Daniel@0
|
15072 name: name,
|
Daniel@0
|
15073 source: this._from,
|
Daniel@0
|
15074 transform: from.transform,
|
Daniel@0
|
15075 modify: from.modify
|
Daniel@0
|
15076 };
|
Daniel@0
|
15077 }
|
Daniel@0
|
15078
|
Daniel@0
|
15079 this._from = name;
|
Daniel@0
|
15080 this._ds = parseData.datasource(this._graph, spec);
|
Daniel@0
|
15081 var node;
|
Daniel@0
|
15082
|
Daniel@0
|
15083 if (geom) {
|
Daniel@0
|
15084 sibling = this.sibling(geom);
|
Daniel@0
|
15085
|
Daniel@0
|
15086 // Bounder reflows, so we need an intermediary node to propagate
|
Daniel@0
|
15087 // the output constructed by the Builder.
|
Daniel@0
|
15088 node = new Node(this._graph).addListener(this._ds.listener());
|
Daniel@0
|
15089 node.evaluate = function() { return sibling._output; };
|
Daniel@0
|
15090
|
Daniel@0
|
15091 if (sibling._isSuper) {
|
Daniel@0
|
15092 sibling.addListener(node);
|
Daniel@0
|
15093 } else {
|
Daniel@0
|
15094 sibling._bounder.addListener(node);
|
Daniel@0
|
15095 }
|
Daniel@0
|
15096 } else {
|
Daniel@0
|
15097 // At this point, we have a new datasource but it is empty as
|
Daniel@0
|
15098 // the propagation cycle has already crossed the datasources.
|
Daniel@0
|
15099 // So, we repulse just this datasource. This should be safe
|
Daniel@0
|
15100 // as the ds isn't connected to the scenegraph yet.
|
Daniel@0
|
15101 output = this._ds.source().last();
|
Daniel@0
|
15102 input = ChangeSet.create(output);
|
Daniel@0
|
15103
|
Daniel@0
|
15104 input.add = output.add;
|
Daniel@0
|
15105 input.mod = output.mod;
|
Daniel@0
|
15106 input.rem = output.rem;
|
Daniel@0
|
15107 input.stamp = null;
|
Daniel@0
|
15108 this._graph.propagate(input, this._ds.listener(), output.stamp);
|
Daniel@0
|
15109 }
|
Daniel@0
|
15110 }
|
Daniel@0
|
15111
|
Daniel@0
|
15112 proto.ds = function() { return this._ds; };
|
Daniel@0
|
15113 proto.parent = function() { return this._parent; };
|
Daniel@0
|
15114 proto.encoder = function() { return this._encoder; };
|
Daniel@0
|
15115 proto.pipeline = function() { return [this]; };
|
Daniel@0
|
15116
|
Daniel@0
|
15117 proto.connect = function() {
|
Daniel@0
|
15118 var builder = this;
|
Daniel@0
|
15119
|
Daniel@0
|
15120 this._graph.connect(this.pipeline());
|
Daniel@0
|
15121 this._encoder._scales.forEach(function(s) {
|
Daniel@0
|
15122 if (!(s = builder._parent.scale(s))) return;
|
Daniel@0
|
15123 s.addListener(builder);
|
Daniel@0
|
15124 });
|
Daniel@0
|
15125
|
Daniel@0
|
15126 if (this._parent) {
|
Daniel@0
|
15127 if (this._isSuper) this.addListener(this._parent._collector);
|
Daniel@0
|
15128 else this._bounder.addListener(this._parent._collector);
|
Daniel@0
|
15129 }
|
Daniel@0
|
15130
|
Daniel@0
|
15131 return (this._status = CONNECTED, this);
|
Daniel@0
|
15132 };
|
Daniel@0
|
15133
|
Daniel@0
|
15134 proto.disconnect = function() {
|
Daniel@0
|
15135 var builder = this;
|
Daniel@0
|
15136 if (!this._listeners.length) return this;
|
Daniel@0
|
15137
|
Daniel@0
|
15138 function disconnectScales(scales) {
|
Daniel@0
|
15139 for(var i=0, len=scales.length, s; i<len; ++i) {
|
Daniel@0
|
15140 if (!(s = builder._parent.scale(scales[i]))) continue;
|
Daniel@0
|
15141 s.removeListener(builder);
|
Daniel@0
|
15142 }
|
Daniel@0
|
15143 }
|
Daniel@0
|
15144
|
Daniel@0
|
15145 Node.prototype.disconnect.call(this);
|
Daniel@0
|
15146 this._graph.disconnect(this.pipeline());
|
Daniel@0
|
15147 disconnectScales(this._encoder._scales);
|
Daniel@0
|
15148 disconnectScales(dl.keys(this._mark._scaleRefs));
|
Daniel@0
|
15149
|
Daniel@0
|
15150 return (this._status = DISCONNECTED, this);
|
Daniel@0
|
15151 };
|
Daniel@0
|
15152
|
Daniel@0
|
15153 proto.sibling = function(name) {
|
Daniel@0
|
15154 return this._parent.child(name, this._parent_id);
|
Daniel@0
|
15155 };
|
Daniel@0
|
15156
|
Daniel@0
|
15157 proto.evaluate = function(input) {
|
Daniel@0
|
15158 log.debug(input, ['building', (this._from || this._def.from), this._def.type]);
|
Daniel@0
|
15159
|
Daniel@0
|
15160 var self = this,
|
Daniel@0
|
15161 def = this._mark.def,
|
Daniel@0
|
15162 props = def.properties || {},
|
Daniel@0
|
15163 update = props.update || {},
|
Daniel@0
|
15164 output, fullUpdate, fcs, data, name;
|
Daniel@0
|
15165
|
Daniel@0
|
15166 if (this._ds) {
|
Daniel@0
|
15167 output = ChangeSet.create(input);
|
Daniel@0
|
15168
|
Daniel@0
|
15169 // We need to determine if any encoder dependencies have been updated.
|
Daniel@0
|
15170 // However, the encoder's data source will likely be updated, and shouldn't
|
Daniel@0
|
15171 // trigger all items to mod.
|
Daniel@0
|
15172 data = output.data[(name=this._ds.name())];
|
Daniel@0
|
15173 delete output.data[name];
|
Daniel@0
|
15174 fullUpdate = this._encoder.reevaluate(output);
|
Daniel@0
|
15175 output.data[name] = data;
|
Daniel@0
|
15176
|
Daniel@0
|
15177 // If a scale or signal in the update propset has been updated,
|
Daniel@0
|
15178 // send forward all items for reencoding if we do an early return.
|
Daniel@0
|
15179 if (fullUpdate) output.mod = this._mark.items.slice();
|
Daniel@0
|
15180
|
Daniel@0
|
15181 fcs = this._ds.last();
|
Daniel@0
|
15182 if (!fcs) throw Error('Builder evaluated before backing DataSource.');
|
Daniel@0
|
15183 if (fcs.stamp > this._stamp) {
|
Daniel@0
|
15184 output = join.call(this, fcs, this._ds.values(), true, fullUpdate);
|
Daniel@0
|
15185 }
|
Daniel@0
|
15186 } else {
|
Daniel@0
|
15187 data = dl.isFunction(this._def.from) ? this._def.from() : [Sentinel];
|
Daniel@0
|
15188 output = join.call(this, input, data);
|
Daniel@0
|
15189 }
|
Daniel@0
|
15190
|
Daniel@0
|
15191 // Stash output before Bounder for downstream reactive geometry.
|
Daniel@0
|
15192 this._output = output = this._graph.evaluate(output, this._encoder);
|
Daniel@0
|
15193
|
Daniel@0
|
15194 // Add any new scale references to the dependency list, and ensure
|
Daniel@0
|
15195 // they're connected.
|
Daniel@0
|
15196 if (update.nested && update.nested.length && this._status === CONNECTED) {
|
Daniel@0
|
15197 dl.keys(this._mark._scaleRefs).forEach(function(s) {
|
Daniel@0
|
15198 var scale = self._parent.scale(s);
|
Daniel@0
|
15199 if (!scale) return;
|
Daniel@0
|
15200
|
Daniel@0
|
15201 scale.addListener(self);
|
Daniel@0
|
15202 self.dependency(Deps.SCALES, s);
|
Daniel@0
|
15203 self._encoder.dependency(Deps.SCALES, s);
|
Daniel@0
|
15204 });
|
Daniel@0
|
15205 }
|
Daniel@0
|
15206
|
Daniel@0
|
15207 // Supernodes calculate bounds too, but only on items marked dirty.
|
Daniel@0
|
15208 if (this._isSuper) {
|
Daniel@0
|
15209 output.mod = output.mod.filter(function(x) { return x._dirty; });
|
Daniel@0
|
15210 output = this._graph.evaluate(output, this._bounder);
|
Daniel@0
|
15211 }
|
Daniel@0
|
15212
|
Daniel@0
|
15213 return output;
|
Daniel@0
|
15214 };
|
Daniel@0
|
15215
|
Daniel@0
|
15216 function newItem() {
|
Daniel@0
|
15217 var item = Tuple.ingest(new Item(this._mark));
|
Daniel@0
|
15218
|
Daniel@0
|
15219 // For the root node's item
|
Daniel@0
|
15220 if (this._def.width) Tuple.set(item, 'width', this._def.width);
|
Daniel@0
|
15221 if (this._def.height) Tuple.set(item, 'height', this._def.height);
|
Daniel@0
|
15222 return item;
|
Daniel@0
|
15223 }
|
Daniel@0
|
15224
|
Daniel@0
|
15225 function join(input, data, ds, fullUpdate) {
|
Daniel@0
|
15226 var output = ChangeSet.create(input),
|
Daniel@0
|
15227 keyf = keyFunction(this._def.key || (ds ? '_id' : null)),
|
Daniel@0
|
15228 prev = this._mark.items || [],
|
Daniel@0
|
15229 rem = ds ? input.rem : prev,
|
Daniel@0
|
15230 mod = Tuple.idMap((!ds || fullUpdate) ? data : input.mod),
|
Daniel@0
|
15231 next = [],
|
Daniel@0
|
15232 i, key, len, item, datum, enter, diff;
|
Daniel@0
|
15233
|
Daniel@0
|
15234 // Only mark rems as exiting. Due to keyf, there may be an add/mod
|
Daniel@0
|
15235 // tuple that replaces it.
|
Daniel@0
|
15236 for (i=0, len=rem.length; i<len; ++i) {
|
Daniel@0
|
15237 item = (rem[i] === prev[i]) ? prev[i] :
|
Daniel@0
|
15238 keyf ? this._map[keyf(rem[i])] : rem[i];
|
Daniel@0
|
15239 item.status = Status.EXIT;
|
Daniel@0
|
15240 }
|
Daniel@0
|
15241
|
Daniel@0
|
15242 for(i=0, len=data.length; i<len; ++i) {
|
Daniel@0
|
15243 datum = data[i];
|
Daniel@0
|
15244 item = keyf ? this._map[key = keyf(datum)] : prev[i];
|
Daniel@0
|
15245 enter = item ? false : (item = newItem.call(this), true);
|
Daniel@0
|
15246 item.status = enter ? Status.ENTER : Status.UPDATE;
|
Daniel@0
|
15247 diff = !enter && item.datum !== datum;
|
Daniel@0
|
15248 item.datum = datum;
|
Daniel@0
|
15249
|
Daniel@0
|
15250 if (keyf) {
|
Daniel@0
|
15251 Tuple.set(item, 'key', key);
|
Daniel@0
|
15252 this._map[key] = item;
|
Daniel@0
|
15253 }
|
Daniel@0
|
15254
|
Daniel@0
|
15255 if (enter) {
|
Daniel@0
|
15256 output.add.push(item);
|
Daniel@0
|
15257 } else if (diff || mod[datum._id]) {
|
Daniel@0
|
15258 output.mod.push(item);
|
Daniel@0
|
15259 }
|
Daniel@0
|
15260
|
Daniel@0
|
15261 next.push(item);
|
Daniel@0
|
15262 }
|
Daniel@0
|
15263
|
Daniel@0
|
15264 for (i=0, len=rem.length; i<len; ++i) {
|
Daniel@0
|
15265 item = (rem[i] === prev[i]) ? prev[i] :
|
Daniel@0
|
15266 keyf ? this._map[key = keyf(rem[i])] : rem[i];
|
Daniel@0
|
15267 if (item.status === Status.EXIT) {
|
Daniel@0
|
15268 item._dirty = true;
|
Daniel@0
|
15269 input.dirty.push(item);
|
Daniel@0
|
15270 next.push(item);
|
Daniel@0
|
15271 output.rem.push(item);
|
Daniel@0
|
15272 if (keyf) this._map[key] = null;
|
Daniel@0
|
15273 }
|
Daniel@0
|
15274 }
|
Daniel@0
|
15275
|
Daniel@0
|
15276 return (this._mark.items = next, output);
|
Daniel@0
|
15277 }
|
Daniel@0
|
15278
|
Daniel@0
|
15279 function keyFunction(key) {
|
Daniel@0
|
15280 if (key == null) return null;
|
Daniel@0
|
15281 var f = dl.array(key).map(dl.accessor);
|
Daniel@0
|
15282 return function(d) {
|
Daniel@0
|
15283 for (var s='', i=0, n=f.length; i<n; ++i) {
|
Daniel@0
|
15284 if (i>0) s += '|';
|
Daniel@0
|
15285 s += String(f[i](d));
|
Daniel@0
|
15286 }
|
Daniel@0
|
15287 return s;
|
Daniel@0
|
15288 };
|
Daniel@0
|
15289 }
|
Daniel@0
|
15290
|
Daniel@0
|
15291 module.exports = Builder;
|
Daniel@0
|
15292 },{"../parse/data":92,"./Bounder":107,"./Encoder":109,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],109:[function(require,module,exports){
|
Daniel@0
|
15293 var dl = require('datalib'),
|
Daniel@0
|
15294 log = require('vega-logging'),
|
Daniel@0
|
15295 df = require('vega-dataflow'),
|
Daniel@0
|
15296 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
15297 Deps = df.Dependencies,
|
Daniel@0
|
15298 bound = require('vega-scenegraph').bound;
|
Daniel@0
|
15299
|
Daniel@0
|
15300 var EMPTY = {};
|
Daniel@0
|
15301
|
Daniel@0
|
15302 function Encoder(graph, mark, builder) {
|
Daniel@0
|
15303 var props = mark.def.properties || {},
|
Daniel@0
|
15304 enter = props.enter,
|
Daniel@0
|
15305 update = props.update,
|
Daniel@0
|
15306 exit = props.exit;
|
Daniel@0
|
15307
|
Daniel@0
|
15308 Node.prototype.init.call(this, graph);
|
Daniel@0
|
15309
|
Daniel@0
|
15310 this._mark = mark;
|
Daniel@0
|
15311 this._builder = builder;
|
Daniel@0
|
15312 var s = this._scales = [];
|
Daniel@0
|
15313
|
Daniel@0
|
15314 // Only scales used in the 'update' property set are set as
|
Daniel@0
|
15315 // encoder depedencies to have targeted reevaluations. However,
|
Daniel@0
|
15316 // we still want scales in 'enter' and 'exit' to be evaluated
|
Daniel@0
|
15317 // before the encoder.
|
Daniel@0
|
15318 if (enter) s.push.apply(s, enter.scales);
|
Daniel@0
|
15319
|
Daniel@0
|
15320 if (update) {
|
Daniel@0
|
15321 this.dependency(Deps.DATA, update.data);
|
Daniel@0
|
15322 this.dependency(Deps.SIGNALS, update.signals);
|
Daniel@0
|
15323 this.dependency(Deps.FIELDS, update.fields);
|
Daniel@0
|
15324 this.dependency(Deps.SCALES, update.scales);
|
Daniel@0
|
15325 s.push.apply(s, update.scales);
|
Daniel@0
|
15326 }
|
Daniel@0
|
15327
|
Daniel@0
|
15328 if (exit) s.push.apply(s, exit.scales);
|
Daniel@0
|
15329
|
Daniel@0
|
15330 return this.mutates(true);
|
Daniel@0
|
15331 }
|
Daniel@0
|
15332
|
Daniel@0
|
15333 var proto = (Encoder.prototype = new Node());
|
Daniel@0
|
15334
|
Daniel@0
|
15335 proto.evaluate = function(input) {
|
Daniel@0
|
15336 log.debug(input, ['encoding', this._mark.def.type]);
|
Daniel@0
|
15337 var graph = this._graph,
|
Daniel@0
|
15338 props = this._mark.def.properties || {},
|
Daniel@0
|
15339 items = this._mark.items,
|
Daniel@0
|
15340 enter = props.enter,
|
Daniel@0
|
15341 update = props.update,
|
Daniel@0
|
15342 exit = props.exit,
|
Daniel@0
|
15343 dirty = input.dirty,
|
Daniel@0
|
15344 preds = graph.predicates(),
|
Daniel@0
|
15345 req = input.request,
|
Daniel@0
|
15346 group = this._mark.group,
|
Daniel@0
|
15347 guide = group && (group.mark.axis || group.mark.legend),
|
Daniel@0
|
15348 db = EMPTY, sg = EMPTY, i, len, item, prop;
|
Daniel@0
|
15349
|
Daniel@0
|
15350 if (req && !guide) {
|
Daniel@0
|
15351 if ((prop = props[req]) && input.mod.length) {
|
Daniel@0
|
15352 db = prop.data ? graph.values(Deps.DATA, prop.data) : null;
|
Daniel@0
|
15353 sg = prop.signals ? graph.values(Deps.SIGNALS, prop.signals) : null;
|
Daniel@0
|
15354
|
Daniel@0
|
15355 for (i=0, len=input.mod.length; i<len; ++i) {
|
Daniel@0
|
15356 item = input.mod[i];
|
Daniel@0
|
15357 encode.call(this, prop, item, input.trans, db, sg, preds, dirty);
|
Daniel@0
|
15358 }
|
Daniel@0
|
15359 }
|
Daniel@0
|
15360
|
Daniel@0
|
15361 return input; // exit early if given request
|
Daniel@0
|
15362 }
|
Daniel@0
|
15363
|
Daniel@0
|
15364 db = values(Deps.DATA, graph, input, props);
|
Daniel@0
|
15365 sg = values(Deps.SIGNALS, graph, input, props);
|
Daniel@0
|
15366
|
Daniel@0
|
15367 // Items marked for removal are at the tail of items. Process them first.
|
Daniel@0
|
15368 for (i=0, len=input.rem.length; i<len; ++i) {
|
Daniel@0
|
15369 item = input.rem[i];
|
Daniel@0
|
15370 if (exit) encode.call(this, exit, item, input.trans, db, sg, preds, dirty);
|
Daniel@0
|
15371 if (input.trans && !exit) input.trans.interpolate(item, EMPTY);
|
Daniel@0
|
15372 else if (!input.trans) items.pop();
|
Daniel@0
|
15373 }
|
Daniel@0
|
15374
|
Daniel@0
|
15375 var update_status = require('./Builder').STATUS.UPDATE;
|
Daniel@0
|
15376 for (i=0, len=input.add.length; i<len; ++i) {
|
Daniel@0
|
15377 item = input.add[i];
|
Daniel@0
|
15378 if (enter) encode.call(this, enter, item, input.trans, db, sg, preds, dirty);
|
Daniel@0
|
15379 if (update) encode.call(this, update, item, input.trans, db, sg, preds, dirty);
|
Daniel@0
|
15380 item.status = update_status;
|
Daniel@0
|
15381 }
|
Daniel@0
|
15382
|
Daniel@0
|
15383 if (update) {
|
Daniel@0
|
15384 for (i=0, len=input.mod.length; i<len; ++i) {
|
Daniel@0
|
15385 item = input.mod[i];
|
Daniel@0
|
15386 encode.call(this, update, item, input.trans, db, sg, preds, dirty);
|
Daniel@0
|
15387 }
|
Daniel@0
|
15388 }
|
Daniel@0
|
15389
|
Daniel@0
|
15390 return input;
|
Daniel@0
|
15391 };
|
Daniel@0
|
15392
|
Daniel@0
|
15393 // Only marshal necessary data and signal values
|
Daniel@0
|
15394 function values(type, graph, input, props) {
|
Daniel@0
|
15395 var p, x, o, add = input.add.length;
|
Daniel@0
|
15396 if ((p=props.enter) && (x=p[type]).length && add) {
|
Daniel@0
|
15397 o = graph.values(type, x, (o=o||{}));
|
Daniel@0
|
15398 }
|
Daniel@0
|
15399 if ((p=props.exit) && (x=p[type]).length && input.rem.length) {
|
Daniel@0
|
15400 o = graph.values(type, x, (o=o||{}));
|
Daniel@0
|
15401 }
|
Daniel@0
|
15402 if ((p=props.update) && (x=p[type]).length && (add || input.mod.length)) {
|
Daniel@0
|
15403 o = graph.values(type, x, (o=o||{}));
|
Daniel@0
|
15404 }
|
Daniel@0
|
15405 return o || EMPTY;
|
Daniel@0
|
15406 }
|
Daniel@0
|
15407
|
Daniel@0
|
15408 function encode(prop, item, trans, db, sg, preds, dirty) {
|
Daniel@0
|
15409 var enc = prop.encode,
|
Daniel@0
|
15410 wasDirty = item._dirty,
|
Daniel@0
|
15411 isDirty = enc.call(enc, item, item.mark.group||item, trans, db, sg, preds);
|
Daniel@0
|
15412
|
Daniel@0
|
15413 item._dirty = isDirty || wasDirty;
|
Daniel@0
|
15414 if (isDirty && !wasDirty) dirty.push(item);
|
Daniel@0
|
15415 }
|
Daniel@0
|
15416
|
Daniel@0
|
15417 // If a specified property set called, or update property set
|
Daniel@0
|
15418 // uses nested fieldrefs, reevaluate all items.
|
Daniel@0
|
15419 proto.reevaluate = function(pulse) {
|
Daniel@0
|
15420 var def = this._mark.def,
|
Daniel@0
|
15421 props = def.properties || {},
|
Daniel@0
|
15422 reeval = dl.isFunction(def.from) || def.orient || pulse.request ||
|
Daniel@0
|
15423 Node.prototype.reevaluate.call(this, pulse);
|
Daniel@0
|
15424
|
Daniel@0
|
15425 return reeval || (props.update ? nestedRefs.call(this) : false);
|
Daniel@0
|
15426 };
|
Daniel@0
|
15427
|
Daniel@0
|
15428 // Test if any nested refs trigger a reflow of mark items.
|
Daniel@0
|
15429 function nestedRefs() {
|
Daniel@0
|
15430 var refs = this._mark.def.properties.update.nested,
|
Daniel@0
|
15431 parent = this._builder,
|
Daniel@0
|
15432 level = 0,
|
Daniel@0
|
15433 i = 0, len = refs.length,
|
Daniel@0
|
15434 ref, ds, stamp;
|
Daniel@0
|
15435
|
Daniel@0
|
15436 for (; i<len; ++i) {
|
Daniel@0
|
15437 ref = refs[i];
|
Daniel@0
|
15438
|
Daniel@0
|
15439 // Scale references are resolved via this._mark._scaleRefs which are
|
Daniel@0
|
15440 // added to dependency lists + connected in Builder.evaluate.
|
Daniel@0
|
15441 if (ref.scale) continue;
|
Daniel@0
|
15442
|
Daniel@0
|
15443 for (; level<ref.level; ++level) {
|
Daniel@0
|
15444 parent = parent.parent();
|
Daniel@0
|
15445 ds = parent.ds();
|
Daniel@0
|
15446 }
|
Daniel@0
|
15447
|
Daniel@0
|
15448 // Compare stamps to determine if a change in a group's properties
|
Daniel@0
|
15449 // or data should trigger a reeval. We cannot check anything fancier
|
Daniel@0
|
15450 // (e.g., pulse.fields) as the ref may use item.datum.
|
Daniel@0
|
15451 stamp = (ref.group ? parent.encoder() : ds.last())._stamp;
|
Daniel@0
|
15452 if (stamp > this._stamp) return true;
|
Daniel@0
|
15453 }
|
Daniel@0
|
15454
|
Daniel@0
|
15455 return false;
|
Daniel@0
|
15456 }
|
Daniel@0
|
15457
|
Daniel@0
|
15458 // Short-circuit encoder if user specifies items
|
Daniel@0
|
15459 Encoder.update = function(graph, trans, request, items, dirty) {
|
Daniel@0
|
15460 items = dl.array(items);
|
Daniel@0
|
15461 var preds = graph.predicates(),
|
Daniel@0
|
15462 db = graph.values(Deps.DATA),
|
Daniel@0
|
15463 sg = graph.values(Deps.SIGNALS),
|
Daniel@0
|
15464 i, len, item, props, prop;
|
Daniel@0
|
15465
|
Daniel@0
|
15466 for (i=0, len=items.length; i<len; ++i) {
|
Daniel@0
|
15467 item = items[i];
|
Daniel@0
|
15468 props = item.mark.def.properties;
|
Daniel@0
|
15469 prop = props && props[request];
|
Daniel@0
|
15470 if (prop) {
|
Daniel@0
|
15471 encode.call(null, prop, item, trans, db, sg, preds, dirty);
|
Daniel@0
|
15472 bound.item(item);
|
Daniel@0
|
15473 }
|
Daniel@0
|
15474 }
|
Daniel@0
|
15475
|
Daniel@0
|
15476 };
|
Daniel@0
|
15477
|
Daniel@0
|
15478 module.exports = Encoder;
|
Daniel@0
|
15479 },{"./Builder":108,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],110:[function(require,module,exports){
|
Daniel@0
|
15480 var dl = require('datalib'),
|
Daniel@0
|
15481 df = require('vega-dataflow'),
|
Daniel@0
|
15482 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
15483 Deps = df.Dependencies,
|
Daniel@0
|
15484 Collector = df.Collector,
|
Daniel@0
|
15485 log = require('vega-logging'),
|
Daniel@0
|
15486 Builder = require('./Builder'),
|
Daniel@0
|
15487 Scale = require('./Scale'),
|
Daniel@0
|
15488 parseAxes = require('../parse/axes'),
|
Daniel@0
|
15489 parseLegends = require('../parse/legends');
|
Daniel@0
|
15490
|
Daniel@0
|
15491 function GroupBuilder() {
|
Daniel@0
|
15492 this._children = {};
|
Daniel@0
|
15493 this._scaler = null;
|
Daniel@0
|
15494 this._recursor = null;
|
Daniel@0
|
15495
|
Daniel@0
|
15496 this._scales = {};
|
Daniel@0
|
15497 this.scale = scale.bind(this);
|
Daniel@0
|
15498 return arguments.length ? this.init.apply(this, arguments) : this;
|
Daniel@0
|
15499 }
|
Daniel@0
|
15500
|
Daniel@0
|
15501 var Types = GroupBuilder.TYPES = {
|
Daniel@0
|
15502 GROUP: "group",
|
Daniel@0
|
15503 MARK: "mark",
|
Daniel@0
|
15504 AXIS: "axis",
|
Daniel@0
|
15505 LEGEND: "legend"
|
Daniel@0
|
15506 };
|
Daniel@0
|
15507
|
Daniel@0
|
15508 var proto = (GroupBuilder.prototype = new Builder());
|
Daniel@0
|
15509
|
Daniel@0
|
15510 proto.init = function(graph, def) {
|
Daniel@0
|
15511 var builder = this, name;
|
Daniel@0
|
15512
|
Daniel@0
|
15513 this._scaler = new Node(graph);
|
Daniel@0
|
15514
|
Daniel@0
|
15515 (def.scales||[]).forEach(function(s) {
|
Daniel@0
|
15516 s = builder.scale((name=s.name), new Scale(graph, s, builder));
|
Daniel@0
|
15517 builder.scale(name+":prev", s);
|
Daniel@0
|
15518 builder._scaler.addListener(s); // Scales should be computed after group is encoded
|
Daniel@0
|
15519 });
|
Daniel@0
|
15520
|
Daniel@0
|
15521 this._recursor = new Node(graph);
|
Daniel@0
|
15522 this._recursor.evaluate = recurse.bind(this);
|
Daniel@0
|
15523
|
Daniel@0
|
15524 var scales = (def.axes||[]).reduce(function(acc, x) {
|
Daniel@0
|
15525 return (acc[x.scale] = 1, acc);
|
Daniel@0
|
15526 }, {});
|
Daniel@0
|
15527
|
Daniel@0
|
15528 scales = (def.legends||[]).reduce(function(acc, x) {
|
Daniel@0
|
15529 return (acc[x.size || x.shape || x.fill || x.stroke], acc);
|
Daniel@0
|
15530 }, scales);
|
Daniel@0
|
15531
|
Daniel@0
|
15532 this._recursor.dependency(Deps.SCALES, dl.keys(scales));
|
Daniel@0
|
15533
|
Daniel@0
|
15534 // We only need a collector for up-propagation of bounds calculation,
|
Daniel@0
|
15535 // so only GroupBuilders, and not regular Builders, have collectors.
|
Daniel@0
|
15536 this._collector = new Collector(graph);
|
Daniel@0
|
15537
|
Daniel@0
|
15538 return Builder.prototype.init.apply(this, arguments);
|
Daniel@0
|
15539 };
|
Daniel@0
|
15540
|
Daniel@0
|
15541 proto.evaluate = function() {
|
Daniel@0
|
15542 var output = Builder.prototype.evaluate.apply(this, arguments),
|
Daniel@0
|
15543 builder = this;
|
Daniel@0
|
15544
|
Daniel@0
|
15545 output.add.forEach(function(group) { buildGroup.call(builder, output, group); });
|
Daniel@0
|
15546 return output;
|
Daniel@0
|
15547 };
|
Daniel@0
|
15548
|
Daniel@0
|
15549 proto.pipeline = function() {
|
Daniel@0
|
15550 return [this, this._scaler, this._recursor, this._collector, this._bounder];
|
Daniel@0
|
15551 };
|
Daniel@0
|
15552
|
Daniel@0
|
15553 proto.disconnect = function() {
|
Daniel@0
|
15554 var builder = this;
|
Daniel@0
|
15555 dl.keys(builder._children).forEach(function(group_id) {
|
Daniel@0
|
15556 builder._children[group_id].forEach(function(c) {
|
Daniel@0
|
15557 builder._recursor.removeListener(c.builder);
|
Daniel@0
|
15558 c.builder.disconnect();
|
Daniel@0
|
15559 });
|
Daniel@0
|
15560 });
|
Daniel@0
|
15561
|
Daniel@0
|
15562 builder._children = {};
|
Daniel@0
|
15563 return Builder.prototype.disconnect.call(this);
|
Daniel@0
|
15564 };
|
Daniel@0
|
15565
|
Daniel@0
|
15566 proto.child = function(name, group_id) {
|
Daniel@0
|
15567 var children = this._children[group_id],
|
Daniel@0
|
15568 i = 0, len = children.length,
|
Daniel@0
|
15569 child;
|
Daniel@0
|
15570
|
Daniel@0
|
15571 for (; i<len; ++i) {
|
Daniel@0
|
15572 child = children[i];
|
Daniel@0
|
15573 if (child.type == Types.MARK && child.builder._def.name == name) break;
|
Daniel@0
|
15574 }
|
Daniel@0
|
15575
|
Daniel@0
|
15576 return child.builder;
|
Daniel@0
|
15577 };
|
Daniel@0
|
15578
|
Daniel@0
|
15579 function recurse(input) {
|
Daniel@0
|
15580 var builder = this,
|
Daniel@0
|
15581 hasMarks = dl.array(this._def.marks).length > 0,
|
Daniel@0
|
15582 hasAxes = dl.array(this._def.axes).length > 0,
|
Daniel@0
|
15583 hasLegends = dl.array(this._def.legends).length > 0,
|
Daniel@0
|
15584 i, j, c, len, group, pipeline, def, inline = false;
|
Daniel@0
|
15585
|
Daniel@0
|
15586 for (i=0, len=input.add.length; i<len; ++i) {
|
Daniel@0
|
15587 group = input.add[i];
|
Daniel@0
|
15588 if (hasMarks) buildMarks.call(this, input, group);
|
Daniel@0
|
15589 if (hasAxes) buildAxes.call(this, input, group);
|
Daniel@0
|
15590 if (hasLegends) buildLegends.call(this, input, group);
|
Daniel@0
|
15591 }
|
Daniel@0
|
15592
|
Daniel@0
|
15593 // Wire up new children builders in reverse to minimize graph rewrites.
|
Daniel@0
|
15594 for (i=input.add.length-1; i>=0; --i) {
|
Daniel@0
|
15595 group = input.add[i];
|
Daniel@0
|
15596 for (j=this._children[group._id].length-1; j>=0; --j) {
|
Daniel@0
|
15597 c = this._children[group._id][j];
|
Daniel@0
|
15598 c.builder.connect();
|
Daniel@0
|
15599 pipeline = c.builder.pipeline();
|
Daniel@0
|
15600 def = c.builder._def;
|
Daniel@0
|
15601
|
Daniel@0
|
15602 // This new child needs to be built during this propagation cycle.
|
Daniel@0
|
15603 // We could add its builder as a listener off the _recursor node,
|
Daniel@0
|
15604 // but try to inline it if we can to minimize graph dispatches.
|
Daniel@0
|
15605 inline = (def.type !== Types.GROUP);
|
Daniel@0
|
15606 inline = inline && (this._graph.data(c.from) !== undefined);
|
Daniel@0
|
15607 inline = inline && (pipeline[pipeline.length-1].listeners().length === 1); // Reactive geom source
|
Daniel@0
|
15608 inline = inline && (def.from && !def.from.mark); // Reactive geom target
|
Daniel@0
|
15609 c.inline = inline;
|
Daniel@0
|
15610
|
Daniel@0
|
15611 if (inline) this._graph.evaluate(input, c.builder);
|
Daniel@0
|
15612 else this._recursor.addListener(c.builder);
|
Daniel@0
|
15613 }
|
Daniel@0
|
15614 }
|
Daniel@0
|
15615
|
Daniel@0
|
15616 function removeTemp(c) {
|
Daniel@0
|
15617 if (c.type == Types.MARK && !c.inline &&
|
Daniel@0
|
15618 builder._graph.data(c.from) !== undefined) {
|
Daniel@0
|
15619 builder._recursor.removeListener(c.builder);
|
Daniel@0
|
15620 }
|
Daniel@0
|
15621 }
|
Daniel@0
|
15622
|
Daniel@0
|
15623 function updateAxis(a) {
|
Daniel@0
|
15624 var scale = a.scale();
|
Daniel@0
|
15625 if (!input.scales[scale.scaleName]) return;
|
Daniel@0
|
15626 a.reset().def();
|
Daniel@0
|
15627 }
|
Daniel@0
|
15628
|
Daniel@0
|
15629 function updateLegend(l) {
|
Daniel@0
|
15630 var scale = l.size() || l.shape() || l.fill() || l.stroke();
|
Daniel@0
|
15631 if (!input.scales[scale.scaleName]) return;
|
Daniel@0
|
15632 l.reset().def();
|
Daniel@0
|
15633 }
|
Daniel@0
|
15634
|
Daniel@0
|
15635 for (i=0, len=input.mod.length; i<len; ++i) {
|
Daniel@0
|
15636 group = input.mod[i];
|
Daniel@0
|
15637
|
Daniel@0
|
15638 // Remove temporary connection for marks that draw from a source
|
Daniel@0
|
15639 if (hasMarks) builder._children[group._id].forEach(removeTemp);
|
Daniel@0
|
15640
|
Daniel@0
|
15641 // Update axis data defs
|
Daniel@0
|
15642 if (hasAxes) group.axes.forEach(updateAxis);
|
Daniel@0
|
15643
|
Daniel@0
|
15644 // Update legend data defs
|
Daniel@0
|
15645 if (hasLegends) group.legends.forEach(updateLegend);
|
Daniel@0
|
15646 }
|
Daniel@0
|
15647
|
Daniel@0
|
15648 function disconnectChildren(c) {
|
Daniel@0
|
15649 builder._recursor.removeListener(c.builder);
|
Daniel@0
|
15650 c.builder.disconnect();
|
Daniel@0
|
15651 }
|
Daniel@0
|
15652
|
Daniel@0
|
15653 for (i=0, len=input.rem.length; i<len; ++i) {
|
Daniel@0
|
15654 group = input.rem[i];
|
Daniel@0
|
15655 // For deleted groups, disconnect their children
|
Daniel@0
|
15656 builder._children[group._id].forEach(disconnectChildren);
|
Daniel@0
|
15657 delete builder._children[group._id];
|
Daniel@0
|
15658 }
|
Daniel@0
|
15659
|
Daniel@0
|
15660 return input;
|
Daniel@0
|
15661 }
|
Daniel@0
|
15662
|
Daniel@0
|
15663 function scale(name, x) {
|
Daniel@0
|
15664 var group = this, s = null;
|
Daniel@0
|
15665 if (arguments.length === 2) return (group._scales[name] = x, x);
|
Daniel@0
|
15666 while (s == null) {
|
Daniel@0
|
15667 s = group._scales[name];
|
Daniel@0
|
15668 group = group.mark ? group.mark.group : group._parent;
|
Daniel@0
|
15669 if (!group) break;
|
Daniel@0
|
15670 }
|
Daniel@0
|
15671 return s;
|
Daniel@0
|
15672 }
|
Daniel@0
|
15673
|
Daniel@0
|
15674 function buildGroup(input, group) {
|
Daniel@0
|
15675 log.debug(input, ["building group", group._id]);
|
Daniel@0
|
15676
|
Daniel@0
|
15677 group._scales = group._scales || {};
|
Daniel@0
|
15678 group.scale = scale.bind(group);
|
Daniel@0
|
15679
|
Daniel@0
|
15680 group.items = group.items || [];
|
Daniel@0
|
15681 this._children[group._id] = this._children[group._id] || [];
|
Daniel@0
|
15682
|
Daniel@0
|
15683 group.axes = group.axes || [];
|
Daniel@0
|
15684 group.axisItems = group.axisItems || [];
|
Daniel@0
|
15685
|
Daniel@0
|
15686 group.legends = group.legends || [];
|
Daniel@0
|
15687 group.legendItems = group.legendItems || [];
|
Daniel@0
|
15688 }
|
Daniel@0
|
15689
|
Daniel@0
|
15690 function buildMarks(input, group) {
|
Daniel@0
|
15691 log.debug(input, ["building children marks #"+group._id]);
|
Daniel@0
|
15692 var marks = this._def.marks,
|
Daniel@0
|
15693 mark, from, inherit, i, len, b;
|
Daniel@0
|
15694
|
Daniel@0
|
15695 for (i=0, len=marks.length; i<len; ++i) {
|
Daniel@0
|
15696 mark = marks[i];
|
Daniel@0
|
15697 from = mark.from || {};
|
Daniel@0
|
15698 inherit = group.datum._facetID;
|
Daniel@0
|
15699 group.items[i] = {group: group, _scaleRefs: {}};
|
Daniel@0
|
15700 b = (mark.type === Types.GROUP) ? new GroupBuilder() : new Builder();
|
Daniel@0
|
15701 b.init(this._graph, mark, group.items[i], this, group._id, inherit);
|
Daniel@0
|
15702 this._children[group._id].push({
|
Daniel@0
|
15703 builder: b,
|
Daniel@0
|
15704 from: from.data || (from.mark ? ("vg_" + group._id + "_" + from.mark) : inherit),
|
Daniel@0
|
15705 type: Types.MARK
|
Daniel@0
|
15706 });
|
Daniel@0
|
15707 }
|
Daniel@0
|
15708 }
|
Daniel@0
|
15709
|
Daniel@0
|
15710 function buildAxes(input, group) {
|
Daniel@0
|
15711 var axes = group.axes,
|
Daniel@0
|
15712 axisItems = group.axisItems,
|
Daniel@0
|
15713 builder = this;
|
Daniel@0
|
15714
|
Daniel@0
|
15715 parseAxes(this._graph, this._def.axes, axes, group);
|
Daniel@0
|
15716 axes.forEach(function(a, i) {
|
Daniel@0
|
15717 var scale = builder._def.axes[i].scale,
|
Daniel@0
|
15718 def = a.def(),
|
Daniel@0
|
15719 b = null;
|
Daniel@0
|
15720
|
Daniel@0
|
15721 axisItems[i] = {group: group, axis: true, layer: def.layer};
|
Daniel@0
|
15722 b = (def.type === Types.GROUP) ? new GroupBuilder() : new Builder();
|
Daniel@0
|
15723 b.init(builder._graph, def, axisItems[i], builder)
|
Daniel@0
|
15724 .dependency(Deps.SCALES, scale);
|
Daniel@0
|
15725 builder._children[group._id].push({ builder: b, type: Types.AXIS, scale: scale });
|
Daniel@0
|
15726 });
|
Daniel@0
|
15727 }
|
Daniel@0
|
15728
|
Daniel@0
|
15729 function buildLegends(input, group) {
|
Daniel@0
|
15730 var legends = group.legends,
|
Daniel@0
|
15731 legendItems = group.legendItems,
|
Daniel@0
|
15732 builder = this;
|
Daniel@0
|
15733
|
Daniel@0
|
15734 parseLegends(this._graph, this._def.legends, legends, group);
|
Daniel@0
|
15735 legends.forEach(function(l, i) {
|
Daniel@0
|
15736 var scale = l.size() || l.shape() || l.fill() || l.stroke(),
|
Daniel@0
|
15737 def = l.def(),
|
Daniel@0
|
15738 b = null;
|
Daniel@0
|
15739
|
Daniel@0
|
15740 legendItems[i] = {group: group, legend: true};
|
Daniel@0
|
15741 b = (def.type === Types.GROUP) ? new GroupBuilder() : new Builder();
|
Daniel@0
|
15742 b.init(builder._graph, def, legendItems[i], builder)
|
Daniel@0
|
15743 .dependency(Deps.SCALES, scale);
|
Daniel@0
|
15744 builder._children[group._id].push({ builder: b, type: Types.LEGEND, scale: scale });
|
Daniel@0
|
15745 });
|
Daniel@0
|
15746 }
|
Daniel@0
|
15747
|
Daniel@0
|
15748 module.exports = GroupBuilder;
|
Daniel@0
|
15749 },{"../parse/axes":90,"../parse/legends":96,"./Builder":108,"./Scale":111,"datalib":24,"vega-dataflow":39,"vega-logging":45}],111:[function(require,module,exports){
|
Daniel@0
|
15750 (function (global){
|
Daniel@0
|
15751 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
15752 dl = require('datalib'),
|
Daniel@0
|
15753 df = require('vega-dataflow'),
|
Daniel@0
|
15754 log = require('vega-logging'),
|
Daniel@0
|
15755 Node = df.Node, // jshint ignore:line
|
Daniel@0
|
15756 Deps = df.Dependencies,
|
Daniel@0
|
15757 Aggregate = require('../transforms/Aggregate');
|
Daniel@0
|
15758
|
Daniel@0
|
15759 var Properties = {
|
Daniel@0
|
15760 width: 1,
|
Daniel@0
|
15761 height: 1
|
Daniel@0
|
15762 };
|
Daniel@0
|
15763
|
Daniel@0
|
15764 var Types = {
|
Daniel@0
|
15765 LINEAR: 'linear',
|
Daniel@0
|
15766 ORDINAL: 'ordinal',
|
Daniel@0
|
15767 LOG: 'log',
|
Daniel@0
|
15768 POWER: 'pow',
|
Daniel@0
|
15769 SQRT: 'sqrt',
|
Daniel@0
|
15770 TIME: 'time',
|
Daniel@0
|
15771 TIME_UTC: 'utc',
|
Daniel@0
|
15772 QUANTILE: 'quantile',
|
Daniel@0
|
15773 QUANTIZE: 'quantize',
|
Daniel@0
|
15774 THRESHOLD: 'threshold'
|
Daniel@0
|
15775 };
|
Daniel@0
|
15776
|
Daniel@0
|
15777 var DataRef = {
|
Daniel@0
|
15778 DOMAIN: 'domain',
|
Daniel@0
|
15779 RANGE: 'range',
|
Daniel@0
|
15780
|
Daniel@0
|
15781 COUNT: 'count',
|
Daniel@0
|
15782 GROUPBY: 'groupby',
|
Daniel@0
|
15783 MIN: 'min',
|
Daniel@0
|
15784 MAX: 'max',
|
Daniel@0
|
15785 VALUE: 'value',
|
Daniel@0
|
15786
|
Daniel@0
|
15787 ASC: 'asc',
|
Daniel@0
|
15788 DESC: 'desc'
|
Daniel@0
|
15789 };
|
Daniel@0
|
15790
|
Daniel@0
|
15791 function Scale(graph, def, parent) {
|
Daniel@0
|
15792 this._def = def;
|
Daniel@0
|
15793 this._parent = parent;
|
Daniel@0
|
15794 this._updated = false;
|
Daniel@0
|
15795 return Node.prototype.init.call(this, graph).reflows(true);
|
Daniel@0
|
15796 }
|
Daniel@0
|
15797
|
Daniel@0
|
15798 var proto = (Scale.prototype = new Node());
|
Daniel@0
|
15799
|
Daniel@0
|
15800 proto.evaluate = function(input) {
|
Daniel@0
|
15801 var self = this,
|
Daniel@0
|
15802 fn = function(group) { scale.call(self, group); };
|
Daniel@0
|
15803
|
Daniel@0
|
15804 this._updated = false;
|
Daniel@0
|
15805 input.add.forEach(fn);
|
Daniel@0
|
15806 input.mod.forEach(fn);
|
Daniel@0
|
15807
|
Daniel@0
|
15808 // Scales are at the end of an encoding pipeline, so they should forward a
|
Daniel@0
|
15809 // reflow pulse. Thus, if multiple scales update in the parent group, we don't
|
Daniel@0
|
15810 // reevaluate child marks multiple times.
|
Daniel@0
|
15811 if (this._updated) {
|
Daniel@0
|
15812 input.scales[this._def.name] = 1;
|
Daniel@0
|
15813 log.debug(input, ["scale", this._def.name]);
|
Daniel@0
|
15814 }
|
Daniel@0
|
15815 return df.ChangeSet.create(input, true);
|
Daniel@0
|
15816 };
|
Daniel@0
|
15817
|
Daniel@0
|
15818 // All of a scale's dependencies are registered during propagation as we parse
|
Daniel@0
|
15819 // dataRefs. So a scale must be responsible for connecting itself to dependents.
|
Daniel@0
|
15820 proto.dependency = function(type, deps) {
|
Daniel@0
|
15821 if (arguments.length == 2) {
|
Daniel@0
|
15822 var method = (type === Deps.DATA ? 'data' : 'signal');
|
Daniel@0
|
15823 deps = dl.array(deps);
|
Daniel@0
|
15824 for (var i=0, len=deps.length; i<len; ++i) {
|
Daniel@0
|
15825 this._graph[method](deps[i]).addListener(this._parent);
|
Daniel@0
|
15826 }
|
Daniel@0
|
15827 }
|
Daniel@0
|
15828
|
Daniel@0
|
15829 return Node.prototype.dependency.call(this, type, deps);
|
Daniel@0
|
15830 };
|
Daniel@0
|
15831
|
Daniel@0
|
15832 function scale(group) {
|
Daniel@0
|
15833 var name = this._def.name,
|
Daniel@0
|
15834 prev = name + ':prev',
|
Daniel@0
|
15835 s = instance.call(this, group.scale(name)),
|
Daniel@0
|
15836 m = s.type===Types.ORDINAL ? ordinal : quantitative,
|
Daniel@0
|
15837 rng = range.call(this, group);
|
Daniel@0
|
15838
|
Daniel@0
|
15839 m.call(this, s, rng, group);
|
Daniel@0
|
15840
|
Daniel@0
|
15841 group.scale(name, s);
|
Daniel@0
|
15842 group.scale(prev, group.scale(prev) || s);
|
Daniel@0
|
15843
|
Daniel@0
|
15844 return s;
|
Daniel@0
|
15845 }
|
Daniel@0
|
15846
|
Daniel@0
|
15847 function instance(scale) {
|
Daniel@0
|
15848 var config = this._graph.config(),
|
Daniel@0
|
15849 type = this._def.type || Types.LINEAR;
|
Daniel@0
|
15850 if (!scale || type !== scale.type) {
|
Daniel@0
|
15851 var ctor = config.scale[type] || d3.scale[type];
|
Daniel@0
|
15852 if (!ctor) throw Error('Unrecognized scale type: ' + type);
|
Daniel@0
|
15853 (scale = ctor()).type = scale.type || type;
|
Daniel@0
|
15854 scale.scaleName = this._def.name;
|
Daniel@0
|
15855 scale._prev = {};
|
Daniel@0
|
15856 }
|
Daniel@0
|
15857 return scale;
|
Daniel@0
|
15858 }
|
Daniel@0
|
15859
|
Daniel@0
|
15860 function ordinal(scale, rng, group) {
|
Daniel@0
|
15861 var def = this._def,
|
Daniel@0
|
15862 prev = scale._prev,
|
Daniel@0
|
15863 dataDrivenRange = false,
|
Daniel@0
|
15864 pad = signal.call(this, def.padding) || 0,
|
Daniel@0
|
15865 outer = def.outerPadding == null ? pad : signal.call(this, def.outerPadding),
|
Daniel@0
|
15866 points = def.points && signal.call(this, def.points),
|
Daniel@0
|
15867 round = signal.call(this, def.round) || def.round == null,
|
Daniel@0
|
15868 domain, str;
|
Daniel@0
|
15869
|
Daniel@0
|
15870 // range pre-processing for data-driven ranges
|
Daniel@0
|
15871 if (dl.isObject(def.range) && !dl.isArray(def.range)) {
|
Daniel@0
|
15872 dataDrivenRange = true;
|
Daniel@0
|
15873 rng = dataRef.call(this, DataRef.RANGE, def.range, scale, group);
|
Daniel@0
|
15874 }
|
Daniel@0
|
15875
|
Daniel@0
|
15876 // domain
|
Daniel@0
|
15877 domain = dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group);
|
Daniel@0
|
15878 if (domain && !dl.equal(prev.domain, domain)) {
|
Daniel@0
|
15879 scale.domain(domain);
|
Daniel@0
|
15880 prev.domain = domain;
|
Daniel@0
|
15881 this._updated = true;
|
Daniel@0
|
15882 }
|
Daniel@0
|
15883
|
Daniel@0
|
15884 // range
|
Daniel@0
|
15885 if (dl.equal(prev.range, rng)) return;
|
Daniel@0
|
15886
|
Daniel@0
|
15887 // width-defined range
|
Daniel@0
|
15888 if (def.bandWidth) {
|
Daniel@0
|
15889 var bw = signal.call(this, def.bandWidth),
|
Daniel@0
|
15890 len = domain.length,
|
Daniel@0
|
15891 space = def.points ? (pad*bw) : (pad*bw*(len-1) + 2*outer),
|
Daniel@0
|
15892 start;
|
Daniel@0
|
15893 if (rng[0] > rng[1]) {
|
Daniel@0
|
15894 start = rng[1] || 0;
|
Daniel@0
|
15895 rng = [start + (bw * len + space), start];
|
Daniel@0
|
15896 } else {
|
Daniel@0
|
15897 start = rng[0] || 0;
|
Daniel@0
|
15898 rng = [start, start + (bw * len + space)];
|
Daniel@0
|
15899 }
|
Daniel@0
|
15900 }
|
Daniel@0
|
15901
|
Daniel@0
|
15902 str = typeof rng[0] === 'string';
|
Daniel@0
|
15903 if (str || rng.length > 2 || rng.length===1 || dataDrivenRange) {
|
Daniel@0
|
15904 scale.range(rng); // color or shape values
|
Daniel@0
|
15905 } else if (points && round) {
|
Daniel@0
|
15906 scale.rangeRoundPoints(rng, pad);
|
Daniel@0
|
15907 } else if (points) {
|
Daniel@0
|
15908 scale.rangePoints(rng, pad);
|
Daniel@0
|
15909 } else if (round) {
|
Daniel@0
|
15910 scale.rangeRoundBands(rng, pad, outer);
|
Daniel@0
|
15911 } else {
|
Daniel@0
|
15912 scale.rangeBands(rng, pad, outer);
|
Daniel@0
|
15913 }
|
Daniel@0
|
15914
|
Daniel@0
|
15915 if (!scale.invert) {
|
Daniel@0
|
15916 scale.invert = function(x, y) {
|
Daniel@0
|
15917 if (arguments.length === 1) {
|
Daniel@0
|
15918 return scale.domain()[d3.bisect(scale.range(), x) - 1];
|
Daniel@0
|
15919 } else if (arguments.length === 2) { // Invert extents
|
Daniel@0
|
15920 if (!dl.isNumber(x) || !dl.isNumber(y)) {
|
Daniel@0
|
15921 throw Error('Extents to ordinal invert are not numbers ('+x+', '+y+').');
|
Daniel@0
|
15922 }
|
Daniel@0
|
15923
|
Daniel@0
|
15924 var points = [],
|
Daniel@0
|
15925 rng = scale.range(),
|
Daniel@0
|
15926 i = 0, len = rng.length, r;
|
Daniel@0
|
15927
|
Daniel@0
|
15928 for(; i<len; ++i) {
|
Daniel@0
|
15929 r = rng[i];
|
Daniel@0
|
15930 if (x < y ? x <= r && r <= y : y <= r && r <= x) {
|
Daniel@0
|
15931 points.push(r);
|
Daniel@0
|
15932 }
|
Daniel@0
|
15933 }
|
Daniel@0
|
15934
|
Daniel@0
|
15935 return points.map(function(p) { return scale.invert(p); });
|
Daniel@0
|
15936 }
|
Daniel@0
|
15937 };
|
Daniel@0
|
15938 }
|
Daniel@0
|
15939
|
Daniel@0
|
15940 prev.range = rng;
|
Daniel@0
|
15941 this._updated = true;
|
Daniel@0
|
15942 }
|
Daniel@0
|
15943
|
Daniel@0
|
15944 function quantitative(scale, rng, group) {
|
Daniel@0
|
15945 var def = this._def,
|
Daniel@0
|
15946 prev = scale._prev,
|
Daniel@0
|
15947 round = signal.call(this, def.round),
|
Daniel@0
|
15948 exponent = signal.call(this, def.exponent),
|
Daniel@0
|
15949 clamp = signal.call(this, def.clamp),
|
Daniel@0
|
15950 nice = signal.call(this, def.nice),
|
Daniel@0
|
15951 domain, interval;
|
Daniel@0
|
15952
|
Daniel@0
|
15953 // domain
|
Daniel@0
|
15954 domain = (def.type === Types.QUANTILE) ?
|
Daniel@0
|
15955 dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group) :
|
Daniel@0
|
15956 domainMinMax.call(this, scale, group);
|
Daniel@0
|
15957 if (domain && !dl.equal(prev.domain, domain)) {
|
Daniel@0
|
15958 scale.domain(domain);
|
Daniel@0
|
15959 prev.domain = domain;
|
Daniel@0
|
15960 this._updated = true;
|
Daniel@0
|
15961 }
|
Daniel@0
|
15962
|
Daniel@0
|
15963 // range
|
Daniel@0
|
15964 // vertical scales should flip by default, so use XOR here
|
Daniel@0
|
15965 if (signal.call(this, def.range) === 'height') rng = rng.reverse();
|
Daniel@0
|
15966 if (dl.equal(prev.range, rng)) return;
|
Daniel@0
|
15967 scale[round && scale.rangeRound ? 'rangeRound' : 'range'](rng);
|
Daniel@0
|
15968 prev.range = rng;
|
Daniel@0
|
15969 this._updated = true;
|
Daniel@0
|
15970
|
Daniel@0
|
15971 // TODO: Support signals for these properties. Until then, only eval
|
Daniel@0
|
15972 // them once.
|
Daniel@0
|
15973 if (this._stamp > 0) return;
|
Daniel@0
|
15974 if (exponent && def.type===Types.POWER) scale.exponent(exponent);
|
Daniel@0
|
15975 if (clamp) scale.clamp(true);
|
Daniel@0
|
15976 if (nice) {
|
Daniel@0
|
15977 if (def.type === Types.TIME) {
|
Daniel@0
|
15978 interval = d3.time[nice];
|
Daniel@0
|
15979 if (!interval) log.error('Unrecognized interval: ' + interval);
|
Daniel@0
|
15980 scale.nice(interval);
|
Daniel@0
|
15981 } else {
|
Daniel@0
|
15982 scale.nice();
|
Daniel@0
|
15983 }
|
Daniel@0
|
15984 }
|
Daniel@0
|
15985 }
|
Daniel@0
|
15986
|
Daniel@0
|
15987 function isUniques(scale) {
|
Daniel@0
|
15988 return scale.type === Types.ORDINAL || scale.type === Types.QUANTILE;
|
Daniel@0
|
15989 }
|
Daniel@0
|
15990
|
Daniel@0
|
15991 function getRefs(def) {
|
Daniel@0
|
15992 return def.fields || dl.array(def);
|
Daniel@0
|
15993 }
|
Daniel@0
|
15994
|
Daniel@0
|
15995 function inherits(refs) {
|
Daniel@0
|
15996 return refs.some(function(r) {
|
Daniel@0
|
15997 if (!r.data) return true;
|
Daniel@0
|
15998 return r.data && dl.array(r.field).some(function(f) {
|
Daniel@0
|
15999 return f.parent;
|
Daniel@0
|
16000 });
|
Daniel@0
|
16001 });
|
Daniel@0
|
16002 }
|
Daniel@0
|
16003
|
Daniel@0
|
16004 function getFields(ref, group) {
|
Daniel@0
|
16005 return dl.array(ref.field).map(function(f) {
|
Daniel@0
|
16006 return f.parent ?
|
Daniel@0
|
16007 dl.accessor(f.parent)(group.datum) :
|
Daniel@0
|
16008 f; // String or {'signal'}
|
Daniel@0
|
16009 });
|
Daniel@0
|
16010 }
|
Daniel@0
|
16011
|
Daniel@0
|
16012 // Scale datarefs can be computed over multiple schema types.
|
Daniel@0
|
16013 // This function determines the type of aggregator created, and
|
Daniel@0
|
16014 // what data is sent to it: values, tuples, or multi-tuples that must
|
Daniel@0
|
16015 // be standardized into a consistent schema.
|
Daniel@0
|
16016 function aggrType(def, scale) {
|
Daniel@0
|
16017 var refs = getRefs(def);
|
Daniel@0
|
16018
|
Daniel@0
|
16019 // If we're operating over only a single domain, send full tuples
|
Daniel@0
|
16020 // through for efficiency (fewer accessor creations/calls)
|
Daniel@0
|
16021 if (refs.length == 1 && dl.array(refs[0].field).length == 1) {
|
Daniel@0
|
16022 return Aggregate.TYPES.TUPLE;
|
Daniel@0
|
16023 }
|
Daniel@0
|
16024
|
Daniel@0
|
16025 // With quantitative scales, we only care about min/max.
|
Daniel@0
|
16026 if (!isUniques(scale)) return Aggregate.TYPES.VALUE;
|
Daniel@0
|
16027
|
Daniel@0
|
16028 // If we don't sort, then we can send values directly to aggrs as well
|
Daniel@0
|
16029 if (!dl.isObject(def.sort)) return Aggregate.TYPES.VALUE;
|
Daniel@0
|
16030
|
Daniel@0
|
16031 return Aggregate.TYPES.MULTI;
|
Daniel@0
|
16032 }
|
Daniel@0
|
16033
|
Daniel@0
|
16034 function getCache(which, def, scale, group) {
|
Daniel@0
|
16035 var refs = getRefs(def),
|
Daniel@0
|
16036 inherit = inherits(refs),
|
Daniel@0
|
16037 atype = aggrType(def, scale),
|
Daniel@0
|
16038 uniques = isUniques(scale),
|
Daniel@0
|
16039 sort = def.sort,
|
Daniel@0
|
16040 ck = '_'+which,
|
Daniel@0
|
16041 fields = getFields(refs[0], group);
|
Daniel@0
|
16042
|
Daniel@0
|
16043 if (scale[ck] || this[ck]) return scale[ck] || this[ck];
|
Daniel@0
|
16044
|
Daniel@0
|
16045 var cache = new Aggregate(this._graph).type(atype),
|
Daniel@0
|
16046 groupby, summarize;
|
Daniel@0
|
16047
|
Daniel@0
|
16048 // If a scale's dataref doesn't inherit data from the group, we can
|
Daniel@0
|
16049 // store the dataref aggregator at the Scale (dataflow node) level.
|
Daniel@0
|
16050 if (inherit) {
|
Daniel@0
|
16051 scale[ck] = cache;
|
Daniel@0
|
16052 } else {
|
Daniel@0
|
16053 this[ck] = cache;
|
Daniel@0
|
16054 }
|
Daniel@0
|
16055
|
Daniel@0
|
16056 if (uniques) {
|
Daniel@0
|
16057 if (atype === Aggregate.TYPES.VALUE) {
|
Daniel@0
|
16058 groupby = [{ name: DataRef.GROUPBY, get: dl.identity }];
|
Daniel@0
|
16059 summarize = {'*': DataRef.COUNT};
|
Daniel@0
|
16060 } else if (atype === Aggregate.TYPES.TUPLE) {
|
Daniel@0
|
16061 groupby = [{ name: DataRef.GROUPBY, get: dl.$(fields[0]) }];
|
Daniel@0
|
16062 summarize = dl.isObject(sort) ? [{
|
Daniel@0
|
16063 field: DataRef.VALUE,
|
Daniel@0
|
16064 get: dl.$(sort.field),
|
Daniel@0
|
16065 ops: [sort.op]
|
Daniel@0
|
16066 }] : {'*': DataRef.COUNT};
|
Daniel@0
|
16067 } else { // atype === Aggregate.TYPES.MULTI
|
Daniel@0
|
16068 groupby = DataRef.GROUPBY;
|
Daniel@0
|
16069 summarize = [{ field: DataRef.VALUE, ops: [sort.op] }];
|
Daniel@0
|
16070 }
|
Daniel@0
|
16071 } else {
|
Daniel@0
|
16072 groupby = [];
|
Daniel@0
|
16073 summarize = [{
|
Daniel@0
|
16074 field: DataRef.VALUE,
|
Daniel@0
|
16075 get: (atype == Aggregate.TYPES.TUPLE) ? dl.$(fields[0]) : dl.identity,
|
Daniel@0
|
16076 ops: [DataRef.MIN, DataRef.MAX],
|
Daniel@0
|
16077 as: [DataRef.MIN, DataRef.MAX]
|
Daniel@0
|
16078 }];
|
Daniel@0
|
16079 }
|
Daniel@0
|
16080
|
Daniel@0
|
16081 cache.param('groupby', groupby)
|
Daniel@0
|
16082 .param('summarize', summarize);
|
Daniel@0
|
16083
|
Daniel@0
|
16084 return (cache._lastUpdate = -1, cache);
|
Daniel@0
|
16085 }
|
Daniel@0
|
16086
|
Daniel@0
|
16087 function dataRef(which, def, scale, group) {
|
Daniel@0
|
16088 if (def == null) { return []; }
|
Daniel@0
|
16089 if (dl.isArray(def)) return def.map(signal.bind(this));
|
Daniel@0
|
16090
|
Daniel@0
|
16091 var self = this, graph = this._graph,
|
Daniel@0
|
16092 refs = getRefs(def),
|
Daniel@0
|
16093 inherit = inherits(refs),
|
Daniel@0
|
16094 atype = aggrType(def, scale),
|
Daniel@0
|
16095 cache = getCache.apply(this, arguments),
|
Daniel@0
|
16096 sort = def.sort,
|
Daniel@0
|
16097 uniques = isUniques(scale),
|
Daniel@0
|
16098 i, rlen, j, flen, ref, fields, field, data, from, so, cmp;
|
Daniel@0
|
16099
|
Daniel@0
|
16100 function addDep(s) {
|
Daniel@0
|
16101 self.dependency(Deps.SIGNALS, s);
|
Daniel@0
|
16102 }
|
Daniel@0
|
16103
|
Daniel@0
|
16104 if (inherit || (!inherit && cache._lastUpdate < this._stamp)) {
|
Daniel@0
|
16105 for (i=0, rlen=refs.length; i<rlen; ++i) {
|
Daniel@0
|
16106 ref = refs[i];
|
Daniel@0
|
16107 from = ref.data || group.datum._facetID;
|
Daniel@0
|
16108 data = graph.data(from).last();
|
Daniel@0
|
16109
|
Daniel@0
|
16110 if (data.stamp <= this._stamp) continue;
|
Daniel@0
|
16111
|
Daniel@0
|
16112 fields = getFields(ref, group);
|
Daniel@0
|
16113 for (j=0, flen=fields.length; j<flen; ++j) {
|
Daniel@0
|
16114 field = fields[j];
|
Daniel@0
|
16115
|
Daniel@0
|
16116 if (atype === Aggregate.TYPES.VALUE) {
|
Daniel@0
|
16117 cache.accessors(null, field);
|
Daniel@0
|
16118 } else if (atype === Aggregate.TYPES.MULTI) {
|
Daniel@0
|
16119 cache.accessors(field, ref.sort || sort.field);
|
Daniel@0
|
16120 } // Else (Tuple-case) is handled by the aggregator accessors by default
|
Daniel@0
|
16121
|
Daniel@0
|
16122 cache.evaluate(data);
|
Daniel@0
|
16123 }
|
Daniel@0
|
16124
|
Daniel@0
|
16125 this.dependency(Deps.DATA, from);
|
Daniel@0
|
16126 cache.dependency(Deps.SIGNALS).forEach(addDep);
|
Daniel@0
|
16127 }
|
Daniel@0
|
16128
|
Daniel@0
|
16129 cache._lastUpdate = this._stamp;
|
Daniel@0
|
16130
|
Daniel@0
|
16131 data = cache.aggr().result();
|
Daniel@0
|
16132 if (uniques) {
|
Daniel@0
|
16133 if (dl.isObject(sort)) {
|
Daniel@0
|
16134 cmp = (so = sort.order) && so.signal ? graph.signalRef(so.signal) : so;
|
Daniel@0
|
16135 cmp = (cmp == DataRef.DESC ? '-' : '+') + sort.op + '_' + DataRef.VALUE;
|
Daniel@0
|
16136 cmp = dl.comparator(cmp);
|
Daniel@0
|
16137 } else if (sort === true) {
|
Daniel@0
|
16138 cmp = dl.comparator(DataRef.GROUPBY);
|
Daniel@0
|
16139 }
|
Daniel@0
|
16140
|
Daniel@0
|
16141 if (cmp) data = data.sort(cmp);
|
Daniel@0
|
16142 cache._values = data.map(function(d) { return d[DataRef.GROUPBY]; });
|
Daniel@0
|
16143 } else {
|
Daniel@0
|
16144 data = data[0];
|
Daniel@0
|
16145 cache._values = !dl.isValid(data) ? [] : [data[DataRef.MIN], data[DataRef.MAX]];
|
Daniel@0
|
16146 }
|
Daniel@0
|
16147 }
|
Daniel@0
|
16148
|
Daniel@0
|
16149 return cache._values;
|
Daniel@0
|
16150 }
|
Daniel@0
|
16151
|
Daniel@0
|
16152 function signal(v) {
|
Daniel@0
|
16153 if (!v || !v.signal) return v;
|
Daniel@0
|
16154 var s = v.signal, ref;
|
Daniel@0
|
16155 this.dependency(Deps.SIGNALS, (ref = dl.field(s))[0]);
|
Daniel@0
|
16156 return this._graph.signalRef(ref);
|
Daniel@0
|
16157 }
|
Daniel@0
|
16158
|
Daniel@0
|
16159 function domainMinMax(scale, group) {
|
Daniel@0
|
16160 var def = this._def,
|
Daniel@0
|
16161 domain = [null, null], s, z;
|
Daniel@0
|
16162
|
Daniel@0
|
16163 if (def.domain !== undefined) {
|
Daniel@0
|
16164 domain = (!dl.isObject(def.domain)) ? domain :
|
Daniel@0
|
16165 dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group);
|
Daniel@0
|
16166 }
|
Daniel@0
|
16167
|
Daniel@0
|
16168 z = domain.length - 1;
|
Daniel@0
|
16169 if (def.domainMin !== undefined) {
|
Daniel@0
|
16170 if (dl.isObject(def.domainMin)) {
|
Daniel@0
|
16171 if (def.domainMin.signal) {
|
Daniel@0
|
16172 domain[0] = dl.isValid(s=signal.call(this, def.domainMin)) ? s : domain[0];
|
Daniel@0
|
16173 } else {
|
Daniel@0
|
16174 domain[0] = dataRef.call(this, DataRef.DOMAIN+DataRef.MIN, def.domainMin, scale, group)[0];
|
Daniel@0
|
16175 }
|
Daniel@0
|
16176 } else {
|
Daniel@0
|
16177 domain[0] = def.domainMin;
|
Daniel@0
|
16178 }
|
Daniel@0
|
16179 }
|
Daniel@0
|
16180 if (def.domainMax !== undefined) {
|
Daniel@0
|
16181 if (dl.isObject(def.domainMax)) {
|
Daniel@0
|
16182 if (def.domainMax.signal) {
|
Daniel@0
|
16183 domain[z] = dl.isValid(s=signal.call(this, def.domainMax)) ? s : domain[z];
|
Daniel@0
|
16184 } else {
|
Daniel@0
|
16185 domain[z] = dataRef.call(this, DataRef.DOMAIN+DataRef.MAX, def.domainMax, scale, group)[1];
|
Daniel@0
|
16186 }
|
Daniel@0
|
16187 } else {
|
Daniel@0
|
16188 domain[z] = def.domainMax;
|
Daniel@0
|
16189 }
|
Daniel@0
|
16190 }
|
Daniel@0
|
16191 if (def.type !== Types.LOG && def.type !== Types.TIME && (def.zero || def.zero===undefined)) {
|
Daniel@0
|
16192 domain[0] = Math.min(0, domain[0]);
|
Daniel@0
|
16193 domain[z] = Math.max(0, domain[z]);
|
Daniel@0
|
16194 }
|
Daniel@0
|
16195 return domain;
|
Daniel@0
|
16196 }
|
Daniel@0
|
16197
|
Daniel@0
|
16198 function range(group) {
|
Daniel@0
|
16199 var def = this._def,
|
Daniel@0
|
16200 config = this._graph.config(),
|
Daniel@0
|
16201 rangeVal = signal.call(this, def.range),
|
Daniel@0
|
16202 rng = [null, null];
|
Daniel@0
|
16203
|
Daniel@0
|
16204 if (rangeVal !== undefined) {
|
Daniel@0
|
16205 if (typeof rangeVal === 'string') {
|
Daniel@0
|
16206 if (Properties[rangeVal]) {
|
Daniel@0
|
16207 rng = [0, group[rangeVal]];
|
Daniel@0
|
16208 } else if (config.range[rangeVal]) {
|
Daniel@0
|
16209 rng = config.range[rangeVal];
|
Daniel@0
|
16210 } else {
|
Daniel@0
|
16211 log.error('Unrecogized range: ' + rangeVal);
|
Daniel@0
|
16212 return rng;
|
Daniel@0
|
16213 }
|
Daniel@0
|
16214 } else if (dl.isArray(rangeVal)) {
|
Daniel@0
|
16215 rng = dl.duplicate(rangeVal).map(signal.bind(this));
|
Daniel@0
|
16216 } else if (dl.isObject(rangeVal)) {
|
Daniel@0
|
16217 return null; // early exit
|
Daniel@0
|
16218 } else {
|
Daniel@0
|
16219 rng = [0, rangeVal];
|
Daniel@0
|
16220 }
|
Daniel@0
|
16221 }
|
Daniel@0
|
16222 if (def.rangeMin !== undefined) {
|
Daniel@0
|
16223 rng[0] = def.rangeMin.signal ?
|
Daniel@0
|
16224 signal.call(this, def.rangeMin) :
|
Daniel@0
|
16225 def.rangeMin;
|
Daniel@0
|
16226 }
|
Daniel@0
|
16227 if (def.rangeMax !== undefined) {
|
Daniel@0
|
16228 rng[rng.length-1] = def.rangeMax.signal ?
|
Daniel@0
|
16229 signal.call(this, def.rangeMax) :
|
Daniel@0
|
16230 def.rangeMax;
|
Daniel@0
|
16231 }
|
Daniel@0
|
16232
|
Daniel@0
|
16233 if (def.reverse !== undefined) {
|
Daniel@0
|
16234 var rev = signal.call(this, def.reverse);
|
Daniel@0
|
16235 if (dl.isObject(rev)) {
|
Daniel@0
|
16236 rev = dl.accessor(rev.field)(group.datum);
|
Daniel@0
|
16237 }
|
Daniel@0
|
16238 if (rev) rng = rng.reverse();
|
Daniel@0
|
16239 }
|
Daniel@0
|
16240
|
Daniel@0
|
16241 return rng;
|
Daniel@0
|
16242 }
|
Daniel@0
|
16243
|
Daniel@0
|
16244 module.exports = Scale;
|
Daniel@0
|
16245 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
16246
|
Daniel@0
|
16247 },{"../transforms/Aggregate":116,"datalib":24,"vega-dataflow":39,"vega-logging":45}],112:[function(require,module,exports){
|
Daniel@0
|
16248 (function (global){
|
Daniel@0
|
16249 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
16250 bound = require('vega-scenegraph').bound,
|
Daniel@0
|
16251 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
16252 Status = require('./Builder').STATUS;
|
Daniel@0
|
16253
|
Daniel@0
|
16254 function Transition(duration, ease) {
|
Daniel@0
|
16255 this.duration = duration || 500;
|
Daniel@0
|
16256 this.ease = ease && d3.ease(ease) || d3.ease('cubic-in-out');
|
Daniel@0
|
16257 this.updates = {next: null};
|
Daniel@0
|
16258 }
|
Daniel@0
|
16259
|
Daniel@0
|
16260 var prototype = Transition.prototype;
|
Daniel@0
|
16261
|
Daniel@0
|
16262 var skip = {
|
Daniel@0
|
16263 'text': 1,
|
Daniel@0
|
16264 'url': 1
|
Daniel@0
|
16265 };
|
Daniel@0
|
16266
|
Daniel@0
|
16267 prototype.interpolate = function(item, values) {
|
Daniel@0
|
16268 var key, curr, next, interp, list = null;
|
Daniel@0
|
16269
|
Daniel@0
|
16270 for (key in values) {
|
Daniel@0
|
16271 curr = item[key];
|
Daniel@0
|
16272 next = values[key];
|
Daniel@0
|
16273 if (curr !== next) {
|
Daniel@0
|
16274 if (skip[key] || curr === undefined) {
|
Daniel@0
|
16275 // skip interpolation for specific keys or undefined start values
|
Daniel@0
|
16276 Tuple.set(item, key, next);
|
Daniel@0
|
16277 } else if (typeof curr === 'number' && !isFinite(curr)) {
|
Daniel@0
|
16278 // for NaN or infinite numeric values, skip to final value
|
Daniel@0
|
16279 Tuple.set(item, key, next);
|
Daniel@0
|
16280 } else {
|
Daniel@0
|
16281 // otherwise lookup interpolator
|
Daniel@0
|
16282 interp = d3.interpolate(curr, next);
|
Daniel@0
|
16283 interp.property = key;
|
Daniel@0
|
16284 (list || (list=[])).push(interp);
|
Daniel@0
|
16285 }
|
Daniel@0
|
16286 }
|
Daniel@0
|
16287 }
|
Daniel@0
|
16288
|
Daniel@0
|
16289 if (list === null && item.status === Status.EXIT) {
|
Daniel@0
|
16290 list = []; // ensure exiting items are included
|
Daniel@0
|
16291 }
|
Daniel@0
|
16292
|
Daniel@0
|
16293 if (list != null) {
|
Daniel@0
|
16294 list.item = item;
|
Daniel@0
|
16295 list.ease = item.mark.ease || this.ease;
|
Daniel@0
|
16296 list.next = this.updates.next;
|
Daniel@0
|
16297 this.updates.next = list;
|
Daniel@0
|
16298 }
|
Daniel@0
|
16299 return this;
|
Daniel@0
|
16300 };
|
Daniel@0
|
16301
|
Daniel@0
|
16302 prototype.start = function(callback) {
|
Daniel@0
|
16303 var t = this, prev = t.updates, curr = prev.next;
|
Daniel@0
|
16304 for (; curr!=null; prev=curr, curr=prev.next) {
|
Daniel@0
|
16305 if (curr.item.status === Status.EXIT) {
|
Daniel@0
|
16306 // Only mark item as exited when it is removed.
|
Daniel@0
|
16307 curr.item.status = Status.UPDATE;
|
Daniel@0
|
16308 curr.remove = true;
|
Daniel@0
|
16309 }
|
Daniel@0
|
16310 }
|
Daniel@0
|
16311 t.callback = callback;
|
Daniel@0
|
16312 d3.timer(function(elapsed) { return step.call(t, elapsed); });
|
Daniel@0
|
16313 };
|
Daniel@0
|
16314
|
Daniel@0
|
16315 function step(elapsed) {
|
Daniel@0
|
16316 var list = this.updates, prev = list, curr = prev.next,
|
Daniel@0
|
16317 duration = this.duration,
|
Daniel@0
|
16318 item, delay, f, e, i, n, stop = true;
|
Daniel@0
|
16319
|
Daniel@0
|
16320 for (; curr!=null; prev=curr, curr=prev.next) {
|
Daniel@0
|
16321 item = curr.item;
|
Daniel@0
|
16322 delay = item.delay || 0;
|
Daniel@0
|
16323
|
Daniel@0
|
16324 f = (elapsed - delay) / duration;
|
Daniel@0
|
16325 if (f < 0) { stop = false; continue; }
|
Daniel@0
|
16326 if (f > 1) f = 1;
|
Daniel@0
|
16327 e = curr.ease(f);
|
Daniel@0
|
16328
|
Daniel@0
|
16329 for (i=0, n=curr.length; i<n; ++i) {
|
Daniel@0
|
16330 item[curr[i].property] = curr[i](e);
|
Daniel@0
|
16331 }
|
Daniel@0
|
16332 item.touch();
|
Daniel@0
|
16333 bound.item(item);
|
Daniel@0
|
16334
|
Daniel@0
|
16335 if (f === 1) {
|
Daniel@0
|
16336 if (curr.remove) {
|
Daniel@0
|
16337 item.status = Status.EXIT;
|
Daniel@0
|
16338 item.remove();
|
Daniel@0
|
16339 }
|
Daniel@0
|
16340 prev.next = curr.next;
|
Daniel@0
|
16341 curr = prev;
|
Daniel@0
|
16342 } else {
|
Daniel@0
|
16343 stop = false;
|
Daniel@0
|
16344 }
|
Daniel@0
|
16345 }
|
Daniel@0
|
16346
|
Daniel@0
|
16347 this.callback();
|
Daniel@0
|
16348 return stop;
|
Daniel@0
|
16349 }
|
Daniel@0
|
16350
|
Daniel@0
|
16351 module.exports = Transition;
|
Daniel@0
|
16352 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
16353
|
Daniel@0
|
16354 },{"./Builder":108,"vega-dataflow":39,"vega-scenegraph":46}],113:[function(require,module,exports){
|
Daniel@0
|
16355 var dl = require('datalib'),
|
Daniel@0
|
16356 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
16357 parseMark = require('../parse/mark');
|
Daniel@0
|
16358
|
Daniel@0
|
16359 var TIME = 'time',
|
Daniel@0
|
16360 UTC = 'utc',
|
Daniel@0
|
16361 STRING = 'string',
|
Daniel@0
|
16362 ORDINAL = 'ordinal',
|
Daniel@0
|
16363 NUMBER = 'number';
|
Daniel@0
|
16364
|
Daniel@0
|
16365 function axs(model) {
|
Daniel@0
|
16366 var scale,
|
Daniel@0
|
16367 config = model.config(),
|
Daniel@0
|
16368 orient = config.axis.orient,
|
Daniel@0
|
16369 offset = 0,
|
Daniel@0
|
16370 titleOffset = config.axis.titleOffset,
|
Daniel@0
|
16371 axisDef = {},
|
Daniel@0
|
16372 layer = 'front',
|
Daniel@0
|
16373 grid = false,
|
Daniel@0
|
16374 title = null,
|
Daniel@0
|
16375 tickMajorSize = config.axis.tickSize,
|
Daniel@0
|
16376 tickMinorSize = config.axis.tickSize,
|
Daniel@0
|
16377 tickEndSize = config.axis.tickSize,
|
Daniel@0
|
16378 tickPadding = config.axis.padding,
|
Daniel@0
|
16379 tickValues = null,
|
Daniel@0
|
16380 tickFormatString = null,
|
Daniel@0
|
16381 tickFormatType = null,
|
Daniel@0
|
16382 tickSubdivide = 0,
|
Daniel@0
|
16383 tickCount = config.axis.ticks,
|
Daniel@0
|
16384 gridLineStyle = {},
|
Daniel@0
|
16385 tickLabelStyle = {},
|
Daniel@0
|
16386 majorTickStyle = {},
|
Daniel@0
|
16387 minorTickStyle = {},
|
Daniel@0
|
16388 titleStyle = {},
|
Daniel@0
|
16389 domainStyle = {},
|
Daniel@0
|
16390 m = { // Axis marks as references for updates
|
Daniel@0
|
16391 gridLines: {},
|
Daniel@0
|
16392 majorTicks: {},
|
Daniel@0
|
16393 minorTicks: {},
|
Daniel@0
|
16394 tickLabels: {},
|
Daniel@0
|
16395 domain: {},
|
Daniel@0
|
16396 title: {}
|
Daniel@0
|
16397 };
|
Daniel@0
|
16398
|
Daniel@0
|
16399 var axis = {};
|
Daniel@0
|
16400
|
Daniel@0
|
16401 function reset() {
|
Daniel@0
|
16402 axisDef.type = null;
|
Daniel@0
|
16403 }
|
Daniel@0
|
16404
|
Daniel@0
|
16405 function ingest(d) {
|
Daniel@0
|
16406 return {data: d};
|
Daniel@0
|
16407 }
|
Daniel@0
|
16408
|
Daniel@0
|
16409 function getTickFormat() {
|
Daniel@0
|
16410 var formatType = tickFormatType || inferFormatType();
|
Daniel@0
|
16411 return getFormatter(formatType, tickFormatString);
|
Daniel@0
|
16412 }
|
Daniel@0
|
16413
|
Daniel@0
|
16414 function inferFormatType() {
|
Daniel@0
|
16415 switch (scale.type) {
|
Daniel@0
|
16416 case TIME: return TIME;
|
Daniel@0
|
16417 case UTC: return UTC;
|
Daniel@0
|
16418 case ORDINAL: return STRING;
|
Daniel@0
|
16419 default: return NUMBER;
|
Daniel@0
|
16420 }
|
Daniel@0
|
16421 }
|
Daniel@0
|
16422
|
Daniel@0
|
16423 // Adapted from d3 log scale
|
Daniel@0
|
16424 // TODO customize? replace with range-size-aware filtering?
|
Daniel@0
|
16425 function logFilter(domain, count, f) {
|
Daniel@0
|
16426 if (count == null) return f;
|
Daniel@0
|
16427 var base = scale.base(),
|
Daniel@0
|
16428 k = Math.min(base, scale.ticks().length / count),
|
Daniel@0
|
16429 v = domain[0] > 0 ? (e = 1e-12, Math.ceil) : (e = -1e-12, Math.floor),
|
Daniel@0
|
16430 e;
|
Daniel@0
|
16431 function log(x) {
|
Daniel@0
|
16432 return (domain[0] < 0 ?
|
Daniel@0
|
16433 -Math.log(x > 0 ? 0 : -x) :
|
Daniel@0
|
16434 Math.log(x < 0 ? 0 : x)) / Math.log(base);
|
Daniel@0
|
16435 }
|
Daniel@0
|
16436 function pow(x) {
|
Daniel@0
|
16437 return domain[0] < 0 ? -Math.pow(base, -x) : Math.pow(base, x);
|
Daniel@0
|
16438 }
|
Daniel@0
|
16439 return function(d) {
|
Daniel@0
|
16440 return pow(v(log(d) + e)) / d >= k ? f(d) : '';
|
Daniel@0
|
16441 };
|
Daniel@0
|
16442 }
|
Daniel@0
|
16443
|
Daniel@0
|
16444 function getFormatter(formatType, str) {
|
Daniel@0
|
16445 var fmt = dl.format,
|
Daniel@0
|
16446 log = scale.type === 'log',
|
Daniel@0
|
16447 domain, f;
|
Daniel@0
|
16448
|
Daniel@0
|
16449 switch (formatType) {
|
Daniel@0
|
16450 case NUMBER:
|
Daniel@0
|
16451 domain = scale.domain();
|
Daniel@0
|
16452 f = fmt.auto.number(domain, tickCount, str || (log ? '.1r' : null));
|
Daniel@0
|
16453 return log ? logFilter(domain, tickCount, f) : f;
|
Daniel@0
|
16454 case TIME: return (str ? fmt : fmt.auto).time(str);
|
Daniel@0
|
16455 case UTC: return (str ? fmt : fmt.auto).utc(str);
|
Daniel@0
|
16456 default: return String;
|
Daniel@0
|
16457 }
|
Daniel@0
|
16458 }
|
Daniel@0
|
16459
|
Daniel@0
|
16460 function getTicks(format) {
|
Daniel@0
|
16461 var major = tickValues || (scale.ticks ? scale.ticks(tickCount) : scale.domain()),
|
Daniel@0
|
16462 minor = axisSubdivide(scale, major, tickSubdivide).map(ingest);
|
Daniel@0
|
16463 major = major.map(function(d) { return (d = ingest(d), d.label = format(d.data), d); });
|
Daniel@0
|
16464 return [major, minor];
|
Daniel@0
|
16465 }
|
Daniel@0
|
16466
|
Daniel@0
|
16467 axis.def = function() {
|
Daniel@0
|
16468 if (!axisDef.type) axis_def(scale);
|
Daniel@0
|
16469
|
Daniel@0
|
16470 var ticks = getTicks(getTickFormat());
|
Daniel@0
|
16471 var tdata = title ? [title].map(ingest) : [];
|
Daniel@0
|
16472
|
Daniel@0
|
16473 axisDef.marks[0].from = function() { return grid ? ticks[0] : []; };
|
Daniel@0
|
16474 axisDef.marks[1].from = function() { return ticks[0]; };
|
Daniel@0
|
16475 axisDef.marks[2].from = function() { return ticks[1]; };
|
Daniel@0
|
16476 axisDef.marks[3].from = axisDef.marks[1].from;
|
Daniel@0
|
16477 axisDef.marks[4].from = function() { return [1]; };
|
Daniel@0
|
16478 axisDef.marks[5].from = function() { return tdata; };
|
Daniel@0
|
16479 axisDef.offset = offset;
|
Daniel@0
|
16480 axisDef.orient = orient;
|
Daniel@0
|
16481 axisDef.layer = layer;
|
Daniel@0
|
16482
|
Daniel@0
|
16483 return axisDef;
|
Daniel@0
|
16484 };
|
Daniel@0
|
16485
|
Daniel@0
|
16486 function axis_def(scale) {
|
Daniel@0
|
16487 // setup scale mapping
|
Daniel@0
|
16488 var newScale, oldScale, range;
|
Daniel@0
|
16489 if (scale.type === ORDINAL) {
|
Daniel@0
|
16490 newScale = {scale: scale.scaleName, offset: 0.5 + scale.rangeBand()/2};
|
Daniel@0
|
16491 oldScale = newScale;
|
Daniel@0
|
16492 } else {
|
Daniel@0
|
16493 newScale = {scale: scale.scaleName, offset: 0.5};
|
Daniel@0
|
16494 oldScale = {scale: scale.scaleName+':prev', offset: 0.5};
|
Daniel@0
|
16495 }
|
Daniel@0
|
16496 range = axisScaleRange(scale);
|
Daniel@0
|
16497
|
Daniel@0
|
16498 // setup axis marks
|
Daniel@0
|
16499 dl.extend(m.gridLines, axisTicks(config));
|
Daniel@0
|
16500 dl.extend(m.majorTicks, axisTicks(config));
|
Daniel@0
|
16501 dl.extend(m.minorTicks, axisTicks(config));
|
Daniel@0
|
16502 dl.extend(m.tickLabels, axisTickLabels(config));
|
Daniel@0
|
16503 dl.extend(m.domain, axisDomain(config));
|
Daniel@0
|
16504 dl.extend(m.title, axisTitle(config));
|
Daniel@0
|
16505 m.gridLines.properties.enter.stroke = {value: config.axis.gridColor};
|
Daniel@0
|
16506 m.gridLines.properties.enter.strokeOpacity = {value: config.axis.gridOpacity};
|
Daniel@0
|
16507
|
Daniel@0
|
16508 // extend axis marks based on axis orientation
|
Daniel@0
|
16509 axisTicksExtend(orient, m.gridLines, oldScale, newScale, Infinity);
|
Daniel@0
|
16510 axisTicksExtend(orient, m.majorTicks, oldScale, newScale, tickMajorSize);
|
Daniel@0
|
16511 axisTicksExtend(orient, m.minorTicks, oldScale, newScale, tickMinorSize);
|
Daniel@0
|
16512 axisLabelExtend(orient, m.tickLabels, oldScale, newScale, tickMajorSize, tickPadding);
|
Daniel@0
|
16513
|
Daniel@0
|
16514 axisDomainExtend(orient, m.domain, range, tickEndSize);
|
Daniel@0
|
16515 axisTitleExtend(orient, m.title, range, titleOffset); // TODO get offset
|
Daniel@0
|
16516
|
Daniel@0
|
16517 // add / override custom style properties
|
Daniel@0
|
16518 dl.extend(m.gridLines.properties.update, gridLineStyle);
|
Daniel@0
|
16519 dl.extend(m.majorTicks.properties.update, majorTickStyle);
|
Daniel@0
|
16520 dl.extend(m.minorTicks.properties.update, minorTickStyle);
|
Daniel@0
|
16521 dl.extend(m.tickLabels.properties.update, tickLabelStyle);
|
Daniel@0
|
16522 dl.extend(m.domain.properties.update, domainStyle);
|
Daniel@0
|
16523 dl.extend(m.title.properties.update, titleStyle);
|
Daniel@0
|
16524
|
Daniel@0
|
16525 var marks = [m.gridLines, m.majorTicks, m.minorTicks, m.tickLabels, m.domain, m.title];
|
Daniel@0
|
16526 dl.extend(axisDef, {
|
Daniel@0
|
16527 type: 'group',
|
Daniel@0
|
16528 interactive: false,
|
Daniel@0
|
16529 properties: {
|
Daniel@0
|
16530 enter: {
|
Daniel@0
|
16531 encode: axisUpdate,
|
Daniel@0
|
16532 scales: [scale.scaleName],
|
Daniel@0
|
16533 signals: [], data: []
|
Daniel@0
|
16534 },
|
Daniel@0
|
16535 update: {
|
Daniel@0
|
16536 encode: axisUpdate,
|
Daniel@0
|
16537 scales: [scale.scaleName],
|
Daniel@0
|
16538 signals: [], data: []
|
Daniel@0
|
16539 }
|
Daniel@0
|
16540 }
|
Daniel@0
|
16541 });
|
Daniel@0
|
16542
|
Daniel@0
|
16543 axisDef.marks = marks.map(function(m) { return parseMark(model, m); });
|
Daniel@0
|
16544 }
|
Daniel@0
|
16545
|
Daniel@0
|
16546 axis.scale = function(x) {
|
Daniel@0
|
16547 if (!arguments.length) return scale;
|
Daniel@0
|
16548 if (scale !== x) { scale = x; reset(); }
|
Daniel@0
|
16549 return axis;
|
Daniel@0
|
16550 };
|
Daniel@0
|
16551
|
Daniel@0
|
16552 axis.orient = function(x) {
|
Daniel@0
|
16553 if (!arguments.length) return orient;
|
Daniel@0
|
16554 if (orient !== x) {
|
Daniel@0
|
16555 orient = x in axisOrients ? x + '' : config.axis.orient;
|
Daniel@0
|
16556 reset();
|
Daniel@0
|
16557 }
|
Daniel@0
|
16558 return axis;
|
Daniel@0
|
16559 };
|
Daniel@0
|
16560
|
Daniel@0
|
16561 axis.title = function(x) {
|
Daniel@0
|
16562 if (!arguments.length) return title;
|
Daniel@0
|
16563 if (title !== x) { title = x; reset(); }
|
Daniel@0
|
16564 return axis;
|
Daniel@0
|
16565 };
|
Daniel@0
|
16566
|
Daniel@0
|
16567 axis.tickCount = function(x) {
|
Daniel@0
|
16568 if (!arguments.length) return tickCount;
|
Daniel@0
|
16569 tickCount = x;
|
Daniel@0
|
16570 return axis;
|
Daniel@0
|
16571 };
|
Daniel@0
|
16572
|
Daniel@0
|
16573 axis.tickValues = function(x) {
|
Daniel@0
|
16574 if (!arguments.length) return tickValues;
|
Daniel@0
|
16575 tickValues = x;
|
Daniel@0
|
16576 return axis;
|
Daniel@0
|
16577 };
|
Daniel@0
|
16578
|
Daniel@0
|
16579 axis.tickFormat = function(x) {
|
Daniel@0
|
16580 if (!arguments.length) return tickFormatString;
|
Daniel@0
|
16581 if (tickFormatString !== x) {
|
Daniel@0
|
16582 tickFormatString = x;
|
Daniel@0
|
16583 reset();
|
Daniel@0
|
16584 }
|
Daniel@0
|
16585 return axis;
|
Daniel@0
|
16586 };
|
Daniel@0
|
16587
|
Daniel@0
|
16588 axis.tickFormatType = function(x) {
|
Daniel@0
|
16589 if (!arguments.length) return tickFormatType;
|
Daniel@0
|
16590 if (tickFormatType !== x) {
|
Daniel@0
|
16591 tickFormatType = x;
|
Daniel@0
|
16592 reset();
|
Daniel@0
|
16593 }
|
Daniel@0
|
16594 return axis;
|
Daniel@0
|
16595 };
|
Daniel@0
|
16596
|
Daniel@0
|
16597 axis.tickSize = function(x, y) {
|
Daniel@0
|
16598 if (!arguments.length) return tickMajorSize;
|
Daniel@0
|
16599 var n = arguments.length - 1,
|
Daniel@0
|
16600 major = +x,
|
Daniel@0
|
16601 minor = n > 1 ? +y : tickMajorSize,
|
Daniel@0
|
16602 end = n > 0 ? +arguments[n] : tickMajorSize;
|
Daniel@0
|
16603
|
Daniel@0
|
16604 if (tickMajorSize !== major ||
|
Daniel@0
|
16605 tickMinorSize !== minor ||
|
Daniel@0
|
16606 tickEndSize !== end) {
|
Daniel@0
|
16607 reset();
|
Daniel@0
|
16608 }
|
Daniel@0
|
16609
|
Daniel@0
|
16610 tickMajorSize = major;
|
Daniel@0
|
16611 tickMinorSize = minor;
|
Daniel@0
|
16612 tickEndSize = end;
|
Daniel@0
|
16613 return axis;
|
Daniel@0
|
16614 };
|
Daniel@0
|
16615
|
Daniel@0
|
16616 axis.tickSubdivide = function(x) {
|
Daniel@0
|
16617 if (!arguments.length) return tickSubdivide;
|
Daniel@0
|
16618 tickSubdivide = +x;
|
Daniel@0
|
16619 return axis;
|
Daniel@0
|
16620 };
|
Daniel@0
|
16621
|
Daniel@0
|
16622 axis.offset = function(x) {
|
Daniel@0
|
16623 if (!arguments.length) return offset;
|
Daniel@0
|
16624 offset = dl.isObject(x) ? x : +x;
|
Daniel@0
|
16625 return axis;
|
Daniel@0
|
16626 };
|
Daniel@0
|
16627
|
Daniel@0
|
16628 axis.tickPadding = function(x) {
|
Daniel@0
|
16629 if (!arguments.length) return tickPadding;
|
Daniel@0
|
16630 if (tickPadding !== +x) { tickPadding = +x; reset(); }
|
Daniel@0
|
16631 return axis;
|
Daniel@0
|
16632 };
|
Daniel@0
|
16633
|
Daniel@0
|
16634 axis.titleOffset = function(x) {
|
Daniel@0
|
16635 if (!arguments.length) return titleOffset;
|
Daniel@0
|
16636 if (titleOffset !== +x) { titleOffset = +x; reset(); }
|
Daniel@0
|
16637 return axis;
|
Daniel@0
|
16638 };
|
Daniel@0
|
16639
|
Daniel@0
|
16640 axis.layer = function(x) {
|
Daniel@0
|
16641 if (!arguments.length) return layer;
|
Daniel@0
|
16642 if (layer !== x) { layer = x; reset(); }
|
Daniel@0
|
16643 return axis;
|
Daniel@0
|
16644 };
|
Daniel@0
|
16645
|
Daniel@0
|
16646 axis.grid = function(x) {
|
Daniel@0
|
16647 if (!arguments.length) return grid;
|
Daniel@0
|
16648 if (grid !== x) { grid = x; reset(); }
|
Daniel@0
|
16649 return axis;
|
Daniel@0
|
16650 };
|
Daniel@0
|
16651
|
Daniel@0
|
16652 axis.gridLineProperties = function(x) {
|
Daniel@0
|
16653 if (!arguments.length) return gridLineStyle;
|
Daniel@0
|
16654 if (gridLineStyle !== x) { gridLineStyle = x; }
|
Daniel@0
|
16655 return axis;
|
Daniel@0
|
16656 };
|
Daniel@0
|
16657
|
Daniel@0
|
16658 axis.majorTickProperties = function(x) {
|
Daniel@0
|
16659 if (!arguments.length) return majorTickStyle;
|
Daniel@0
|
16660 if (majorTickStyle !== x) { majorTickStyle = x; }
|
Daniel@0
|
16661 return axis;
|
Daniel@0
|
16662 };
|
Daniel@0
|
16663
|
Daniel@0
|
16664 axis.minorTickProperties = function(x) {
|
Daniel@0
|
16665 if (!arguments.length) return minorTickStyle;
|
Daniel@0
|
16666 if (minorTickStyle !== x) { minorTickStyle = x; }
|
Daniel@0
|
16667 return axis;
|
Daniel@0
|
16668 };
|
Daniel@0
|
16669
|
Daniel@0
|
16670 axis.tickLabelProperties = function(x) {
|
Daniel@0
|
16671 if (!arguments.length) return tickLabelStyle;
|
Daniel@0
|
16672 if (tickLabelStyle !== x) { tickLabelStyle = x; }
|
Daniel@0
|
16673 return axis;
|
Daniel@0
|
16674 };
|
Daniel@0
|
16675
|
Daniel@0
|
16676 axis.titleProperties = function(x) {
|
Daniel@0
|
16677 if (!arguments.length) return titleStyle;
|
Daniel@0
|
16678 if (titleStyle !== x) { titleStyle = x; }
|
Daniel@0
|
16679 return axis;
|
Daniel@0
|
16680 };
|
Daniel@0
|
16681
|
Daniel@0
|
16682 axis.domainProperties = function(x) {
|
Daniel@0
|
16683 if (!arguments.length) return domainStyle;
|
Daniel@0
|
16684 if (domainStyle !== x) { domainStyle = x; }
|
Daniel@0
|
16685 return axis;
|
Daniel@0
|
16686 };
|
Daniel@0
|
16687
|
Daniel@0
|
16688 axis.reset = function() {
|
Daniel@0
|
16689 reset();
|
Daniel@0
|
16690 return axis;
|
Daniel@0
|
16691 };
|
Daniel@0
|
16692
|
Daniel@0
|
16693 return axis;
|
Daniel@0
|
16694 }
|
Daniel@0
|
16695
|
Daniel@0
|
16696 var axisOrients = {top: 1, right: 1, bottom: 1, left: 1};
|
Daniel@0
|
16697
|
Daniel@0
|
16698 function axisSubdivide(scale, ticks, m) {
|
Daniel@0
|
16699 var subticks = [];
|
Daniel@0
|
16700 if (m && ticks.length > 1) {
|
Daniel@0
|
16701 var extent = axisScaleExtent(scale.domain()),
|
Daniel@0
|
16702 i = -1,
|
Daniel@0
|
16703 n = ticks.length,
|
Daniel@0
|
16704 d = (ticks[1] - ticks[0]) / ++m,
|
Daniel@0
|
16705 j,
|
Daniel@0
|
16706 v;
|
Daniel@0
|
16707 while (++i < n) {
|
Daniel@0
|
16708 for (j = m; --j > 0;) {
|
Daniel@0
|
16709 if ((v = +ticks[i] - j * d) >= extent[0]) {
|
Daniel@0
|
16710 subticks.push(v);
|
Daniel@0
|
16711 }
|
Daniel@0
|
16712 }
|
Daniel@0
|
16713 }
|
Daniel@0
|
16714 for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) {
|
Daniel@0
|
16715 subticks.push(v);
|
Daniel@0
|
16716 }
|
Daniel@0
|
16717 }
|
Daniel@0
|
16718 return subticks;
|
Daniel@0
|
16719 }
|
Daniel@0
|
16720
|
Daniel@0
|
16721 function axisScaleExtent(domain) {
|
Daniel@0
|
16722 var start = domain[0], stop = domain[domain.length - 1];
|
Daniel@0
|
16723 return start < stop ? [start, stop] : [stop, start];
|
Daniel@0
|
16724 }
|
Daniel@0
|
16725
|
Daniel@0
|
16726 function axisScaleRange(scale) {
|
Daniel@0
|
16727 return scale.rangeExtent ?
|
Daniel@0
|
16728 scale.rangeExtent() :
|
Daniel@0
|
16729 axisScaleExtent(scale.range());
|
Daniel@0
|
16730 }
|
Daniel@0
|
16731
|
Daniel@0
|
16732 var axisAlign = {
|
Daniel@0
|
16733 bottom: 'center',
|
Daniel@0
|
16734 top: 'center',
|
Daniel@0
|
16735 left: 'right',
|
Daniel@0
|
16736 right: 'left'
|
Daniel@0
|
16737 };
|
Daniel@0
|
16738
|
Daniel@0
|
16739 var axisBaseline = {
|
Daniel@0
|
16740 bottom: 'top',
|
Daniel@0
|
16741 top: 'bottom',
|
Daniel@0
|
16742 left: 'middle',
|
Daniel@0
|
16743 right: 'middle'
|
Daniel@0
|
16744 };
|
Daniel@0
|
16745
|
Daniel@0
|
16746 function axisLabelExtend(orient, labels, oldScale, newScale, size, pad) {
|
Daniel@0
|
16747 size = Math.max(size, 0) + pad;
|
Daniel@0
|
16748 if (orient === 'left' || orient === 'top') {
|
Daniel@0
|
16749 size *= -1;
|
Daniel@0
|
16750 }
|
Daniel@0
|
16751 if (orient === 'top' || orient === 'bottom') {
|
Daniel@0
|
16752 dl.extend(labels.properties.enter, {
|
Daniel@0
|
16753 x: oldScale,
|
Daniel@0
|
16754 y: {value: size},
|
Daniel@0
|
16755 });
|
Daniel@0
|
16756 dl.extend(labels.properties.update, {
|
Daniel@0
|
16757 x: newScale,
|
Daniel@0
|
16758 y: {value: size},
|
Daniel@0
|
16759 align: {value: 'center'},
|
Daniel@0
|
16760 baseline: {value: axisBaseline[orient]}
|
Daniel@0
|
16761 });
|
Daniel@0
|
16762 } else {
|
Daniel@0
|
16763 dl.extend(labels.properties.enter, {
|
Daniel@0
|
16764 x: {value: size},
|
Daniel@0
|
16765 y: oldScale,
|
Daniel@0
|
16766 });
|
Daniel@0
|
16767 dl.extend(labels.properties.update, {
|
Daniel@0
|
16768 x: {value: size},
|
Daniel@0
|
16769 y: newScale,
|
Daniel@0
|
16770 align: {value: axisAlign[orient]},
|
Daniel@0
|
16771 baseline: {value: 'middle'}
|
Daniel@0
|
16772 });
|
Daniel@0
|
16773 }
|
Daniel@0
|
16774 }
|
Daniel@0
|
16775
|
Daniel@0
|
16776 function axisTicksExtend(orient, ticks, oldScale, newScale, size) {
|
Daniel@0
|
16777 var sign = (orient === 'left' || orient === 'top') ? -1 : 1;
|
Daniel@0
|
16778 if (size === Infinity) {
|
Daniel@0
|
16779 size = (orient === 'top' || orient === 'bottom') ?
|
Daniel@0
|
16780 {field: {group: 'height', level: 2}, mult: -sign} :
|
Daniel@0
|
16781 {field: {group: 'width', level: 2}, mult: -sign};
|
Daniel@0
|
16782 } else {
|
Daniel@0
|
16783 size = {value: sign * size};
|
Daniel@0
|
16784 }
|
Daniel@0
|
16785 if (orient === 'top' || orient === 'bottom') {
|
Daniel@0
|
16786 dl.extend(ticks.properties.enter, {
|
Daniel@0
|
16787 x: oldScale,
|
Daniel@0
|
16788 y: {value: 0},
|
Daniel@0
|
16789 y2: size
|
Daniel@0
|
16790 });
|
Daniel@0
|
16791 dl.extend(ticks.properties.update, {
|
Daniel@0
|
16792 x: newScale,
|
Daniel@0
|
16793 y: {value: 0},
|
Daniel@0
|
16794 y2: size
|
Daniel@0
|
16795 });
|
Daniel@0
|
16796 dl.extend(ticks.properties.exit, {
|
Daniel@0
|
16797 x: newScale,
|
Daniel@0
|
16798 });
|
Daniel@0
|
16799 } else {
|
Daniel@0
|
16800 dl.extend(ticks.properties.enter, {
|
Daniel@0
|
16801 x: {value: 0},
|
Daniel@0
|
16802 x2: size,
|
Daniel@0
|
16803 y: oldScale
|
Daniel@0
|
16804 });
|
Daniel@0
|
16805 dl.extend(ticks.properties.update, {
|
Daniel@0
|
16806 x: {value: 0},
|
Daniel@0
|
16807 x2: size,
|
Daniel@0
|
16808 y: newScale
|
Daniel@0
|
16809 });
|
Daniel@0
|
16810 dl.extend(ticks.properties.exit, {
|
Daniel@0
|
16811 y: newScale,
|
Daniel@0
|
16812 });
|
Daniel@0
|
16813 }
|
Daniel@0
|
16814 }
|
Daniel@0
|
16815
|
Daniel@0
|
16816 function axisTitleExtend(orient, title, range, offset) {
|
Daniel@0
|
16817 var mid = ~~((range[0] + range[1]) / 2),
|
Daniel@0
|
16818 sign = (orient === 'top' || orient === 'left') ? -1 : 1;
|
Daniel@0
|
16819
|
Daniel@0
|
16820 if (orient === 'bottom' || orient === 'top') {
|
Daniel@0
|
16821 dl.extend(title.properties.update, {
|
Daniel@0
|
16822 x: {value: mid},
|
Daniel@0
|
16823 y: {value: sign*offset},
|
Daniel@0
|
16824 angle: {value: 0}
|
Daniel@0
|
16825 });
|
Daniel@0
|
16826 } else {
|
Daniel@0
|
16827 dl.extend(title.properties.update, {
|
Daniel@0
|
16828 x: {value: sign*offset},
|
Daniel@0
|
16829 y: {value: mid},
|
Daniel@0
|
16830 angle: {value: orient === 'left' ? -90 : 90}
|
Daniel@0
|
16831 });
|
Daniel@0
|
16832 }
|
Daniel@0
|
16833 }
|
Daniel@0
|
16834
|
Daniel@0
|
16835 function axisDomainExtend(orient, domain, range, size) {
|
Daniel@0
|
16836 var path;
|
Daniel@0
|
16837 if (orient === 'top' || orient === 'left') {
|
Daniel@0
|
16838 size = -1 * size;
|
Daniel@0
|
16839 }
|
Daniel@0
|
16840 if (orient === 'bottom' || orient === 'top') {
|
Daniel@0
|
16841 path = 'M' + range[0] + ',' + size + 'V0H' + range[1] + 'V' + size;
|
Daniel@0
|
16842 } else {
|
Daniel@0
|
16843 path = 'M' + size + ',' + range[0] + 'H0V' + range[1] + 'H' + size;
|
Daniel@0
|
16844 }
|
Daniel@0
|
16845 domain.properties.update.path = {value: path};
|
Daniel@0
|
16846 }
|
Daniel@0
|
16847
|
Daniel@0
|
16848 function axisUpdate(item, group, trans) {
|
Daniel@0
|
16849 var o = trans ? {} : item,
|
Daniel@0
|
16850 offset = item.mark.def.offset,
|
Daniel@0
|
16851 orient = item.mark.def.orient,
|
Daniel@0
|
16852 width = group.width,
|
Daniel@0
|
16853 height = group.height; // TODO fallback to global w,h?
|
Daniel@0
|
16854
|
Daniel@0
|
16855 if (dl.isArray(offset)) {
|
Daniel@0
|
16856 var ofx = offset[0],
|
Daniel@0
|
16857 ofy = offset[1];
|
Daniel@0
|
16858
|
Daniel@0
|
16859 switch (orient) {
|
Daniel@0
|
16860 case 'left': { Tuple.set(o, 'x', -ofx); Tuple.set(o, 'y', ofy); break; }
|
Daniel@0
|
16861 case 'right': { Tuple.set(o, 'x', width + ofx); Tuple.set(o, 'y', ofy); break; }
|
Daniel@0
|
16862 case 'bottom': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', height + ofy); break; }
|
Daniel@0
|
16863 case 'top': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', -ofy); break; }
|
Daniel@0
|
16864 default: { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', ofy); }
|
Daniel@0
|
16865 }
|
Daniel@0
|
16866 } else {
|
Daniel@0
|
16867 if (dl.isObject(offset)) {
|
Daniel@0
|
16868 offset = -group.scale(offset.scale)(offset.value);
|
Daniel@0
|
16869 }
|
Daniel@0
|
16870
|
Daniel@0
|
16871 switch (orient) {
|
Daniel@0
|
16872 case 'left': { Tuple.set(o, 'x', -offset); Tuple.set(o, 'y', 0); break; }
|
Daniel@0
|
16873 case 'right': { Tuple.set(o, 'x', width + offset); Tuple.set(o, 'y', 0); break; }
|
Daniel@0
|
16874 case 'bottom': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', height + offset); break; }
|
Daniel@0
|
16875 case 'top': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', -offset); break; }
|
Daniel@0
|
16876 default: { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', 0); }
|
Daniel@0
|
16877 }
|
Daniel@0
|
16878 }
|
Daniel@0
|
16879
|
Daniel@0
|
16880 if (trans) trans.interpolate(item, o);
|
Daniel@0
|
16881 return true;
|
Daniel@0
|
16882 }
|
Daniel@0
|
16883
|
Daniel@0
|
16884 function axisTicks(config) {
|
Daniel@0
|
16885 return {
|
Daniel@0
|
16886 type: 'rule',
|
Daniel@0
|
16887 interactive: false,
|
Daniel@0
|
16888 key: 'data',
|
Daniel@0
|
16889 properties: {
|
Daniel@0
|
16890 enter: {
|
Daniel@0
|
16891 stroke: {value: config.axis.tickColor},
|
Daniel@0
|
16892 strokeWidth: {value: config.axis.tickWidth},
|
Daniel@0
|
16893 opacity: {value: 1e-6}
|
Daniel@0
|
16894 },
|
Daniel@0
|
16895 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
16896 update: { opacity: {value: 1} }
|
Daniel@0
|
16897 }
|
Daniel@0
|
16898 };
|
Daniel@0
|
16899 }
|
Daniel@0
|
16900
|
Daniel@0
|
16901 function axisTickLabels(config) {
|
Daniel@0
|
16902 return {
|
Daniel@0
|
16903 type: 'text',
|
Daniel@0
|
16904 interactive: true,
|
Daniel@0
|
16905 key: 'data',
|
Daniel@0
|
16906 properties: {
|
Daniel@0
|
16907 enter: {
|
Daniel@0
|
16908 fill: {value: config.axis.tickLabelColor},
|
Daniel@0
|
16909 font: {value: config.axis.tickLabelFont},
|
Daniel@0
|
16910 fontSize: {value: config.axis.tickLabelFontSize},
|
Daniel@0
|
16911 opacity: {value: 1e-6},
|
Daniel@0
|
16912 text: {field: 'label'}
|
Daniel@0
|
16913 },
|
Daniel@0
|
16914 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
16915 update: { opacity: {value: 1} }
|
Daniel@0
|
16916 }
|
Daniel@0
|
16917 };
|
Daniel@0
|
16918 }
|
Daniel@0
|
16919
|
Daniel@0
|
16920 function axisTitle(config) {
|
Daniel@0
|
16921 return {
|
Daniel@0
|
16922 type: 'text',
|
Daniel@0
|
16923 interactive: true,
|
Daniel@0
|
16924 properties: {
|
Daniel@0
|
16925 enter: {
|
Daniel@0
|
16926 font: {value: config.axis.titleFont},
|
Daniel@0
|
16927 fontSize: {value: config.axis.titleFontSize},
|
Daniel@0
|
16928 fontWeight: {value: config.axis.titleFontWeight},
|
Daniel@0
|
16929 fill: {value: config.axis.titleColor},
|
Daniel@0
|
16930 align: {value: 'center'},
|
Daniel@0
|
16931 baseline: {value: 'middle'},
|
Daniel@0
|
16932 text: {field: 'data'}
|
Daniel@0
|
16933 },
|
Daniel@0
|
16934 update: {}
|
Daniel@0
|
16935 }
|
Daniel@0
|
16936 };
|
Daniel@0
|
16937 }
|
Daniel@0
|
16938
|
Daniel@0
|
16939 function axisDomain(config) {
|
Daniel@0
|
16940 return {
|
Daniel@0
|
16941 type: 'path',
|
Daniel@0
|
16942 interactive: false,
|
Daniel@0
|
16943 properties: {
|
Daniel@0
|
16944 enter: {
|
Daniel@0
|
16945 x: {value: 0.5},
|
Daniel@0
|
16946 y: {value: 0.5},
|
Daniel@0
|
16947 stroke: {value: config.axis.axisColor},
|
Daniel@0
|
16948 strokeWidth: {value: config.axis.axisWidth}
|
Daniel@0
|
16949 },
|
Daniel@0
|
16950 update: {}
|
Daniel@0
|
16951 }
|
Daniel@0
|
16952 };
|
Daniel@0
|
16953 }
|
Daniel@0
|
16954
|
Daniel@0
|
16955 module.exports = axs;
|
Daniel@0
|
16956 },{"../parse/mark":97,"datalib":24,"vega-dataflow":39}],114:[function(require,module,exports){
|
Daniel@0
|
16957 (function (global){
|
Daniel@0
|
16958 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
16959 dl = require('datalib'),
|
Daniel@0
|
16960 Gradient = require('vega-scenegraph').Gradient,
|
Daniel@0
|
16961 parseProperties = require('../parse/properties'),
|
Daniel@0
|
16962 parseMark = require('../parse/mark');
|
Daniel@0
|
16963
|
Daniel@0
|
16964 function lgnd(model) {
|
Daniel@0
|
16965 var size = null,
|
Daniel@0
|
16966 shape = null,
|
Daniel@0
|
16967 fill = null,
|
Daniel@0
|
16968 stroke = null,
|
Daniel@0
|
16969 spacing = null,
|
Daniel@0
|
16970 values = null,
|
Daniel@0
|
16971 format = null,
|
Daniel@0
|
16972 formatString = null,
|
Daniel@0
|
16973 config = model.config(),
|
Daniel@0
|
16974 title,
|
Daniel@0
|
16975 orient = 'right',
|
Daniel@0
|
16976 offset = config.legend.offset,
|
Daniel@0
|
16977 padding = config.legend.padding,
|
Daniel@0
|
16978 tickArguments = [5],
|
Daniel@0
|
16979 legendStyle = {},
|
Daniel@0
|
16980 symbolStyle = {},
|
Daniel@0
|
16981 gradientStyle = {},
|
Daniel@0
|
16982 titleStyle = {},
|
Daniel@0
|
16983 labelStyle = {},
|
Daniel@0
|
16984 m = { // Legend marks as references for updates
|
Daniel@0
|
16985 titles: {},
|
Daniel@0
|
16986 symbols: {},
|
Daniel@0
|
16987 labels: {},
|
Daniel@0
|
16988 gradient: {}
|
Daniel@0
|
16989 };
|
Daniel@0
|
16990
|
Daniel@0
|
16991 var legend = {},
|
Daniel@0
|
16992 legendDef = {};
|
Daniel@0
|
16993
|
Daniel@0
|
16994 function reset() { legendDef.type = null; }
|
Daniel@0
|
16995 function ingest(d, i) { return {data: d, index: i}; }
|
Daniel@0
|
16996
|
Daniel@0
|
16997 legend.def = function() {
|
Daniel@0
|
16998 var scale = size || shape || fill || stroke;
|
Daniel@0
|
16999
|
Daniel@0
|
17000 format = !formatString ? null : ((scale.type === 'time') ?
|
Daniel@0
|
17001 dl.format.time(formatString) : dl.format.number(formatString));
|
Daniel@0
|
17002
|
Daniel@0
|
17003 if (!legendDef.type) {
|
Daniel@0
|
17004 legendDef = (scale===fill || scale===stroke) && !discrete(scale.type) ?
|
Daniel@0
|
17005 quantDef(scale) : ordinalDef(scale);
|
Daniel@0
|
17006 }
|
Daniel@0
|
17007 legendDef.orient = orient;
|
Daniel@0
|
17008 legendDef.offset = offset;
|
Daniel@0
|
17009 legendDef.padding = padding;
|
Daniel@0
|
17010 return legendDef;
|
Daniel@0
|
17011 };
|
Daniel@0
|
17012
|
Daniel@0
|
17013 function discrete(type) {
|
Daniel@0
|
17014 return type==='ordinal' || type==='quantize' ||
|
Daniel@0
|
17015 type==='quantile' || type==='threshold';
|
Daniel@0
|
17016 }
|
Daniel@0
|
17017
|
Daniel@0
|
17018 function ordinalDef(scale) {
|
Daniel@0
|
17019 var def = o_legend_def(size, shape, fill, stroke);
|
Daniel@0
|
17020
|
Daniel@0
|
17021 // generate data
|
Daniel@0
|
17022 var data = (values == null ?
|
Daniel@0
|
17023 (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) :
|
Daniel@0
|
17024 values).map(ingest);
|
Daniel@0
|
17025 var fmt = format==null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : String) : format;
|
Daniel@0
|
17026
|
Daniel@0
|
17027 // determine spacing between legend entries
|
Daniel@0
|
17028 var fs, range, offset, pad=5, domain = d3.range(data.length);
|
Daniel@0
|
17029 if (size) {
|
Daniel@0
|
17030 range = data.map(function(x) { return Math.sqrt(size(x.data)); });
|
Daniel@0
|
17031 offset = d3.max(range);
|
Daniel@0
|
17032 range = range.reduce(function(a,b,i,z) {
|
Daniel@0
|
17033 if (i > 0) a[i] = a[i-1] + z[i-1]/2 + pad;
|
Daniel@0
|
17034 return (a[i] += b/2, a); }, [0]).map(Math.round);
|
Daniel@0
|
17035 } else {
|
Daniel@0
|
17036 offset = Math.round(Math.sqrt(config.legend.symbolSize));
|
Daniel@0
|
17037 range = spacing ||
|
Daniel@0
|
17038 (fs = labelStyle.fontSize) && (fs.value + pad) ||
|
Daniel@0
|
17039 (config.legend.labelFontSize + pad);
|
Daniel@0
|
17040 range = domain.map(function(d,i) {
|
Daniel@0
|
17041 return Math.round(offset/2 + i*range);
|
Daniel@0
|
17042 });
|
Daniel@0
|
17043 }
|
Daniel@0
|
17044
|
Daniel@0
|
17045 // account for padding and title size
|
Daniel@0
|
17046 var sz = padding, ts;
|
Daniel@0
|
17047 if (title) {
|
Daniel@0
|
17048 ts = titleStyle.fontSize;
|
Daniel@0
|
17049 sz += 5 + ((ts && ts.value) || config.legend.titleFontSize);
|
Daniel@0
|
17050 }
|
Daniel@0
|
17051 for (var i=0, n=range.length; i<n; ++i) range[i] += sz;
|
Daniel@0
|
17052
|
Daniel@0
|
17053 // build scale for label layout
|
Daniel@0
|
17054 var scaleSpec = {
|
Daniel@0
|
17055 name: 'legend',
|
Daniel@0
|
17056 type: 'ordinal',
|
Daniel@0
|
17057 points: true,
|
Daniel@0
|
17058 domain: domain,
|
Daniel@0
|
17059 range: range
|
Daniel@0
|
17060 };
|
Daniel@0
|
17061
|
Daniel@0
|
17062 // update legend def
|
Daniel@0
|
17063 var tdata = (title ? [title] : []).map(ingest);
|
Daniel@0
|
17064 data.forEach(function(d) {
|
Daniel@0
|
17065 d.label = fmt(d.data);
|
Daniel@0
|
17066 d.offset = offset;
|
Daniel@0
|
17067 });
|
Daniel@0
|
17068 def.scales = [ scaleSpec ];
|
Daniel@0
|
17069 def.marks[0].from = function() { return tdata; };
|
Daniel@0
|
17070 def.marks[1].from = function() { return data; };
|
Daniel@0
|
17071 def.marks[2].from = def.marks[1].from;
|
Daniel@0
|
17072
|
Daniel@0
|
17073 return def;
|
Daniel@0
|
17074 }
|
Daniel@0
|
17075
|
Daniel@0
|
17076 function o_legend_def(size, shape, fill, stroke) {
|
Daniel@0
|
17077 // setup legend marks
|
Daniel@0
|
17078 var titles = dl.extend(m.titles, vg_legendTitle(config)),
|
Daniel@0
|
17079 symbols = dl.extend(m.symbols, vg_legendSymbols(config)),
|
Daniel@0
|
17080 labels = dl.extend(m.labels, vg_vLegendLabels(config));
|
Daniel@0
|
17081
|
Daniel@0
|
17082 // extend legend marks
|
Daniel@0
|
17083 vg_legendSymbolExtend(symbols, size, shape, fill, stroke);
|
Daniel@0
|
17084
|
Daniel@0
|
17085 // add / override custom style properties
|
Daniel@0
|
17086 dl.extend(titles.properties.update, titleStyle);
|
Daniel@0
|
17087 dl.extend(symbols.properties.update, symbolStyle);
|
Daniel@0
|
17088 dl.extend(labels.properties.update, labelStyle);
|
Daniel@0
|
17089
|
Daniel@0
|
17090 // padding from legend border
|
Daniel@0
|
17091 titles.properties.enter.x.value += padding;
|
Daniel@0
|
17092 titles.properties.enter.y.value += padding;
|
Daniel@0
|
17093 labels.properties.enter.x.offset += padding + 1;
|
Daniel@0
|
17094 symbols.properties.enter.x.offset = padding + 1;
|
Daniel@0
|
17095 labels.properties.update.x.offset += padding + 1;
|
Daniel@0
|
17096 symbols.properties.update.x.offset = padding + 1;
|
Daniel@0
|
17097
|
Daniel@0
|
17098 dl.extend(legendDef, {
|
Daniel@0
|
17099 type: 'group',
|
Daniel@0
|
17100 interactive: false,
|
Daniel@0
|
17101 properties: {
|
Daniel@0
|
17102 enter: parseProperties(model, 'group', legendStyle),
|
Daniel@0
|
17103 vg_legendPosition: {
|
Daniel@0
|
17104 encode: vg_legendPosition,
|
Daniel@0
|
17105 signals: [], scales:[], data: [], fields: []
|
Daniel@0
|
17106 }
|
Daniel@0
|
17107 }
|
Daniel@0
|
17108 });
|
Daniel@0
|
17109
|
Daniel@0
|
17110 legendDef.marks = [titles, symbols, labels].map(function(m) { return parseMark(model, m); });
|
Daniel@0
|
17111 return legendDef;
|
Daniel@0
|
17112 }
|
Daniel@0
|
17113
|
Daniel@0
|
17114 function quantDef(scale) {
|
Daniel@0
|
17115 var def = q_legend_def(scale),
|
Daniel@0
|
17116 dom = scale.domain(),
|
Daniel@0
|
17117 data = (values == null ?
|
Daniel@0
|
17118 (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) :
|
Daniel@0
|
17119 values).map(ingest),
|
Daniel@0
|
17120 width = (gradientStyle.width && gradientStyle.width.value) || config.legend.gradientWidth,
|
Daniel@0
|
17121 fmt = format==null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : String) : format;
|
Daniel@0
|
17122
|
Daniel@0
|
17123 // build scale for label layout
|
Daniel@0
|
17124 var layoutSpec = {
|
Daniel@0
|
17125 name: 'legend',
|
Daniel@0
|
17126 type: scale.type,
|
Daniel@0
|
17127 round: true,
|
Daniel@0
|
17128 zero: false,
|
Daniel@0
|
17129 domain: [dom[0], dom[dom.length-1]],
|
Daniel@0
|
17130 range: [padding, width+padding]
|
Daniel@0
|
17131 };
|
Daniel@0
|
17132 if (scale.type==='pow') layoutSpec.exponent = scale.exponent();
|
Daniel@0
|
17133
|
Daniel@0
|
17134 // update legend def
|
Daniel@0
|
17135 var tdata = (title ? [title] : []).map(ingest);
|
Daniel@0
|
17136 data.forEach(function(d,i) {
|
Daniel@0
|
17137 d.label = fmt(d.data);
|
Daniel@0
|
17138 d.align = i==(data.length-1) ? 'right' : i===0 ? 'left' : 'center';
|
Daniel@0
|
17139 });
|
Daniel@0
|
17140 def.scales = [ layoutSpec ];
|
Daniel@0
|
17141 def.marks[0].from = function() { return tdata; };
|
Daniel@0
|
17142 def.marks[1].from = function() { return [1]; };
|
Daniel@0
|
17143 def.marks[2].from = function() { return data; };
|
Daniel@0
|
17144 return def;
|
Daniel@0
|
17145 }
|
Daniel@0
|
17146
|
Daniel@0
|
17147 function q_legend_def(scale) {
|
Daniel@0
|
17148 // setup legend marks
|
Daniel@0
|
17149 var titles = dl.extend(m.titles, vg_legendTitle(config)),
|
Daniel@0
|
17150 gradient = dl.extend(m.gradient, vg_legendGradient(config)),
|
Daniel@0
|
17151 labels = dl.extend(m.labels, vg_hLegendLabels(config)),
|
Daniel@0
|
17152 grad = new Gradient();
|
Daniel@0
|
17153
|
Daniel@0
|
17154 // setup color gradient
|
Daniel@0
|
17155 var dom = scale.domain(),
|
Daniel@0
|
17156 min = dom[0],
|
Daniel@0
|
17157 max = dom[dom.length-1],
|
Daniel@0
|
17158 f = scale.copy().domain([min, max]).range([0,1]);
|
Daniel@0
|
17159
|
Daniel@0
|
17160 var stops = (scale.type !== 'linear' && scale.ticks) ?
|
Daniel@0
|
17161 scale.ticks.call(scale, 15) : dom;
|
Daniel@0
|
17162 if (min !== stops[0]) stops.unshift(min);
|
Daniel@0
|
17163 if (max !== stops[stops.length-1]) stops.push(max);
|
Daniel@0
|
17164
|
Daniel@0
|
17165 for (var i=0, n=stops.length; i<n; ++i) {
|
Daniel@0
|
17166 grad.stop(f(stops[i]), scale(stops[i]));
|
Daniel@0
|
17167 }
|
Daniel@0
|
17168 gradient.properties.enter.fill = {value: grad};
|
Daniel@0
|
17169
|
Daniel@0
|
17170 // add / override custom style properties
|
Daniel@0
|
17171 dl.extend(titles.properties.update, titleStyle);
|
Daniel@0
|
17172 dl.extend(gradient.properties.update, gradientStyle);
|
Daniel@0
|
17173 dl.extend(labels.properties.update, labelStyle);
|
Daniel@0
|
17174
|
Daniel@0
|
17175 // account for gradient size
|
Daniel@0
|
17176 var gp = gradient.properties, gh = gradientStyle.height,
|
Daniel@0
|
17177 hh = (gh && gh.value) || gp.enter.height.value;
|
Daniel@0
|
17178 labels.properties.enter.y.value = hh;
|
Daniel@0
|
17179 labels.properties.update.y.value = hh;
|
Daniel@0
|
17180
|
Daniel@0
|
17181 // account for title size as needed
|
Daniel@0
|
17182 if (title) {
|
Daniel@0
|
17183 var tp = titles.properties, fs = titleStyle.fontSize,
|
Daniel@0
|
17184 sz = 4 + ((fs && fs.value) || tp.enter.fontSize.value);
|
Daniel@0
|
17185 gradient.properties.enter.y.value += sz;
|
Daniel@0
|
17186 labels.properties.enter.y.value += sz;
|
Daniel@0
|
17187 gradient.properties.update.y.value += sz;
|
Daniel@0
|
17188 labels.properties.update.y.value += sz;
|
Daniel@0
|
17189 }
|
Daniel@0
|
17190
|
Daniel@0
|
17191 // padding from legend border
|
Daniel@0
|
17192 titles.properties.enter.x.value += padding;
|
Daniel@0
|
17193 titles.properties.enter.y.value += padding;
|
Daniel@0
|
17194 gradient.properties.enter.x.value += padding;
|
Daniel@0
|
17195 gradient.properties.enter.y.value += padding;
|
Daniel@0
|
17196 labels.properties.enter.y.value += padding;
|
Daniel@0
|
17197 gradient.properties.update.x.value += padding;
|
Daniel@0
|
17198 gradient.properties.update.y.value += padding;
|
Daniel@0
|
17199 labels.properties.update.y.value += padding;
|
Daniel@0
|
17200
|
Daniel@0
|
17201 dl.extend(legendDef, {
|
Daniel@0
|
17202 type: 'group',
|
Daniel@0
|
17203 interactive: false,
|
Daniel@0
|
17204 properties: {
|
Daniel@0
|
17205 enter: parseProperties(model, 'group', legendStyle),
|
Daniel@0
|
17206 vg_legendPosition: {
|
Daniel@0
|
17207 encode: vg_legendPosition,
|
Daniel@0
|
17208 signals: [], scales: [], data: [], fields: []
|
Daniel@0
|
17209 }
|
Daniel@0
|
17210 }
|
Daniel@0
|
17211 });
|
Daniel@0
|
17212
|
Daniel@0
|
17213 legendDef.marks = [titles, gradient, labels].map(function(m) { return parseMark(model, m); });
|
Daniel@0
|
17214 return legendDef;
|
Daniel@0
|
17215 }
|
Daniel@0
|
17216
|
Daniel@0
|
17217 legend.size = function(x) {
|
Daniel@0
|
17218 if (!arguments.length) return size;
|
Daniel@0
|
17219 if (size !== x) { size = x; reset(); }
|
Daniel@0
|
17220 return legend;
|
Daniel@0
|
17221 };
|
Daniel@0
|
17222
|
Daniel@0
|
17223 legend.shape = function(x) {
|
Daniel@0
|
17224 if (!arguments.length) return shape;
|
Daniel@0
|
17225 if (shape !== x) { shape = x; reset(); }
|
Daniel@0
|
17226 return legend;
|
Daniel@0
|
17227 };
|
Daniel@0
|
17228
|
Daniel@0
|
17229 legend.fill = function(x) {
|
Daniel@0
|
17230 if (!arguments.length) return fill;
|
Daniel@0
|
17231 if (fill !== x) { fill = x; reset(); }
|
Daniel@0
|
17232 return legend;
|
Daniel@0
|
17233 };
|
Daniel@0
|
17234
|
Daniel@0
|
17235 legend.stroke = function(x) {
|
Daniel@0
|
17236 if (!arguments.length) return stroke;
|
Daniel@0
|
17237 if (stroke !== x) { stroke = x; reset(); }
|
Daniel@0
|
17238 return legend;
|
Daniel@0
|
17239 };
|
Daniel@0
|
17240
|
Daniel@0
|
17241 legend.title = function(x) {
|
Daniel@0
|
17242 if (!arguments.length) return title;
|
Daniel@0
|
17243 if (title !== x) { title = x; reset(); }
|
Daniel@0
|
17244 return legend;
|
Daniel@0
|
17245 };
|
Daniel@0
|
17246
|
Daniel@0
|
17247 legend.format = function(x) {
|
Daniel@0
|
17248 if (!arguments.length) return formatString;
|
Daniel@0
|
17249 if (formatString !== x) {
|
Daniel@0
|
17250 formatString = x;
|
Daniel@0
|
17251 reset();
|
Daniel@0
|
17252 }
|
Daniel@0
|
17253 return legend;
|
Daniel@0
|
17254 };
|
Daniel@0
|
17255
|
Daniel@0
|
17256 legend.spacing = function(x) {
|
Daniel@0
|
17257 if (!arguments.length) return spacing;
|
Daniel@0
|
17258 if (spacing !== +x) { spacing = +x; reset(); }
|
Daniel@0
|
17259 return legend;
|
Daniel@0
|
17260 };
|
Daniel@0
|
17261
|
Daniel@0
|
17262 legend.orient = function(x) {
|
Daniel@0
|
17263 if (!arguments.length) return orient;
|
Daniel@0
|
17264 orient = x in vg_legendOrients ? x + '' : config.legend.orient;
|
Daniel@0
|
17265 return legend;
|
Daniel@0
|
17266 };
|
Daniel@0
|
17267
|
Daniel@0
|
17268 legend.offset = function(x) {
|
Daniel@0
|
17269 if (!arguments.length) return offset;
|
Daniel@0
|
17270 offset = +x;
|
Daniel@0
|
17271 return legend;
|
Daniel@0
|
17272 };
|
Daniel@0
|
17273
|
Daniel@0
|
17274 legend.values = function(x) {
|
Daniel@0
|
17275 if (!arguments.length) return values;
|
Daniel@0
|
17276 values = x;
|
Daniel@0
|
17277 return legend;
|
Daniel@0
|
17278 };
|
Daniel@0
|
17279
|
Daniel@0
|
17280 legend.legendProperties = function(x) {
|
Daniel@0
|
17281 if (!arguments.length) return legendStyle;
|
Daniel@0
|
17282 legendStyle = x;
|
Daniel@0
|
17283 return legend;
|
Daniel@0
|
17284 };
|
Daniel@0
|
17285
|
Daniel@0
|
17286 legend.symbolProperties = function(x) {
|
Daniel@0
|
17287 if (!arguments.length) return symbolStyle;
|
Daniel@0
|
17288 symbolStyle = x;
|
Daniel@0
|
17289 return legend;
|
Daniel@0
|
17290 };
|
Daniel@0
|
17291
|
Daniel@0
|
17292 legend.gradientProperties = function(x) {
|
Daniel@0
|
17293 if (!arguments.length) return gradientStyle;
|
Daniel@0
|
17294 gradientStyle = x;
|
Daniel@0
|
17295 return legend;
|
Daniel@0
|
17296 };
|
Daniel@0
|
17297
|
Daniel@0
|
17298 legend.labelProperties = function(x) {
|
Daniel@0
|
17299 if (!arguments.length) return labelStyle;
|
Daniel@0
|
17300 labelStyle = x;
|
Daniel@0
|
17301 return legend;
|
Daniel@0
|
17302 };
|
Daniel@0
|
17303
|
Daniel@0
|
17304 legend.titleProperties = function(x) {
|
Daniel@0
|
17305 if (!arguments.length) return titleStyle;
|
Daniel@0
|
17306 titleStyle = x;
|
Daniel@0
|
17307 return legend;
|
Daniel@0
|
17308 };
|
Daniel@0
|
17309
|
Daniel@0
|
17310 legend.reset = function() {
|
Daniel@0
|
17311 reset();
|
Daniel@0
|
17312 return legend;
|
Daniel@0
|
17313 };
|
Daniel@0
|
17314
|
Daniel@0
|
17315 return legend;
|
Daniel@0
|
17316 }
|
Daniel@0
|
17317
|
Daniel@0
|
17318 var vg_legendOrients = {right: 1, left: 1};
|
Daniel@0
|
17319
|
Daniel@0
|
17320 function vg_legendPosition(item, group, trans, db, signals, predicates) {
|
Daniel@0
|
17321 var o = trans ? {} : item, gx,
|
Daniel@0
|
17322 offset = item.mark.def.offset,
|
Daniel@0
|
17323 orient = item.mark.def.orient,
|
Daniel@0
|
17324 pad = item.mark.def.padding * 2,
|
Daniel@0
|
17325 lw = ~~item.bounds.width() + (item.width ? 0 : pad),
|
Daniel@0
|
17326 lh = ~~item.bounds.height() + (item.height ? 0 : pad),
|
Daniel@0
|
17327 pos = group._legendPositions ||
|
Daniel@0
|
17328 (group._legendPositions = {right: 0.5, left: 0.5});
|
Daniel@0
|
17329
|
Daniel@0
|
17330 o.x = 0.5;
|
Daniel@0
|
17331 o.width = lw;
|
Daniel@0
|
17332 o.y = pos[orient];
|
Daniel@0
|
17333 pos[orient] += (o.height = lh);
|
Daniel@0
|
17334
|
Daniel@0
|
17335 // HACK: use to estimate group bounds during animated transition
|
Daniel@0
|
17336 if (!trans && group.bounds) {
|
Daniel@0
|
17337 group.bounds.delta = group.bounds.x2 - group.width;
|
Daniel@0
|
17338 }
|
Daniel@0
|
17339
|
Daniel@0
|
17340 switch (orient) {
|
Daniel@0
|
17341 case 'left': {
|
Daniel@0
|
17342 gx = group.bounds ? group.bounds.x1 : 0;
|
Daniel@0
|
17343 o.x += gx - offset - lw;
|
Daniel@0
|
17344 break;
|
Daniel@0
|
17345 }
|
Daniel@0
|
17346 case 'right': {
|
Daniel@0
|
17347 gx = group.width + (group.bounds && trans ? group.bounds.delta : 0);
|
Daniel@0
|
17348 o.x += gx + offset;
|
Daniel@0
|
17349 break;
|
Daniel@0
|
17350 }
|
Daniel@0
|
17351 }
|
Daniel@0
|
17352
|
Daniel@0
|
17353 if (trans) trans.interpolate(item, o);
|
Daniel@0
|
17354 var enc = item.mark.def.properties.enter.encode;
|
Daniel@0
|
17355 enc.call(enc, item, group, trans, db, signals, predicates);
|
Daniel@0
|
17356 return true;
|
Daniel@0
|
17357 }
|
Daniel@0
|
17358
|
Daniel@0
|
17359 function vg_legendSymbolExtend(mark, size, shape, fill, stroke) {
|
Daniel@0
|
17360 var e = mark.properties.enter,
|
Daniel@0
|
17361 u = mark.properties.update;
|
Daniel@0
|
17362 if (size) e.size = u.size = {scale: size.scaleName, field: 'data'};
|
Daniel@0
|
17363 if (shape) e.shape = u.shape = {scale: shape.scaleName, field: 'data'};
|
Daniel@0
|
17364 if (fill) e.fill = u.fill = {scale: fill.scaleName, field: 'data'};
|
Daniel@0
|
17365 if (stroke) e.stroke = u.stroke = {scale: stroke.scaleName, field: 'data'};
|
Daniel@0
|
17366 }
|
Daniel@0
|
17367
|
Daniel@0
|
17368 function vg_legendTitle(config) {
|
Daniel@0
|
17369 var cfg = config.legend;
|
Daniel@0
|
17370 return {
|
Daniel@0
|
17371 type: 'text',
|
Daniel@0
|
17372 interactive: false,
|
Daniel@0
|
17373 key: 'data',
|
Daniel@0
|
17374 properties: {
|
Daniel@0
|
17375 enter: {
|
Daniel@0
|
17376 x: {value: 0},
|
Daniel@0
|
17377 y: {value: 0},
|
Daniel@0
|
17378 fill: {value: cfg.titleColor},
|
Daniel@0
|
17379 font: {value: cfg.titleFont},
|
Daniel@0
|
17380 fontSize: {value: cfg.titleFontSize},
|
Daniel@0
|
17381 fontWeight: {value: cfg.titleFontWeight},
|
Daniel@0
|
17382 baseline: {value: 'top'},
|
Daniel@0
|
17383 text: {field: 'data'},
|
Daniel@0
|
17384 opacity: {value: 1e-6}
|
Daniel@0
|
17385 },
|
Daniel@0
|
17386 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
17387 update: { opacity: {value: 1} }
|
Daniel@0
|
17388 }
|
Daniel@0
|
17389 };
|
Daniel@0
|
17390 }
|
Daniel@0
|
17391
|
Daniel@0
|
17392 function vg_legendSymbols(config) {
|
Daniel@0
|
17393 var cfg = config.legend;
|
Daniel@0
|
17394 return {
|
Daniel@0
|
17395 type: 'symbol',
|
Daniel@0
|
17396 interactive: false,
|
Daniel@0
|
17397 key: 'data',
|
Daniel@0
|
17398 properties: {
|
Daniel@0
|
17399 enter: {
|
Daniel@0
|
17400 x: {field: 'offset', mult: 0.5},
|
Daniel@0
|
17401 y: {scale: 'legend', field: 'index'},
|
Daniel@0
|
17402 shape: {value: cfg.symbolShape},
|
Daniel@0
|
17403 size: {value: cfg.symbolSize},
|
Daniel@0
|
17404 stroke: {value: cfg.symbolColor},
|
Daniel@0
|
17405 strokeWidth: {value: cfg.symbolStrokeWidth},
|
Daniel@0
|
17406 opacity: {value: 1e-6}
|
Daniel@0
|
17407 },
|
Daniel@0
|
17408 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
17409 update: {
|
Daniel@0
|
17410 x: {field: 'offset', mult: 0.5},
|
Daniel@0
|
17411 y: {scale: 'legend', field: 'index'},
|
Daniel@0
|
17412 opacity: {value: 1}
|
Daniel@0
|
17413 }
|
Daniel@0
|
17414 }
|
Daniel@0
|
17415 };
|
Daniel@0
|
17416 }
|
Daniel@0
|
17417
|
Daniel@0
|
17418 function vg_vLegendLabels(config) {
|
Daniel@0
|
17419 var cfg = config.legend;
|
Daniel@0
|
17420 return {
|
Daniel@0
|
17421 type: 'text',
|
Daniel@0
|
17422 interactive: false,
|
Daniel@0
|
17423 key: 'data',
|
Daniel@0
|
17424 properties: {
|
Daniel@0
|
17425 enter: {
|
Daniel@0
|
17426 x: {field: 'offset', offset: 5},
|
Daniel@0
|
17427 y: {scale: 'legend', field: 'index'},
|
Daniel@0
|
17428 fill: {value: cfg.labelColor},
|
Daniel@0
|
17429 font: {value: cfg.labelFont},
|
Daniel@0
|
17430 fontSize: {value: cfg.labelFontSize},
|
Daniel@0
|
17431 align: {value: cfg.labelAlign},
|
Daniel@0
|
17432 baseline: {value: cfg.labelBaseline},
|
Daniel@0
|
17433 text: {field: 'label'},
|
Daniel@0
|
17434 opacity: {value: 1e-6}
|
Daniel@0
|
17435 },
|
Daniel@0
|
17436 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
17437 update: {
|
Daniel@0
|
17438 opacity: {value: 1},
|
Daniel@0
|
17439 x: {field: 'offset', offset: 5},
|
Daniel@0
|
17440 y: {scale: 'legend', field: 'index'},
|
Daniel@0
|
17441 }
|
Daniel@0
|
17442 }
|
Daniel@0
|
17443 };
|
Daniel@0
|
17444 }
|
Daniel@0
|
17445
|
Daniel@0
|
17446 function vg_legendGradient(config) {
|
Daniel@0
|
17447 var cfg = config.legend;
|
Daniel@0
|
17448 return {
|
Daniel@0
|
17449 type: 'rect',
|
Daniel@0
|
17450 interactive: false,
|
Daniel@0
|
17451 properties: {
|
Daniel@0
|
17452 enter: {
|
Daniel@0
|
17453 x: {value: 0},
|
Daniel@0
|
17454 y: {value: 0},
|
Daniel@0
|
17455 width: {value: cfg.gradientWidth},
|
Daniel@0
|
17456 height: {value: cfg.gradientHeight},
|
Daniel@0
|
17457 stroke: {value: cfg.gradientStrokeColor},
|
Daniel@0
|
17458 strokeWidth: {value: cfg.gradientStrokeWidth},
|
Daniel@0
|
17459 opacity: {value: 1e-6}
|
Daniel@0
|
17460 },
|
Daniel@0
|
17461 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
17462 update: {
|
Daniel@0
|
17463 x: {value: 0},
|
Daniel@0
|
17464 y: {value: 0},
|
Daniel@0
|
17465 opacity: {value: 1}
|
Daniel@0
|
17466 }
|
Daniel@0
|
17467 }
|
Daniel@0
|
17468 };
|
Daniel@0
|
17469 }
|
Daniel@0
|
17470
|
Daniel@0
|
17471 function vg_hLegendLabels(config) {
|
Daniel@0
|
17472 var cfg = config.legend;
|
Daniel@0
|
17473 return {
|
Daniel@0
|
17474 type: 'text',
|
Daniel@0
|
17475 interactive: false,
|
Daniel@0
|
17476 key: 'data',
|
Daniel@0
|
17477 properties: {
|
Daniel@0
|
17478 enter: {
|
Daniel@0
|
17479 x: {scale: 'legend', field: 'data'},
|
Daniel@0
|
17480 y: {value: 20},
|
Daniel@0
|
17481 dy: {value: 2},
|
Daniel@0
|
17482 fill: {value: cfg.labelColor},
|
Daniel@0
|
17483 font: {value: cfg.labelFont},
|
Daniel@0
|
17484 fontSize: {value: cfg.labelFontSize},
|
Daniel@0
|
17485 align: {field: 'align'},
|
Daniel@0
|
17486 baseline: {value: 'top'},
|
Daniel@0
|
17487 text: {field: 'label'},
|
Daniel@0
|
17488 opacity: {value: 1e-6}
|
Daniel@0
|
17489 },
|
Daniel@0
|
17490 exit: { opacity: {value: 1e-6} },
|
Daniel@0
|
17491 update: {
|
Daniel@0
|
17492 x: {scale: 'legend', field: 'data'},
|
Daniel@0
|
17493 y: {value: 20},
|
Daniel@0
|
17494 opacity: {value: 1}
|
Daniel@0
|
17495 }
|
Daniel@0
|
17496 }
|
Daniel@0
|
17497 };
|
Daniel@0
|
17498 }
|
Daniel@0
|
17499
|
Daniel@0
|
17500 module.exports = lgnd;
|
Daniel@0
|
17501 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
17502
|
Daniel@0
|
17503 },{"../parse/mark":97,"../parse/properties":102,"datalib":24,"vega-scenegraph":46}],115:[function(require,module,exports){
|
Daniel@0
|
17504 module.exports = function visit(node, func) {
|
Daniel@0
|
17505 var i, n, s, m, items;
|
Daniel@0
|
17506 if (func(node)) return true;
|
Daniel@0
|
17507
|
Daniel@0
|
17508 var sets = ['items', 'axisItems', 'legendItems'];
|
Daniel@0
|
17509 for (s=0, m=sets.length; s<m; ++s) {
|
Daniel@0
|
17510 if ((items = node[sets[s]])) {
|
Daniel@0
|
17511 for (i=0, n=items.length; i<n; ++i) {
|
Daniel@0
|
17512 if (visit(items[i], func)) return true;
|
Daniel@0
|
17513 }
|
Daniel@0
|
17514 }
|
Daniel@0
|
17515 }
|
Daniel@0
|
17516 };
|
Daniel@0
|
17517 },{}],116:[function(require,module,exports){
|
Daniel@0
|
17518 var dl = require('datalib'),
|
Daniel@0
|
17519 df = require('vega-dataflow'),
|
Daniel@0
|
17520 log = require('vega-logging'),
|
Daniel@0
|
17521 ChangeSet = df.ChangeSet,
|
Daniel@0
|
17522 Tuple = df.Tuple,
|
Daniel@0
|
17523 Deps = df.Dependencies,
|
Daniel@0
|
17524 Transform = require('./Transform'),
|
Daniel@0
|
17525 Facetor = require('./Facetor');
|
Daniel@0
|
17526
|
Daniel@0
|
17527 function Aggregate(graph) {
|
Daniel@0
|
17528 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
17529
|
Daniel@0
|
17530 Transform.addParameters(this, {
|
Daniel@0
|
17531 groupby: {type: 'array<field>'},
|
Daniel@0
|
17532 summarize: {
|
Daniel@0
|
17533 type: 'custom',
|
Daniel@0
|
17534 set: function(summarize) {
|
Daniel@0
|
17535 var signalDeps = {},
|
Daniel@0
|
17536 tx = this._transform,
|
Daniel@0
|
17537 i, len, f, fields, name, ops;
|
Daniel@0
|
17538
|
Daniel@0
|
17539 if (!dl.isArray(fields = summarize)) { // Object syntax from dl
|
Daniel@0
|
17540 fields = [];
|
Daniel@0
|
17541 for (name in summarize) {
|
Daniel@0
|
17542 ops = dl.array(summarize[name]);
|
Daniel@0
|
17543 fields.push({field: name, ops: ops});
|
Daniel@0
|
17544 }
|
Daniel@0
|
17545 }
|
Daniel@0
|
17546
|
Daniel@0
|
17547 function sg(x) { if (x.signal) signalDeps[x.signal] = 1; }
|
Daniel@0
|
17548
|
Daniel@0
|
17549 for (i=0, len=fields.length; i<len; ++i) {
|
Daniel@0
|
17550 f = fields[i];
|
Daniel@0
|
17551 if (f.field.signal) { signalDeps[f.field.signal] = 1; }
|
Daniel@0
|
17552 dl.array(f.ops).forEach(sg);
|
Daniel@0
|
17553 dl.array(f.as).forEach(sg);
|
Daniel@0
|
17554 }
|
Daniel@0
|
17555
|
Daniel@0
|
17556 tx._fields = fields;
|
Daniel@0
|
17557 tx._aggr = null;
|
Daniel@0
|
17558 tx.dependency(Deps.SIGNALS, dl.keys(signalDeps));
|
Daniel@0
|
17559 return tx;
|
Daniel@0
|
17560 }
|
Daniel@0
|
17561 }
|
Daniel@0
|
17562 });
|
Daniel@0
|
17563
|
Daniel@0
|
17564 this._aggr = null; // dl.Aggregator
|
Daniel@0
|
17565 this._input = null; // Used by Facetor._on_keep.
|
Daniel@0
|
17566 this._args = null; // To cull re-computation.
|
Daniel@0
|
17567 this._fields = [];
|
Daniel@0
|
17568 this._out = [];
|
Daniel@0
|
17569
|
Daniel@0
|
17570 this._type = TYPES.TUPLE;
|
Daniel@0
|
17571 this._acc = {groupby: dl.true, value: dl.true};
|
Daniel@0
|
17572
|
Daniel@0
|
17573 return this.router(true).produces(true);
|
Daniel@0
|
17574 }
|
Daniel@0
|
17575
|
Daniel@0
|
17576 var prototype = (Aggregate.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
17577 prototype.constructor = Aggregate;
|
Daniel@0
|
17578
|
Daniel@0
|
17579 var TYPES = Aggregate.TYPES = {
|
Daniel@0
|
17580 VALUE: 1,
|
Daniel@0
|
17581 TUPLE: 2,
|
Daniel@0
|
17582 MULTI: 3
|
Daniel@0
|
17583 };
|
Daniel@0
|
17584
|
Daniel@0
|
17585 Aggregate.VALID_OPS = [
|
Daniel@0
|
17586 'values', 'count', 'valid', 'missing', 'distinct',
|
Daniel@0
|
17587 'sum', 'mean', 'average', 'variance', 'variancep', 'stdev',
|
Daniel@0
|
17588 'stdevp', 'median', 'q1', 'q3', 'modeskew', 'min', 'max',
|
Daniel@0
|
17589 'argmin', 'argmax'
|
Daniel@0
|
17590 ];
|
Daniel@0
|
17591
|
Daniel@0
|
17592 prototype.type = function(type) {
|
Daniel@0
|
17593 return (this._type = type, this);
|
Daniel@0
|
17594 };
|
Daniel@0
|
17595
|
Daniel@0
|
17596 prototype.accessors = function(groupby, value) {
|
Daniel@0
|
17597 var acc = this._acc;
|
Daniel@0
|
17598 acc.groupby = dl.$(groupby) || dl.true;
|
Daniel@0
|
17599 acc.value = dl.$(value) || dl.true;
|
Daniel@0
|
17600 };
|
Daniel@0
|
17601
|
Daniel@0
|
17602 prototype.aggr = function() {
|
Daniel@0
|
17603 if (this._aggr) return this._aggr;
|
Daniel@0
|
17604
|
Daniel@0
|
17605 var g = this._graph,
|
Daniel@0
|
17606 hasGetter = false,
|
Daniel@0
|
17607 args = [],
|
Daniel@0
|
17608 groupby = this.param('groupby').field,
|
Daniel@0
|
17609 value = function(x) { return x.signal ? g.signalRef(x.signal) : x; };
|
Daniel@0
|
17610
|
Daniel@0
|
17611 // Prepare summarize fields.
|
Daniel@0
|
17612 var fields = this._fields.map(function(f) {
|
Daniel@0
|
17613 var field = {
|
Daniel@0
|
17614 name: value(f.field),
|
Daniel@0
|
17615 as: dl.array(f.as),
|
Daniel@0
|
17616 ops: dl.array(value(f.ops)).map(value),
|
Daniel@0
|
17617 get: f.get
|
Daniel@0
|
17618 };
|
Daniel@0
|
17619 hasGetter = hasGetter || field.get != null;
|
Daniel@0
|
17620 args.push(field.name);
|
Daniel@0
|
17621 return field;
|
Daniel@0
|
17622 });
|
Daniel@0
|
17623
|
Daniel@0
|
17624 // If there is an arbitrary getter, all bets are off.
|
Daniel@0
|
17625 // Otherwise, we can check argument fields to cull re-computation.
|
Daniel@0
|
17626 groupby.forEach(function(g) {
|
Daniel@0
|
17627 if (g.get) hasGetter = true;
|
Daniel@0
|
17628 args.push(g.name || g);
|
Daniel@0
|
17629 });
|
Daniel@0
|
17630 this._args = hasGetter || !fields.length ? null : args;
|
Daniel@0
|
17631
|
Daniel@0
|
17632 if (!fields.length) fields = {'*': 'values'};
|
Daniel@0
|
17633
|
Daniel@0
|
17634 // Instatiate our aggregator instance.
|
Daniel@0
|
17635 // Facetor is a special subclass that can facet into data pipelines.
|
Daniel@0
|
17636 var aggr = this._aggr = new Facetor()
|
Daniel@0
|
17637 .groupby(groupby)
|
Daniel@0
|
17638 .stream(true)
|
Daniel@0
|
17639 .summarize(fields);
|
Daniel@0
|
17640
|
Daniel@0
|
17641 // Collect output fields sets by this aggregate.
|
Daniel@0
|
17642 this._out = getFields(aggr);
|
Daniel@0
|
17643
|
Daniel@0
|
17644 // If we are processing tuples, key them by '_id'.
|
Daniel@0
|
17645 if (this._type !== TYPES.VALUE) { aggr.key('_id'); }
|
Daniel@0
|
17646
|
Daniel@0
|
17647 return aggr;
|
Daniel@0
|
17648 };
|
Daniel@0
|
17649
|
Daniel@0
|
17650 function getFields(aggr) {
|
Daniel@0
|
17651 // Collect the output fields set by this aggregate.
|
Daniel@0
|
17652 var f = [], i, n, j, m, dims, vals, meas;
|
Daniel@0
|
17653
|
Daniel@0
|
17654 dims = aggr._dims;
|
Daniel@0
|
17655 for (i=0, n=dims.length; i<n; ++i) {
|
Daniel@0
|
17656 f.push(dims[i].name);
|
Daniel@0
|
17657 }
|
Daniel@0
|
17658
|
Daniel@0
|
17659 vals = aggr._aggr;
|
Daniel@0
|
17660 for (i=0, n=vals.length; i<n; ++i) {
|
Daniel@0
|
17661 meas = vals[i].measures.fields;
|
Daniel@0
|
17662 for (j=0, m=meas.length; j<m; ++j) {
|
Daniel@0
|
17663 f.push(meas[j]);
|
Daniel@0
|
17664 }
|
Daniel@0
|
17665 }
|
Daniel@0
|
17666
|
Daniel@0
|
17667 return f;
|
Daniel@0
|
17668 }
|
Daniel@0
|
17669
|
Daniel@0
|
17670 prototype.transform = function(input, reset) {
|
Daniel@0
|
17671 log.debug(input, ['aggregate']);
|
Daniel@0
|
17672 this._input = input; // Used by Facetor._on_keep.
|
Daniel@0
|
17673
|
Daniel@0
|
17674 var output = ChangeSet.create(input),
|
Daniel@0
|
17675 aggr = this.aggr(),
|
Daniel@0
|
17676 out = this._out,
|
Daniel@0
|
17677 args = this._args,
|
Daniel@0
|
17678 reeval = true,
|
Daniel@0
|
17679 p = Tuple.prev,
|
Daniel@0
|
17680 add, rem, mod, i;
|
Daniel@0
|
17681
|
Daniel@0
|
17682 // Upon reset, retract prior tuples and re-initialize.
|
Daniel@0
|
17683 if (reset) {
|
Daniel@0
|
17684 output.rem.push.apply(output.rem, aggr.result());
|
Daniel@0
|
17685 aggr.clear();
|
Daniel@0
|
17686 this._aggr = null;
|
Daniel@0
|
17687 aggr = this.aggr();
|
Daniel@0
|
17688 }
|
Daniel@0
|
17689
|
Daniel@0
|
17690 // Get update methods according to input type.
|
Daniel@0
|
17691 if (this._type === TYPES.TUPLE) {
|
Daniel@0
|
17692 add = function(x) { aggr._add(x); Tuple.prev_init(x); };
|
Daniel@0
|
17693 rem = function(x) { aggr._rem(p(x)); };
|
Daniel@0
|
17694 mod = function(x) { aggr._mod(x, p(x)); };
|
Daniel@0
|
17695 } else {
|
Daniel@0
|
17696 var gby = this._acc.groupby,
|
Daniel@0
|
17697 val = this._acc.value,
|
Daniel@0
|
17698 get = this._type === TYPES.VALUE ? val : function(x) {
|
Daniel@0
|
17699 return { _id: x._id, groupby: gby(x), value: val(x) };
|
Daniel@0
|
17700 };
|
Daniel@0
|
17701 add = function(x) { aggr._add(get(x)); Tuple.prev_init(x); };
|
Daniel@0
|
17702 rem = function(x) { aggr._rem(get(p(x))); };
|
Daniel@0
|
17703 mod = function(x) { aggr._mod(get(x), get(p(x))); };
|
Daniel@0
|
17704 }
|
Daniel@0
|
17705
|
Daniel@0
|
17706 input.add.forEach(add);
|
Daniel@0
|
17707 if (reset) {
|
Daniel@0
|
17708 // A signal change triggered reflow. Add everything.
|
Daniel@0
|
17709 // No need for rem, we cleared the aggregator.
|
Daniel@0
|
17710 input.mod.forEach(add);
|
Daniel@0
|
17711 } else {
|
Daniel@0
|
17712 input.rem.forEach(rem);
|
Daniel@0
|
17713
|
Daniel@0
|
17714 // If possible, check argument fields to see if we need to re-process mods.
|
Daniel@0
|
17715 if (args) for (i=0, reeval=false; i<args.length; ++i) {
|
Daniel@0
|
17716 if (input.fields[args[i]]) { reeval = true; break; }
|
Daniel@0
|
17717 }
|
Daniel@0
|
17718 if (reeval) input.mod.forEach(mod);
|
Daniel@0
|
17719 }
|
Daniel@0
|
17720
|
Daniel@0
|
17721 // Indicate output fields and return aggregate tuples.
|
Daniel@0
|
17722 for (i=0; i<out.length; ++i) {
|
Daniel@0
|
17723 output.fields[out[i]] = 1;
|
Daniel@0
|
17724 }
|
Daniel@0
|
17725 return aggr.changes(output);
|
Daniel@0
|
17726 };
|
Daniel@0
|
17727
|
Daniel@0
|
17728 module.exports = Aggregate;
|
Daniel@0
|
17729 },{"./Facetor":122,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],117:[function(require,module,exports){
|
Daniel@0
|
17730 var Base = require('./Transform').prototype;
|
Daniel@0
|
17731
|
Daniel@0
|
17732 function BatchTransform() {
|
Daniel@0
|
17733 // Nearest appropriate collector.
|
Daniel@0
|
17734 // Set by the dataflow Graph during connection.
|
Daniel@0
|
17735 this._collector = null;
|
Daniel@0
|
17736 }
|
Daniel@0
|
17737
|
Daniel@0
|
17738 var prototype = (BatchTransform.prototype = Object.create(Base));
|
Daniel@0
|
17739 prototype.constructor = BatchTransform;
|
Daniel@0
|
17740
|
Daniel@0
|
17741 prototype.init = function(graph) {
|
Daniel@0
|
17742 Base.init.call(this, graph);
|
Daniel@0
|
17743 return this.batch(true);
|
Daniel@0
|
17744 };
|
Daniel@0
|
17745
|
Daniel@0
|
17746 prototype.transform = function(input) {
|
Daniel@0
|
17747 return this.batchTransform(input, this._collector.data());
|
Daniel@0
|
17748 };
|
Daniel@0
|
17749
|
Daniel@0
|
17750 prototype.batchTransform = function(/* input, data */) {
|
Daniel@0
|
17751 };
|
Daniel@0
|
17752
|
Daniel@0
|
17753 module.exports = BatchTransform;
|
Daniel@0
|
17754 },{"./Transform":135}],118:[function(require,module,exports){
|
Daniel@0
|
17755 var bins = require('datalib').bins,
|
Daniel@0
|
17756 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
17757 log = require('vega-logging'),
|
Daniel@0
|
17758 Transform = require('./Transform');
|
Daniel@0
|
17759
|
Daniel@0
|
17760 function Bin(graph) {
|
Daniel@0
|
17761 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
17762 Transform.addParameters(this, {
|
Daniel@0
|
17763 field: {type: 'field'},
|
Daniel@0
|
17764 min: {type: 'value'},
|
Daniel@0
|
17765 max: {type: 'value'},
|
Daniel@0
|
17766 base: {type: 'value', default: 10},
|
Daniel@0
|
17767 maxbins: {type: 'value', default: 20},
|
Daniel@0
|
17768 step: {type: 'value'},
|
Daniel@0
|
17769 steps: {type: 'value'},
|
Daniel@0
|
17770 minstep: {type: 'value'},
|
Daniel@0
|
17771 div: {type: 'array<value>', default: [5, 2]}
|
Daniel@0
|
17772 });
|
Daniel@0
|
17773
|
Daniel@0
|
17774 this._output = {bin: 'bin'};
|
Daniel@0
|
17775 return this.mutates(true);
|
Daniel@0
|
17776 }
|
Daniel@0
|
17777
|
Daniel@0
|
17778 var prototype = (Bin.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
17779 prototype.constructor = Bin;
|
Daniel@0
|
17780
|
Daniel@0
|
17781 prototype.transform = function(input) {
|
Daniel@0
|
17782 log.debug(input, ['binning']);
|
Daniel@0
|
17783
|
Daniel@0
|
17784 var output = this._output.bin,
|
Daniel@0
|
17785 step = this.param('step'),
|
Daniel@0
|
17786 steps = this.param('steps'),
|
Daniel@0
|
17787 minstep = this.param('minstep'),
|
Daniel@0
|
17788 get = this.param('field').accessor,
|
Daniel@0
|
17789 opt = {
|
Daniel@0
|
17790 min: this.param('min'),
|
Daniel@0
|
17791 max: this.param('max'),
|
Daniel@0
|
17792 base: this.param('base'),
|
Daniel@0
|
17793 maxbins: this.param('maxbins'),
|
Daniel@0
|
17794 div: this.param('div')
|
Daniel@0
|
17795 };
|
Daniel@0
|
17796
|
Daniel@0
|
17797 if (step) opt.step = step;
|
Daniel@0
|
17798 if (steps) opt.steps = steps;
|
Daniel@0
|
17799 if (minstep) opt.minstep = minstep;
|
Daniel@0
|
17800 var b = bins(opt);
|
Daniel@0
|
17801
|
Daniel@0
|
17802 function update(d) {
|
Daniel@0
|
17803 var v = get(d);
|
Daniel@0
|
17804 v = v == null ? null
|
Daniel@0
|
17805 : b.start + b.step * ~~((v - b.start) / b.step);
|
Daniel@0
|
17806 Tuple.set(d, output, v);
|
Daniel@0
|
17807 }
|
Daniel@0
|
17808 input.add.forEach(update);
|
Daniel@0
|
17809 input.mod.forEach(update);
|
Daniel@0
|
17810 input.rem.forEach(update);
|
Daniel@0
|
17811
|
Daniel@0
|
17812 input.fields[output] = 1;
|
Daniel@0
|
17813 return input;
|
Daniel@0
|
17814 };
|
Daniel@0
|
17815
|
Daniel@0
|
17816 module.exports = Bin;
|
Daniel@0
|
17817 },{"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],119:[function(require,module,exports){
|
Daniel@0
|
17818 var df = require('vega-dataflow'),
|
Daniel@0
|
17819 Tuple = df.Tuple,
|
Daniel@0
|
17820 log = require('vega-logging'),
|
Daniel@0
|
17821 Transform = require('./Transform');
|
Daniel@0
|
17822
|
Daniel@0
|
17823 function CountPattern(graph) {
|
Daniel@0
|
17824 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
17825 Transform.addParameters(this, {
|
Daniel@0
|
17826 field: {type: 'field', default: 'data'},
|
Daniel@0
|
17827 pattern: {type: 'value', default: '[\\w\']+'},
|
Daniel@0
|
17828 case: {type: 'value', default: 'lower'},
|
Daniel@0
|
17829 stopwords: {type: 'value', default: ''}
|
Daniel@0
|
17830 });
|
Daniel@0
|
17831
|
Daniel@0
|
17832 this._output = {text: 'text', count: 'count'};
|
Daniel@0
|
17833
|
Daniel@0
|
17834 return this.router(true).produces(true);
|
Daniel@0
|
17835 }
|
Daniel@0
|
17836
|
Daniel@0
|
17837 var prototype = (CountPattern.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
17838 prototype.constructor = CountPattern;
|
Daniel@0
|
17839
|
Daniel@0
|
17840 prototype.transform = function(input, reset) {
|
Daniel@0
|
17841 log.debug(input, ['countpattern']);
|
Daniel@0
|
17842
|
Daniel@0
|
17843 var get = this.param('field').accessor,
|
Daniel@0
|
17844 pattern = this.param('pattern'),
|
Daniel@0
|
17845 stop = this.param('stopwords'),
|
Daniel@0
|
17846 rem = false;
|
Daniel@0
|
17847
|
Daniel@0
|
17848 // update parameters
|
Daniel@0
|
17849 if (this._stop !== stop) {
|
Daniel@0
|
17850 this._stop = stop;
|
Daniel@0
|
17851 this._stop_re = new RegExp('^' + stop + '$', 'i');
|
Daniel@0
|
17852 reset = true;
|
Daniel@0
|
17853 }
|
Daniel@0
|
17854
|
Daniel@0
|
17855 if (this._pattern !== pattern) {
|
Daniel@0
|
17856 this._pattern = pattern;
|
Daniel@0
|
17857 this._match = new RegExp(this._pattern, 'g');
|
Daniel@0
|
17858 reset = true;
|
Daniel@0
|
17859 }
|
Daniel@0
|
17860
|
Daniel@0
|
17861 if (reset) this._counts = {};
|
Daniel@0
|
17862
|
Daniel@0
|
17863 function curr(t) { return (Tuple.prev_init(t), get(t)); }
|
Daniel@0
|
17864 function prev(t) { return get(Tuple.prev(t)); }
|
Daniel@0
|
17865
|
Daniel@0
|
17866 this._add(input.add, curr);
|
Daniel@0
|
17867 if (!reset) this._rem(input.rem, prev);
|
Daniel@0
|
17868 if (reset || (rem = input.fields[get.field])) {
|
Daniel@0
|
17869 if (rem) this._rem(input.mod, prev);
|
Daniel@0
|
17870 this._add(input.mod, curr);
|
Daniel@0
|
17871 }
|
Daniel@0
|
17872
|
Daniel@0
|
17873 // generate output tuples
|
Daniel@0
|
17874 return this._changeset(input);
|
Daniel@0
|
17875 };
|
Daniel@0
|
17876
|
Daniel@0
|
17877 prototype._changeset = function(input) {
|
Daniel@0
|
17878 var counts = this._counts,
|
Daniel@0
|
17879 tuples = this._tuples || (this._tuples = {}),
|
Daniel@0
|
17880 change = df.ChangeSet.create(input),
|
Daniel@0
|
17881 out = this._output, w, t, c;
|
Daniel@0
|
17882
|
Daniel@0
|
17883 for (w in counts) {
|
Daniel@0
|
17884 t = tuples[w];
|
Daniel@0
|
17885 c = counts[w] || 0;
|
Daniel@0
|
17886 if (!t && c) {
|
Daniel@0
|
17887 tuples[w] = (t = Tuple.ingest({}));
|
Daniel@0
|
17888 t[out.text] = w;
|
Daniel@0
|
17889 t[out.count] = c;
|
Daniel@0
|
17890 change.add.push(t);
|
Daniel@0
|
17891 } else if (c === 0) {
|
Daniel@0
|
17892 if (t) change.rem.push(t);
|
Daniel@0
|
17893 delete counts[w];
|
Daniel@0
|
17894 delete tuples[w];
|
Daniel@0
|
17895 } else if (t[out.count] !== c) {
|
Daniel@0
|
17896 Tuple.set(t, out.count, c);
|
Daniel@0
|
17897 change.mod.push(t);
|
Daniel@0
|
17898 }
|
Daniel@0
|
17899 }
|
Daniel@0
|
17900 return change;
|
Daniel@0
|
17901 };
|
Daniel@0
|
17902
|
Daniel@0
|
17903 prototype._tokenize = function(text) {
|
Daniel@0
|
17904 switch (this.param('case')) {
|
Daniel@0
|
17905 case 'upper': text = text.toUpperCase(); break;
|
Daniel@0
|
17906 case 'lower': text = text.toLowerCase(); break;
|
Daniel@0
|
17907 }
|
Daniel@0
|
17908 return text.match(this._match);
|
Daniel@0
|
17909 };
|
Daniel@0
|
17910
|
Daniel@0
|
17911 prototype._add = function(tuples, get) {
|
Daniel@0
|
17912 var counts = this._counts,
|
Daniel@0
|
17913 stop = this._stop_re,
|
Daniel@0
|
17914 tok, i, j, t;
|
Daniel@0
|
17915
|
Daniel@0
|
17916 for (j=0; j<tuples.length; ++j) {
|
Daniel@0
|
17917 tok = this._tokenize(get(tuples[j]));
|
Daniel@0
|
17918 for (i=0; i<tok.length; ++i) {
|
Daniel@0
|
17919 if (!stop.test(t=tok[i])) {
|
Daniel@0
|
17920 counts[t] = 1 + (counts[t] || 0);
|
Daniel@0
|
17921 }
|
Daniel@0
|
17922 }
|
Daniel@0
|
17923 }
|
Daniel@0
|
17924 };
|
Daniel@0
|
17925
|
Daniel@0
|
17926 prototype._rem = function(tuples, get) {
|
Daniel@0
|
17927 var counts = this._counts,
|
Daniel@0
|
17928 stop = this._stop_re,
|
Daniel@0
|
17929 tok, i, j, t;
|
Daniel@0
|
17930
|
Daniel@0
|
17931 for (j=0; j<tuples.length; ++j) {
|
Daniel@0
|
17932 tok = this._tokenize(get(tuples[j]));
|
Daniel@0
|
17933 for (i=0; i<tok.length; ++i) {
|
Daniel@0
|
17934 if (!stop.test(t=tok[i])) {
|
Daniel@0
|
17935 counts[t] -= 1;
|
Daniel@0
|
17936 }
|
Daniel@0
|
17937 }
|
Daniel@0
|
17938 }
|
Daniel@0
|
17939 };
|
Daniel@0
|
17940
|
Daniel@0
|
17941 module.exports = CountPattern;
|
Daniel@0
|
17942 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],120:[function(require,module,exports){
|
Daniel@0
|
17943 var df = require('vega-dataflow'),
|
Daniel@0
|
17944 ChangeSet = df.ChangeSet,
|
Daniel@0
|
17945 Tuple = df.Tuple,
|
Daniel@0
|
17946 SIGNALS = df.Dependencies.SIGNALS,
|
Daniel@0
|
17947 log = require('vega-logging'),
|
Daniel@0
|
17948 Transform = require('./Transform'),
|
Daniel@0
|
17949 BatchTransform = require('./BatchTransform');
|
Daniel@0
|
17950
|
Daniel@0
|
17951 function Cross(graph) {
|
Daniel@0
|
17952 BatchTransform.prototype.init.call(this, graph);
|
Daniel@0
|
17953 Transform.addParameters(this, {
|
Daniel@0
|
17954 with: {type: 'data'},
|
Daniel@0
|
17955 diagonal: {type: 'value', default: 'true'},
|
Daniel@0
|
17956 filter: {type: 'expr'}
|
Daniel@0
|
17957 });
|
Daniel@0
|
17958
|
Daniel@0
|
17959 this._output = {'left': 'a', 'right': 'b'};
|
Daniel@0
|
17960 this._lastRem = null; // Most recent stamp that rem occured.
|
Daniel@0
|
17961 this._lastWith = null; // Last time we crossed w/withds.
|
Daniel@0
|
17962 this._ids = {};
|
Daniel@0
|
17963 this._cache = {};
|
Daniel@0
|
17964
|
Daniel@0
|
17965 return this.router(true).produces(true);
|
Daniel@0
|
17966 }
|
Daniel@0
|
17967
|
Daniel@0
|
17968 var prototype = (Cross.prototype = Object.create(BatchTransform.prototype));
|
Daniel@0
|
17969 prototype.constructor = Cross;
|
Daniel@0
|
17970
|
Daniel@0
|
17971 // Each cached incoming tuple also has a stamp to track if we need to do
|
Daniel@0
|
17972 // lazy filtering of removed tuples.
|
Daniel@0
|
17973 function cache(x, t) {
|
Daniel@0
|
17974 var c = this._cache[x._id] = this._cache[x._id] || {c: [], s: this._stamp};
|
Daniel@0
|
17975 c.c.push(t);
|
Daniel@0
|
17976 }
|
Daniel@0
|
17977
|
Daniel@0
|
17978 function add(output, left, data, diag, test, x) {
|
Daniel@0
|
17979 var i = 0, len = data.length, t = {}, y, id;
|
Daniel@0
|
17980
|
Daniel@0
|
17981 for (; i<len; ++i) {
|
Daniel@0
|
17982 y = data[i];
|
Daniel@0
|
17983 id = left ? x._id+'_'+y._id : y._id+'_'+x._id;
|
Daniel@0
|
17984 if (this._ids[id]) continue;
|
Daniel@0
|
17985 if (x._id == y._id && !diag) continue;
|
Daniel@0
|
17986
|
Daniel@0
|
17987 t[this._output.left] = left ? x : y;
|
Daniel@0
|
17988 t[this._output.right] = left ? y : x;
|
Daniel@0
|
17989
|
Daniel@0
|
17990 // Only ingest a tuple if we keep it around.
|
Daniel@0
|
17991 if (!test || test(t)) {
|
Daniel@0
|
17992 output.add.push(t=Tuple.ingest(t));
|
Daniel@0
|
17993 cache.call(this, x, t);
|
Daniel@0
|
17994 cache.call(this, y, t);
|
Daniel@0
|
17995 this._ids[id] = 1;
|
Daniel@0
|
17996 t = {};
|
Daniel@0
|
17997 }
|
Daniel@0
|
17998 }
|
Daniel@0
|
17999 }
|
Daniel@0
|
18000
|
Daniel@0
|
18001 function mod(output, left, x) {
|
Daniel@0
|
18002 var cross = this,
|
Daniel@0
|
18003 c = this._cache[x._id];
|
Daniel@0
|
18004
|
Daniel@0
|
18005 if (this._lastRem > c.s) { // Removed tuples haven't been filtered yet
|
Daniel@0
|
18006 c.c = c.c.filter(function(y) {
|
Daniel@0
|
18007 var t = y[cross._output[left ? 'right' : 'left']];
|
Daniel@0
|
18008 return cross._cache[t._id] !== null;
|
Daniel@0
|
18009 });
|
Daniel@0
|
18010 c.s = this._lastRem;
|
Daniel@0
|
18011 }
|
Daniel@0
|
18012
|
Daniel@0
|
18013 output.mod.push.apply(output.mod, c.c);
|
Daniel@0
|
18014 }
|
Daniel@0
|
18015
|
Daniel@0
|
18016 function rem(output, x) {
|
Daniel@0
|
18017 output.rem.push.apply(output.rem, this._cache[x._id].c);
|
Daniel@0
|
18018 this._cache[x._id] = null;
|
Daniel@0
|
18019 this._lastRem = this._stamp;
|
Daniel@0
|
18020 }
|
Daniel@0
|
18021
|
Daniel@0
|
18022 function upFields(input, output) {
|
Daniel@0
|
18023 if (input.add.length || input.rem.length) {
|
Daniel@0
|
18024 output.fields[this._output.left] = 1;
|
Daniel@0
|
18025 output.fields[this._output.right] = 1;
|
Daniel@0
|
18026 }
|
Daniel@0
|
18027 }
|
Daniel@0
|
18028
|
Daniel@0
|
18029 prototype.batchTransform = function(input, data) {
|
Daniel@0
|
18030 log.debug(input, ['crossing']);
|
Daniel@0
|
18031
|
Daniel@0
|
18032 var w = this.param('with'),
|
Daniel@0
|
18033 f = this.param('filter'),
|
Daniel@0
|
18034 diag = this.param('diagonal'),
|
Daniel@0
|
18035 graph = this._graph,
|
Daniel@0
|
18036 signals = graph.values(SIGNALS, this.dependency(SIGNALS)),
|
Daniel@0
|
18037 test = f ? function(x) {return f(x, null, signals); } : null,
|
Daniel@0
|
18038 selfCross = (!w.name),
|
Daniel@0
|
18039 woutput = selfCross ? input : w.source.last(),
|
Daniel@0
|
18040 wdata = selfCross ? data : w.source.values(),
|
Daniel@0
|
18041 output = ChangeSet.create(input),
|
Daniel@0
|
18042 r = rem.bind(this, output);
|
Daniel@0
|
18043
|
Daniel@0
|
18044 input.rem.forEach(r);
|
Daniel@0
|
18045 input.add.forEach(add.bind(this, output, true, wdata, diag, test));
|
Daniel@0
|
18046
|
Daniel@0
|
18047 if (!selfCross && woutput.stamp > this._lastWith) {
|
Daniel@0
|
18048 woutput.rem.forEach(r);
|
Daniel@0
|
18049 woutput.add.forEach(add.bind(this, output, false, data, diag, test));
|
Daniel@0
|
18050 woutput.mod.forEach(mod.bind(this, output, false));
|
Daniel@0
|
18051 upFields.call(this, woutput, output);
|
Daniel@0
|
18052 this._lastWith = woutput.stamp;
|
Daniel@0
|
18053 }
|
Daniel@0
|
18054
|
Daniel@0
|
18055 // Mods need to come after all removals have been run.
|
Daniel@0
|
18056 input.mod.forEach(mod.bind(this, output, true));
|
Daniel@0
|
18057 upFields.call(this, input, output);
|
Daniel@0
|
18058
|
Daniel@0
|
18059 return output;
|
Daniel@0
|
18060 };
|
Daniel@0
|
18061
|
Daniel@0
|
18062 module.exports = Cross;
|
Daniel@0
|
18063 },{"./BatchTransform":117,"./Transform":135,"vega-dataflow":39,"vega-logging":45}],121:[function(require,module,exports){
|
Daniel@0
|
18064 var Transform = require('./Transform'),
|
Daniel@0
|
18065 Aggregate = require('./Aggregate');
|
Daniel@0
|
18066
|
Daniel@0
|
18067 function Facet(graph) {
|
Daniel@0
|
18068 Transform.addParameters(this, {
|
Daniel@0
|
18069 transform: {
|
Daniel@0
|
18070 type: "custom",
|
Daniel@0
|
18071 set: function(pipeline) {
|
Daniel@0
|
18072 return (this._transform._pipeline = pipeline, this._transform);
|
Daniel@0
|
18073 },
|
Daniel@0
|
18074 get: function() {
|
Daniel@0
|
18075 var parse = require('../parse/transforms'),
|
Daniel@0
|
18076 facet = this._transform;
|
Daniel@0
|
18077 return facet._pipeline.map(function(t) {
|
Daniel@0
|
18078 return parse(facet._graph, t);
|
Daniel@0
|
18079 });
|
Daniel@0
|
18080 }
|
Daniel@0
|
18081 }
|
Daniel@0
|
18082 });
|
Daniel@0
|
18083
|
Daniel@0
|
18084 this._pipeline = [];
|
Daniel@0
|
18085 return Aggregate.call(this, graph);
|
Daniel@0
|
18086 }
|
Daniel@0
|
18087
|
Daniel@0
|
18088 var prototype = (Facet.prototype = Object.create(Aggregate.prototype));
|
Daniel@0
|
18089 prototype.constructor = Facet;
|
Daniel@0
|
18090
|
Daniel@0
|
18091 prototype.aggr = function() {
|
Daniel@0
|
18092 return Aggregate.prototype.aggr.call(this).facet(this);
|
Daniel@0
|
18093 };
|
Daniel@0
|
18094
|
Daniel@0
|
18095 module.exports = Facet;
|
Daniel@0
|
18096 },{"../parse/transforms":106,"./Aggregate":116,"./Transform":135}],122:[function(require,module,exports){
|
Daniel@0
|
18097 var dl = require('datalib'),
|
Daniel@0
|
18098 Aggregator = dl.Aggregator,
|
Daniel@0
|
18099 Base = Aggregator.prototype,
|
Daniel@0
|
18100 df = require('vega-dataflow'),
|
Daniel@0
|
18101 Tuple = df.Tuple,
|
Daniel@0
|
18102 log = require('vega-logging'),
|
Daniel@0
|
18103 facetID = 0;
|
Daniel@0
|
18104
|
Daniel@0
|
18105 function Facetor() {
|
Daniel@0
|
18106 Aggregator.call(this);
|
Daniel@0
|
18107 this._facet = null;
|
Daniel@0
|
18108 this._facetID = ++facetID;
|
Daniel@0
|
18109 }
|
Daniel@0
|
18110
|
Daniel@0
|
18111 var prototype = (Facetor.prototype = Object.create(Base));
|
Daniel@0
|
18112 prototype.constructor = Facetor;
|
Daniel@0
|
18113
|
Daniel@0
|
18114 prototype.facet = function(f) {
|
Daniel@0
|
18115 return arguments.length ? (this._facet = f, this) : this._facet;
|
Daniel@0
|
18116 };
|
Daniel@0
|
18117
|
Daniel@0
|
18118 prototype._ingest = function(t) {
|
Daniel@0
|
18119 return Tuple.ingest(t, null);
|
Daniel@0
|
18120 };
|
Daniel@0
|
18121
|
Daniel@0
|
18122 prototype._assign = Tuple.set;
|
Daniel@0
|
18123
|
Daniel@0
|
18124 function disconnect_cell(facet) {
|
Daniel@0
|
18125 log.debug({}, ['disconnecting cell', this.tuple._id]);
|
Daniel@0
|
18126 var pipeline = this.ds.pipeline();
|
Daniel@0
|
18127 facet.removeListener(pipeline[0]);
|
Daniel@0
|
18128 facet._graph.removeListener(pipeline[0]);
|
Daniel@0
|
18129 facet._graph.disconnect(pipeline);
|
Daniel@0
|
18130 }
|
Daniel@0
|
18131
|
Daniel@0
|
18132 prototype._newcell = function(x, key) {
|
Daniel@0
|
18133 var cell = Base._newcell.call(this, x, key),
|
Daniel@0
|
18134 facet = this._facet;
|
Daniel@0
|
18135
|
Daniel@0
|
18136 if (facet) {
|
Daniel@0
|
18137 var graph = facet._graph,
|
Daniel@0
|
18138 tuple = cell.tuple,
|
Daniel@0
|
18139 pipeline = facet.param('transform');
|
Daniel@0
|
18140 cell.ds = graph.data(tuple._facetID, pipeline, tuple);
|
Daniel@0
|
18141 cell.disconnect = disconnect_cell;
|
Daniel@0
|
18142 facet.addListener(pipeline[0]);
|
Daniel@0
|
18143 }
|
Daniel@0
|
18144
|
Daniel@0
|
18145 return cell;
|
Daniel@0
|
18146 };
|
Daniel@0
|
18147
|
Daniel@0
|
18148 prototype._newtuple = function(x, key) {
|
Daniel@0
|
18149 var t = Base._newtuple.call(this, x);
|
Daniel@0
|
18150 if (this._facet) {
|
Daniel@0
|
18151 Tuple.set(t, 'key', key);
|
Daniel@0
|
18152 Tuple.set(t, '_facetID', this._facetID + '_' + key);
|
Daniel@0
|
18153 }
|
Daniel@0
|
18154 return t;
|
Daniel@0
|
18155 };
|
Daniel@0
|
18156
|
Daniel@0
|
18157 prototype.clear = function() {
|
Daniel@0
|
18158 if (this._facet) {
|
Daniel@0
|
18159 for (var k in this._cells) {
|
Daniel@0
|
18160 this._cells[k].disconnect(this._facet);
|
Daniel@0
|
18161 }
|
Daniel@0
|
18162 }
|
Daniel@0
|
18163 return Base.clear.call(this);
|
Daniel@0
|
18164 };
|
Daniel@0
|
18165
|
Daniel@0
|
18166 prototype._on_add = function(x, cell) {
|
Daniel@0
|
18167 if (this._facet) cell.ds._input.add.push(x);
|
Daniel@0
|
18168 };
|
Daniel@0
|
18169
|
Daniel@0
|
18170 prototype._on_rem = function(x, cell) {
|
Daniel@0
|
18171 if (this._facet) cell.ds._input.rem.push(x);
|
Daniel@0
|
18172 };
|
Daniel@0
|
18173
|
Daniel@0
|
18174 prototype._on_mod = function(x, prev, cell0, cell1) {
|
Daniel@0
|
18175 if (this._facet) { // Propagate tuples
|
Daniel@0
|
18176 if (cell0 === cell1) {
|
Daniel@0
|
18177 cell0.ds._input.mod.push(x);
|
Daniel@0
|
18178 } else {
|
Daniel@0
|
18179 cell0.ds._input.rem.push(x);
|
Daniel@0
|
18180 cell1.ds._input.add.push(x);
|
Daniel@0
|
18181 }
|
Daniel@0
|
18182 }
|
Daniel@0
|
18183 };
|
Daniel@0
|
18184
|
Daniel@0
|
18185 prototype._on_drop = function(cell) {
|
Daniel@0
|
18186 if (this._facet) cell.disconnect(this._facet);
|
Daniel@0
|
18187 };
|
Daniel@0
|
18188
|
Daniel@0
|
18189 prototype._on_keep = function(cell) {
|
Daniel@0
|
18190 // propagate sort, signals, fields, etc.
|
Daniel@0
|
18191 if (this._facet) df.ChangeSet.copy(this._input, cell.ds._input);
|
Daniel@0
|
18192 };
|
Daniel@0
|
18193
|
Daniel@0
|
18194 module.exports = Facetor;
|
Daniel@0
|
18195 },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],123:[function(require,module,exports){
|
Daniel@0
|
18196 var df = require('vega-dataflow'),
|
Daniel@0
|
18197 SIGNALS = df.Dependencies.SIGNALS,
|
Daniel@0
|
18198 log = require('vega-logging'),
|
Daniel@0
|
18199 Transform = require('./Transform');
|
Daniel@0
|
18200
|
Daniel@0
|
18201 function Filter(graph) {
|
Daniel@0
|
18202 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18203 Transform.addParameters(this, {test: {type: 'expr'}});
|
Daniel@0
|
18204
|
Daniel@0
|
18205 this._skip = {};
|
Daniel@0
|
18206 return this.router(true);
|
Daniel@0
|
18207 }
|
Daniel@0
|
18208
|
Daniel@0
|
18209 var prototype = (Filter.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18210 prototype.constructor = Filter;
|
Daniel@0
|
18211
|
Daniel@0
|
18212 prototype.transform = function(input) {
|
Daniel@0
|
18213 log.debug(input, ['filtering']);
|
Daniel@0
|
18214
|
Daniel@0
|
18215 var output = df.ChangeSet.create(input),
|
Daniel@0
|
18216 graph = this._graph,
|
Daniel@0
|
18217 skip = this._skip,
|
Daniel@0
|
18218 test = this.param('test'),
|
Daniel@0
|
18219 signals = graph.values(SIGNALS, this.dependency(SIGNALS));
|
Daniel@0
|
18220
|
Daniel@0
|
18221 input.rem.forEach(function(x) {
|
Daniel@0
|
18222 if (skip[x._id] !== 1) output.rem.push(x);
|
Daniel@0
|
18223 else skip[x._id] = 0;
|
Daniel@0
|
18224 });
|
Daniel@0
|
18225
|
Daniel@0
|
18226 input.add.forEach(function(x) {
|
Daniel@0
|
18227 if (test(x, null, signals)) output.add.push(x);
|
Daniel@0
|
18228 else skip[x._id] = 1;
|
Daniel@0
|
18229 });
|
Daniel@0
|
18230
|
Daniel@0
|
18231 input.mod.forEach(function(x) {
|
Daniel@0
|
18232 var b = test(x, null, signals),
|
Daniel@0
|
18233 s = (skip[x._id] === 1);
|
Daniel@0
|
18234 if (b && s) {
|
Daniel@0
|
18235 skip[x._id] = 0;
|
Daniel@0
|
18236 output.add.push(x);
|
Daniel@0
|
18237 } else if (b && !s) {
|
Daniel@0
|
18238 output.mod.push(x);
|
Daniel@0
|
18239 } else if (!b && s) {
|
Daniel@0
|
18240 // do nothing, keep skip true
|
Daniel@0
|
18241 } else { // !b && !s
|
Daniel@0
|
18242 output.rem.push(x);
|
Daniel@0
|
18243 skip[x._id] = 1;
|
Daniel@0
|
18244 }
|
Daniel@0
|
18245 });
|
Daniel@0
|
18246
|
Daniel@0
|
18247 return output;
|
Daniel@0
|
18248 };
|
Daniel@0
|
18249
|
Daniel@0
|
18250 module.exports = Filter;
|
Daniel@0
|
18251 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],124:[function(require,module,exports){
|
Daniel@0
|
18252 var df = require('vega-dataflow'),
|
Daniel@0
|
18253 Tuple = df.Tuple,
|
Daniel@0
|
18254 log = require('vega-logging'),
|
Daniel@0
|
18255 Transform = require('./Transform');
|
Daniel@0
|
18256
|
Daniel@0
|
18257 function Fold(graph) {
|
Daniel@0
|
18258 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18259 Transform.addParameters(this, {
|
Daniel@0
|
18260 fields: {type: 'array<field>'}
|
Daniel@0
|
18261 });
|
Daniel@0
|
18262
|
Daniel@0
|
18263 this._output = {key: 'key', value: 'value'};
|
Daniel@0
|
18264 this._cache = {};
|
Daniel@0
|
18265
|
Daniel@0
|
18266 return this.router(true).produces(true);
|
Daniel@0
|
18267 }
|
Daniel@0
|
18268
|
Daniel@0
|
18269 var prototype = (Fold.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18270 prototype.constructor = Fold;
|
Daniel@0
|
18271
|
Daniel@0
|
18272 prototype._reset = function(input, output) {
|
Daniel@0
|
18273 for (var id in this._cache) {
|
Daniel@0
|
18274 output.rem.push.apply(output.rem, this._cache[id]);
|
Daniel@0
|
18275 }
|
Daniel@0
|
18276 this._cache = {};
|
Daniel@0
|
18277 };
|
Daniel@0
|
18278
|
Daniel@0
|
18279 prototype._tuple = function(x, i, len) {
|
Daniel@0
|
18280 var list = this._cache[x._id] || (this._cache[x._id] = Array(len));
|
Daniel@0
|
18281 return list[i] ? Tuple.rederive(x, list[i]) : (list[i] = Tuple.derive(x));
|
Daniel@0
|
18282 };
|
Daniel@0
|
18283
|
Daniel@0
|
18284 prototype._fn = function(data, on, out) {
|
Daniel@0
|
18285 var i, j, n, m, d, t;
|
Daniel@0
|
18286 for (i=0, n=data.length; i<n; ++i) {
|
Daniel@0
|
18287 d = data[i];
|
Daniel@0
|
18288 for (j=0, m=on.field.length; j<m; ++j) {
|
Daniel@0
|
18289 t = this._tuple(d, j, m);
|
Daniel@0
|
18290 Tuple.set(t, this._output.key, on.field[j]);
|
Daniel@0
|
18291 Tuple.set(t, this._output.value, on.accessor[j](d));
|
Daniel@0
|
18292 out.push(t);
|
Daniel@0
|
18293 }
|
Daniel@0
|
18294 }
|
Daniel@0
|
18295 };
|
Daniel@0
|
18296
|
Daniel@0
|
18297 prototype.transform = function(input, reset) {
|
Daniel@0
|
18298 log.debug(input, ['folding']);
|
Daniel@0
|
18299
|
Daniel@0
|
18300 var fold = this,
|
Daniel@0
|
18301 on = this.param('fields'),
|
Daniel@0
|
18302 output = df.ChangeSet.create(input);
|
Daniel@0
|
18303
|
Daniel@0
|
18304 if (reset) this._reset(input, output);
|
Daniel@0
|
18305
|
Daniel@0
|
18306 this._fn(input.add, on, output.add);
|
Daniel@0
|
18307 this._fn(input.mod, on, reset ? output.add : output.mod);
|
Daniel@0
|
18308 input.rem.forEach(function(x) {
|
Daniel@0
|
18309 output.rem.push.apply(output.rem, fold._cache[x._id]);
|
Daniel@0
|
18310 fold._cache[x._id] = null;
|
Daniel@0
|
18311 });
|
Daniel@0
|
18312
|
Daniel@0
|
18313 // If we're only propagating values, don't mark key/value as updated.
|
Daniel@0
|
18314 if (input.add.length || input.rem.length ||
|
Daniel@0
|
18315 on.field.some(function(f) { return !!input.fields[f]; })) {
|
Daniel@0
|
18316 output.fields[this._output.key] = 1;
|
Daniel@0
|
18317 output.fields[this._output.value] = 1;
|
Daniel@0
|
18318 }
|
Daniel@0
|
18319 return output;
|
Daniel@0
|
18320 };
|
Daniel@0
|
18321
|
Daniel@0
|
18322 module.exports = Fold;
|
Daniel@0
|
18323 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],125:[function(require,module,exports){
|
Daniel@0
|
18324 (function (global){
|
Daniel@0
|
18325 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
18326 df = require('vega-dataflow'),
|
Daniel@0
|
18327 Tuple = df.Tuple,
|
Daniel@0
|
18328 ChangeSet = df.ChangeSet,
|
Daniel@0
|
18329 log = require('vega-logging'),
|
Daniel@0
|
18330 Transform = require('./Transform');
|
Daniel@0
|
18331
|
Daniel@0
|
18332 function Force(graph) {
|
Daniel@0
|
18333 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18334
|
Daniel@0
|
18335 this._prev = null;
|
Daniel@0
|
18336 this._interactive = false;
|
Daniel@0
|
18337 this._setup = true;
|
Daniel@0
|
18338 this._nodes = [];
|
Daniel@0
|
18339 this._links = [];
|
Daniel@0
|
18340 this._layout = d3.layout.force();
|
Daniel@0
|
18341
|
Daniel@0
|
18342 Transform.addParameters(this, {
|
Daniel@0
|
18343 size: {type: 'array<value>', default: [500, 500]},
|
Daniel@0
|
18344 bound: {type: 'value', default: true},
|
Daniel@0
|
18345 links: {type: 'data'},
|
Daniel@0
|
18346
|
Daniel@0
|
18347 // TODO: for now force these to be value params only (pun-intended)
|
Daniel@0
|
18348 // Can update to include fields after Parameter refactoring.
|
Daniel@0
|
18349 linkStrength: {type: 'value', default: 1},
|
Daniel@0
|
18350 linkDistance: {type: 'value', default: 20},
|
Daniel@0
|
18351 charge: {type: 'value', default: -30},
|
Daniel@0
|
18352
|
Daniel@0
|
18353 chargeDistance: {type: 'value', default: Infinity},
|
Daniel@0
|
18354 friction: {type: 'value', default: 0.9},
|
Daniel@0
|
18355 theta: {type: 'value', default: 0.8},
|
Daniel@0
|
18356 gravity: {type: 'value', default: 0.1},
|
Daniel@0
|
18357 alpha: {type: 'value', default: 0.1},
|
Daniel@0
|
18358 iterations: {type: 'value', default: 500},
|
Daniel@0
|
18359
|
Daniel@0
|
18360 interactive: {type: 'value', default: this._interactive},
|
Daniel@0
|
18361 active: {type: 'value', default: this._prev},
|
Daniel@0
|
18362 fixed: {type: 'data'}
|
Daniel@0
|
18363 });
|
Daniel@0
|
18364
|
Daniel@0
|
18365 this._output = {
|
Daniel@0
|
18366 'x': 'layout_x',
|
Daniel@0
|
18367 'y': 'layout_y'
|
Daniel@0
|
18368 };
|
Daniel@0
|
18369
|
Daniel@0
|
18370 return this.mutates(true);
|
Daniel@0
|
18371 }
|
Daniel@0
|
18372
|
Daniel@0
|
18373 var prototype = (Force.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18374 prototype.constructor = Force;
|
Daniel@0
|
18375
|
Daniel@0
|
18376 prototype.transform = function(nodeInput, reset) {
|
Daniel@0
|
18377 log.debug(nodeInput, ['force']);
|
Daniel@0
|
18378 reset = reset - (nodeInput.signals.active ? 1 : 0);
|
Daniel@0
|
18379
|
Daniel@0
|
18380 // get variables
|
Daniel@0
|
18381 var interactive = this.param('interactive'),
|
Daniel@0
|
18382 linkSource = this.param('links').source,
|
Daniel@0
|
18383 linkInput = linkSource.last(),
|
Daniel@0
|
18384 active = this.param('active'),
|
Daniel@0
|
18385 output = this._output,
|
Daniel@0
|
18386 layout = this._layout,
|
Daniel@0
|
18387 nodes = this._nodes,
|
Daniel@0
|
18388 links = this._links;
|
Daniel@0
|
18389
|
Daniel@0
|
18390 // configure nodes, links and layout
|
Daniel@0
|
18391 if (linkInput.stamp < nodeInput.stamp) linkInput = null;
|
Daniel@0
|
18392 this.configure(nodeInput, linkInput, interactive, reset);
|
Daniel@0
|
18393
|
Daniel@0
|
18394 // run batch layout
|
Daniel@0
|
18395 if (!interactive) {
|
Daniel@0
|
18396 var iterations = this.param('iterations');
|
Daniel@0
|
18397 for (var i=0; i<iterations; ++i) layout.tick();
|
Daniel@0
|
18398 layout.stop();
|
Daniel@0
|
18399 }
|
Daniel@0
|
18400
|
Daniel@0
|
18401 // update node positions
|
Daniel@0
|
18402 this.update(active);
|
Daniel@0
|
18403
|
Daniel@0
|
18404 // re-up alpha on parameter change
|
Daniel@0
|
18405 if (reset || active !== this._prev && active && active.update) {
|
Daniel@0
|
18406 layout.alpha(this.param('alpha')); // re-start layout
|
Daniel@0
|
18407 }
|
Daniel@0
|
18408
|
Daniel@0
|
18409 // update active node status,
|
Daniel@0
|
18410 if (active !== this._prev) {
|
Daniel@0
|
18411 this._prev = active;
|
Daniel@0
|
18412 }
|
Daniel@0
|
18413
|
Daniel@0
|
18414 // process removed nodes or edges
|
Daniel@0
|
18415 if (nodeInput.rem.length) {
|
Daniel@0
|
18416 layout.nodes(this._nodes = Tuple.idFilter(nodes, nodeInput.rem));
|
Daniel@0
|
18417 }
|
Daniel@0
|
18418 if (linkInput && linkInput.rem.length) {
|
Daniel@0
|
18419 layout.links(this._links = Tuple.idFilter(links, linkInput.rem));
|
Daniel@0
|
18420 }
|
Daniel@0
|
18421
|
Daniel@0
|
18422 // return changeset
|
Daniel@0
|
18423 nodeInput.fields[output.x] = 1;
|
Daniel@0
|
18424 nodeInput.fields[output.y] = 1;
|
Daniel@0
|
18425 return nodeInput;
|
Daniel@0
|
18426 };
|
Daniel@0
|
18427
|
Daniel@0
|
18428 prototype.configure = function(nodeInput, linkInput, interactive, reset) {
|
Daniel@0
|
18429 // check if we need to run configuration
|
Daniel@0
|
18430 var layout = this._layout,
|
Daniel@0
|
18431 update = this._setup || nodeInput.add.length ||
|
Daniel@0
|
18432 linkInput && linkInput.add.length ||
|
Daniel@0
|
18433 interactive !== this._interactive ||
|
Daniel@0
|
18434 this.param('charge') !== layout.charge() ||
|
Daniel@0
|
18435 this.param('linkStrength') !== layout.linkStrength() ||
|
Daniel@0
|
18436 this.param('linkDistance') !== layout.linkDistance();
|
Daniel@0
|
18437
|
Daniel@0
|
18438 if (update || reset) {
|
Daniel@0
|
18439 // a parameter changed, so update tick-only parameters
|
Daniel@0
|
18440 layout
|
Daniel@0
|
18441 .size(this.param('size'))
|
Daniel@0
|
18442 .chargeDistance(this.param('chargeDistance'))
|
Daniel@0
|
18443 .theta(this.param('theta'))
|
Daniel@0
|
18444 .gravity(this.param('gravity'))
|
Daniel@0
|
18445 .friction(this.param('friction'));
|
Daniel@0
|
18446 }
|
Daniel@0
|
18447
|
Daniel@0
|
18448 if (!update) return; // if no more updates needed, return now
|
Daniel@0
|
18449
|
Daniel@0
|
18450 this._setup = false;
|
Daniel@0
|
18451 this._interactive = interactive;
|
Daniel@0
|
18452
|
Daniel@0
|
18453 var force = this,
|
Daniel@0
|
18454 graph = this._graph,
|
Daniel@0
|
18455 nodes = this._nodes,
|
Daniel@0
|
18456 links = this._links, a, i;
|
Daniel@0
|
18457
|
Daniel@0
|
18458 // process added nodes
|
Daniel@0
|
18459 for (a=nodeInput.add, i=0; i<a.length; ++i) {
|
Daniel@0
|
18460 nodes.push({tuple: a[i]});
|
Daniel@0
|
18461 }
|
Daniel@0
|
18462
|
Daniel@0
|
18463 // process added edges
|
Daniel@0
|
18464 if (linkInput) for (a=linkInput.add, i=0; i<a.length; ++i) {
|
Daniel@0
|
18465 // TODO add configurable source/target accessors
|
Daniel@0
|
18466 // TODO support lookup by node id
|
Daniel@0
|
18467 // TODO process 'mod' of edge source or target?
|
Daniel@0
|
18468 links.push({
|
Daniel@0
|
18469 tuple: a[i],
|
Daniel@0
|
18470 source: nodes[a[i].source],
|
Daniel@0
|
18471 target: nodes[a[i].target]
|
Daniel@0
|
18472 });
|
Daniel@0
|
18473 }
|
Daniel@0
|
18474
|
Daniel@0
|
18475 // setup handler for force layout tick events
|
Daniel@0
|
18476 var tickHandler = !interactive ? null : function() {
|
Daniel@0
|
18477 // re-schedule the transform, force reflow
|
Daniel@0
|
18478 graph.propagate(ChangeSet.create(null, true), force);
|
Daniel@0
|
18479 };
|
Daniel@0
|
18480
|
Daniel@0
|
18481 // configure the rest of the layout
|
Daniel@0
|
18482 layout
|
Daniel@0
|
18483 .linkStrength(this.param('linkStrength'))
|
Daniel@0
|
18484 .linkDistance(this.param('linkDistance'))
|
Daniel@0
|
18485 .charge(this.param('charge'))
|
Daniel@0
|
18486 .nodes(nodes)
|
Daniel@0
|
18487 .links(links)
|
Daniel@0
|
18488 .on('tick', tickHandler)
|
Daniel@0
|
18489 .start().alpha(this.param('alpha'));
|
Daniel@0
|
18490 };
|
Daniel@0
|
18491
|
Daniel@0
|
18492 prototype.update = function(active) {
|
Daniel@0
|
18493 var output = this._output,
|
Daniel@0
|
18494 bound = this.param('bound'),
|
Daniel@0
|
18495 fixed = this.param('fixed'),
|
Daniel@0
|
18496 size = this.param('size'),
|
Daniel@0
|
18497 nodes = this._nodes,
|
Daniel@0
|
18498 lut = {}, id, i, n, t, x, y;
|
Daniel@0
|
18499
|
Daniel@0
|
18500 if (fixed && fixed.source) {
|
Daniel@0
|
18501 // TODO: could cache and update as needed?
|
Daniel@0
|
18502 fixed = fixed.source.values();
|
Daniel@0
|
18503 for (i=0, n=fixed.length; i<n; ++i) {
|
Daniel@0
|
18504 lut[fixed[i].id] = 1;
|
Daniel@0
|
18505 }
|
Daniel@0
|
18506 }
|
Daniel@0
|
18507
|
Daniel@0
|
18508 for (i=0; i<nodes.length; ++i) {
|
Daniel@0
|
18509 n = nodes[i];
|
Daniel@0
|
18510 t = n.tuple;
|
Daniel@0
|
18511 id = t._id;
|
Daniel@0
|
18512
|
Daniel@0
|
18513 if (active && active.id === id) {
|
Daniel@0
|
18514 n.fixed = 1;
|
Daniel@0
|
18515 if (active.update) {
|
Daniel@0
|
18516 n.x = n.px = active.x;
|
Daniel@0
|
18517 n.y = n.py = active.y;
|
Daniel@0
|
18518 }
|
Daniel@0
|
18519 } else {
|
Daniel@0
|
18520 n.fixed = lut[id] || 0;
|
Daniel@0
|
18521 }
|
Daniel@0
|
18522
|
Daniel@0
|
18523 x = bound ? Math.max(0, Math.min(n.x, size[0])) : n.x;
|
Daniel@0
|
18524 y = bound ? Math.max(0, Math.min(n.y, size[1])) : n.y;
|
Daniel@0
|
18525 Tuple.set(t, output.x, x);
|
Daniel@0
|
18526 Tuple.set(t, output.y, y);
|
Daniel@0
|
18527 }
|
Daniel@0
|
18528 };
|
Daniel@0
|
18529
|
Daniel@0
|
18530 module.exports = Force;
|
Daniel@0
|
18531 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
18532
|
Daniel@0
|
18533 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],126:[function(require,module,exports){
|
Daniel@0
|
18534 var df = require('vega-dataflow'),
|
Daniel@0
|
18535 Tuple = df.Tuple,
|
Daniel@0
|
18536 SIGNALS = df.Dependencies.SIGNALS,
|
Daniel@0
|
18537 log = require('vega-logging'),
|
Daniel@0
|
18538 Transform = require('./Transform');
|
Daniel@0
|
18539
|
Daniel@0
|
18540 function Formula(graph) {
|
Daniel@0
|
18541 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18542 Transform.addParameters(this, {
|
Daniel@0
|
18543 field: {type: 'value'},
|
Daniel@0
|
18544 expr: {type: 'expr'}
|
Daniel@0
|
18545 });
|
Daniel@0
|
18546
|
Daniel@0
|
18547 return this.mutates(true);
|
Daniel@0
|
18548 }
|
Daniel@0
|
18549
|
Daniel@0
|
18550 var prototype = (Formula.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18551 prototype.constructor = Formula;
|
Daniel@0
|
18552
|
Daniel@0
|
18553 prototype.transform = function(input) {
|
Daniel@0
|
18554 log.debug(input, ['formulating']);
|
Daniel@0
|
18555
|
Daniel@0
|
18556 var g = this._graph,
|
Daniel@0
|
18557 field = this.param('field'),
|
Daniel@0
|
18558 expr = this.param('expr'),
|
Daniel@0
|
18559 signals = g.values(SIGNALS, this.dependency(SIGNALS));
|
Daniel@0
|
18560
|
Daniel@0
|
18561 function set(x) {
|
Daniel@0
|
18562 Tuple.set(x, field, expr(x, null, signals));
|
Daniel@0
|
18563 }
|
Daniel@0
|
18564
|
Daniel@0
|
18565 input.add.forEach(set);
|
Daniel@0
|
18566
|
Daniel@0
|
18567 if (this.reevaluate(input)) {
|
Daniel@0
|
18568 input.mod.forEach(set);
|
Daniel@0
|
18569 }
|
Daniel@0
|
18570
|
Daniel@0
|
18571 input.fields[field] = 1;
|
Daniel@0
|
18572 return input;
|
Daniel@0
|
18573 };
|
Daniel@0
|
18574
|
Daniel@0
|
18575 module.exports = Formula;
|
Daniel@0
|
18576 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],127:[function(require,module,exports){
|
Daniel@0
|
18577 (function (global){
|
Daniel@0
|
18578 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
18579 dl = require('datalib'),
|
Daniel@0
|
18580 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
18581 log = require('vega-logging'),
|
Daniel@0
|
18582 Transform = require('./Transform');
|
Daniel@0
|
18583
|
Daniel@0
|
18584 function Geo(graph) {
|
Daniel@0
|
18585 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18586 Transform.addParameters(this, Geo.Parameters);
|
Daniel@0
|
18587 Transform.addParameters(this, {
|
Daniel@0
|
18588 lon: {type: 'field'},
|
Daniel@0
|
18589 lat: {type: 'field'}
|
Daniel@0
|
18590 });
|
Daniel@0
|
18591
|
Daniel@0
|
18592 this._output = {
|
Daniel@0
|
18593 'x': 'layout_x',
|
Daniel@0
|
18594 'y': 'layout_y'
|
Daniel@0
|
18595 };
|
Daniel@0
|
18596 return this.mutates(true);
|
Daniel@0
|
18597 }
|
Daniel@0
|
18598
|
Daniel@0
|
18599 Geo.Parameters = {
|
Daniel@0
|
18600 projection: {type: 'value', default: 'mercator'},
|
Daniel@0
|
18601 center: {type: 'array<value>'},
|
Daniel@0
|
18602 translate: {type: 'array<value>'},
|
Daniel@0
|
18603 rotate: {type: 'array<value>'},
|
Daniel@0
|
18604 scale: {type: 'value'},
|
Daniel@0
|
18605 precision: {type: 'value'},
|
Daniel@0
|
18606 clipAngle: {type: 'value'},
|
Daniel@0
|
18607 clipExtent: {type: 'value'}
|
Daniel@0
|
18608 };
|
Daniel@0
|
18609
|
Daniel@0
|
18610 Geo.d3Projection = function() {
|
Daniel@0
|
18611 var p = this.param('projection'),
|
Daniel@0
|
18612 param = Geo.Parameters,
|
Daniel@0
|
18613 proj, name, value;
|
Daniel@0
|
18614
|
Daniel@0
|
18615 if (p !== this._mode) {
|
Daniel@0
|
18616 this._mode = p;
|
Daniel@0
|
18617 this._projection = d3.geo[p]();
|
Daniel@0
|
18618 }
|
Daniel@0
|
18619 proj = this._projection;
|
Daniel@0
|
18620
|
Daniel@0
|
18621 for (name in param) {
|
Daniel@0
|
18622 if (name === 'projection' || !proj[name]) continue;
|
Daniel@0
|
18623 value = this.param(name);
|
Daniel@0
|
18624 if (value === undefined || (dl.isArray(value) && value.length === 0)) {
|
Daniel@0
|
18625 continue;
|
Daniel@0
|
18626 }
|
Daniel@0
|
18627 if (value !== proj[name]()) {
|
Daniel@0
|
18628 proj[name](value);
|
Daniel@0
|
18629 }
|
Daniel@0
|
18630 }
|
Daniel@0
|
18631
|
Daniel@0
|
18632 return proj;
|
Daniel@0
|
18633 };
|
Daniel@0
|
18634
|
Daniel@0
|
18635 var prototype = (Geo.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18636 prototype.constructor = Geo;
|
Daniel@0
|
18637
|
Daniel@0
|
18638 prototype.transform = function(input) {
|
Daniel@0
|
18639 log.debug(input, ['geo']);
|
Daniel@0
|
18640
|
Daniel@0
|
18641 var output = this._output,
|
Daniel@0
|
18642 lon = this.param('lon').accessor,
|
Daniel@0
|
18643 lat = this.param('lat').accessor,
|
Daniel@0
|
18644 proj = Geo.d3Projection.call(this);
|
Daniel@0
|
18645
|
Daniel@0
|
18646 function set(t) {
|
Daniel@0
|
18647 var ll = [lon(t), lat(t)];
|
Daniel@0
|
18648 var xy = proj(ll) || [null, null];
|
Daniel@0
|
18649 Tuple.set(t, output.x, xy[0]);
|
Daniel@0
|
18650 Tuple.set(t, output.y, xy[1]);
|
Daniel@0
|
18651 }
|
Daniel@0
|
18652
|
Daniel@0
|
18653 input.add.forEach(set);
|
Daniel@0
|
18654 if (this.reevaluate(input)) {
|
Daniel@0
|
18655 input.mod.forEach(set);
|
Daniel@0
|
18656 input.rem.forEach(set);
|
Daniel@0
|
18657 }
|
Daniel@0
|
18658
|
Daniel@0
|
18659 input.fields[output.x] = 1;
|
Daniel@0
|
18660 input.fields[output.y] = 1;
|
Daniel@0
|
18661 return input;
|
Daniel@0
|
18662 };
|
Daniel@0
|
18663
|
Daniel@0
|
18664 module.exports = Geo;
|
Daniel@0
|
18665 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
18666
|
Daniel@0
|
18667 },{"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],128:[function(require,module,exports){
|
Daniel@0
|
18668 (function (global){
|
Daniel@0
|
18669 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
18670 dl = require('datalib'),
|
Daniel@0
|
18671 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
18672 log = require('vega-logging'),
|
Daniel@0
|
18673 Geo = require('./Geo'),
|
Daniel@0
|
18674 Transform = require('./Transform');
|
Daniel@0
|
18675
|
Daniel@0
|
18676 function GeoPath(graph) {
|
Daniel@0
|
18677 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18678 Transform.addParameters(this, Geo.Parameters);
|
Daniel@0
|
18679 Transform.addParameters(this, {
|
Daniel@0
|
18680 field: {type: 'field', default: null},
|
Daniel@0
|
18681 });
|
Daniel@0
|
18682
|
Daniel@0
|
18683 this._output = {
|
Daniel@0
|
18684 'path': 'layout_path'
|
Daniel@0
|
18685 };
|
Daniel@0
|
18686 return this.mutates(true);
|
Daniel@0
|
18687 }
|
Daniel@0
|
18688
|
Daniel@0
|
18689 var prototype = (GeoPath.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18690 prototype.constructor = GeoPath;
|
Daniel@0
|
18691
|
Daniel@0
|
18692 prototype.transform = function(input) {
|
Daniel@0
|
18693 log.debug(input, ['geopath']);
|
Daniel@0
|
18694
|
Daniel@0
|
18695 var output = this._output,
|
Daniel@0
|
18696 geojson = this.param('field').accessor || dl.identity,
|
Daniel@0
|
18697 proj = Geo.d3Projection.call(this),
|
Daniel@0
|
18698 path = d3.geo.path().projection(proj);
|
Daniel@0
|
18699
|
Daniel@0
|
18700 function set(t) {
|
Daniel@0
|
18701 Tuple.set(t, output.path, path(geojson(t)));
|
Daniel@0
|
18702 }
|
Daniel@0
|
18703
|
Daniel@0
|
18704 input.add.forEach(set);
|
Daniel@0
|
18705 if (this.reevaluate(input)) {
|
Daniel@0
|
18706 input.mod.forEach(set);
|
Daniel@0
|
18707 input.rem.forEach(set);
|
Daniel@0
|
18708 }
|
Daniel@0
|
18709
|
Daniel@0
|
18710 input.fields[output.path] = 1;
|
Daniel@0
|
18711 return input;
|
Daniel@0
|
18712 };
|
Daniel@0
|
18713
|
Daniel@0
|
18714 module.exports = GeoPath;
|
Daniel@0
|
18715 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
18716
|
Daniel@0
|
18717 },{"./Geo":127,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],129:[function(require,module,exports){
|
Daniel@0
|
18718 var Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
18719 log = require('vega-logging'),
|
Daniel@0
|
18720 Transform = require('./Transform');
|
Daniel@0
|
18721
|
Daniel@0
|
18722 function LinkPath(graph) {
|
Daniel@0
|
18723 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18724 Transform.addParameters(this, {
|
Daniel@0
|
18725 sourceX: {type: 'field', default: '_source.layout_x'},
|
Daniel@0
|
18726 sourceY: {type: 'field', default: '_source.layout_y'},
|
Daniel@0
|
18727 targetX: {type: 'field', default: '_target.layout_x'},
|
Daniel@0
|
18728 targetY: {type: 'field', default: '_target.layout_y'},
|
Daniel@0
|
18729 tension: {type: 'value', default: 0.2},
|
Daniel@0
|
18730 shape: {type: 'value', default: 'line'}
|
Daniel@0
|
18731 });
|
Daniel@0
|
18732
|
Daniel@0
|
18733 this._output = {'path': 'layout_path'};
|
Daniel@0
|
18734 return this.mutates(true);
|
Daniel@0
|
18735 }
|
Daniel@0
|
18736
|
Daniel@0
|
18737 var prototype = (LinkPath.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18738 prototype.constructor = LinkPath;
|
Daniel@0
|
18739
|
Daniel@0
|
18740 function line(sx, sy, tx, ty) {
|
Daniel@0
|
18741 return 'M' + sx + ',' + sy +
|
Daniel@0
|
18742 'L' + tx + ',' + ty;
|
Daniel@0
|
18743 }
|
Daniel@0
|
18744
|
Daniel@0
|
18745 function curve(sx, sy, tx, ty, tension) {
|
Daniel@0
|
18746 var dx = tx - sx,
|
Daniel@0
|
18747 dy = ty - sy,
|
Daniel@0
|
18748 ix = tension * (dx + dy),
|
Daniel@0
|
18749 iy = tension * (dy - dx);
|
Daniel@0
|
18750 return 'M' + sx + ',' + sy +
|
Daniel@0
|
18751 'C' + (sx+ix) + ',' + (sy+iy) +
|
Daniel@0
|
18752 ' ' + (tx+iy) + ',' + (ty-ix) +
|
Daniel@0
|
18753 ' ' + tx + ',' + ty;
|
Daniel@0
|
18754 }
|
Daniel@0
|
18755
|
Daniel@0
|
18756 function diagonalX(sx, sy, tx, ty) {
|
Daniel@0
|
18757 var m = (sx + tx) / 2;
|
Daniel@0
|
18758 return 'M' + sx + ',' + sy +
|
Daniel@0
|
18759 'C' + m + ',' + sy +
|
Daniel@0
|
18760 ' ' + m + ',' + ty +
|
Daniel@0
|
18761 ' ' + tx + ',' + ty;
|
Daniel@0
|
18762 }
|
Daniel@0
|
18763
|
Daniel@0
|
18764 function diagonalY(sx, sy, tx, ty) {
|
Daniel@0
|
18765 var m = (sy + ty) / 2;
|
Daniel@0
|
18766 return 'M' + sx + ',' + sy +
|
Daniel@0
|
18767 'C' + sx + ',' + m +
|
Daniel@0
|
18768 ' ' + tx + ',' + m +
|
Daniel@0
|
18769 ' ' + tx + ',' + ty;
|
Daniel@0
|
18770 }
|
Daniel@0
|
18771
|
Daniel@0
|
18772 var shapes = {
|
Daniel@0
|
18773 line: line,
|
Daniel@0
|
18774 curve: curve,
|
Daniel@0
|
18775 diagonal: diagonalX,
|
Daniel@0
|
18776 diagonalX: diagonalX,
|
Daniel@0
|
18777 diagonalY: diagonalY
|
Daniel@0
|
18778 };
|
Daniel@0
|
18779
|
Daniel@0
|
18780 prototype.transform = function(input) {
|
Daniel@0
|
18781 log.debug(input, ['linkpath']);
|
Daniel@0
|
18782
|
Daniel@0
|
18783 var output = this._output,
|
Daniel@0
|
18784 shape = shapes[this.param('shape')] || shapes.line,
|
Daniel@0
|
18785 sourceX = this.param('sourceX').accessor,
|
Daniel@0
|
18786 sourceY = this.param('sourceY').accessor,
|
Daniel@0
|
18787 targetX = this.param('targetX').accessor,
|
Daniel@0
|
18788 targetY = this.param('targetY').accessor,
|
Daniel@0
|
18789 tension = this.param('tension');
|
Daniel@0
|
18790
|
Daniel@0
|
18791 function set(t) {
|
Daniel@0
|
18792 var path = shape(sourceX(t), sourceY(t), targetX(t), targetY(t), tension);
|
Daniel@0
|
18793 Tuple.set(t, output.path, path);
|
Daniel@0
|
18794 }
|
Daniel@0
|
18795
|
Daniel@0
|
18796 input.add.forEach(set);
|
Daniel@0
|
18797 if (this.reevaluate(input)) {
|
Daniel@0
|
18798 input.mod.forEach(set);
|
Daniel@0
|
18799 input.rem.forEach(set);
|
Daniel@0
|
18800 }
|
Daniel@0
|
18801
|
Daniel@0
|
18802 input.fields[output.path] = 1;
|
Daniel@0
|
18803 return input;
|
Daniel@0
|
18804 };
|
Daniel@0
|
18805
|
Daniel@0
|
18806 module.exports = LinkPath;
|
Daniel@0
|
18807 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],130:[function(require,module,exports){
|
Daniel@0
|
18808 var Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
18809 log = require('vega-logging'),
|
Daniel@0
|
18810 Transform = require('./Transform');
|
Daniel@0
|
18811
|
Daniel@0
|
18812 function Lookup(graph) {
|
Daniel@0
|
18813 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
18814 Transform.addParameters(this, {
|
Daniel@0
|
18815 on: {type: 'data'},
|
Daniel@0
|
18816 onKey: {type: 'field', default: null},
|
Daniel@0
|
18817 as: {type: 'array<value>'},
|
Daniel@0
|
18818 keys: {type: 'array<field>', default: ['data']},
|
Daniel@0
|
18819 default: {type: 'value'}
|
Daniel@0
|
18820 });
|
Daniel@0
|
18821
|
Daniel@0
|
18822 return this.mutates(true);
|
Daniel@0
|
18823 }
|
Daniel@0
|
18824
|
Daniel@0
|
18825 var prototype = (Lookup.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
18826 prototype.constructor = Lookup;
|
Daniel@0
|
18827
|
Daniel@0
|
18828 prototype.transform = function(input, reset) {
|
Daniel@0
|
18829 log.debug(input, ['lookup']);
|
Daniel@0
|
18830
|
Daniel@0
|
18831 var on = this.param('on'),
|
Daniel@0
|
18832 onLast = on.source.last(),
|
Daniel@0
|
18833 onData = on.source.values(),
|
Daniel@0
|
18834 onKey = this.param('onKey'),
|
Daniel@0
|
18835 onF = onKey.field,
|
Daniel@0
|
18836 keys = this.param('keys'),
|
Daniel@0
|
18837 get = keys.accessor,
|
Daniel@0
|
18838 as = this.param('as'),
|
Daniel@0
|
18839 defaultValue = this.param('default'),
|
Daniel@0
|
18840 lut = this._lut,
|
Daniel@0
|
18841 i, v;
|
Daniel@0
|
18842
|
Daniel@0
|
18843 // build lookup table on init, withKey modified, or tuple add/rem
|
Daniel@0
|
18844 if (lut == null || this._on !== onF || onF && onLast.fields[onF] ||
|
Daniel@0
|
18845 onLast.add.length || onLast.rem.length)
|
Daniel@0
|
18846 {
|
Daniel@0
|
18847 if (onF) { // build hash from withKey field
|
Daniel@0
|
18848 onKey = onKey.accessor;
|
Daniel@0
|
18849 for (lut={}, i=0; i<onData.length; ++i) {
|
Daniel@0
|
18850 lut[onKey(v = onData[i])] = v;
|
Daniel@0
|
18851 }
|
Daniel@0
|
18852 } else { // otherwise, use index-based lookup
|
Daniel@0
|
18853 lut = onData;
|
Daniel@0
|
18854 }
|
Daniel@0
|
18855 this._lut = lut;
|
Daniel@0
|
18856 this._on = onF;
|
Daniel@0
|
18857 reset = true;
|
Daniel@0
|
18858 }
|
Daniel@0
|
18859
|
Daniel@0
|
18860 function set(t) {
|
Daniel@0
|
18861 for (var i=0; i<get.length; ++i) {
|
Daniel@0
|
18862 var v = lut[get[i](t)] || defaultValue;
|
Daniel@0
|
18863 Tuple.set(t, as[i], v);
|
Daniel@0
|
18864 }
|
Daniel@0
|
18865 }
|
Daniel@0
|
18866
|
Daniel@0
|
18867 input.add.forEach(set);
|
Daniel@0
|
18868 var run = keys.field.some(function(f) { return input.fields[f]; });
|
Daniel@0
|
18869 if (run || reset) {
|
Daniel@0
|
18870 input.mod.forEach(set);
|
Daniel@0
|
18871 input.rem.forEach(set);
|
Daniel@0
|
18872 }
|
Daniel@0
|
18873
|
Daniel@0
|
18874 as.forEach(function(k) { input.fields[k] = 1; });
|
Daniel@0
|
18875 return input;
|
Daniel@0
|
18876 };
|
Daniel@0
|
18877
|
Daniel@0
|
18878 module.exports = Lookup;
|
Daniel@0
|
18879 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],131:[function(require,module,exports){
|
Daniel@0
|
18880 var dl = require('datalib'),
|
Daniel@0
|
18881 Deps = require('vega-dataflow').Dependencies,
|
Daniel@0
|
18882 expr = require('../parse/expr');
|
Daniel@0
|
18883
|
Daniel@0
|
18884 var arrayType = /array/i,
|
Daniel@0
|
18885 dataType = /data/i,
|
Daniel@0
|
18886 fieldType = /field/i,
|
Daniel@0
|
18887 exprType = /expr/i,
|
Daniel@0
|
18888 valType = /value/i;
|
Daniel@0
|
18889
|
Daniel@0
|
18890 function Parameter(name, type, transform) {
|
Daniel@0
|
18891 this._name = name;
|
Daniel@0
|
18892 this._type = type;
|
Daniel@0
|
18893 this._transform = transform;
|
Daniel@0
|
18894
|
Daniel@0
|
18895 // If parameter is defined w/signals, it must be resolved
|
Daniel@0
|
18896 // on every pulse.
|
Daniel@0
|
18897 this._value = [];
|
Daniel@0
|
18898 this._accessors = [];
|
Daniel@0
|
18899 this._resolution = false;
|
Daniel@0
|
18900 this._signals = {};
|
Daniel@0
|
18901 }
|
Daniel@0
|
18902
|
Daniel@0
|
18903 var prototype = Parameter.prototype;
|
Daniel@0
|
18904
|
Daniel@0
|
18905 function get() {
|
Daniel@0
|
18906 var isArray = arrayType.test(this._type),
|
Daniel@0
|
18907 isData = dataType.test(this._type),
|
Daniel@0
|
18908 isField = fieldType.test(this._type);
|
Daniel@0
|
18909
|
Daniel@0
|
18910 var val = isArray ? this._value : this._value[0],
|
Daniel@0
|
18911 acc = isArray ? this._accessors : this._accessors[0];
|
Daniel@0
|
18912
|
Daniel@0
|
18913 if (!dl.isValid(acc) && valType.test(this._type)) {
|
Daniel@0
|
18914 return val;
|
Daniel@0
|
18915 } else {
|
Daniel@0
|
18916 return isData ? { name: val, source: acc } :
|
Daniel@0
|
18917 isField ? { field: val, accessor: acc } : val;
|
Daniel@0
|
18918 }
|
Daniel@0
|
18919 }
|
Daniel@0
|
18920
|
Daniel@0
|
18921 prototype.get = function() {
|
Daniel@0
|
18922 var graph = this._transform._graph,
|
Daniel@0
|
18923 isData = dataType.test(this._type),
|
Daniel@0
|
18924 isField = fieldType.test(this._type),
|
Daniel@0
|
18925 s, idx, val;
|
Daniel@0
|
18926
|
Daniel@0
|
18927 // If we don't require resolution, return the value immediately.
|
Daniel@0
|
18928 if (!this._resolution) return get.call(this);
|
Daniel@0
|
18929
|
Daniel@0
|
18930 if (isData) {
|
Daniel@0
|
18931 this._accessors = this._value.map(function(v) { return graph.data(v); });
|
Daniel@0
|
18932 return get.call(this); // TODO: support signal as dataTypes
|
Daniel@0
|
18933 }
|
Daniel@0
|
18934
|
Daniel@0
|
18935 for (s in this._signals) {
|
Daniel@0
|
18936 idx = this._signals[s];
|
Daniel@0
|
18937 val = graph.signalRef(s);
|
Daniel@0
|
18938
|
Daniel@0
|
18939 if (isField) {
|
Daniel@0
|
18940 this._accessors[idx] = this._value[idx] != val ?
|
Daniel@0
|
18941 dl.accessor(val) : this._accessors[idx];
|
Daniel@0
|
18942 }
|
Daniel@0
|
18943
|
Daniel@0
|
18944 this._value[idx] = val;
|
Daniel@0
|
18945 }
|
Daniel@0
|
18946
|
Daniel@0
|
18947 return get.call(this);
|
Daniel@0
|
18948 };
|
Daniel@0
|
18949
|
Daniel@0
|
18950 prototype.set = function(value) {
|
Daniel@0
|
18951 var p = this,
|
Daniel@0
|
18952 isExpr = exprType.test(this._type),
|
Daniel@0
|
18953 isData = dataType.test(this._type),
|
Daniel@0
|
18954 isField = fieldType.test(this._type);
|
Daniel@0
|
18955
|
Daniel@0
|
18956 this._value = dl.array(value).map(function(v, i) {
|
Daniel@0
|
18957 if (dl.isString(v)) {
|
Daniel@0
|
18958 if (isExpr) {
|
Daniel@0
|
18959 var e = expr(v);
|
Daniel@0
|
18960 p._transform.dependency(Deps.FIELDS, e.fields);
|
Daniel@0
|
18961 p._transform.dependency(Deps.SIGNALS, e.globals);
|
Daniel@0
|
18962 return e.fn;
|
Daniel@0
|
18963 } else if (isField) { // Backwards compatibility
|
Daniel@0
|
18964 p._accessors[i] = dl.accessor(v);
|
Daniel@0
|
18965 p._transform.dependency(Deps.FIELDS, dl.field(v));
|
Daniel@0
|
18966 } else if (isData) {
|
Daniel@0
|
18967 p._resolution = true;
|
Daniel@0
|
18968 p._transform.dependency(Deps.DATA, v);
|
Daniel@0
|
18969 }
|
Daniel@0
|
18970 return v;
|
Daniel@0
|
18971 } else if (v.value !== undefined) {
|
Daniel@0
|
18972 return v.value;
|
Daniel@0
|
18973 } else if (v.field !== undefined) {
|
Daniel@0
|
18974 p._accessors[i] = dl.accessor(v.field);
|
Daniel@0
|
18975 p._transform.dependency(Deps.FIELDS, dl.field(v.field));
|
Daniel@0
|
18976 return v.field;
|
Daniel@0
|
18977 } else if (v.signal !== undefined) {
|
Daniel@0
|
18978 p._resolution = true;
|
Daniel@0
|
18979 p._signals[v.signal] = i;
|
Daniel@0
|
18980 p._transform.dependency(Deps.SIGNALS, v.signal);
|
Daniel@0
|
18981 return v.signal;
|
Daniel@0
|
18982 }
|
Daniel@0
|
18983
|
Daniel@0
|
18984 return v;
|
Daniel@0
|
18985 });
|
Daniel@0
|
18986
|
Daniel@0
|
18987 return p._transform;
|
Daniel@0
|
18988 };
|
Daniel@0
|
18989
|
Daniel@0
|
18990 module.exports = Parameter;
|
Daniel@0
|
18991 },{"../parse/expr":94,"datalib":24,"vega-dataflow":39}],132:[function(require,module,exports){
|
Daniel@0
|
18992 var dl = require('datalib'),
|
Daniel@0
|
18993 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
18994 log = require('vega-logging'),
|
Daniel@0
|
18995 Transform = require('./Transform'),
|
Daniel@0
|
18996 BatchTransform = require('./BatchTransform');
|
Daniel@0
|
18997
|
Daniel@0
|
18998 function Pie(graph) {
|
Daniel@0
|
18999 BatchTransform.prototype.init.call(this, graph);
|
Daniel@0
|
19000 Transform.addParameters(this, {
|
Daniel@0
|
19001 field: {type: 'field', default: null},
|
Daniel@0
|
19002 startAngle: {type: 'value', default: 0},
|
Daniel@0
|
19003 endAngle: {type: 'value', default: 2 * Math.PI},
|
Daniel@0
|
19004 sort: {type: 'value', default: false}
|
Daniel@0
|
19005 });
|
Daniel@0
|
19006
|
Daniel@0
|
19007 this._output = {
|
Daniel@0
|
19008 'start': 'layout_start',
|
Daniel@0
|
19009 'end': 'layout_end',
|
Daniel@0
|
19010 'mid': 'layout_mid'
|
Daniel@0
|
19011 };
|
Daniel@0
|
19012
|
Daniel@0
|
19013 return this.mutates(true);
|
Daniel@0
|
19014 }
|
Daniel@0
|
19015
|
Daniel@0
|
19016 var prototype = (Pie.prototype = Object.create(BatchTransform.prototype));
|
Daniel@0
|
19017 prototype.constructor = Pie;
|
Daniel@0
|
19018
|
Daniel@0
|
19019 function ones() { return 1; }
|
Daniel@0
|
19020
|
Daniel@0
|
19021 prototype.batchTransform = function(input, data) {
|
Daniel@0
|
19022 log.debug(input, ['pie']);
|
Daniel@0
|
19023
|
Daniel@0
|
19024 var output = this._output,
|
Daniel@0
|
19025 field = this.param('field').accessor || ones,
|
Daniel@0
|
19026 start = this.param('startAngle'),
|
Daniel@0
|
19027 stop = this.param('endAngle'),
|
Daniel@0
|
19028 sort = this.param('sort');
|
Daniel@0
|
19029
|
Daniel@0
|
19030 var values = data.map(field),
|
Daniel@0
|
19031 a = start,
|
Daniel@0
|
19032 k = (stop - start) / dl.sum(values),
|
Daniel@0
|
19033 index = dl.range(data.length),
|
Daniel@0
|
19034 i, t, v;
|
Daniel@0
|
19035
|
Daniel@0
|
19036 if (sort) {
|
Daniel@0
|
19037 index.sort(function(a, b) {
|
Daniel@0
|
19038 return values[a] - values[b];
|
Daniel@0
|
19039 });
|
Daniel@0
|
19040 }
|
Daniel@0
|
19041
|
Daniel@0
|
19042 for (i=0; i<index.length; ++i) {
|
Daniel@0
|
19043 t = data[index[i]];
|
Daniel@0
|
19044 v = values[index[i]];
|
Daniel@0
|
19045 Tuple.set(t, output.start, a);
|
Daniel@0
|
19046 Tuple.set(t, output.mid, (a + 0.5 * v * k));
|
Daniel@0
|
19047 Tuple.set(t, output.end, (a += v * k));
|
Daniel@0
|
19048 }
|
Daniel@0
|
19049
|
Daniel@0
|
19050 input.fields[output.start] = 1;
|
Daniel@0
|
19051 input.fields[output.end] = 1;
|
Daniel@0
|
19052 input.fields[output.mid] = 1;
|
Daniel@0
|
19053 return input;
|
Daniel@0
|
19054 };
|
Daniel@0
|
19055
|
Daniel@0
|
19056 module.exports = Pie;
|
Daniel@0
|
19057 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],133:[function(require,module,exports){
|
Daniel@0
|
19058 var dl = require('datalib'),
|
Daniel@0
|
19059 log = require('vega-logging'),
|
Daniel@0
|
19060 Transform = require('./Transform');
|
Daniel@0
|
19061
|
Daniel@0
|
19062 function Sort(graph) {
|
Daniel@0
|
19063 Transform.prototype.init.call(this, graph);
|
Daniel@0
|
19064 Transform.addParameters(this, {by: {type: 'array<field>'} });
|
Daniel@0
|
19065 this.router(true);
|
Daniel@0
|
19066 }
|
Daniel@0
|
19067
|
Daniel@0
|
19068 var prototype = (Sort.prototype = Object.create(Transform.prototype));
|
Daniel@0
|
19069 prototype.constructor = Sort;
|
Daniel@0
|
19070
|
Daniel@0
|
19071 prototype.transform = function(input) {
|
Daniel@0
|
19072 log.debug(input, ['sorting']);
|
Daniel@0
|
19073
|
Daniel@0
|
19074 if (input.add.length || input.mod.length || input.rem.length) {
|
Daniel@0
|
19075 input.sort = dl.comparator(this.param('by').field);
|
Daniel@0
|
19076 }
|
Daniel@0
|
19077 return input;
|
Daniel@0
|
19078 };
|
Daniel@0
|
19079
|
Daniel@0
|
19080 module.exports = Sort;
|
Daniel@0
|
19081 },{"./Transform":135,"datalib":24,"vega-logging":45}],134:[function(require,module,exports){
|
Daniel@0
|
19082 var dl = require('datalib'),
|
Daniel@0
|
19083 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
19084 log = require('vega-logging'),
|
Daniel@0
|
19085 Transform = require('./Transform'),
|
Daniel@0
|
19086 BatchTransform = require('./BatchTransform');
|
Daniel@0
|
19087
|
Daniel@0
|
19088 function Stack(graph) {
|
Daniel@0
|
19089 BatchTransform.prototype.init.call(this, graph);
|
Daniel@0
|
19090 Transform.addParameters(this, {
|
Daniel@0
|
19091 groupby: {type: 'array<field>'},
|
Daniel@0
|
19092 sortby: {type: 'array<field>'},
|
Daniel@0
|
19093 field: {type: 'field'},
|
Daniel@0
|
19094 offset: {type: 'value', default: 'zero'}
|
Daniel@0
|
19095 });
|
Daniel@0
|
19096
|
Daniel@0
|
19097 this._output = {
|
Daniel@0
|
19098 'start': 'layout_start',
|
Daniel@0
|
19099 'end': 'layout_end',
|
Daniel@0
|
19100 'mid': 'layout_mid'
|
Daniel@0
|
19101 };
|
Daniel@0
|
19102 return this.mutates(true);
|
Daniel@0
|
19103 }
|
Daniel@0
|
19104
|
Daniel@0
|
19105 var prototype = (Stack.prototype = Object.create(BatchTransform.prototype));
|
Daniel@0
|
19106 prototype.constructor = Stack;
|
Daniel@0
|
19107
|
Daniel@0
|
19108 prototype.batchTransform = function(input, data) {
|
Daniel@0
|
19109 log.debug(input, ['stacking']);
|
Daniel@0
|
19110
|
Daniel@0
|
19111 var groupby = this.param('groupby').accessor,
|
Daniel@0
|
19112 sortby = dl.comparator(this.param('sortby').field),
|
Daniel@0
|
19113 field = this.param('field').accessor,
|
Daniel@0
|
19114 offset = this.param('offset'),
|
Daniel@0
|
19115 output = this._output;
|
Daniel@0
|
19116
|
Daniel@0
|
19117 // partition, sum, and sort the stack groups
|
Daniel@0
|
19118 var groups = partition(data, groupby, sortby, field);
|
Daniel@0
|
19119
|
Daniel@0
|
19120 // compute stack layouts per group
|
Daniel@0
|
19121 for (var i=0, max=groups.max; i<groups.length; ++i) {
|
Daniel@0
|
19122 var group = groups[i],
|
Daniel@0
|
19123 sum = group.sum,
|
Daniel@0
|
19124 off = offset==='center' ? (max - sum)/2 : 0,
|
Daniel@0
|
19125 scale = offset==='normalize' ? (1/sum) : 1,
|
Daniel@0
|
19126 j, x, a, b = off, v = 0;
|
Daniel@0
|
19127
|
Daniel@0
|
19128 // set stack coordinates for each datum in group
|
Daniel@0
|
19129 for (j=0; j<group.length; ++j) {
|
Daniel@0
|
19130 x = group[j];
|
Daniel@0
|
19131 a = b; // use previous value for start point
|
Daniel@0
|
19132 v += field(x);
|
Daniel@0
|
19133 b = scale * v + off; // compute end point
|
Daniel@0
|
19134 Tuple.set(x, output.start, a);
|
Daniel@0
|
19135 Tuple.set(x, output.end, b);
|
Daniel@0
|
19136 Tuple.set(x, output.mid, 0.5 * (a + b));
|
Daniel@0
|
19137 }
|
Daniel@0
|
19138 }
|
Daniel@0
|
19139
|
Daniel@0
|
19140 input.fields[output.start] = 1;
|
Daniel@0
|
19141 input.fields[output.end] = 1;
|
Daniel@0
|
19142 input.fields[output.mid] = 1;
|
Daniel@0
|
19143 return input;
|
Daniel@0
|
19144 };
|
Daniel@0
|
19145
|
Daniel@0
|
19146 function partition(data, groupby, sortby, field) {
|
Daniel@0
|
19147 var groups = [],
|
Daniel@0
|
19148 get = function(f) { return f(x); },
|
Daniel@0
|
19149 map, i, x, k, g, s, max;
|
Daniel@0
|
19150
|
Daniel@0
|
19151 // partition data points into stack groups
|
Daniel@0
|
19152 if (groupby == null) {
|
Daniel@0
|
19153 groups.push(data.slice());
|
Daniel@0
|
19154 } else {
|
Daniel@0
|
19155 for (map={}, i=0; i<data.length; ++i) {
|
Daniel@0
|
19156 x = data[i];
|
Daniel@0
|
19157 k = groupby.map(get);
|
Daniel@0
|
19158 g = map[k] || (groups.push(map[k] = []), map[k]);
|
Daniel@0
|
19159 g.push(x);
|
Daniel@0
|
19160 }
|
Daniel@0
|
19161 }
|
Daniel@0
|
19162
|
Daniel@0
|
19163 // compute sums of groups, sort groups as needed
|
Daniel@0
|
19164 for (k=0, max=0; k<groups.length; ++k) {
|
Daniel@0
|
19165 g = groups[k];
|
Daniel@0
|
19166 for (i=0, s=0; i<g.length; ++i) {
|
Daniel@0
|
19167 s += field(g[i]);
|
Daniel@0
|
19168 }
|
Daniel@0
|
19169 g.sum = s;
|
Daniel@0
|
19170 if (s > max) max = s;
|
Daniel@0
|
19171 if (sortby != null) g.sort(sortby);
|
Daniel@0
|
19172 }
|
Daniel@0
|
19173 groups.max = max;
|
Daniel@0
|
19174
|
Daniel@0
|
19175 return groups;
|
Daniel@0
|
19176 }
|
Daniel@0
|
19177
|
Daniel@0
|
19178 module.exports = Stack;
|
Daniel@0
|
19179 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],135:[function(require,module,exports){
|
Daniel@0
|
19180 var df = require('vega-dataflow'),
|
Daniel@0
|
19181 Base = df.Node.prototype, // jshint ignore:line
|
Daniel@0
|
19182 Deps = df.Dependencies,
|
Daniel@0
|
19183 Parameter = require('./Parameter');
|
Daniel@0
|
19184
|
Daniel@0
|
19185 function Transform(graph) {
|
Daniel@0
|
19186 if (graph) Base.init.call(this, graph);
|
Daniel@0
|
19187 }
|
Daniel@0
|
19188
|
Daniel@0
|
19189 Transform.addParameters = function(proto, params) {
|
Daniel@0
|
19190 proto._parameters = proto._parameters || {};
|
Daniel@0
|
19191 for (var name in params) {
|
Daniel@0
|
19192 var p = params[name],
|
Daniel@0
|
19193 param = new Parameter(name, p.type, proto);
|
Daniel@0
|
19194
|
Daniel@0
|
19195 proto._parameters[name] = param;
|
Daniel@0
|
19196
|
Daniel@0
|
19197 if (p.type === 'custom') {
|
Daniel@0
|
19198 if (p.set) param.set = p.set.bind(param);
|
Daniel@0
|
19199 if (p.get) param.get = p.get.bind(param);
|
Daniel@0
|
19200 }
|
Daniel@0
|
19201
|
Daniel@0
|
19202 if (p.hasOwnProperty('default')) param.set(p.default);
|
Daniel@0
|
19203 }
|
Daniel@0
|
19204 };
|
Daniel@0
|
19205
|
Daniel@0
|
19206 var prototype = (Transform.prototype = Object.create(Base));
|
Daniel@0
|
19207 prototype.constructor = Transform;
|
Daniel@0
|
19208
|
Daniel@0
|
19209 prototype.param = function(name, value) {
|
Daniel@0
|
19210 var param = this._parameters[name];
|
Daniel@0
|
19211 return (param === undefined) ? this :
|
Daniel@0
|
19212 (arguments.length === 1) ? param.get() : param.set(value);
|
Daniel@0
|
19213 };
|
Daniel@0
|
19214
|
Daniel@0
|
19215 // Perform transformation. Subclasses should override.
|
Daniel@0
|
19216 prototype.transform = function(input/*, reset */) {
|
Daniel@0
|
19217 return input;
|
Daniel@0
|
19218 };
|
Daniel@0
|
19219
|
Daniel@0
|
19220 prototype.evaluate = function(input) {
|
Daniel@0
|
19221 // Many transforms store caches that must be invalidated if
|
Daniel@0
|
19222 // a signal value has changed.
|
Daniel@0
|
19223 var reset = this._stamp < input.stamp &&
|
Daniel@0
|
19224 this.dependency(Deps.SIGNALS).reduce(function(c, s) {
|
Daniel@0
|
19225 return c += input.signals[s] ? 1 : 0;
|
Daniel@0
|
19226 }, 0);
|
Daniel@0
|
19227 return this.transform(input, reset);
|
Daniel@0
|
19228 };
|
Daniel@0
|
19229
|
Daniel@0
|
19230 prototype.output = function(map) {
|
Daniel@0
|
19231 for (var key in this._output) {
|
Daniel@0
|
19232 if (map[key] !== undefined) {
|
Daniel@0
|
19233 this._output[key] = map[key];
|
Daniel@0
|
19234 }
|
Daniel@0
|
19235 }
|
Daniel@0
|
19236 return this;
|
Daniel@0
|
19237 };
|
Daniel@0
|
19238
|
Daniel@0
|
19239 module.exports = Transform;
|
Daniel@0
|
19240 },{"./Parameter":131,"vega-dataflow":39}],136:[function(require,module,exports){
|
Daniel@0
|
19241 (function (global){
|
Daniel@0
|
19242 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
19243 dl = require('datalib'),
|
Daniel@0
|
19244 Tuple = require('vega-dataflow').Tuple,
|
Daniel@0
|
19245 log = require('vega-logging'),
|
Daniel@0
|
19246 Transform = require('./Transform'),
|
Daniel@0
|
19247 BatchTransform = require('./BatchTransform');
|
Daniel@0
|
19248
|
Daniel@0
|
19249 var defaultRatio = 0.5 * (1 + Math.sqrt(5));
|
Daniel@0
|
19250
|
Daniel@0
|
19251 function Treemap(graph) {
|
Daniel@0
|
19252 BatchTransform.prototype.init.call(this, graph);
|
Daniel@0
|
19253 Transform.addParameters(this, {
|
Daniel@0
|
19254 // hierarchy parameters
|
Daniel@0
|
19255 sort: {type: 'array<field>', default: ['-value']},
|
Daniel@0
|
19256 children: {type: 'field', default: 'children'},
|
Daniel@0
|
19257 field: {type: 'field', default: 'value'},
|
Daniel@0
|
19258 // treemap parameters
|
Daniel@0
|
19259 size: {type: 'array<value>', default: [500, 500]},
|
Daniel@0
|
19260 round: {type: 'value', default: true},
|
Daniel@0
|
19261 sticky: {type: 'value', default: false},
|
Daniel@0
|
19262 ratio: {type: 'value', default: defaultRatio},
|
Daniel@0
|
19263 padding: {type: 'value', default: null},
|
Daniel@0
|
19264 mode: {type: 'value', default: 'squarify'}
|
Daniel@0
|
19265 });
|
Daniel@0
|
19266
|
Daniel@0
|
19267 this._layout = d3.layout.treemap();
|
Daniel@0
|
19268
|
Daniel@0
|
19269 this._output = {
|
Daniel@0
|
19270 'x': 'layout_x',
|
Daniel@0
|
19271 'y': 'layout_y',
|
Daniel@0
|
19272 'width': 'layout_width',
|
Daniel@0
|
19273 'height': 'layout_height',
|
Daniel@0
|
19274 'depth': 'layout_depth',
|
Daniel@0
|
19275 };
|
Daniel@0
|
19276 return this.mutates(true);
|
Daniel@0
|
19277 }
|
Daniel@0
|
19278
|
Daniel@0
|
19279 var prototype = (Treemap.prototype = Object.create(BatchTransform.prototype));
|
Daniel@0
|
19280 prototype.constructor = Treemap;
|
Daniel@0
|
19281
|
Daniel@0
|
19282 prototype.batchTransform = function(input, data) {
|
Daniel@0
|
19283 log.debug(input, ['treemap']);
|
Daniel@0
|
19284
|
Daniel@0
|
19285 // get variables
|
Daniel@0
|
19286 var layout = this._layout,
|
Daniel@0
|
19287 output = this._output;
|
Daniel@0
|
19288
|
Daniel@0
|
19289 // configure layout
|
Daniel@0
|
19290 layout
|
Daniel@0
|
19291 .sort(dl.comparator(this.param('sort').field))
|
Daniel@0
|
19292 .children(this.param('children').accessor)
|
Daniel@0
|
19293 .value(this.param('field').accessor)
|
Daniel@0
|
19294 .size(this.param('size'))
|
Daniel@0
|
19295 .round(this.param('round'))
|
Daniel@0
|
19296 .sticky(this.param('sticky'))
|
Daniel@0
|
19297 .ratio(this.param('ratio'))
|
Daniel@0
|
19298 .padding(this.param('padding'))
|
Daniel@0
|
19299 .mode(this.param('mode'))
|
Daniel@0
|
19300 .nodes(data[0]);
|
Daniel@0
|
19301
|
Daniel@0
|
19302 // copy layout values to nodes
|
Daniel@0
|
19303 data.forEach(function(n) {
|
Daniel@0
|
19304 Tuple.set(n, output.x, n.x);
|
Daniel@0
|
19305 Tuple.set(n, output.y, n.y);
|
Daniel@0
|
19306 Tuple.set(n, output.width, n.dx);
|
Daniel@0
|
19307 Tuple.set(n, output.height, n.dy);
|
Daniel@0
|
19308 Tuple.set(n, output.depth, n.depth);
|
Daniel@0
|
19309 });
|
Daniel@0
|
19310
|
Daniel@0
|
19311 // return changeset
|
Daniel@0
|
19312 input.fields[output.x] = 1;
|
Daniel@0
|
19313 input.fields[output.y] = 1;
|
Daniel@0
|
19314 input.fields[output.width] = 1;
|
Daniel@0
|
19315 input.fields[output.height] = 1;
|
Daniel@0
|
19316 return input;
|
Daniel@0
|
19317 };
|
Daniel@0
|
19318
|
Daniel@0
|
19319 module.exports = Treemap;
|
Daniel@0
|
19320 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
19321
|
Daniel@0
|
19322 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],137:[function(require,module,exports){
|
Daniel@0
|
19323 (function (global){
|
Daniel@0
|
19324 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
19325 Tuple = require('vega-dataflow/src/Tuple'),
|
Daniel@0
|
19326 log = require('vega-logging'),
|
Daniel@0
|
19327 Transform = require('./Transform'),
|
Daniel@0
|
19328 BatchTransform = require('./BatchTransform');
|
Daniel@0
|
19329
|
Daniel@0
|
19330 function Voronoi(graph) {
|
Daniel@0
|
19331 BatchTransform.prototype.init.call(this, graph);
|
Daniel@0
|
19332 Transform.addParameters(this, {
|
Daniel@0
|
19333 clipExtent: {type: 'array<value>', default: [[-1e5,-1e5],[1e5,1e5]]},
|
Daniel@0
|
19334 x: {type: 'field', default: 'layout_x'},
|
Daniel@0
|
19335 y: {type: 'field', default: 'layout_y'}
|
Daniel@0
|
19336 });
|
Daniel@0
|
19337
|
Daniel@0
|
19338 this._layout = d3.geom.voronoi();
|
Daniel@0
|
19339 this._output = {'path': 'layout_path'};
|
Daniel@0
|
19340
|
Daniel@0
|
19341 return this.mutates(true);
|
Daniel@0
|
19342 }
|
Daniel@0
|
19343
|
Daniel@0
|
19344 var prototype = (Voronoi.prototype = Object.create(BatchTransform.prototype));
|
Daniel@0
|
19345 prototype.constructor = Voronoi;
|
Daniel@0
|
19346
|
Daniel@0
|
19347 prototype.batchTransform = function(input, data) {
|
Daniel@0
|
19348 log.debug(input, ['voronoi']);
|
Daniel@0
|
19349
|
Daniel@0
|
19350 // get variables
|
Daniel@0
|
19351 var pathname = this._output.path;
|
Daniel@0
|
19352
|
Daniel@0
|
19353 // configure layout
|
Daniel@0
|
19354 var polygons = this._layout
|
Daniel@0
|
19355 .clipExtent(this.param('clipExtent'))
|
Daniel@0
|
19356 .x(this.param('x').accessor)
|
Daniel@0
|
19357 .y(this.param('y').accessor)
|
Daniel@0
|
19358 (data);
|
Daniel@0
|
19359
|
Daniel@0
|
19360 // build and assign path strings
|
Daniel@0
|
19361 for (var i=0; i<data.length; ++i) {
|
Daniel@0
|
19362 Tuple.set(data[i], pathname, 'M' + polygons[i].join('L') + 'Z');
|
Daniel@0
|
19363 }
|
Daniel@0
|
19364
|
Daniel@0
|
19365 // return changeset
|
Daniel@0
|
19366 input.fields[pathname] = 1;
|
Daniel@0
|
19367 return input;
|
Daniel@0
|
19368 };
|
Daniel@0
|
19369
|
Daniel@0
|
19370 module.exports = Voronoi;
|
Daniel@0
|
19371 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
19372
|
Daniel@0
|
19373 },{"./BatchTransform":117,"./Transform":135,"vega-dataflow/src/Tuple":38,"vega-logging":45}],138:[function(require,module,exports){
|
Daniel@0
|
19374 (function (global){
|
Daniel@0
|
19375 var dl = require('datalib'),
|
Daniel@0
|
19376 d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
|
Daniel@0
|
19377 d3_cloud = (typeof window !== "undefined" ? window['d3']['layout']['cloud'] : typeof global !== "undefined" ? global['d3']['layout']['cloud'] : null),
|
Daniel@0
|
19378 Tuple = require('vega-dataflow/src/Tuple'),
|
Daniel@0
|
19379 log = require('vega-logging'),
|
Daniel@0
|
19380 Transform = require('./Transform'),
|
Daniel@0
|
19381 BatchTransform = require('./BatchTransform');
|
Daniel@0
|
19382
|
Daniel@0
|
19383 function Wordcloud(graph) {
|
Daniel@0
|
19384 BatchTransform.prototype.init.call(this, graph);
|
Daniel@0
|
19385 Transform.addParameters(this, {
|
Daniel@0
|
19386 size: {type: 'array<value>', default: [900, 500]},
|
Daniel@0
|
19387 text: {type: 'field', default: 'data'},
|
Daniel@0
|
19388 rotate: {type: 'field|value', default: 0},
|
Daniel@0
|
19389 font: {type: 'field|value', default: {value: 'sans-serif'}},
|
Daniel@0
|
19390 fontSize: {type: 'field|value', default: 14},
|
Daniel@0
|
19391 fontStyle: {type: 'field|value', default: {value: 'normal'}},
|
Daniel@0
|
19392 fontWeight: {type: 'field|value', default: {value: 'normal'}},
|
Daniel@0
|
19393 fontScale: {type: 'array<value>', default: [10, 50]},
|
Daniel@0
|
19394 padding: {type: 'value', default: 1},
|
Daniel@0
|
19395 spiral: {type: 'value', default: 'archimedean'}
|
Daniel@0
|
19396 });
|
Daniel@0
|
19397
|
Daniel@0
|
19398 this._layout = d3_cloud();
|
Daniel@0
|
19399
|
Daniel@0
|
19400 this._output = {
|
Daniel@0
|
19401 'x': 'layout_x',
|
Daniel@0
|
19402 'y': 'layout_y',
|
Daniel@0
|
19403 'font': 'layout_font',
|
Daniel@0
|
19404 'fontSize': 'layout_fontSize',
|
Daniel@0
|
19405 'fontStyle': 'layout_fontStyle',
|
Daniel@0
|
19406 'fontWeight': 'layout_fontWeight',
|
Daniel@0
|
19407 'rotate': 'layout_rotate',
|
Daniel@0
|
19408 };
|
Daniel@0
|
19409
|
Daniel@0
|
19410 return this.mutates(true);
|
Daniel@0
|
19411 }
|
Daniel@0
|
19412
|
Daniel@0
|
19413 var prototype = (Wordcloud.prototype = Object.create(BatchTransform.prototype));
|
Daniel@0
|
19414 prototype.constructor = Wordcloud;
|
Daniel@0
|
19415
|
Daniel@0
|
19416 function get(p) {
|
Daniel@0
|
19417 return (p && p.accessor) || p;
|
Daniel@0
|
19418 }
|
Daniel@0
|
19419
|
Daniel@0
|
19420 function wrap(tuple) {
|
Daniel@0
|
19421 var x = Object.create(tuple);
|
Daniel@0
|
19422 x._tuple = tuple;
|
Daniel@0
|
19423 return x;
|
Daniel@0
|
19424 }
|
Daniel@0
|
19425
|
Daniel@0
|
19426 prototype.batchTransform = function(input, data) {
|
Daniel@0
|
19427 log.debug(input, ['wordcloud']);
|
Daniel@0
|
19428
|
Daniel@0
|
19429 // get variables
|
Daniel@0
|
19430 var layout = this._layout,
|
Daniel@0
|
19431 output = this._output,
|
Daniel@0
|
19432 fontSize = this.param('fontSize'),
|
Daniel@0
|
19433 range = fontSize.accessor && this.param('fontScale'),
|
Daniel@0
|
19434 size, scale;
|
Daniel@0
|
19435 fontSize = fontSize.accessor || d3.functor(fontSize);
|
Daniel@0
|
19436
|
Daniel@0
|
19437 // create font size scaling function as needed
|
Daniel@0
|
19438 if (range.length) {
|
Daniel@0
|
19439 scale = d3.scale.sqrt()
|
Daniel@0
|
19440 .domain(dl.extent(data, size=fontSize))
|
Daniel@0
|
19441 .range(range);
|
Daniel@0
|
19442 fontSize = function(x) { return scale(size(x)); };
|
Daniel@0
|
19443 }
|
Daniel@0
|
19444
|
Daniel@0
|
19445 // configure layout
|
Daniel@0
|
19446 layout
|
Daniel@0
|
19447 .size(this.param('size'))
|
Daniel@0
|
19448 .text(get(this.param('text')))
|
Daniel@0
|
19449 .padding(this.param('padding'))
|
Daniel@0
|
19450 .spiral(this.param('spiral'))
|
Daniel@0
|
19451 .rotate(get(this.param('rotate')))
|
Daniel@0
|
19452 .font(get(this.param('font')))
|
Daniel@0
|
19453 .fontStyle(get(this.param('fontStyle')))
|
Daniel@0
|
19454 .fontWeight(get(this.param('fontWeight')))
|
Daniel@0
|
19455 .fontSize(fontSize)
|
Daniel@0
|
19456 .words(data.map(wrap)) // wrap to avoid tuple writes
|
Daniel@0
|
19457 .on('end', function(words) {
|
Daniel@0
|
19458 var size = layout.size(),
|
Daniel@0
|
19459 dx = size[0] >> 1,
|
Daniel@0
|
19460 dy = size[1] >> 1,
|
Daniel@0
|
19461 w, t, i, len;
|
Daniel@0
|
19462
|
Daniel@0
|
19463 for (i=0, len=words.length; i<len; ++i) {
|
Daniel@0
|
19464 w = words[i];
|
Daniel@0
|
19465 t = w._tuple;
|
Daniel@0
|
19466 Tuple.set(t, output.x, w.x + dx);
|
Daniel@0
|
19467 Tuple.set(t, output.y, w.y + dy);
|
Daniel@0
|
19468 Tuple.set(t, output.font, w.font);
|
Daniel@0
|
19469 Tuple.set(t, output.fontSize, w.size);
|
Daniel@0
|
19470 Tuple.set(t, output.fontStyle, w.style);
|
Daniel@0
|
19471 Tuple.set(t, output.fontWeight, w.weight);
|
Daniel@0
|
19472 Tuple.set(t, output.rotate, w.rotate);
|
Daniel@0
|
19473 }
|
Daniel@0
|
19474 })
|
Daniel@0
|
19475 .start();
|
Daniel@0
|
19476
|
Daniel@0
|
19477 // return changeset
|
Daniel@0
|
19478 for (var key in output) input.fields[output[key]] = 1;
|
Daniel@0
|
19479 return input;
|
Daniel@0
|
19480 };
|
Daniel@0
|
19481
|
Daniel@0
|
19482 module.exports = Wordcloud;
|
Daniel@0
|
19483 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
Daniel@0
|
19484
|
Daniel@0
|
19485 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow/src/Tuple":38,"vega-logging":45}],139:[function(require,module,exports){
|
Daniel@0
|
19486 module.exports = {
|
Daniel@0
|
19487 aggregate: require('./Aggregate'),
|
Daniel@0
|
19488 bin: require('./Bin'),
|
Daniel@0
|
19489 cross: require('./Cross'),
|
Daniel@0
|
19490 countpattern: require('./CountPattern'),
|
Daniel@0
|
19491 linkpath: require('./LinkPath'),
|
Daniel@0
|
19492 facet: require('./Facet'),
|
Daniel@0
|
19493 filter: require('./Filter'),
|
Daniel@0
|
19494 fold: require('./Fold'),
|
Daniel@0
|
19495 force: require('./Force'),
|
Daniel@0
|
19496 formula: require('./Formula'),
|
Daniel@0
|
19497 geo: require('./Geo'),
|
Daniel@0
|
19498 geopath: require('./GeoPath'),
|
Daniel@0
|
19499 lookup: require('./Lookup'),
|
Daniel@0
|
19500 pie: require('./Pie'),
|
Daniel@0
|
19501 sort: require('./Sort'),
|
Daniel@0
|
19502 stack: require('./Stack'),
|
Daniel@0
|
19503 treemap: require('./Treemap'),
|
Daniel@0
|
19504 voronoi: require('./Voronoi'),
|
Daniel@0
|
19505 wordcloud: require('./Wordcloud')
|
Daniel@0
|
19506 };
|
Daniel@0
|
19507 },{"./Aggregate":116,"./Bin":118,"./CountPattern":119,"./Cross":120,"./Facet":121,"./Filter":123,"./Fold":124,"./Force":125,"./Formula":126,"./Geo":127,"./GeoPath":128,"./LinkPath":129,"./Lookup":130,"./Pie":132,"./Sort":133,"./Stack":134,"./Treemap":136,"./Voronoi":137,"./Wordcloud":138}]},{},[1])(1)
|
Daniel@0
|
19508 });
|
Daniel@0
|
19509 //# sourceMappingURL=vega.js.map
|