comparison src/DML/VendorAssetsBundle/Resources/assets/vega/2.2.6/vega.js @ 0:493bcb69166c

added public content
author Daniel Wolff
date Tue, 09 Feb 2016 20:54:02 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:493bcb69166c
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){
2 module.exports = {
3 version: '2.2.6',
4 dataflow: require('vega-dataflow'),
5 parse: require('./src/parse/'),
6 scene: {
7 Bounder: require('./src/scene/Bounder'),
8 Builder: require('./src/scene/Builder'),
9 Encoder: require('./src/scene/Encoder'),
10 GroupBuilder: require('./src/scene/GroupBuilder'),
11 },
12 transforms: require('./src/transforms'),
13 schema: require('./src/core/schema'),
14 config: require('./src/core/config'),
15 util: require('datalib'),
16 debug: require('vega-logging').debug
17 };
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){
19
20 },{}],3:[function(require,module,exports){
21 (function (global, factory) {
22 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
23 typeof define === 'function' && define.amd ? define(['exports'], factory) :
24 factory((global.dsv = {}));
25 }(this, function (exports) { 'use strict';
26
27 var dsv = function(delimiter) {
28 var reFormat = new RegExp("[\"" + delimiter + "\n]"),
29 delimiterCode = delimiter.charCodeAt(0);
30
31 function parse(text, f) {
32 var o;
33 return parseRows(text, function(row, i) {
34 if (o) return o(row, i - 1);
35 var a = new Function("d", "return {" + row.map(function(name, i) {
36 return JSON.stringify(name) + ": d[" + i + "]";
37 }).join(",") + "}");
38 o = f ? function(row, i) { return f(a(row), i); } : a;
39 });
40 }
41
42 function parseRows(text, f) {
43 var EOL = {}, // sentinel value for end-of-line
44 EOF = {}, // sentinel value for end-of-file
45 rows = [], // output rows
46 N = text.length,
47 I = 0, // current character index
48 n = 0, // the current line number
49 t, // the current token
50 eol; // is the current token followed by EOL?
51
52 function token() {
53 if (I >= N) return EOF; // special case: end of file
54 if (eol) return eol = false, EOL; // special case: end of line
55
56 // special case: quotes
57 var j = I;
58 if (text.charCodeAt(j) === 34) {
59 var i = j;
60 while (i++ < N) {
61 if (text.charCodeAt(i) === 34) {
62 if (text.charCodeAt(i + 1) !== 34) break;
63 ++i;
64 }
65 }
66 I = i + 2;
67 var c = text.charCodeAt(i + 1);
68 if (c === 13) {
69 eol = true;
70 if (text.charCodeAt(i + 2) === 10) ++I;
71 } else if (c === 10) {
72 eol = true;
73 }
74 return text.slice(j + 1, i).replace(/""/g, "\"");
75 }
76
77 // common case: find next delimiter or newline
78 while (I < N) {
79 var c = text.charCodeAt(I++), k = 1;
80 if (c === 10) eol = true; // \n
81 else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
82 else if (c !== delimiterCode) continue;
83 return text.slice(j, I - k);
84 }
85
86 // special case: last token before EOF
87 return text.slice(j);
88 }
89
90 while ((t = token()) !== EOF) {
91 var a = [];
92 while (t !== EOL && t !== EOF) {
93 a.push(t);
94 t = token();
95 }
96 if (f && (a = f(a, n++)) == null) continue;
97 rows.push(a);
98 }
99
100 return rows;
101 }
102
103 function format(rows) {
104 if (Array.isArray(rows[0])) return formatRows(rows); // deprecated; use formatRows
105 var fieldSet = Object.create(null), fields = [];
106
107 // Compute unique fields in order of discovery.
108 rows.forEach(function(row) {
109 for (var field in row) {
110 if (!((field += "") in fieldSet)) {
111 fields.push(fieldSet[field] = field);
112 }
113 }
114 });
115
116 return [fields.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
117 return fields.map(function(field) {
118 return formatValue(row[field]);
119 }).join(delimiter);
120 })).join("\n");
121 }
122
123 function formatRows(rows) {
124 return rows.map(formatRow).join("\n");
125 }
126
127 function formatRow(row) {
128 return row.map(formatValue).join(delimiter);
129 }
130
131 function formatValue(text) {
132 return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text;
133 }
134
135 return {
136 parse: parse,
137 parseRows: parseRows,
138 format: format,
139 formatRows: formatRows
140 };
141 }
142
143 exports.csv = dsv(",");
144 exports.tsv = dsv("\t");
145
146 exports.dsv = dsv;
147
148 }));
149 },{}],4:[function(require,module,exports){
150 if (typeof Map === "undefined") {
151 Map = function() { this.clear(); };
152 Map.prototype = {
153 set: function(k, v) { this._[k] = v; return this; },
154 get: function(k) { return this._[k]; },
155 has: function(k) { return k in this._; },
156 delete: function(k) { return k in this._ && delete this._[k]; },
157 clear: function() { this._ = Object.create(null); },
158 get size() { var n = 0; for (var k in this._) ++n; return n; },
159 forEach: function(c) { for (var k in this._) c(this._[k], k, this); }
160 };
161 } else (function() {
162 var m = new Map;
163 if (m.set(0, 0) !== m) {
164 m = m.set;
165 Map.prototype.set = function() { m.apply(this, arguments); return this; };
166 }
167 })();
168
169 (function (global, factory) {
170 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
171 typeof define === 'function' && define.amd ? define(['exports'], factory) :
172 factory((global.format = {}));
173 }(this, function (exports) { 'use strict';
174
175 var zhCn = {
176 decimal: ".",
177 thousands: ",",
178 grouping: [3],
179 currency: ["¥", ""]
180 };
181
182 var ruRu = {
183 decimal: ",",
184 thousands: "\xa0",
185 grouping: [3],
186 currency: ["", "\xa0руб."]
187 };
188
189 var ptBr = {
190 decimal: ",",
191 thousands: ".",
192 grouping: [3],
193 currency: ["R$", ""]
194 };
195
196 var plPl = {
197 decimal: ",",
198 thousands: ".",
199 grouping: [3],
200 currency: ["", "zł"]
201 };
202
203 var nlNl = {
204 decimal: ",",
205 thousands: ".",
206 grouping: [3],
207 currency: ["€\xa0", ""]
208 };
209
210 var mkMk = {
211 decimal: ",",
212 thousands: ".",
213 grouping: [3],
214 currency: ["", "\xa0ден."]
215 };
216
217 var jaJp = {
218 decimal: ".",
219 thousands: ",",
220 grouping: [3],
221 currency: ["", "円"]
222 };
223
224 var itIt = {
225 decimal: ",",
226 thousands: ".",
227 grouping: [3],
228 currency: ["€", ""]
229 };
230
231 var heIl = {
232 decimal: ".",
233 thousands: ",",
234 grouping: [3],
235 currency: ["₪", ""]
236 };
237
238 var frFr = {
239 decimal: ",",
240 thousands: ".",
241 grouping: [3],
242 currency: ["", "\xa0€"]
243 };
244
245 var frCa = {
246 decimal: ",",
247 thousands: "\xa0",
248 grouping: [3],
249 currency: ["", "$"]
250 };
251
252 var fiFi = {
253 decimal: ",",
254 thousands: "\xa0",
255 grouping: [3],
256 currency: ["", "\xa0€"]
257 };
258
259 var esEs = {
260 decimal: ",",
261 thousands: ".",
262 grouping: [3],
263 currency: ["", "\xa0€"]
264 };
265
266 var enUs = {
267 decimal: ".",
268 thousands: ",",
269 grouping: [3],
270 currency: ["$", ""]
271 };
272
273 var enGb = {
274 decimal: ".",
275 thousands: ",",
276 grouping: [3],
277 currency: ["£", ""]
278 };
279
280 var enCa = {
281 decimal: ".",
282 thousands: ",",
283 grouping: [3],
284 currency: ["$", ""]
285 };
286
287 var deDe = {
288 decimal: ",",
289 thousands: ".",
290 grouping: [3],
291 currency: ["", "\xa0€"]
292 };
293
294 var caEs = {
295 decimal: ",",
296 thousands: ".",
297 grouping: [3],
298 currency: ["", "\xa0€"]
299 };
300
301
302 // Computes the decimal coefficient and exponent of the specified number x with
303 // significant digits p, where x is positive and p is in [1, 21] or undefined.
304 // For example, formatDecimal(1.23) returns ["123", 0].
305 function formatDecimal(x, p) {
306 if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
307 var i, coefficient = x.slice(0, i);
308
309 // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
310 // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
311 return [
312 coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
313 +x.slice(i + 1)
314 ];
315 }
316
317 function exponent(x) {
318 return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
319 }
320
321 var prefixExponent;
322
323 function formatPrefixAuto(x, p) {
324 var d = formatDecimal(x, p);
325 if (!d) return x + "";
326 var coefficient = d[0],
327 exponent = d[1],
328 i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
329 n = coefficient.length;
330 return i === n ? coefficient
331 : i > n ? coefficient + new Array(i - n + 1).join("0")
332 : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
333 : "0." + new Array(1 - i).join("0") + formatDecimal(x, p + i - 1)[0]; // less than 1y!
334 }
335
336 function formatRounded(x, p) {
337 var d = formatDecimal(x, p);
338 if (!d) return x + "";
339 var coefficient = d[0],
340 exponent = d[1];
341 return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
342 : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
343 : coefficient + new Array(exponent - coefficient.length + 2).join("0");
344 }
345
346 function formatDefault(x, p) {
347 x = x.toPrecision(p);
348
349 out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
350 switch (x[i]) {
351 case ".": i0 = i1 = i; break;
352 case "0": if (i0 === 0) i0 = i; i1 = i; break;
353 case "e": break out;
354 default: if (i0 > 0) i0 = 0; break;
355 }
356 }
357
358 return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
359 }
360
361 var formatTypes = {
362 "": formatDefault,
363 "%": function(x, p) { return (x * 100).toFixed(p); },
364 "b": function(x) { return Math.round(x).toString(2); },
365 "c": function(x) { return x + ""; },
366 "d": function(x) { return Math.round(x).toString(10); },
367 "e": function(x, p) { return x.toExponential(p); },
368 "f": function(x, p) { return x.toFixed(p); },
369 "g": function(x, p) { return x.toPrecision(p); },
370 "o": function(x) { return Math.round(x).toString(8); },
371 "p": function(x, p) { return formatRounded(x * 100, p); },
372 "r": formatRounded,
373 "s": formatPrefixAuto,
374 "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
375 "x": function(x) { return Math.round(x).toString(16); }
376 };
377
378
379 // [[fill]align][sign][symbol][0][width][,][.precision][type]
380 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
381
382 function formatSpecifier(specifier) {
383 return new FormatSpecifier(specifier);
384 }
385
386 function FormatSpecifier(specifier) {
387 if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
388
389 var match,
390 fill = match[1] || " ",
391 align = match[2] || ">",
392 sign = match[3] || "-",
393 symbol = match[4] || "",
394 zero = !!match[5],
395 width = match[6] && +match[6],
396 comma = !!match[7],
397 precision = match[8] && +match[8].slice(1),
398 type = match[9] || "";
399
400 // The "n" type is an alias for ",g".
401 if (type === "n") comma = true, type = "g";
402
403 // Map invalid types to the default format.
404 else if (!formatTypes[type]) type = "";
405
406 // If zero fill is specified, padding goes after sign and before digits.
407 if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
408
409 this.fill = fill;
410 this.align = align;
411 this.sign = sign;
412 this.symbol = symbol;
413 this.zero = zero;
414 this.width = width;
415 this.comma = comma;
416 this.precision = precision;
417 this.type = type;
418 }
419
420 FormatSpecifier.prototype.toString = function() {
421 return this.fill
422 + this.align
423 + this.sign
424 + this.symbol
425 + (this.zero ? "0" : "")
426 + (this.width == null ? "" : Math.max(1, this.width | 0))
427 + (this.comma ? "," : "")
428 + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
429 + this.type;
430 };
431
432 function formatGroup(grouping, thousands) {
433 return function(value, width) {
434 var i = value.length,
435 t = [],
436 j = 0,
437 g = grouping[0],
438 length = 0;
439
440 while (i > 0 && g > 0) {
441 if (length + g + 1 > width) g = Math.max(1, width - length);
442 t.push(value.substring(i -= g, i + g));
443 if ((length += g + 1) > width) break;
444 g = grouping[j = (j + 1) % grouping.length];
445 }
446
447 return t.reverse().join(thousands);
448 };
449 }
450
451 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
452
453 function identity(x) {
454 return x;
455 }
456
457 function locale(locale) {
458 var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity,
459 currency = locale.currency,
460 decimal = locale.decimal;
461
462 function format(specifier) {
463 specifier = formatSpecifier(specifier);
464
465 var fill = specifier.fill,
466 align = specifier.align,
467 sign = specifier.sign,
468 symbol = specifier.symbol,
469 zero = specifier.zero,
470 width = specifier.width,
471 comma = specifier.comma,
472 precision = specifier.precision,
473 type = specifier.type;
474
475 // Compute the prefix and suffix.
476 // For SI-prefix, the suffix is lazily computed.
477 var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
478 suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
479
480 // What format function should we use?
481 // Is this an integer type?
482 // Can this type generate exponential notation?
483 var formatType = formatTypes[type],
484 maybeSuffix = !type || /[defgprs%]/.test(type);
485
486 // Set the default precision if not specified,
487 // or clamp the specified precision to the supported range.
488 // For significant precision, it must be in [1, 21].
489 // For fixed precision, it must be in [0, 20].
490 precision = precision == null ? (type ? 6 : 12)
491 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
492 : Math.max(0, Math.min(20, precision));
493
494 return function(value) {
495 var valuePrefix = prefix,
496 valueSuffix = suffix;
497
498 if (type === "c") {
499 valueSuffix = formatType(value) + valueSuffix;
500 value = "";
501 } else {
502 value = +value;
503
504 // Convert negative to positive, and compute the prefix.
505 // Note that -0 is not less than 0, but 1 / -0 is!
506 var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
507
508 // Perform the initial formatting.
509 value = formatType(value, precision);
510
511 // Compute the prefix and suffix.
512 valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
513 valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
514
515 // Break the formatted value into the integer “value” part that can be
516 // grouped, and fractional or exponential “suffix” part that is not.
517 if (maybeSuffix) {
518 var i = -1, n = value.length, c;
519 while (++i < n) {
520 if (c = value.charCodeAt(i), 48 > c || c > 57) {
521 valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
522 value = value.slice(0, i);
523 break;
524 }
525 }
526 }
527 }
528
529 // If the fill character is not "0", grouping is applied before padding.
530 if (comma && !zero) value = group(value, Infinity);
531
532 // Compute the padding.
533 var length = valuePrefix.length + value.length + valueSuffix.length,
534 padding = length < width ? new Array(width - length + 1).join(fill) : "";
535
536 // If the fill character is "0", grouping is applied after padding.
537 if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
538
539 // Reconstruct the final output based on the desired alignment.
540 switch (align) {
541 case "<": return valuePrefix + value + valueSuffix + padding;
542 case "=": return valuePrefix + padding + value + valueSuffix;
543 case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
544 }
545 return padding + valuePrefix + value + valueSuffix;
546 };
547 }
548
549 function formatPrefix(specifier, value) {
550 var f = format((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
551 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
552 k = Math.pow(10, -e),
553 prefix = prefixes[8 + e / 3];
554 return function(value) {
555 return f(k * value) + prefix;
556 };
557 }
558
559 return {
560 format: format,
561 formatPrefix: formatPrefix
562 };
563 }
564
565 function precisionRound(step, max) {
566 return Math.max(0, exponent(Math.abs(max)) - exponent(Math.abs(step))) + 1;
567 }
568
569 function precisionPrefix(step, value) {
570 return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
571 }
572
573 function precisionFixed(step) {
574 return Math.max(0, -exponent(Math.abs(step)));
575 }
576
577 var localeDefinitions = (new Map)
578 .set("ca-ES", caEs)
579 .set("de-DE", deDe)
580 .set("en-CA", enCa)
581 .set("en-GB", enGb)
582 .set("en-US", enUs)
583 .set("es-ES", esEs)
584 .set("fi-FI", fiFi)
585 .set("fr-CA", frCa)
586 .set("fr-FR", frFr)
587 .set("he-IL", heIl)
588 .set("it-IT", itIt)
589 .set("ja-JP", jaJp)
590 .set("mk-MK", mkMk)
591 .set("nl-NL", nlNl)
592 .set("pl-PL", plPl)
593 .set("pt-BR", ptBr)
594 .set("ru-RU", ruRu)
595 .set("zh-CN", zhCn);
596
597 var defaultLocale = locale(enUs);
598 exports.format = defaultLocale.format;
599 exports.formatPrefix = defaultLocale.formatPrefix;
600
601 function localeFormat(definition) {
602 if (typeof definition === "string") {
603 definition = localeDefinitions.get(definition);
604 if (!definition) return null;
605 }
606 return locale(definition);
607 }
608 ;
609
610 exports.localeFormat = localeFormat;
611 exports.formatSpecifier = formatSpecifier;
612 exports.precisionFixed = precisionFixed;
613 exports.precisionPrefix = precisionPrefix;
614 exports.precisionRound = precisionRound;
615
616 }));
617 },{}],5:[function(require,module,exports){
618 if (typeof Map === "undefined") {
619 Map = function() { this.clear(); };
620 Map.prototype = {
621 set: function(k, v) { this._[k] = v; return this; },
622 get: function(k) { return this._[k]; },
623 has: function(k) { return k in this._; },
624 delete: function(k) { return k in this._ && delete this._[k]; },
625 clear: function() { this._ = Object.create(null); },
626 get size() { var n = 0; for (var k in this._) ++n; return n; },
627 forEach: function(c) { for (var k in this._) c(this._[k], k, this); }
628 };
629 } else (function() {
630 var m = new Map;
631 if (m.set(0, 0) !== m) {
632 m = m.set;
633 Map.prototype.set = function() { m.apply(this, arguments); return this; };
634 }
635 })();
636
637 (function (global, factory) {
638 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
639 typeof define === 'function' && define.amd ? define(['exports'], factory) :
640 factory((global.timeFormat = {}));
641 }(this, function (exports) { 'use strict';
642
643 var zhCn = {
644 dateTime: "%a %b %e %X %Y",
645 date: "%Y/%-m/%-d",
646 time: "%H:%M:%S",
647 periods: ["上午", "下午"],
648 days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
649 shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
650 months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
651 shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
652 };
653
654 var ruRu = {
655 dateTime: "%A, %e %B %Y г. %X",
656 date: "%d.%m.%Y",
657 time: "%H:%M:%S",
658 periods: ["AM", "PM"],
659 days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
660 shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
661 months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
662 shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
663 };
664
665 var ptBr = {
666 dateTime: "%A, %e de %B de %Y. %X",
667 date: "%d/%m/%Y",
668 time: "%H:%M:%S",
669 periods: ["AM", "PM"],
670 days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
671 shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
672 months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
673 shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
674 };
675
676 var plPl = {
677 dateTime: "%A, %e %B %Y, %X",
678 date: "%d/%m/%Y",
679 time: "%H:%M:%S",
680 periods: ["AM", "PM"], // unused
681 days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
682 shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."],
683 months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
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. */
685 };
686
687 var nlNl = {
688 dateTime: "%a %e %B %Y %T",
689 date: "%d-%m-%Y",
690 time: "%H:%M:%S",
691 periods: ["AM", "PM"], // unused
692 days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"],
693 shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"],
694 months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"],
695 shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"]
696 };
697
698 var mkMk = {
699 dateTime: "%A, %e %B %Y г. %X",
700 date: "%d.%m.%Y",
701 time: "%H:%M:%S",
702 periods: ["AM", "PM"],
703 days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"],
704 shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"],
705 months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"],
706 shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"]
707 };
708
709 var jaJp = {
710 dateTime: "%Y %b %e %a %X",
711 date: "%Y/%m/%d",
712 time: "%H:%M:%S",
713 periods: ["AM", "PM"],
714 days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
715 shortDays: ["日", "月", "火", "水", "木", "金", "土"],
716 months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"],
717 shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
718 };
719
720 var itIt = {
721 dateTime: "%A %e %B %Y, %X",
722 date: "%d/%m/%Y",
723 time: "%H:%M:%S",
724 periods: ["AM", "PM"], // unused
725 days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
726 shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
727 months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
728 shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"]
729 };
730
731 var heIl = {
732 dateTime: "%A, %e ב%B %Y %X",
733 date: "%d.%m.%Y",
734 time: "%H:%M:%S",
735 periods: ["AM", "PM"],
736 days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"],
737 shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"],
738 months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
739 shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"]
740 };
741
742 var frFr = {
743 dateTime: "%A, le %e %B %Y, %X",
744 date: "%d/%m/%Y",
745 time: "%H:%M:%S",
746 periods: ["AM", "PM"], // unused
747 days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
748 shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
749 months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
750 shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
751 };
752
753 var frCa = {
754 dateTime: "%a %e %b %Y %X",
755 date: "%Y-%m-%d",
756 time: "%H:%M:%S",
757 periods: ["", ""],
758 days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
759 shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"],
760 months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
761 shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"]
762 };
763
764 var fiFi = {
765 dateTime: "%A, %-d. %Bta %Y klo %X",
766 date: "%-d.%-m.%Y",
767 time: "%H:%M:%S",
768 periods: ["a.m.", "p.m."],
769 days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
770 shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"],
771 months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"],
772 shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"]
773 };
774
775 var esEs = {
776 dateTime: "%A, %e de %B de %Y, %X",
777 date: "%d/%m/%Y",
778 time: "%H:%M:%S",
779 periods: ["AM", "PM"],
780 days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
781 shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
782 months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
783 shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
784 };
785
786 var enUs = {
787 dateTime: "%a %b %e %X %Y",
788 date: "%m/%d/%Y",
789 time: "%H:%M:%S",
790 periods: ["AM", "PM"],
791 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
792 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
793 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
794 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
795 };
796
797 var enGb = {
798 dateTime: "%a %e %b %X %Y",
799 date: "%d/%m/%Y",
800 time: "%H:%M:%S",
801 periods: ["AM", "PM"],
802 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
803 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
804 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
805 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
806 };
807
808 var enCa = {
809 dateTime: "%a %b %e %X %Y",
810 date: "%Y-%m-%d",
811 time: "%H:%M:%S",
812 periods: ["AM", "PM"],
813 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
814 shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
815 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
816 shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
817 };
818
819 var deDe = {
820 dateTime: "%A, der %e. %B %Y, %X",
821 date: "%d.%m.%Y",
822 time: "%H:%M:%S",
823 periods: ["AM", "PM"], // unused
824 days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
825 shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
826 months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
827 shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
828 };
829
830 var caEs = {
831 dateTime: "%A, %e de %B de %Y, %X",
832 date: "%d/%m/%Y",
833 time: "%H:%M:%S",
834 periods: ["AM", "PM"],
835 days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
836 shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."],
837 months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
838 shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."]
839 };
840
841 var t0 = new Date;
842 var t1 = new Date;
843
844 function newInterval(floori, offseti, count) {
845
846 function interval(date) {
847 return floori(date = new Date(+date)), date;
848 }
849
850 interval.floor = interval;
851
852 interval.round = function(date) {
853 var d0 = new Date(+date),
854 d1 = new Date(date - 1);
855 floori(d0), floori(d1), offseti(d1, 1);
856 return date - d0 < d1 - date ? d0 : d1;
857 };
858
859 interval.ceil = function(date) {
860 return floori(date = new Date(date - 1)), offseti(date, 1), date;
861 };
862
863 interval.offset = function(date, step) {
864 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
865 };
866
867 interval.range = function(start, stop, step) {
868 var range = [];
869 start = new Date(start - 1);
870 stop = new Date(+stop);
871 step = step == null ? 1 : Math.floor(step);
872 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
873 offseti(start, 1), floori(start);
874 if (start < stop) range.push(new Date(+start));
875 while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));
876 return range;
877 };
878
879 interval.filter = function(test) {
880 return newInterval(function(date) {
881 while (floori(date), !test(date)) date.setTime(date - 1);
882 }, function(date, step) {
883 while (--step >= 0) while (offseti(date, 1), !test(date));
884 });
885 };
886
887 if (count) interval.count = function(start, end) {
888 t0.setTime(+start), t1.setTime(+end);
889 floori(t0), floori(t1);
890 return Math.floor(count(t0, t1));
891 };
892
893 return interval;
894 }
895
896 var day = newInterval(function(date) {
897 date.setHours(0, 0, 0, 0);
898 }, function(date, step) {
899 date.setDate(date.getDate() + step);
900 }, function(start, end) {
901 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;
902 });
903
904 function weekday(i) {
905 return newInterval(function(date) {
906 date.setHours(0, 0, 0, 0);
907 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
908 }, function(date, step) {
909 date.setDate(date.getDate() + step * 7);
910 }, function(start, end) {
911 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;
912 });
913 }
914
915 var sunday = weekday(0);
916 var monday = weekday(1);
917
918 var year = newInterval(function(date) {
919 date.setHours(0, 0, 0, 0);
920 date.setMonth(0, 1);
921 }, function(date, step) {
922 date.setFullYear(date.getFullYear() + step);
923 }, function(start, end) {
924 return end.getFullYear() - start.getFullYear();
925 });
926
927 var utcDay = newInterval(function(date) {
928 date.setUTCHours(0, 0, 0, 0);
929 }, function(date, step) {
930 date.setUTCDate(date.getUTCDate() + step);
931 }, function(start, end) {
932 return (end - start) / 864e5;
933 });
934
935 function utcWeekday(i) {
936 return newInterval(function(date) {
937 date.setUTCHours(0, 0, 0, 0);
938 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
939 }, function(date, step) {
940 date.setUTCDate(date.getUTCDate() + step * 7);
941 }, function(start, end) {
942 return (end - start) / 6048e5;
943 });
944 }
945
946 var utcSunday = utcWeekday(0);
947 var utcMonday = utcWeekday(1);
948
949 var utcYear = newInterval(function(date) {
950 date.setUTCHours(0, 0, 0, 0);
951 date.setUTCMonth(0, 1);
952 }, function(date, step) {
953 date.setUTCFullYear(date.getUTCFullYear() + step);
954 }, function(start, end) {
955 return end.getUTCFullYear() - start.getUTCFullYear();
956 });
957
958 function localDate(d) {
959 if (0 <= d.y && d.y < 100) {
960 var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
961 date.setFullYear(d.y);
962 return date;
963 }
964 return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
965 }
966
967 function utcDate(d) {
968 if (0 <= d.y && d.y < 100) {
969 var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
970 date.setUTCFullYear(d.y);
971 return date;
972 }
973 return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
974 }
975
976 function newYear(y) {
977 return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
978 }
979
980 function locale(locale) {
981 var locale_dateTime = locale.dateTime,
982 locale_date = locale.date,
983 locale_time = locale.time,
984 locale_periods = locale.periods,
985 locale_weekdays = locale.days,
986 locale_shortWeekdays = locale.shortDays,
987 locale_months = locale.months,
988 locale_shortMonths = locale.shortMonths;
989
990 var periodLookup = formatLookup(locale_periods),
991 weekdayRe = formatRe(locale_weekdays),
992 weekdayLookup = formatLookup(locale_weekdays),
993 shortWeekdayRe = formatRe(locale_shortWeekdays),
994 shortWeekdayLookup = formatLookup(locale_shortWeekdays),
995 monthRe = formatRe(locale_months),
996 monthLookup = formatLookup(locale_months),
997 shortMonthRe = formatRe(locale_shortMonths),
998 shortMonthLookup = formatLookup(locale_shortMonths);
999
1000 var formats = {
1001 "a": formatShortWeekday,
1002 "A": formatWeekday,
1003 "b": formatShortMonth,
1004 "B": formatMonth,
1005 "c": null,
1006 "d": formatDayOfMonth,
1007 "e": formatDayOfMonth,
1008 "H": formatHour24,
1009 "I": formatHour12,
1010 "j": formatDayOfYear,
1011 "L": formatMilliseconds,
1012 "m": formatMonthNumber,
1013 "M": formatMinutes,
1014 "p": formatPeriod,
1015 "S": formatSeconds,
1016 "U": formatWeekNumberSunday,
1017 "w": formatWeekdayNumber,
1018 "W": formatWeekNumberMonday,
1019 "x": null,
1020 "X": null,
1021 "y": formatYear,
1022 "Y": formatFullYear,
1023 "Z": formatZone,
1024 "%": formatLiteralPercent
1025 };
1026
1027 var utcFormats = {
1028 "a": formatUTCShortWeekday,
1029 "A": formatUTCWeekday,
1030 "b": formatUTCShortMonth,
1031 "B": formatUTCMonth,
1032 "c": null,
1033 "d": formatUTCDayOfMonth,
1034 "e": formatUTCDayOfMonth,
1035 "H": formatUTCHour24,
1036 "I": formatUTCHour12,
1037 "j": formatUTCDayOfYear,
1038 "L": formatUTCMilliseconds,
1039 "m": formatUTCMonthNumber,
1040 "M": formatUTCMinutes,
1041 "p": formatUTCPeriod,
1042 "S": formatUTCSeconds,
1043 "U": formatUTCWeekNumberSunday,
1044 "w": formatUTCWeekdayNumber,
1045 "W": formatUTCWeekNumberMonday,
1046 "x": null,
1047 "X": null,
1048 "y": formatUTCYear,
1049 "Y": formatUTCFullYear,
1050 "Z": formatUTCZone,
1051 "%": formatLiteralPercent
1052 };
1053
1054 var parses = {
1055 "a": parseShortWeekday,
1056 "A": parseWeekday,
1057 "b": parseShortMonth,
1058 "B": parseMonth,
1059 "c": parseLocaleDateTime,
1060 "d": parseDayOfMonth,
1061 "e": parseDayOfMonth,
1062 "H": parseHour24,
1063 "I": parseHour24,
1064 "j": parseDayOfYear,
1065 "L": parseMilliseconds,
1066 "m": parseMonthNumber,
1067 "M": parseMinutes,
1068 "p": parsePeriod,
1069 "S": parseSeconds,
1070 "U": parseWeekNumberSunday,
1071 "w": parseWeekdayNumber,
1072 "W": parseWeekNumberMonday,
1073 "x": parseLocaleDate,
1074 "X": parseLocaleTime,
1075 "y": parseYear,
1076 "Y": parseFullYear,
1077 "Z": parseZone,
1078 "%": parseLiteralPercent
1079 };
1080
1081 // These recursive directive definitions must be deferred.
1082 formats.x = newFormat(locale_date, formats);
1083 formats.X = newFormat(locale_time, formats);
1084 formats.c = newFormat(locale_dateTime, formats);
1085 utcFormats.x = newFormat(locale_date, utcFormats);
1086 utcFormats.X = newFormat(locale_time, utcFormats);
1087 utcFormats.c = newFormat(locale_dateTime, utcFormats);
1088
1089 function newFormat(specifier, formats) {
1090 return function(date) {
1091 var string = [],
1092 i = -1,
1093 j = 0,
1094 n = specifier.length,
1095 c,
1096 pad,
1097 format;
1098
1099 while (++i < n) {
1100 if (specifier.charCodeAt(i) === 37) {
1101 string.push(specifier.slice(j, i));
1102 if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
1103 if (format = formats[c]) c = format(date, pad == null ? (c === "e" ? " " : "0") : pad);
1104 string.push(c);
1105 j = i + 1;
1106 }
1107 }
1108
1109 string.push(specifier.slice(j, i));
1110 return string.join("");
1111 };
1112 }
1113
1114 function newParse(specifier, newDate) {
1115 return function(string) {
1116 var d = newYear(1900),
1117 i = parseSpecifier(d, specifier, string, 0);
1118 if (i != string.length) return null;
1119
1120 // The am-pm flag is 0 for AM, and 1 for PM.
1121 if ("p" in d) d.H = d.H % 12 + d.p * 12;
1122
1123 // If a time zone is specified, all fields are interpreted as UTC and then
1124 // offset according to the specified time zone.
1125 if ("Z" in d) {
1126 if ("w" in d && ("W" in d || "U" in d)) {
1127 var day = utcDate(newYear(d.y)).getUTCDay();
1128 if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day;
1129 d.m = 0;
1130 d.d = d.w + d.U * 7 - (day + 6) % 7;
1131 }
1132 d.H += d.Z / 100 | 0;
1133 d.M += d.Z % 100;
1134 return utcDate(d);
1135 }
1136
1137 // Otherwise, all fields are in local time.
1138 if ("w" in d && ("W" in d || "U" in d)) {
1139 var day = newDate(newYear(d.y)).getDay();
1140 if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day;
1141 d.m = 0;
1142 d.d = d.w + d.U * 7 - (day + 6) % 7;
1143 }
1144 return newDate(d);
1145 };
1146 }
1147
1148 function parseSpecifier(d, specifier, string, j) {
1149 var i = 0,
1150 n = specifier.length,
1151 m = string.length,
1152 c,
1153 parse;
1154
1155 while (i < n) {
1156 if (j >= m) return -1;
1157 c = specifier.charCodeAt(i++);
1158 if (c === 37) {
1159 c = specifier.charAt(i++);
1160 parse = parses[c in pads ? specifier.charAt(i++) : c];
1161 if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
1162 } else if (c != string.charCodeAt(j++)) {
1163 return -1;
1164 }
1165 }
1166
1167 return j;
1168 }
1169
1170 function parseShortWeekday(d, string, i) {
1171 var n = shortWeekdayRe.exec(string.slice(i));
1172 return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
1173 }
1174
1175 function parseWeekday(d, string, i) {
1176 var n = weekdayRe.exec(string.slice(i));
1177 return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
1178 }
1179
1180 function parseShortMonth(d, string, i) {
1181 var n = shortMonthRe.exec(string.slice(i));
1182 return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
1183 }
1184
1185 function parseMonth(d, string, i) {
1186 var n = monthRe.exec(string.slice(i));
1187 return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
1188 }
1189
1190 function parseLocaleDateTime(d, string, i) {
1191 return parseSpecifier(d, locale_dateTime, string, i);
1192 }
1193
1194 function parseLocaleDate(d, string, i) {
1195 return parseSpecifier(d, locale_date, string, i);
1196 }
1197
1198 function parseLocaleTime(d, string, i) {
1199 return parseSpecifier(d, locale_time, string, i);
1200 }
1201
1202 function parsePeriod(d, string, i) {
1203 var n = periodLookup.get(string.slice(i, i += 2).toLowerCase());
1204 return n == null ? -1 : (d.p = n, i);
1205 }
1206
1207 function formatShortWeekday(d) {
1208 return locale_shortWeekdays[d.getDay()];
1209 }
1210
1211 function formatWeekday(d) {
1212 return locale_weekdays[d.getDay()];
1213 }
1214
1215 function formatShortMonth(d) {
1216 return locale_shortMonths[d.getMonth()];
1217 }
1218
1219 function formatMonth(d) {
1220 return locale_months[d.getMonth()];
1221 }
1222
1223 function formatPeriod(d) {
1224 return locale_periods[+(d.getHours() >= 12)];
1225 }
1226
1227 function formatUTCShortWeekday(d) {
1228 return locale_shortWeekdays[d.getUTCDay()];
1229 }
1230
1231 function formatUTCWeekday(d) {
1232 return locale_weekdays[d.getUTCDay()];
1233 }
1234
1235 function formatUTCShortMonth(d) {
1236 return locale_shortMonths[d.getUTCMonth()];
1237 }
1238
1239 function formatUTCMonth(d) {
1240 return locale_months[d.getUTCMonth()];
1241 }
1242
1243 function formatUTCPeriod(d) {
1244 return locale_periods[+(d.getUTCHours() >= 12)];
1245 }
1246
1247 return {
1248 format: function(specifier) {
1249 var f = newFormat(specifier += "", formats);
1250 f.parse = newParse(specifier, localDate);
1251 f.toString = function() { return specifier; };
1252 return f;
1253 },
1254 utcFormat: function(specifier) {
1255 var f = newFormat(specifier += "", utcFormats);
1256 f.parse = newParse(specifier, utcDate);
1257 f.toString = function() { return specifier; };
1258 return f;
1259 }
1260 };
1261 }
1262
1263 var pads = {"-": "", "_": " ", "0": "0"};
1264 var numberRe = /^\s*\d+/;
1265 var percentRe = /^%/;
1266 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
1267
1268 function pad(value, fill, width) {
1269 var sign = value < 0 ? "-" : "",
1270 string = (sign ? -value : value) + "",
1271 length = string.length;
1272 return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
1273 }
1274
1275 function requote(s) {
1276 return s.replace(requoteRe, "\\$&");
1277 }
1278
1279 function formatRe(names) {
1280 return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
1281 }
1282
1283 function formatLookup(names) {
1284 var map = new Map, i = -1, n = names.length;
1285 while (++i < n) map.set(names[i].toLowerCase(), i);
1286 return map;
1287 }
1288
1289 function parseWeekdayNumber(d, string, i) {
1290 var n = numberRe.exec(string.slice(i, i + 1));
1291 return n ? (d.w = +n[0], i + n[0].length) : -1;
1292 }
1293
1294 function parseWeekNumberSunday(d, string, i) {
1295 var n = numberRe.exec(string.slice(i));
1296 return n ? (d.U = +n[0], i + n[0].length) : -1;
1297 }
1298
1299 function parseWeekNumberMonday(d, string, i) {
1300 var n = numberRe.exec(string.slice(i));
1301 return n ? (d.W = +n[0], i + n[0].length) : -1;
1302 }
1303
1304 function parseFullYear(d, string, i) {
1305 var n = numberRe.exec(string.slice(i, i + 4));
1306 return n ? (d.y = +n[0], i + n[0].length) : -1;
1307 }
1308
1309 function parseYear(d, string, i) {
1310 var n = numberRe.exec(string.slice(i, i + 2));
1311 return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
1312 }
1313
1314 function parseZone(d, string, i) {
1315 return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5))
1316 ? (d.Z = -string, i + 5) // sign differs from getTimezoneOffset!
1317 : -1;
1318 }
1319
1320 function parseMonthNumber(d, string, i) {
1321 var n = numberRe.exec(string.slice(i, i + 2));
1322 return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
1323 }
1324
1325 function parseDayOfMonth(d, string, i) {
1326 var n = numberRe.exec(string.slice(i, i + 2));
1327 return n ? (d.d = +n[0], i + n[0].length) : -1;
1328 }
1329
1330 function parseDayOfYear(d, string, i) {
1331 var n = numberRe.exec(string.slice(i, i + 3));
1332 return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
1333 }
1334
1335 function parseHour24(d, string, i) {
1336 var n = numberRe.exec(string.slice(i, i + 2));
1337 return n ? (d.H = +n[0], i + n[0].length) : -1;
1338 }
1339
1340 function parseMinutes(d, string, i) {
1341 var n = numberRe.exec(string.slice(i, i + 2));
1342 return n ? (d.M = +n[0], i + n[0].length) : -1;
1343 }
1344
1345 function parseSeconds(d, string, i) {
1346 var n = numberRe.exec(string.slice(i, i + 2));
1347 return n ? (d.S = +n[0], i + n[0].length) : -1;
1348 }
1349
1350 function parseMilliseconds(d, string, i) {
1351 var n = numberRe.exec(string.slice(i, i + 3));
1352 return n ? (d.L = +n[0], i + n[0].length) : -1;
1353 }
1354
1355 function parseLiteralPercent(d, string, i) {
1356 var n = percentRe.exec(string.slice(i, i + 1));
1357 return n ? i + n[0].length : -1;
1358 }
1359
1360 function formatDayOfMonth(d, p) {
1361 return pad(d.getDate(), p, 2);
1362 }
1363
1364 function formatHour24(d, p) {
1365 return pad(d.getHours(), p, 2);
1366 }
1367
1368 function formatHour12(d, p) {
1369 return pad(d.getHours() % 12 || 12, p, 2);
1370 }
1371
1372 function formatDayOfYear(d, p) {
1373 return pad(1 + day.count(year(d), d), p, 3);
1374 }
1375
1376 function formatMilliseconds(d, p) {
1377 return pad(d.getMilliseconds(), p, 3);
1378 }
1379
1380 function formatMonthNumber(d, p) {
1381 return pad(d.getMonth() + 1, p, 2);
1382 }
1383
1384 function formatMinutes(d, p) {
1385 return pad(d.getMinutes(), p, 2);
1386 }
1387
1388 function formatSeconds(d, p) {
1389 return pad(d.getSeconds(), p, 2);
1390 }
1391
1392 function formatWeekNumberSunday(d, p) {
1393 return pad(sunday.count(year(d), d), p, 2);
1394 }
1395
1396 function formatWeekdayNumber(d) {
1397 return d.getDay();
1398 }
1399
1400 function formatWeekNumberMonday(d, p) {
1401 return pad(monday.count(year(d), d), p, 2);
1402 }
1403
1404 function formatYear(d, p) {
1405 return pad(d.getFullYear() % 100, p, 2);
1406 }
1407
1408 function formatFullYear(d, p) {
1409 return pad(d.getFullYear() % 10000, p, 4);
1410 }
1411
1412 function formatZone(d) {
1413 var z = d.getTimezoneOffset();
1414 return (z > 0 ? "-" : (z *= -1, "+"))
1415 + pad(z / 60 | 0, "0", 2)
1416 + pad(z % 60, "0", 2);
1417 }
1418
1419 function formatUTCDayOfMonth(d, p) {
1420 return pad(d.getUTCDate(), p, 2);
1421 }
1422
1423 function formatUTCHour24(d, p) {
1424 return pad(d.getUTCHours(), p, 2);
1425 }
1426
1427 function formatUTCHour12(d, p) {
1428 return pad(d.getUTCHours() % 12 || 12, p, 2);
1429 }
1430
1431 function formatUTCDayOfYear(d, p) {
1432 return pad(1 + utcDay.count(utcYear(d), d), p, 3);
1433 }
1434
1435 function formatUTCMilliseconds(d, p) {
1436 return pad(d.getUTCMilliseconds(), p, 3);
1437 }
1438
1439 function formatUTCMonthNumber(d, p) {
1440 return pad(d.getUTCMonth() + 1, p, 2);
1441 }
1442
1443 function formatUTCMinutes(d, p) {
1444 return pad(d.getUTCMinutes(), p, 2);
1445 }
1446
1447 function formatUTCSeconds(d, p) {
1448 return pad(d.getUTCSeconds(), p, 2);
1449 }
1450
1451 function formatUTCWeekNumberSunday(d, p) {
1452 return pad(utcSunday.count(utcYear(d), d), p, 2);
1453 }
1454
1455 function formatUTCWeekdayNumber(d) {
1456 return d.getUTCDay();
1457 }
1458
1459 function formatUTCWeekNumberMonday(d, p) {
1460 return pad(utcMonday.count(utcYear(d), d), p, 2);
1461 }
1462
1463 function formatUTCYear(d, p) {
1464 return pad(d.getUTCFullYear() % 100, p, 2);
1465 }
1466
1467 function formatUTCFullYear(d, p) {
1468 return pad(d.getUTCFullYear() % 10000, p, 4);
1469 }
1470
1471 function formatUTCZone() {
1472 return "+0000";
1473 }
1474
1475 function formatLiteralPercent() {
1476 return "%";
1477 }
1478
1479 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
1480
1481 function formatIsoNative(date) {
1482 return date.toISOString();
1483 }
1484
1485 formatIsoNative.parse = function(string) {
1486 var date = new Date(string);
1487 return isNaN(date) ? null : date;
1488 };
1489
1490 formatIsoNative.toString = function() {
1491 return isoSpecifier;
1492 };
1493
1494 var formatIso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z")
1495 ? formatIsoNative
1496 : enUs.utcFormat(isoSpecifier);
1497
1498 var isoFormat = formatIso;
1499
1500 var localeDefinitions = (new Map)
1501 .set("ca-ES", caEs)
1502 .set("de-DE", deDe)
1503 .set("en-CA", enCa)
1504 .set("en-GB", enGb)
1505 .set("en-US", enUs)
1506 .set("es-ES", esEs)
1507 .set("fi-FI", fiFi)
1508 .set("fr-CA", frCa)
1509 .set("fr-FR", frFr)
1510 .set("he-IL", heIl)
1511 .set("it-IT", itIt)
1512 .set("ja-JP", jaJp)
1513 .set("mk-MK", mkMk)
1514 .set("nl-NL", nlNl)
1515 .set("pl-PL", plPl)
1516 .set("pt-BR", ptBr)
1517 .set("ru-RU", ruRu)
1518 .set("zh-CN", zhCn);
1519
1520 var defaultLocale = locale(enUs);
1521 exports.format = defaultLocale.format;
1522 exports.utcFormat = defaultLocale.utcFormat;
1523
1524 function localeFormat(definition) {
1525 if (typeof definition === "string") {
1526 definition = localeDefinitions.get(definition);
1527 if (!definition) return null;
1528 }
1529 return locale(definition);
1530 }
1531 ;
1532
1533 exports.localeFormat = localeFormat;
1534 exports.isoFormat = isoFormat;
1535
1536 }));
1537 },{}],6:[function(require,module,exports){
1538 (function (global, factory) {
1539 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
1540 typeof define === 'function' && define.amd ? define(['exports'], factory) :
1541 factory((global.time = {}));
1542 }(this, function (exports) { 'use strict';
1543
1544 var t1 = new Date;
1545
1546 var t0 = new Date;
1547
1548 function newInterval(floori, offseti, count) {
1549
1550 function interval(date) {
1551 return floori(date = new Date(+date)), date;
1552 }
1553
1554 interval.floor = interval;
1555
1556 interval.round = function(date) {
1557 var d0 = new Date(+date),
1558 d1 = new Date(date - 1);
1559 floori(d0), floori(d1), offseti(d1, 1);
1560 return date - d0 < d1 - date ? d0 : d1;
1561 };
1562
1563 interval.ceil = function(date) {
1564 return floori(date = new Date(date - 1)), offseti(date, 1), date;
1565 };
1566
1567 interval.offset = function(date, step) {
1568 return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
1569 };
1570
1571 interval.range = function(start, stop, step) {
1572 var range = [];
1573 start = new Date(start - 1);
1574 stop = new Date(+stop);
1575 step = step == null ? 1 : Math.floor(step);
1576 if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
1577 offseti(start, 1), floori(start);
1578 if (start < stop) range.push(new Date(+start));
1579 while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));
1580 return range;
1581 };
1582
1583 interval.filter = function(test) {
1584 return newInterval(function(date) {
1585 while (floori(date), !test(date)) date.setTime(date - 1);
1586 }, function(date, step) {
1587 while (--step >= 0) while (offseti(date, 1), !test(date));
1588 });
1589 };
1590
1591 if (count) interval.count = function(start, end) {
1592 t0.setTime(+start), t1.setTime(+end);
1593 floori(t0), floori(t1);
1594 return Math.floor(count(t0, t1));
1595 };
1596
1597 return interval;
1598 }
1599
1600 var second = newInterval(function(date) {
1601 date.setMilliseconds(0);
1602 }, function(date, step) {
1603 date.setTime(+date + step * 1e3);
1604 }, function(start, end) {
1605 return (end - start) / 1e3;
1606 });
1607
1608 exports.seconds = second.range;
1609
1610 var minute = newInterval(function(date) {
1611 date.setSeconds(0, 0);
1612 }, function(date, step) {
1613 date.setTime(+date + step * 6e4);
1614 }, function(start, end) {
1615 return (end - start) / 6e4;
1616 });
1617
1618 exports.minutes = minute.range;
1619
1620 var hour = newInterval(function(date) {
1621 date.setMinutes(0, 0, 0);
1622 }, function(date, step) {
1623 date.setTime(+date + step * 36e5);
1624 }, function(start, end) {
1625 return (end - start) / 36e5;
1626 });
1627
1628 exports.hours = hour.range;
1629
1630 var day = newInterval(function(date) {
1631 date.setHours(0, 0, 0, 0);
1632 }, function(date, step) {
1633 date.setDate(date.getDate() + step);
1634 }, function(start, end) {
1635 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;
1636 });
1637
1638 exports.days = day.range;
1639
1640 function weekday(i) {
1641 return newInterval(function(date) {
1642 date.setHours(0, 0, 0, 0);
1643 date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
1644 }, function(date, step) {
1645 date.setDate(date.getDate() + step * 7);
1646 }, function(start, end) {
1647 return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;
1648 });
1649 }
1650
1651 exports.sunday = weekday(0);
1652
1653 exports.sundays = exports.sunday.range;
1654
1655 exports.monday = weekday(1);
1656
1657 exports.mondays = exports.monday.range;
1658
1659 exports.tuesday = weekday(2);
1660
1661 exports.tuesdays = exports.tuesday.range;
1662
1663 exports.wednesday = weekday(3);
1664
1665 exports.wednesdays = exports.wednesday.range;
1666
1667 exports.thursday = weekday(4);
1668
1669 exports.thursdays = exports.thursday.range;
1670
1671 exports.friday = weekday(5);
1672
1673 exports.fridays = exports.friday.range;
1674
1675 exports.saturday = weekday(6);
1676
1677 exports.saturdays = exports.saturday.range;
1678
1679 var week = exports.sunday;
1680
1681 exports.weeks = week.range;
1682
1683 var month = newInterval(function(date) {
1684 date.setHours(0, 0, 0, 0);
1685 date.setDate(1);
1686 }, function(date, step) {
1687 date.setMonth(date.getMonth() + step);
1688 }, function(start, end) {
1689 return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
1690 });
1691
1692 exports.months = month.range;
1693
1694 var year = newInterval(function(date) {
1695 date.setHours(0, 0, 0, 0);
1696 date.setMonth(0, 1);
1697 }, function(date, step) {
1698 date.setFullYear(date.getFullYear() + step);
1699 }, function(start, end) {
1700 return end.getFullYear() - start.getFullYear();
1701 });
1702
1703 exports.years = year.range;
1704
1705 var utcSecond = newInterval(function(date) {
1706 date.setUTCMilliseconds(0);
1707 }, function(date, step) {
1708 date.setTime(+date + step * 1e3);
1709 }, function(start, end) {
1710 return (end - start) / 1e3;
1711 });
1712
1713 exports.utcSeconds = utcSecond.range;
1714
1715 var utcMinute = newInterval(function(date) {
1716 date.setUTCSeconds(0, 0);
1717 }, function(date, step) {
1718 date.setTime(+date + step * 6e4);
1719 }, function(start, end) {
1720 return (end - start) / 6e4;
1721 });
1722
1723 exports.utcMinutes = utcMinute.range;
1724
1725 var utcHour = newInterval(function(date) {
1726 date.setUTCMinutes(0, 0, 0);
1727 }, function(date, step) {
1728 date.setTime(+date + step * 36e5);
1729 }, function(start, end) {
1730 return (end - start) / 36e5;
1731 });
1732
1733 exports.utcHours = utcHour.range;
1734
1735 var utcDay = newInterval(function(date) {
1736 date.setUTCHours(0, 0, 0, 0);
1737 }, function(date, step) {
1738 date.setUTCDate(date.getUTCDate() + step);
1739 }, function(start, end) {
1740 return (end - start) / 864e5;
1741 });
1742
1743 exports.utcDays = utcDay.range;
1744
1745 function utcWeekday(i) {
1746 return newInterval(function(date) {
1747 date.setUTCHours(0, 0, 0, 0);
1748 date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
1749 }, function(date, step) {
1750 date.setUTCDate(date.getUTCDate() + step * 7);
1751 }, function(start, end) {
1752 return (end - start) / 6048e5;
1753 });
1754 }
1755
1756 exports.utcSunday = utcWeekday(0);
1757
1758 exports.utcSundays = exports.utcSunday.range;
1759
1760 exports.utcMonday = utcWeekday(1);
1761
1762 exports.utcMondays = exports.utcMonday.range;
1763
1764 exports.utcTuesday = utcWeekday(2);
1765
1766 exports.utcTuesdays = exports.utcTuesday.range;
1767
1768 exports.utcWednesday = utcWeekday(3);
1769
1770 exports.utcWednesdays = exports.utcWednesday.range;
1771
1772 exports.utcThursday = utcWeekday(4);
1773
1774 exports.utcThursdays = exports.utcThursday.range;
1775
1776 exports.utcFriday = utcWeekday(5);
1777
1778 exports.utcFridays = exports.utcFriday.range;
1779
1780 exports.utcSaturday = utcWeekday(6);
1781
1782 exports.utcSaturdays = exports.utcSaturday.range;
1783
1784 var utcWeek = exports.utcSunday;
1785
1786 exports.utcWeeks = utcWeek.range;
1787
1788 var utcMonth = newInterval(function(date) {
1789 date.setUTCHours(0, 0, 0, 0);
1790 date.setUTCDate(1);
1791 }, function(date, step) {
1792 date.setUTCMonth(date.getUTCMonth() + step);
1793 }, function(start, end) {
1794 return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
1795 });
1796
1797 exports.utcMonths = utcMonth.range;
1798
1799 var utcYear = newInterval(function(date) {
1800 date.setUTCHours(0, 0, 0, 0);
1801 date.setUTCMonth(0, 1);
1802 }, function(date, step) {
1803 date.setUTCFullYear(date.getUTCFullYear() + step);
1804 }, function(start, end) {
1805 return end.getUTCFullYear() - start.getUTCFullYear();
1806 });
1807
1808 exports.utcYears = utcYear.range;
1809
1810 exports.interval = newInterval;
1811 exports.second = second;
1812 exports.minute = minute;
1813 exports.hour = hour;
1814 exports.day = day;
1815 exports.week = week;
1816 exports.month = month;
1817 exports.year = year;
1818 exports.utcSecond = utcSecond;
1819 exports.utcMinute = utcMinute;
1820 exports.utcHour = utcHour;
1821 exports.utcDay = utcDay;
1822 exports.utcWeek = utcWeek;
1823 exports.utcMonth = utcMonth;
1824 exports.utcYear = utcYear;
1825
1826 }));
1827 },{}],7:[function(require,module,exports){
1828 var util = require('../util'),
1829 Measures = require('./measures'),
1830 Collector = require('./collector');
1831
1832 function Aggregator() {
1833 this._cells = {};
1834 this._aggr = [];
1835 this._stream = false;
1836 }
1837
1838 var Flags = Aggregator.Flags = {
1839 ADD_CELL: 1,
1840 MOD_CELL: 2
1841 };
1842
1843 var proto = Aggregator.prototype;
1844
1845 // Parameters
1846
1847 proto.stream = function(v) {
1848 if (v == null) return this._stream;
1849 this._stream = !!v;
1850 this._aggr = [];
1851 return this;
1852 };
1853
1854 // key accessor to use for streaming removes
1855 proto.key = function(key) {
1856 if (key == null) return this._key;
1857 this._key = util.$(key);
1858 return this;
1859 };
1860
1861 // Input: array of objects of the form
1862 // {name: string, get: function}
1863 proto.groupby = function(dims) {
1864 this._dims = util.array(dims).map(function(d, i) {
1865 d = util.isString(d) ? {name: d, get: util.$(d)}
1866 : util.isFunction(d) ? {name: util.name(d) || d.name || ('_' + i), get: d}
1867 : (d.name && util.isFunction(d.get)) ? d : null;
1868 if (d == null) throw 'Invalid groupby argument: ' + d;
1869 return d;
1870 });
1871 return this.clear();
1872 };
1873
1874 // Input: array of objects of the form
1875 // {name: string, ops: [string, ...]}
1876 proto.summarize = function(fields) {
1877 fields = summarize_args(fields);
1878 this._count = true;
1879 var aggr = (this._aggr = []),
1880 m, f, i, j, op, as, get;
1881
1882 for (i=0; i<fields.length; ++i) {
1883 for (j=0, m=[], f=fields[i]; j<f.ops.length; ++j) {
1884 op = f.ops[j];
1885 if (op !== 'count') this._count = false;
1886 as = (f.as && f.as[j]) || (op + (f.name==='*' ? '' : '_'+f.name));
1887 m.push(Measures[op](as));
1888 }
1889 get = f.get && util.$(f.get) ||
1890 (f.name === '*' ? util.identity : util.$(f.name));
1891 aggr.push({
1892 name: f.name,
1893 measures: Measures.create(
1894 m,
1895 this._stream, // streaming remove flag
1896 get, // input tuple getter
1897 this._assign) // output tuple setter
1898 });
1899 }
1900 return this.clear();
1901 };
1902
1903 // Convenience method to summarize by count
1904 proto.count = function() {
1905 return this.summarize({'*':'count'});
1906 };
1907
1908 // Override to perform custom tuple value assignment
1909 proto._assign = function(object, name, value) {
1910 object[name] = value;
1911 };
1912
1913 function summarize_args(fields) {
1914 if (util.isArray(fields)) { return fields; }
1915 if (fields == null) { return []; }
1916 var a = [], name, ops;
1917 for (name in fields) {
1918 ops = util.array(fields[name]);
1919 a.push({name: name, ops: ops});
1920 }
1921 return a;
1922 }
1923
1924 // Cell Management
1925
1926 proto.clear = function() {
1927 return (this._cells = {}, this);
1928 };
1929
1930 proto._cellkey = function(x) {
1931 var d = this._dims,
1932 n = d.length, i,
1933 k = String(d[0].get(x));
1934 for (i=1; i<n; ++i) {
1935 k += '|' + d[i].get(x);
1936 }
1937 return k;
1938 };
1939
1940 proto._cell = function(x) {
1941 var key = this._dims.length ? this._cellkey(x) : '';
1942 return this._cells[key] || (this._cells[key] = this._newcell(x, key));
1943 };
1944
1945 proto._newcell = function(x, key) {
1946 var cell = {
1947 num: 0,
1948 tuple: this._newtuple(x, key),
1949 flag: Flags.ADD_CELL,
1950 aggs: {}
1951 };
1952
1953 var aggr = this._aggr, i;
1954 for (i=0; i<aggr.length; ++i) {
1955 cell.aggs[aggr[i].name] = new aggr[i].measures(cell, cell.tuple);
1956 }
1957 if (cell.collect) {
1958 cell.data = new Collector(this._key);
1959 }
1960 return cell;
1961 };
1962
1963 proto._newtuple = function(x) {
1964 var dims = this._dims,
1965 t = {}, i, n;
1966 for (i=0, n=dims.length; i<n; ++i) {
1967 t[dims[i].name] = dims[i].get(x);
1968 }
1969 return this._ingest(t);
1970 };
1971
1972 // Override to perform custom tuple ingestion
1973 proto._ingest = util.identity;
1974
1975 // Process Tuples
1976
1977 proto._add = function(x) {
1978 var cell = this._cell(x),
1979 aggr = this._aggr, i;
1980
1981 cell.num += 1;
1982 if (!this._count) { // skip if count-only
1983 if (cell.collect) cell.data.add(x);
1984 for (i=0; i<aggr.length; ++i) {
1985 cell.aggs[aggr[i].name].add(x);
1986 }
1987 }
1988 cell.flag |= Flags.MOD_CELL;
1989 if (this._on_add) this._on_add(x, cell);
1990 };
1991
1992 proto._rem = function(x) {
1993 var cell = this._cell(x),
1994 aggr = this._aggr, i;
1995
1996 cell.num -= 1;
1997 if (!this._count) { // skip if count-only
1998 if (cell.collect) cell.data.rem(x);
1999 for (i=0; i<aggr.length; ++i) {
2000 cell.aggs[aggr[i].name].rem(x);
2001 }
2002 }
2003 cell.flag |= Flags.MOD_CELL;
2004 if (this._on_rem) this._on_rem(x, cell);
2005 };
2006
2007 proto._mod = function(curr, prev) {
2008 var cell0 = this._cell(prev),
2009 cell1 = this._cell(curr),
2010 aggr = this._aggr, i;
2011
2012 if (cell0 !== cell1) {
2013 cell0.num -= 1;
2014 cell1.num += 1;
2015 if (cell0.collect) cell0.data.rem(prev);
2016 if (cell1.collect) cell1.data.add(curr);
2017 } else if (cell0.collect && !util.isObject(curr)) {
2018 cell0.data.rem(prev);
2019 cell0.data.add(curr);
2020 }
2021
2022 for (i=0; i<aggr.length; ++i) {
2023 cell0.aggs[aggr[i].name].rem(prev);
2024 cell1.aggs[aggr[i].name].add(curr);
2025 }
2026 cell0.flag |= Flags.MOD_CELL;
2027 cell1.flag |= Flags.MOD_CELL;
2028 if (this._on_mod) this._on_mod(curr, prev, cell0, cell1);
2029 };
2030
2031 proto.result = function() {
2032 var result = [],
2033 aggr = this._aggr,
2034 cell, i, k;
2035
2036 for (k in this._cells) {
2037 cell = this._cells[k];
2038 if (cell.num > 0) {
2039 // consolidate collector values
2040 if (cell.collect) {
2041 cell.data.values();
2042 }
2043 // update tuple properties
2044 for (i=0; i<aggr.length; ++i) {
2045 cell.aggs[aggr[i].name].set();
2046 }
2047 // add output tuple
2048 result.push(cell.tuple);
2049 } else {
2050 delete this._cells[k];
2051 }
2052 cell.flag = 0;
2053 }
2054
2055 this._rems = false;
2056 return result;
2057 };
2058
2059 proto.changes = function(output) {
2060 var changes = output || {add:[], rem:[], mod:[]},
2061 aggr = this._aggr,
2062 cell, flag, i, k;
2063
2064 for (k in this._cells) {
2065 cell = this._cells[k];
2066 flag = cell.flag;
2067
2068 // consolidate collector values
2069 if (cell.collect) {
2070 cell.data.values();
2071 }
2072
2073 // update tuple properties
2074 for (i=0; i<aggr.length; ++i) {
2075 cell.aggs[aggr[i].name].set();
2076 }
2077
2078 // organize output tuples
2079 if (cell.num <= 0) {
2080 changes.rem.push(cell.tuple); // if (flag === Flags.MOD_CELL) { ??
2081 delete this._cells[k];
2082 if (this._on_drop) this._on_drop(cell);
2083 } else {
2084 if (this._on_keep) this._on_keep(cell);
2085 if (flag & Flags.ADD_CELL) {
2086 changes.add.push(cell.tuple);
2087 } else if (flag & Flags.MOD_CELL) {
2088 changes.mod.push(cell.tuple);
2089 }
2090 }
2091
2092 cell.flag = 0;
2093 }
2094
2095 this._rems = false;
2096 return changes;
2097 };
2098
2099 proto.execute = function(input) {
2100 return this.clear().insert(input).result();
2101 };
2102
2103 proto.insert = function(input) {
2104 this._consolidate();
2105 for (var i=0; i<input.length; ++i) {
2106 this._add(input[i]);
2107 }
2108 return this;
2109 };
2110
2111 proto.remove = function(input) {
2112 if (!this._stream) {
2113 throw 'Aggregator not configured for streaming removes.' +
2114 ' Call stream(true) prior to calling summarize.';
2115 }
2116 for (var i=0; i<input.length; ++i) {
2117 this._rem(input[i]);
2118 }
2119 this._rems = true;
2120 return this;
2121 };
2122
2123 // consolidate removals
2124 proto._consolidate = function() {
2125 if (!this._rems) return;
2126 for (var k in this._cells) {
2127 if (this._cells[k].collect) {
2128 this._cells[k].data.values();
2129 }
2130 }
2131 this._rems = false;
2132 };
2133
2134 module.exports = Aggregator;
2135 },{"../util":29,"./collector":8,"./measures":10}],8:[function(require,module,exports){
2136 var util = require('../util');
2137 var stats = require('../stats');
2138
2139 var REM = '__dl_rem__';
2140
2141 function Collector(key) {
2142 this._add = [];
2143 this._rem = [];
2144 this._key = key || null;
2145 this._last = null;
2146 }
2147
2148 var proto = Collector.prototype;
2149
2150 proto.add = function(v) {
2151 this._add.push(v);
2152 };
2153
2154 proto.rem = function(v) {
2155 this._rem.push(v);
2156 };
2157
2158 proto.values = function() {
2159 this._get = null;
2160 if (this._rem.length === 0) return this._add;
2161
2162 var a = this._add,
2163 r = this._rem,
2164 k = this._key,
2165 x = Array(a.length - r.length),
2166 i, j, n, m;
2167
2168 if (!util.isObject(r[0])) {
2169 // processing raw values
2170 m = stats.count.map(r);
2171 for (i=0, j=0, n=a.length; i<n; ++i) {
2172 if (m[a[i]] > 0) {
2173 m[a[i]] -= 1;
2174 } else {
2175 x[j++] = a[i];
2176 }
2177 }
2178 } else if (k) {
2179 // has unique key field, so use that
2180 m = util.toMap(r, k);
2181 for (i=0, j=0, n=a.length; i<n; ++i) {
2182 if (!m.hasOwnProperty(k(a[i]))) { x[j++] = a[i]; }
2183 }
2184 } else {
2185 // no unique key, mark tuples directly
2186 for (i=0, n=r.length; i<n; ++i) {
2187 r[i][REM] = 1;
2188 }
2189 for (i=0, j=0, n=a.length; i<n; ++i) {
2190 if (!a[i][REM]) { x[j++] = a[i]; }
2191 }
2192 for (i=0, n=r.length; i<n; ++i) {
2193 delete r[i][REM];
2194 }
2195 }
2196
2197 this._rem = [];
2198 return (this._add = x);
2199 };
2200
2201 // memoizing statistics methods
2202
2203 proto.extent = function(get) {
2204 if (this._get !== get || !this._ext) {
2205 var v = this.values(),
2206 i = stats.extent.index(v, get);
2207 this._ext = [v[i[0]], v[i[1]]];
2208 this._get = get;
2209 }
2210 return this._ext;
2211 };
2212
2213 proto.argmin = function(get) {
2214 return this.extent(get)[0];
2215 };
2216
2217 proto.argmax = function(get) {
2218 return this.extent(get)[1];
2219 };
2220
2221 proto.min = function(get) {
2222 var m = this.extent(get)[0];
2223 return m ? get(m) : +Infinity;
2224 };
2225
2226 proto.max = function(get) {
2227 var m = this.extent(get)[1];
2228 return m ? get(m) : -Infinity;
2229 };
2230
2231 proto.quartile = function(get) {
2232 if (this._get !== get || !this._q) {
2233 this._q = stats.quartile(this.values(), get);
2234 this._get = get;
2235 }
2236 return this._q;
2237 };
2238
2239 proto.q1 = function(get) {
2240 return this.quartile(get)[0];
2241 };
2242
2243 proto.q2 = function(get) {
2244 return this.quartile(get)[1];
2245 };
2246
2247 proto.q3 = function(get) {
2248 return this.quartile(get)[2];
2249 };
2250
2251 module.exports = Collector;
2252
2253 },{"../stats":26,"../util":29}],9:[function(require,module,exports){
2254 var util = require('../util');
2255 var Aggregator = require('./aggregator');
2256
2257 module.exports = function() {
2258 // flatten arguments into a single array
2259 var args = [].reduce.call(arguments, function(a, x) {
2260 return a.concat(util.array(x));
2261 }, []);
2262 // create and return an aggregator
2263 return new Aggregator()
2264 .groupby(args)
2265 .summarize({'*':'values'});
2266 };
2267
2268 },{"../util":29,"./aggregator":7}],10:[function(require,module,exports){
2269 var util = require('../util');
2270
2271 var types = {
2272 'values': measure({
2273 name: 'values',
2274 init: 'cell.collect = true;',
2275 set: 'cell.data.values()', idx: -1
2276 }),
2277 'count': measure({
2278 name: 'count',
2279 set: 'cell.num'
2280 }),
2281 'missing': measure({
2282 name: 'missing',
2283 set: 'this.missing'
2284 }),
2285 'valid': measure({
2286 name: 'valid',
2287 set: 'this.valid'
2288 }),
2289 'sum': measure({
2290 name: 'sum',
2291 init: 'this.sum = 0;',
2292 add: 'this.sum += v;',
2293 rem: 'this.sum -= v;',
2294 set: 'this.sum'
2295 }),
2296 'mean': measure({
2297 name: 'mean',
2298 init: 'this.mean = 0;',
2299 add: 'var d = v - this.mean; this.mean += d / this.valid;',
2300 rem: 'var d = v - this.mean; this.mean -= this.valid ? d / this.valid : this.mean;',
2301 set: 'this.mean'
2302 }),
2303 'average': measure({
2304 name: 'average',
2305 set: 'this.mean',
2306 req: ['mean'], idx: 1
2307 }),
2308 'variance': measure({
2309 name: 'variance',
2310 init: 'this.dev = 0;',
2311 add: 'this.dev += d * (v - this.mean);',
2312 rem: 'this.dev -= d * (v - this.mean);',
2313 set: 'this.valid > 1 ? this.dev / (this.valid-1) : 0',
2314 req: ['mean'], idx: 1
2315 }),
2316 'variancep': measure({
2317 name: 'variancep',
2318 set: 'this.valid > 1 ? this.dev / this.valid : 0',
2319 req: ['variance'], idx: 2
2320 }),
2321 'stdev': measure({
2322 name: 'stdev',
2323 set: 'this.valid > 1 ? Math.sqrt(this.dev / (this.valid-1)) : 0',
2324 req: ['variance'], idx: 2
2325 }),
2326 'stdevp': measure({
2327 name: 'stdevp',
2328 set: 'this.valid > 1 ? Math.sqrt(this.dev / this.valid) : 0',
2329 req: ['variance'], idx: 2
2330 }),
2331 'median': measure({
2332 name: 'median',
2333 set: 'cell.data.q2(this.get)',
2334 req: ['values'], idx: 3
2335 }),
2336 'q1': measure({
2337 name: 'q1',
2338 set: 'cell.data.q1(this.get)',
2339 req: ['values'], idx: 3
2340 }),
2341 'q3': measure({
2342 name: 'q3',
2343 set: 'cell.data.q3(this.get)',
2344 req: ['values'], idx: 3
2345 }),
2346 'distinct': measure({
2347 name: 'distinct',
2348 set: 'this.distinct(cell.data.values(), this.get)',
2349 req: ['values'], idx: 3
2350 }),
2351 'argmin': measure({
2352 name: 'argmin',
2353 add: 'if (v < this.min) this.argmin = t;',
2354 rem: 'if (v <= this.min) this.argmin = null;',
2355 set: 'this.argmin = this.argmin || cell.data.argmin(this.get)',
2356 req: ['min'], str: ['values'], idx: 3
2357 }),
2358 'argmax': measure({
2359 name: 'argmax',
2360 add: 'if (v > this.max) this.argmax = t;',
2361 rem: 'if (v >= this.max) this.argmax = null;',
2362 set: 'this.argmax = this.argmax || cell.data.argmax(this.get)',
2363 req: ['max'], str: ['values'], idx: 3
2364 }),
2365 'min': measure({
2366 name: 'min',
2367 init: 'this.min = +Infinity;',
2368 add: 'if (v < this.min) this.min = v;',
2369 rem: 'if (v <= this.min) this.min = NaN;',
2370 set: 'this.min = (isNaN(this.min) ? cell.data.min(this.get) : this.min)',
2371 str: ['values'], idx: 4
2372 }),
2373 'max': measure({
2374 name: 'max',
2375 init: 'this.max = -Infinity;',
2376 add: 'if (v > this.max) this.max = v;',
2377 rem: 'if (v >= this.max) this.max = NaN;',
2378 set: 'this.max = (isNaN(this.max) ? cell.data.max(this.get) : this.max)',
2379 str: ['values'], idx: 4
2380 }),
2381 'modeskew': measure({
2382 name: 'modeskew',
2383 set: 'this.dev===0 ? 0 : (this.mean - cell.data.q2(this.get)) / Math.sqrt(this.dev/(this.valid-1))',
2384 req: ['mean', 'stdev', 'median'], idx: 5
2385 })
2386 };
2387
2388 function measure(base) {
2389 return function(out) {
2390 var m = util.extend({init:'', add:'', rem:'', idx:0}, base);
2391 m.out = out || base.name;
2392 return m;
2393 };
2394 }
2395
2396 function resolve(agg, stream) {
2397 function collect(m, a) {
2398 function helper(r) { if (!m[r]) collect(m, m[r] = types[r]()); }
2399 if (a.req) a.req.forEach(helper);
2400 if (stream && a.str) a.str.forEach(helper);
2401 return m;
2402 }
2403 var map = agg.reduce(
2404 collect,
2405 agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {})
2406 );
2407 return util.vals(map).sort(function(a, b) { return a.idx - b.idx; });
2408 }
2409
2410 function create(agg, stream, accessor, mutator) {
2411 var all = resolve(agg, stream),
2412 ctr = 'this.cell = cell; this.tuple = t; this.valid = 0; this.missing = 0;',
2413 add = 'if (v==null) this.missing++; if (!this.isValid(v)) return; ++this.valid;',
2414 rem = 'if (v==null) this.missing--; if (!this.isValid(v)) return; --this.valid;',
2415 set = 'var t = this.tuple; var cell = this.cell;';
2416
2417 all.forEach(function(a) {
2418 if (a.idx < 0) {
2419 ctr = a.init + ctr;
2420 add = a.add + add;
2421 rem = a.rem + rem;
2422 } else {
2423 ctr += a.init;
2424 add += a.add;
2425 rem += a.rem;
2426 }
2427 });
2428 agg.slice()
2429 .sort(function(a, b) { return a.idx - b.idx; })
2430 .forEach(function(a) {
2431 set += 'this.assign(t,\''+a.out+'\','+a.set+');';
2432 });
2433 set += 'return t;';
2434
2435 /* jshint evil: true */
2436 ctr = Function('cell', 't', ctr);
2437 ctr.prototype.assign = mutator;
2438 ctr.prototype.add = Function('t', 'var v = this.get(t);' + add);
2439 ctr.prototype.rem = Function('t', 'var v = this.get(t);' + rem);
2440 ctr.prototype.set = Function(set);
2441 ctr.prototype.get = accessor;
2442 ctr.prototype.distinct = require('../stats').count.distinct;
2443 ctr.prototype.isValid = util.isValid;
2444 ctr.fields = agg.map(util.$('out'));
2445 return ctr;
2446 }
2447
2448 types.create = create;
2449 module.exports = types;
2450 },{"../stats":26,"../util":29}],11:[function(require,module,exports){
2451 var util = require('../util'),
2452 time = require('../time'),
2453 EPSILON = 1e-15;
2454
2455 function bins(opt) {
2456 if (!opt) { throw Error("Missing binning options."); }
2457
2458 // determine range
2459 var maxb = opt.maxbins || 15,
2460 base = opt.base || 10,
2461 logb = Math.log(base),
2462 div = opt.div || [5, 2],
2463 min = opt.min,
2464 max = opt.max,
2465 span = max - min,
2466 step, level, minstep, precision, v, i, eps;
2467
2468 if (opt.step) {
2469 // if step size is explicitly given, use that
2470 step = opt.step;
2471 } else if (opt.steps) {
2472 // if provided, limit choice to acceptable step sizes
2473 step = opt.steps[Math.min(
2474 opt.steps.length - 1,
2475 bisect(opt.steps, span/maxb, 0, opt.steps.length)
2476 )];
2477 } else {
2478 // else use span to determine step size
2479 level = Math.ceil(Math.log(maxb) / logb);
2480 minstep = opt.minstep || 0;
2481 step = Math.max(
2482 minstep,
2483 Math.pow(base, Math.round(Math.log(span) / logb) - level)
2484 );
2485
2486 // increase step size if too many bins
2487 do { step *= base; } while (Math.ceil(span/step) > maxb);
2488
2489 // decrease step size if allowed
2490 for (i=0; i<div.length; ++i) {
2491 v = step / div[i];
2492 if (v >= minstep && span / v <= maxb) step = v;
2493 }
2494 }
2495
2496 // update precision, min and max
2497 v = Math.log(step);
2498 precision = v >= 0 ? 0 : ~~(-v / logb) + 1;
2499 eps = Math.pow(base, -precision - 1);
2500 min = Math.min(min, Math.floor(min / step + eps) * step);
2501 max = Math.ceil(max / step) * step;
2502
2503 return {
2504 start: min,
2505 stop: max,
2506 step: step,
2507 unit: {precision: precision},
2508 value: value,
2509 index: index
2510 };
2511 }
2512
2513 function bisect(a, x, lo, hi) {
2514 while (lo < hi) {
2515 var mid = lo + hi >>> 1;
2516 if (util.cmp(a[mid], x) < 0) { lo = mid + 1; }
2517 else { hi = mid; }
2518 }
2519 return lo;
2520 }
2521
2522 function value(v) {
2523 return this.step * Math.floor(v / this.step + EPSILON);
2524 }
2525
2526 function index(v) {
2527 return Math.floor((v - this.start) / this.step + EPSILON);
2528 }
2529
2530 function date_value(v) {
2531 return this.unit.date(value.call(this, v));
2532 }
2533
2534 function date_index(v) {
2535 return index.call(this, this.unit.unit(v));
2536 }
2537
2538 bins.date = function(opt) {
2539 if (!opt) { throw Error("Missing date binning options."); }
2540
2541 // find time step, then bin
2542 var units = opt.utc ? time.utc : time,
2543 dmin = opt.min,
2544 dmax = opt.max,
2545 maxb = opt.maxbins || 20,
2546 minb = opt.minbins || 4,
2547 span = (+dmax) - (+dmin),
2548 unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb),
2549 spec = bins({
2550 min: unit.min != null ? unit.min : unit.unit(dmin),
2551 max: unit.max != null ? unit.max : unit.unit(dmax),
2552 maxbins: maxb,
2553 minstep: unit.minstep,
2554 steps: unit.step
2555 });
2556
2557 spec.unit = unit;
2558 spec.index = date_index;
2559 if (!opt.raw) spec.value = date_value;
2560 return spec;
2561 };
2562
2563 module.exports = bins;
2564
2565 },{"../time":28,"../util":29}],12:[function(require,module,exports){
2566 var bins = require('./bins'),
2567 gen = require('../generate'),
2568 type = require('../import/type'),
2569 util = require('../util'),
2570 stats = require('../stats');
2571
2572 var qtype = {
2573 'integer': 1,
2574 'number': 1,
2575 'date': 1
2576 };
2577
2578 function $bin(values, f, opt) {
2579 opt = options(values, f, opt);
2580 var b = spec(opt);
2581 return !b ? (opt.accessor || util.identity) :
2582 util.$func('bin', b.unit.unit ?
2583 function(x) { return b.value(b.unit.unit(x)); } :
2584 function(x) { return b.value(x); }
2585 )(opt.accessor);
2586 }
2587
2588 function histogram(values, f, opt) {
2589 opt = options(values, f, opt);
2590 var b = spec(opt);
2591 return b ?
2592 numerical(values, opt.accessor, b) :
2593 categorical(values, opt.accessor, opt && opt.sort);
2594 }
2595
2596 function spec(opt) {
2597 var t = opt.type, b = null;
2598 if (t == null || qtype[t]) {
2599 if (t === 'integer' && opt.minstep == null) opt.minstep = 1;
2600 b = (t === 'date') ? bins.date(opt) : bins(opt);
2601 }
2602 return b;
2603 }
2604
2605 function options() {
2606 var a = arguments,
2607 i = 0,
2608 values = util.isArray(a[i]) ? a[i++] : null,
2609 f = util.isFunction(a[i]) || util.isString(a[i]) ? util.$(a[i++]) : null,
2610 opt = util.extend({}, a[i]);
2611
2612 if (values) {
2613 opt.type = opt.type || type(values, f);
2614 if (qtype[opt.type]) {
2615 var ext = stats.extent(values, f);
2616 opt = util.extend({min: ext[0], max: ext[1]}, opt);
2617 }
2618 }
2619 if (f) { opt.accessor = f; }
2620 return opt;
2621 }
2622
2623 function numerical(values, f, b) {
2624 var h = gen.range(b.start, b.stop + b.step/2, b.step)
2625 .map(function(v) { return {value: b.value(v), count: 0}; });
2626
2627 for (var i=0, v, j; i<values.length; ++i) {
2628 v = f ? f(values[i]) : values[i];
2629 if (util.isValid(v)) {
2630 j = b.index(v);
2631 if (j < 0 || j >= h.length || !isFinite(j)) continue;
2632 h[j].count += 1;
2633 }
2634 }
2635 h.bins = b;
2636 return h;
2637 }
2638
2639 function categorical(values, f, sort) {
2640 var u = stats.unique(values, f),
2641 c = stats.count.map(values, f);
2642 return u.map(function(k) { return {value: k, count: c[k]}; })
2643 .sort(util.comparator(sort ? '-count' : '+value'));
2644 }
2645
2646 module.exports = {
2647 $bin: $bin,
2648 histogram: histogram
2649 };
2650 },{"../generate":14,"../import/type":23,"../stats":26,"../util":29,"./bins":11}],13:[function(require,module,exports){
2651 var d3_time = require('d3-time'),
2652 d3_timeF = require('d3-time-format'),
2653 d3_numberF = require('d3-format'),
2654 numberF = d3_numberF, // defaults to EN-US
2655 timeF = d3_timeF; // defaults to EN-US
2656
2657 function numberLocale(l) {
2658 var f = d3_numberF.localeFormat(l);
2659 if (f == null) throw Error('Unrecognized locale: ' + l);
2660 numberF = f;
2661 }
2662
2663 function timeLocale(l) {
2664 var f = d3_timeF.localeFormat(l);
2665 if (f == null) throw Error('Unrecognized locale: ' + l);
2666 timeF = f;
2667 }
2668
2669 module.exports = {
2670 // Update number formatter to use provided locale configuration.
2671 // For more see https://github.com/d3/d3-format
2672 numberLocale: numberLocale,
2673 number: function(f) { return numberF.format(f); },
2674 numberPrefix: function(f, v) { return numberF.formatPrefix(f, v); },
2675
2676 // Update time formatter to use provided locale configuration.
2677 // For more see https://github.com/d3/d3-time-format
2678 timeLocale: timeLocale,
2679 time: function(f) { return timeF.format(f); },
2680 utc: function(f) { return timeF.utcFormat(f); },
2681
2682 // Set number and time locale simultaneously.
2683 locale: function(l) { numberLocale(l); timeLocale(l); },
2684
2685 // automatic formatting functions
2686 auto: {
2687 number: numberAutoFormat,
2688 time: function() { return timeAutoFormat(); },
2689 utc: function() { return utcAutoFormat(); }
2690 }
2691 };
2692
2693 var e10 = Math.sqrt(50),
2694 e5 = Math.sqrt(10),
2695 e2 = Math.sqrt(2);
2696
2697 function intervals(domain, count) {
2698 if (!domain.length) domain = [0];
2699 if (count == null) count = 10;
2700
2701 var start = domain[0],
2702 stop = domain[domain.length - 1];
2703
2704 if (stop < start) { error = stop; stop = start; start = error; }
2705
2706 var span = (stop - start) || (count = 1, start || stop || 1),
2707 step = Math.pow(10, Math.floor(Math.log(span / count) / Math.LN10)),
2708 error = span / count / step;
2709
2710 // Filter ticks to get closer to the desired count.
2711 if (error >= e10) step *= 10;
2712 else if (error >= e5) step *= 5;
2713 else if (error >= e2) step *= 2;
2714
2715 // Round start and stop values to step interval.
2716 return [
2717 Math.ceil(start / step) * step,
2718 Math.floor(stop / step) * step + step / 2, // inclusive
2719 step
2720 ];
2721 }
2722
2723 function numberAutoFormat(domain, count, f) {
2724 var range = intervals(domain, count);
2725 if (f == null) {
2726 f = ',.' + d3_numberF.precisionFixed(range[2]) + 'f';
2727 } else {
2728 switch (f = d3_numberF.formatSpecifier(f), f.type) {
2729 case 's': {
2730 var value = Math.max(Math.abs(range[0]), Math.abs(range[1]));
2731 if (f.precision == null) f.precision = d3_numberF.precisionPrefix(range[2], value);
2732 return numberF.formatPrefix(f, value);
2733 }
2734 case '':
2735 case 'e':
2736 case 'g':
2737 case 'p':
2738 case 'r': {
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');
2740 break;
2741 }
2742 case 'f':
2743 case '%': {
2744 if (f.precision == null) f.precision = d3_numberF.precisionFixed(range[2]) - (f.type === '%') * 2;
2745 break;
2746 }
2747 }
2748 }
2749 return numberF.format(f);
2750 }
2751
2752 function timeAutoFormat() {
2753 var f = timeF.format,
2754 formatMillisecond = f('.%L'),
2755 formatSecond = f(':%S'),
2756 formatMinute = f('%I:%M'),
2757 formatHour = f('%I %p'),
2758 formatDay = f('%a %d'),
2759 formatWeek = f('%b %d'),
2760 formatMonth = f('%B'),
2761 formatYear = f('%Y');
2762
2763 return function(date) {
2764 var d = +date;
2765 return (d3_time.second(date) < d ? formatMillisecond
2766 : d3_time.minute(date) < d ? formatSecond
2767 : d3_time.hour(date) < d ? formatMinute
2768 : d3_time.day(date) < d ? formatHour
2769 : d3_time.month(date) < d ?
2770 (d3_time.week(date) < d ? formatDay : formatWeek)
2771 : d3_time.year(date) < d ? formatMonth
2772 : formatYear)(date);
2773 };
2774 }
2775
2776 function utcAutoFormat() {
2777 var f = timeF.utcFormat,
2778 formatMillisecond = f('.%L'),
2779 formatSecond = f(':%S'),
2780 formatMinute = f('%I:%M'),
2781 formatHour = f('%I %p'),
2782 formatDay = f('%a %d'),
2783 formatWeek = f('%b %d'),
2784 formatMonth = f('%B'),
2785 formatYear = f('%Y');
2786
2787 return function(date) {
2788 var d = +date;
2789 return (d3_time.utcSecond(date) < d ? formatMillisecond
2790 : d3_time.utcMinute(date) < d ? formatSecond
2791 : d3_time.utcHour(date) < d ? formatMinute
2792 : d3_time.utcDay(date) < d ? formatHour
2793 : d3_time.utcMonth(date) < d ?
2794 (d3_time.utcWeek(date) < d ? formatDay : formatWeek)
2795 : d3_time.utcYear(date) < d ? formatMonth
2796 : formatYear)(date);
2797 };
2798 }
2799
2800 },{"d3-format":4,"d3-time":6,"d3-time-format":5}],14:[function(require,module,exports){
2801 var gen = module.exports = {};
2802
2803 gen.repeat = function(val, n) {
2804 var a = Array(n), i;
2805 for (i=0; i<n; ++i) a[i] = val;
2806 return a;
2807 };
2808
2809 gen.zeros = function(n) {
2810 return gen.repeat(0, n);
2811 };
2812
2813 gen.range = function(start, stop, step) {
2814 if (arguments.length < 3) {
2815 step = 1;
2816 if (arguments.length < 2) {
2817 stop = start;
2818 start = 0;
2819 }
2820 }
2821 if ((stop - start) / step == Infinity) throw new Error('Infinite range');
2822 var range = [], i = -1, j;
2823 if (step < 0) while ((j = start + step * ++i) > stop) range.push(j);
2824 else while ((j = start + step * ++i) < stop) range.push(j);
2825 return range;
2826 };
2827
2828 gen.random = {};
2829
2830 gen.random.uniform = function(min, max) {
2831 if (max === undefined) {
2832 max = min === undefined ? 1 : min;
2833 min = 0;
2834 }
2835 var d = max - min;
2836 var f = function() {
2837 return min + d * Math.random();
2838 };
2839 f.samples = function(n) { return gen.zeros(n).map(f); };
2840 return f;
2841 };
2842
2843 gen.random.integer = function(a, b) {
2844 if (b === undefined) {
2845 b = a;
2846 a = 0;
2847 }
2848 var d = b - a;
2849 var f = function() {
2850 return a + Math.floor(d * Math.random());
2851 };
2852 f.samples = function(n) { return gen.zeros(n).map(f); };
2853 return f;
2854 };
2855
2856 gen.random.normal = function(mean, stdev) {
2857 mean = mean || 0;
2858 stdev = stdev || 1;
2859 var next;
2860 var f = function() {
2861 var x = 0, y = 0, rds, c;
2862 if (next !== undefined) {
2863 x = next;
2864 next = undefined;
2865 return x;
2866 }
2867 do {
2868 x = Math.random()*2-1;
2869 y = Math.random()*2-1;
2870 rds = x*x + y*y;
2871 } while (rds === 0 || rds > 1);
2872 c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform
2873 next = mean + y*c*stdev;
2874 return mean + x*c*stdev;
2875 };
2876 f.samples = function(n) { return gen.zeros(n).map(f); };
2877 return f;
2878 };
2879 },{}],15:[function(require,module,exports){
2880 var util = require('../../util');
2881 var d3_dsv = require('d3-dsv');
2882
2883 function dsv(data, format) {
2884 if (data) {
2885 var h = format.header;
2886 data = (h ? h.join(format.delimiter) + '\n' : '') + data;
2887 }
2888 return d3_dsv.dsv(format.delimiter).parse(data);
2889 }
2890
2891 dsv.delimiter = function(delim) {
2892 var fmt = {delimiter: delim};
2893 return function(data, format) {
2894 return dsv(data, format ? util.extend(format, fmt) : fmt);
2895 };
2896 };
2897
2898 module.exports = dsv;
2899 },{"../../util":29,"d3-dsv":3}],16:[function(require,module,exports){
2900 var dsv = require('./dsv');
2901
2902 module.exports = {
2903 json: require('./json'),
2904 topojson: require('./topojson'),
2905 treejson: require('./treejson'),
2906 dsv: dsv,
2907 csv: dsv.delimiter(','),
2908 tsv: dsv.delimiter('\t')
2909 };
2910 },{"./dsv":15,"./json":17,"./topojson":18,"./treejson":19}],17:[function(require,module,exports){
2911 var util = require('../../util');
2912
2913 module.exports = function(data, format) {
2914 var d = util.isObject(data) && !util.isBuffer(data) ?
2915 data : JSON.parse(data);
2916 if (format && format.property) {
2917 d = util.accessor(format.property)(d);
2918 }
2919 return d;
2920 };
2921
2922 },{"../../util":29}],18:[function(require,module,exports){
2923 (function (global){
2924 var json = require('./json');
2925
2926 var reader = function(data, format) {
2927 var topojson = reader.topojson;
2928 if (topojson == null) { throw Error('TopoJSON library not loaded.'); }
2929
2930 var t = json(data, format), obj;
2931
2932 if (format && format.feature) {
2933 if ((obj = t.objects[format.feature])) {
2934 return topojson.feature(t, obj).features;
2935 } else {
2936 throw Error('Invalid TopoJSON object: ' + format.feature);
2937 }
2938 } else if (format && format.mesh) {
2939 if ((obj = t.objects[format.mesh])) {
2940 return [topojson.mesh(t, t.objects[format.mesh])];
2941 } else {
2942 throw Error('Invalid TopoJSON object: ' + format.mesh);
2943 }
2944 } else {
2945 throw Error('Missing TopoJSON feature or mesh parameter.');
2946 }
2947 };
2948
2949 reader.topojson = (typeof window !== "undefined" ? window['topojson'] : typeof global !== "undefined" ? global['topojson'] : null);
2950 module.exports = reader;
2951 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2952
2953 },{"./json":17}],19:[function(require,module,exports){
2954 var json = require('./json');
2955
2956 module.exports = function(data, format) {
2957 data = json(data, format);
2958 return toTable(data, (format && format.children));
2959 };
2960
2961 function toTable(root, childrenField) {
2962 childrenField = childrenField || 'children';
2963 var table = [];
2964
2965 function visit(node) {
2966 table.push(node);
2967 var children = node[childrenField];
2968 if (children) {
2969 for (var i=0; i<children.length; ++i) {
2970 visit(children[i], node);
2971 }
2972 }
2973 }
2974
2975 visit(root, null);
2976 return (table.root = root, table);
2977 }
2978 },{"./json":17}],20:[function(require,module,exports){
2979 // Matches absolute URLs with optional protocol
2980 // https://... file://... //...
2981 var protocol_re = /^([A-Za-z]+:)?\/\//;
2982
2983 // Special treatment in node.js for the file: protocol
2984 var fileProtocol = 'file://';
2985
2986 // Validate and cleanup URL to ensure that it is allowed to be accessed
2987 // Returns cleaned up URL, or false if access is not allowed
2988 function sanitizeUrl(opt) {
2989 var url = opt.url;
2990 if (!url && opt.file) { return fileProtocol + opt.file; }
2991
2992 // In case this is a relative url (has no host), prepend opt.baseURL
2993 if (opt.baseURL && !protocol_re.test(url)) {
2994 if (!startsWith(url, '/') && opt.baseURL[opt.baseURL.length-1] !== '/') {
2995 url = '/' + url; // Ensure that there is a slash between the baseURL (e.g. hostname) and url
2996 }
2997 url = opt.baseURL + url;
2998 }
2999 // relative protocol, starts with '//'
3000 if (!load.useXHR && startsWith(url, '//')) {
3001 url = (opt.defaultProtocol || 'http') + ':' + url;
3002 }
3003 // If opt.domainWhiteList is set, only allows url, whose hostname
3004 // * Is the same as the origin (window.location.hostname)
3005 // * Equals one of the values in the whitelist
3006 // * Is a proper subdomain of one of the values in the whitelist
3007 if (opt.domainWhiteList) {
3008 var domain, origin;
3009 if (load.useXHR) {
3010 var a = document.createElement('a');
3011 a.href = url;
3012 // From http://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript
3013 // IE doesn't populate all link properties when setting .href with a relative URL,
3014 // however .href will return an absolute URL which then can be used on itself
3015 // to populate these additional fields.
3016 if (a.host === '') {
3017 a.href = a.href;
3018 }
3019 domain = a.hostname.toLowerCase();
3020 origin = window.location.hostname;
3021 } else {
3022 // relative protocol is broken: https://github.com/defunctzombie/node-url/issues/5
3023 var parts = require('url').parse(url);
3024 domain = parts.hostname;
3025 origin = null;
3026 }
3027
3028 if (origin !== domain) {
3029 var whiteListed = opt.domainWhiteList.some(function(d) {
3030 var idx = domain.length - d.length;
3031 return d === domain ||
3032 (idx > 1 && domain[idx-1] === '.' && domain.lastIndexOf(d) === idx);
3033 });
3034 if (!whiteListed) {
3035 throw 'URL is not whitelisted: ' + url;
3036 }
3037 }
3038 }
3039 return url;
3040 }
3041
3042 function load(opt, callback) {
3043 var error = callback || function(e) { throw e; }, url;
3044
3045 try {
3046 url = load.sanitizeUrl(opt); // enable override
3047 } catch (err) {
3048 error(err);
3049 return;
3050 }
3051
3052 if (!url) {
3053 error('Invalid URL: ' + opt.url);
3054 } else if (load.useXHR) {
3055 // on client, use xhr
3056 return xhr(url, callback);
3057 } else if (startsWith(url, fileProtocol)) {
3058 // on server, if url starts with 'file://', strip it and load from file
3059 return file(url.slice(fileProtocol.length), callback);
3060 } else if (url.indexOf('://') < 0) { // TODO better protocol check?
3061 // on server, if no protocol assume file
3062 return file(url, callback);
3063 } else {
3064 // for regular URLs on server
3065 return http(url, callback);
3066 }
3067 }
3068
3069 function xhrHasResponse(request) {
3070 var type = request.responseType;
3071 return type && type !== 'text' ?
3072 request.response : // null on error
3073 request.responseText; // '' on error
3074 }
3075
3076 function xhr(url, callback) {
3077 var async = !!callback;
3078 var request = new XMLHttpRequest();
3079 // If IE does not support CORS, use XDomainRequest (copied from d3.xhr)
3080 if (this.XDomainRequest &&
3081 !('withCredentials' in request) &&
3082 /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
3083
3084 function respond() {
3085 var status = request.status;
3086 if (!status && xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
3087 callback(null, request.responseText);
3088 } else {
3089 callback(request, null);
3090 }
3091 }
3092
3093 if (async) {
3094 if ('onload' in request) {
3095 request.onload = request.onerror = respond;
3096 } else {
3097 request.onreadystatechange = function() {
3098 if (request.readyState > 3) respond();
3099 };
3100 }
3101 }
3102
3103 request.open('GET', url, async);
3104 request.send();
3105
3106 if (!async && xhrHasResponse(request)) {
3107 return request.responseText;
3108 }
3109 }
3110
3111 function file(filename, callback) {
3112 var fs = require('fs');
3113 if (!callback) {
3114 return fs.readFileSync(filename, 'utf8');
3115 }
3116 fs.readFile(filename, callback);
3117 }
3118
3119 function http(url, callback) {
3120 if (!callback) {
3121 return require('sync-request')('GET', url).getBody();
3122 }
3123
3124 var options = {url: url, encoding: null, gzip: true};
3125 require('request')(options, function(error, response, body) {
3126 if (!error && response.statusCode === 200) {
3127 callback(null, body);
3128 } else {
3129 error = error ||
3130 'Load failed with response code ' + response.statusCode + '.';
3131 callback(error, null);
3132 }
3133 });
3134 }
3135
3136 function startsWith(string, searchString) {
3137 return string == null ? false : string.lastIndexOf(searchString, 0) === 0;
3138 }
3139
3140 load.sanitizeUrl = sanitizeUrl;
3141
3142 load.useXHR = (typeof XMLHttpRequest !== 'undefined');
3143
3144 module.exports = load;
3145
3146 },{"fs":2,"request":2,"sync-request":2,"url":2}],21:[function(require,module,exports){
3147 var util = require('../util');
3148 var type = require('./type');
3149 var formats = require('./formats');
3150
3151 function read(data, format) {
3152 var type = (format && format.type) || 'json';
3153 data = formats[type](data, format);
3154 if (format && format.parse) parse(data, format.parse);
3155 return data;
3156 }
3157
3158 function parse(data, types) {
3159 var cols, parsers, d, i, j, clen, len = data.length;
3160
3161 types = (types==='auto') ? type.inferAll(data) : util.duplicate(types);
3162 cols = util.keys(types);
3163 parsers = cols.map(function(c) { return type.parsers[types[c]]; });
3164
3165 for (i=0, clen=cols.length; i<len; ++i) {
3166 d = data[i];
3167 for (j=0; j<clen; ++j) {
3168 d[cols[j]] = parsers[j](d[cols[j]]);
3169 }
3170 }
3171 type.annotation(data, types);
3172 }
3173
3174 read.formats = formats;
3175 module.exports = read;
3176
3177 },{"../util":29,"./formats":16,"./type":23}],22:[function(require,module,exports){
3178 var util = require('../util');
3179 var load = require('./load');
3180 var read = require('./read');
3181
3182 module.exports = util
3183 .keys(read.formats)
3184 .reduce(function(out, type) {
3185 out[type] = function(opt, format, callback) {
3186 // process arguments
3187 if (util.isString(opt)) { opt = {url: opt}; }
3188 if (arguments.length === 2 && util.isFunction(format)) {
3189 callback = format;
3190 format = undefined;
3191 }
3192
3193 // set up read format
3194 format = util.extend({parse: 'auto'}, format);
3195 format.type = type;
3196
3197 // load data
3198 var data = load(opt, callback ? function(error, data) {
3199 if (error) { callback(error, null); return; }
3200 try {
3201 // data loaded, now parse it (async)
3202 data = read(data, format);
3203 callback(null, data);
3204 } catch (e) {
3205 callback(e, null);
3206 }
3207 } : undefined);
3208
3209 // data loaded, now parse it (sync)
3210 if (!callback) return read(data, format);
3211 };
3212 return out;
3213 }, {});
3214
3215 },{"../util":29,"./load":20,"./read":21}],23:[function(require,module,exports){
3216 var util = require('../util');
3217
3218 var TYPES = '__types__';
3219
3220 var PARSERS = {
3221 boolean: util.boolean,
3222 integer: util.number,
3223 number: util.number,
3224 date: util.date,
3225 string: function(x) { return x==='' ? null : x; }
3226 };
3227
3228 var TESTS = {
3229 boolean: function(x) { return x==='true' || x==='false' || util.isBoolean(x); },
3230 integer: function(x) { return TESTS.number(x) && (x=+x) === ~~x; },
3231 number: function(x) { return !isNaN(+x) && !util.isDate(x); },
3232 date: function(x) { return !isNaN(Date.parse(x)); }
3233 };
3234
3235 function annotation(data, types) {
3236 if (!types) return data && data[TYPES] || null;
3237 data[TYPES] = types;
3238 }
3239
3240 function type(values, f) {
3241 f = util.$(f);
3242 var v, i, n;
3243
3244 // if data array has type annotations, use them
3245 if (values[TYPES]) {
3246 v = f(values[TYPES]);
3247 if (util.isString(v)) return v;
3248 }
3249
3250 for (i=0, n=values.length; !util.isValid(v) && i<n; ++i) {
3251 v = f ? f(values[i]) : values[i];
3252 }
3253
3254 return util.isDate(v) ? 'date' :
3255 util.isNumber(v) ? 'number' :
3256 util.isBoolean(v) ? 'boolean' :
3257 util.isString(v) ? 'string' : null;
3258 }
3259
3260 function typeAll(data, fields) {
3261 if (!data.length) return;
3262 fields = fields || util.keys(data[0]);
3263 return fields.reduce(function(types, f) {
3264 return (types[f] = type(data, f), types);
3265 }, {});
3266 }
3267
3268 function infer(values, f) {
3269 f = util.$(f);
3270 var i, j, v;
3271
3272 // types to test for, in precedence order
3273 var types = ['boolean', 'integer', 'number', 'date'];
3274
3275 for (i=0; i<values.length; ++i) {
3276 // get next value to test
3277 v = f ? f(values[i]) : values[i];
3278 // test value against remaining types
3279 for (j=0; j<types.length; ++j) {
3280 if (util.isValid(v) && !TESTS[types[j]](v)) {
3281 types.splice(j, 1);
3282 j -= 1;
3283 }
3284 }
3285 // if no types left, return 'string'
3286 if (types.length === 0) return 'string';
3287 }
3288
3289 return types[0];
3290 }
3291
3292 function inferAll(data, fields) {
3293 fields = fields || util.keys(data[0]);
3294 return fields.reduce(function(types, f) {
3295 types[f] = infer(data, f);
3296 return types;
3297 }, {});
3298 }
3299
3300 type.annotation = annotation;
3301 type.all = typeAll;
3302 type.infer = infer;
3303 type.inferAll = inferAll;
3304 type.parsers = PARSERS;
3305 module.exports = type;
3306 },{"../util":29}],24:[function(require,module,exports){
3307 var util = require('./util');
3308
3309 var dl = {
3310 version: '1.4.6',
3311 load: require('./import/load'),
3312 read: require('./import/read'),
3313 type: require('./import/type'),
3314 Aggregator: require('./aggregate/aggregator'),
3315 groupby: require('./aggregate/groupby'),
3316 bins: require('./bins/bins'),
3317 $bin: require('./bins/histogram').$bin,
3318 histogram: require('./bins/histogram').histogram,
3319 format: require('./format'),
3320 print: require('./print'),
3321 template: require('./template'),
3322 time: require('./time')
3323 };
3324
3325 util.extend(dl, util);
3326 util.extend(dl, require('./generate'));
3327 util.extend(dl, require('./stats'));
3328 util.extend(dl, require('./import/readers'));
3329
3330 module.exports = dl;
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){
3332 var util = require('./util');
3333 var type = require('./import/type');
3334 var stats = require('./stats');
3335 var template = require('./template');
3336
3337 var FMT = {
3338 'date': '|time:"%m/%d/%Y %H:%M:%S"',
3339 'number': '|number:".4f"',
3340 'integer': '|number:"d"'
3341 };
3342
3343 var POS = {
3344 'number': 'left',
3345 'integer': 'left'
3346 };
3347
3348 module.exports.table = function(data, opt) {
3349 opt = util.extend({separator:' ', minwidth: 8, maxwidth: 15}, opt);
3350 var fields = opt.fields || util.keys(data[0]),
3351 types = type.all(data);
3352
3353 if (opt.start || opt.limit) {
3354 var a = opt.start || 0,
3355 b = opt.limit ? a + opt.limit : data.length;
3356 data = data.slice(a, b);
3357 }
3358
3359 // determine char width of fields
3360 var lens = fields.map(function(name) {
3361 var format = FMT[types[name]] || '',
3362 t = template('{{' + name + format + '}}'),
3363 l = stats.max(data, function(x) { return t(x).length; });
3364 l = Math.max(Math.min(name.length, opt.minwidth), l);
3365 return opt.maxwidth > 0 ? Math.min(l, opt.maxwidth) : l;
3366 });
3367
3368 // print header row
3369 var head = fields.map(function(name, i) {
3370 return util.truncate(util.pad(name, lens[i], 'center'), lens[i]);
3371 }).join(opt.separator);
3372
3373 // build template function for each row
3374 var tmpl = template(fields.map(function(name, i) {
3375 return '{{' +
3376 name +
3377 (FMT[types[name]] || '') +
3378 ('|pad:' + lens[i] + ',' + (POS[types[name]] || 'right')) +
3379 ('|truncate:' + lens[i]) +
3380 '}}';
3381 }).join(opt.separator));
3382
3383 // print table
3384 return head + "\n" + data.map(tmpl).join('\n');
3385 };
3386
3387 module.exports.summary = function(s) {
3388 s = s ? s.__summary__ ? s : stats.summary(s) : this;
3389 var str = [], i, n;
3390 for (i=0, n=s.length; i<n; ++i) {
3391 str.push('-- ' + s[i].field + ' --');
3392 if (s[i].type === 'string' || s[i].distinct < 10) {
3393 str.push(printCategoricalProfile(s[i]));
3394 } else {
3395 str.push(printQuantitativeProfile(s[i]));
3396 }
3397 str.push('');
3398 }
3399 return str.join('\n');
3400 };
3401
3402 function printQuantitativeProfile(p) {
3403 return [
3404 'valid: ' + p.valid,
3405 'missing: ' + p.missing,
3406 'distinct: ' + p.distinct,
3407 'min: ' + p.min,
3408 'max: ' + p.max,
3409 'median: ' + p.median,
3410 'mean: ' + p.mean,
3411 'stdev: ' + p.stdev,
3412 'modeskew: ' + p.modeskew
3413 ].join('\n');
3414 }
3415
3416 function printCategoricalProfile(p) {
3417 var list = [
3418 'valid: ' + p.valid,
3419 'missing: ' + p.missing,
3420 'distinct: ' + p.distinct,
3421 'top values: '
3422 ];
3423 var u = p.unique;
3424 var top = util.keys(u)
3425 .sort(function(a,b) { return u[b] - u[a]; })
3426 .slice(0, 6)
3427 .map(function(v) { return ' \'' + v + '\' (' + u[v] + ')'; });
3428 return list.concat(top).join('\n');
3429 }
3430 },{"./import/type":23,"./stats":26,"./template":27,"./util":29}],26:[function(require,module,exports){
3431 var util = require('./util');
3432 var type = require('./import/type');
3433 var gen = require('./generate');
3434 var stats = {};
3435
3436 // Collect unique values.
3437 // Output: an array of unique values, in first-observed order
3438 stats.unique = function(values, f, results) {
3439 f = util.$(f);
3440 results = results || [];
3441 var u = {}, v, i, n;
3442 for (i=0, n=values.length; i<n; ++i) {
3443 v = f ? f(values[i]) : values[i];
3444 if (v in u) continue;
3445 u[v] = 1;
3446 results.push(v);
3447 }
3448 return results;
3449 };
3450
3451 // Return the length of the input array.
3452 stats.count = function(values) {
3453 return values && values.length || 0;
3454 };
3455
3456 // Count the number of non-null, non-undefined, non-NaN values.
3457 stats.count.valid = function(values, f) {
3458 f = util.$(f);
3459 var v, i, n, valid = 0;
3460 for (i=0, n=values.length; i<n; ++i) {
3461 v = f ? f(values[i]) : values[i];
3462 if (util.isValid(v)) valid += 1;
3463 }
3464 return valid;
3465 };
3466
3467 // Count the number of null or undefined values.
3468 stats.count.missing = function(values, f) {
3469 f = util.$(f);
3470 var v, i, n, count = 0;
3471 for (i=0, n=values.length; i<n; ++i) {
3472 v = f ? f(values[i]) : values[i];
3473 if (v == null) count += 1;
3474 }
3475 return count;
3476 };
3477
3478 // Count the number of distinct values.
3479 // Null, undefined and NaN are each considered distinct values.
3480 stats.count.distinct = function(values, f) {
3481 f = util.$(f);
3482 var u = {}, v, i, n, count = 0;
3483 for (i=0, n=values.length; i<n; ++i) {
3484 v = f ? f(values[i]) : values[i];
3485 if (v in u) continue;
3486 u[v] = 1;
3487 count += 1;
3488 }
3489 return count;
3490 };
3491
3492 // Construct a map from distinct values to occurrence counts.
3493 stats.count.map = function(values, f) {
3494 f = util.$(f);
3495 var map = {}, v, i, n;
3496 for (i=0, n=values.length; i<n; ++i) {
3497 v = f ? f(values[i]) : values[i];
3498 map[v] = (v in map) ? map[v] + 1 : 1;
3499 }
3500 return map;
3501 };
3502
3503 // Compute the median of an array of numbers.
3504 stats.median = function(values, f) {
3505 if (f) values = values.map(util.$(f));
3506 values = values.filter(util.isValid).sort(util.cmp);
3507 return stats.quantile(values, 0.5);
3508 };
3509
3510 // Computes the quartile boundaries of an array of numbers.
3511 stats.quartile = function(values, f) {
3512 if (f) values = values.map(util.$(f));
3513 values = values.filter(util.isValid).sort(util.cmp);
3514 var q = stats.quantile;
3515 return [q(values, 0.25), q(values, 0.50), q(values, 0.75)];
3516 };
3517
3518 // Compute the quantile of a sorted array of numbers.
3519 // Adapted from the D3.js implementation.
3520 stats.quantile = function(values, f, p) {
3521 if (p === undefined) { p = f; f = util.identity; }
3522 f = util.$(f);
3523 var H = (values.length - 1) * p + 1,
3524 h = Math.floor(H),
3525 v = +f(values[h - 1]),
3526 e = H - h;
3527 return e ? v + e * (f(values[h]) - v) : v;
3528 };
3529
3530 // Compute the sum of an array of numbers.
3531 stats.sum = function(values, f) {
3532 f = util.$(f);
3533 for (var sum=0, i=0, n=values.length, v; i<n; ++i) {
3534 v = f ? f(values[i]) : values[i];
3535 if (util.isValid(v)) sum += v;
3536 }
3537 return sum;
3538 };
3539
3540 // Compute the mean (average) of an array of numbers.
3541 stats.mean = function(values, f) {
3542 f = util.$(f);
3543 var mean = 0, delta, i, n, c, v;
3544 for (i=0, c=0, n=values.length; i<n; ++i) {
3545 v = f ? f(values[i]) : values[i];
3546 if (util.isValid(v)) {
3547 delta = v - mean;
3548 mean = mean + delta / (++c);
3549 }
3550 }
3551 return mean;
3552 };
3553
3554 // Compute the sample variance of an array of numbers.
3555 stats.variance = function(values, f) {
3556 f = util.$(f);
3557 if (!util.isArray(values) || values.length < 2) return 0;
3558 var mean = 0, M2 = 0, delta, i, c, v;
3559 for (i=0, c=0; i<values.length; ++i) {
3560 v = f ? f(values[i]) : values[i];
3561 if (util.isValid(v)) {
3562 delta = v - mean;
3563 mean = mean + delta / (++c);
3564 M2 = M2 + delta * (v - mean);
3565 }
3566 }
3567 M2 = M2 / (c - 1);
3568 return M2;
3569 };
3570
3571 // Compute the sample standard deviation of an array of numbers.
3572 stats.stdev = function(values, f) {
3573 return Math.sqrt(stats.variance(values, f));
3574 };
3575
3576 // Compute the Pearson mode skewness ((median-mean)/stdev) of an array of numbers.
3577 stats.modeskew = function(values, f) {
3578 var avg = stats.mean(values, f),
3579 med = stats.median(values, f),
3580 std = stats.stdev(values, f);
3581 return std === 0 ? 0 : (avg - med) / std;
3582 };
3583
3584 // Find the minimum value in an array.
3585 stats.min = function(values, f) {
3586 return stats.extent(values, f)[0];
3587 };
3588
3589 // Find the maximum value in an array.
3590 stats.max = function(values, f) {
3591 return stats.extent(values, f)[1];
3592 };
3593
3594 // Find the minimum and maximum of an array of values.
3595 stats.extent = function(values, f) {
3596 f = util.$(f);
3597 var a, b, v, i, n = values.length;
3598 for (i=0; i<n; ++i) {
3599 v = f ? f(values[i]) : values[i];
3600 if (util.isValid(v)) { a = b = v; break; }
3601 }
3602 for (; i<n; ++i) {
3603 v = f ? f(values[i]) : values[i];
3604 if (util.isValid(v)) {
3605 if (v < a) a = v;
3606 if (v > b) b = v;
3607 }
3608 }
3609 return [a, b];
3610 };
3611
3612 // Find the integer indices of the minimum and maximum values.
3613 stats.extent.index = function(values, f) {
3614 f = util.$(f);
3615 var x = -1, y = -1, a, b, v, i, n = values.length;
3616 for (i=0; i<n; ++i) {
3617 v = f ? f(values[i]) : values[i];
3618 if (util.isValid(v)) { a = b = v; x = y = i; break; }
3619 }
3620 for (; i<n; ++i) {
3621 v = f ? f(values[i]) : values[i];
3622 if (util.isValid(v)) {
3623 if (v < a) { a = v; x = i; }
3624 if (v > b) { b = v; y = i; }
3625 }
3626 }
3627 return [x, y];
3628 };
3629
3630 // Compute the dot product of two arrays of numbers.
3631 stats.dot = function(values, a, b) {
3632 var sum = 0, i, v;
3633 if (!b) {
3634 if (values.length !== a.length) {
3635 throw Error('Array lengths must match.');
3636 }
3637 for (i=0; i<values.length; ++i) {
3638 v = values[i] * a[i];
3639 if (v === v) sum += v;
3640 }
3641 } else {
3642 a = util.$(a);
3643 b = util.$(b);
3644 for (i=0; i<values.length; ++i) {
3645 v = a(values[i]) * b(values[i]);
3646 if (v === v) sum += v;
3647 }
3648 }
3649 return sum;
3650 };
3651
3652 // Compute ascending rank scores for an array of values.
3653 // Ties are assigned their collective mean rank.
3654 stats.rank = function(values, f) {
3655 f = util.$(f) || util.identity;
3656 var a = values.map(function(v, i) {
3657 return {idx: i, val: f(v)};
3658 })
3659 .sort(util.comparator('val'));
3660
3661 var n = values.length,
3662 r = Array(n),
3663 tie = -1, p = {}, i, v, mu;
3664
3665 for (i=0; i<n; ++i) {
3666 v = a[i].val;
3667 if (tie < 0 && p === v) {
3668 tie = i - 1;
3669 } else if (tie > -1 && p !== v) {
3670 mu = 1 + (i-1 + tie) / 2;
3671 for (; tie<i; ++tie) r[a[tie].idx] = mu;
3672 tie = -1;
3673 }
3674 r[a[i].idx] = i + 1;
3675 p = v;
3676 }
3677
3678 if (tie > -1) {
3679 mu = 1 + (n-1 + tie) / 2;
3680 for (; tie<n; ++tie) r[a[tie].idx] = mu;
3681 }
3682
3683 return r;
3684 };
3685
3686 // Compute the sample Pearson product-moment correlation of two arrays of numbers.
3687 stats.cor = function(values, a, b) {
3688 var fn = b;
3689 b = fn ? values.map(util.$(b)) : a;
3690 a = fn ? values.map(util.$(a)) : values;
3691
3692 var dot = stats.dot(a, b),
3693 mua = stats.mean(a),
3694 mub = stats.mean(b),
3695 sda = stats.stdev(a),
3696 sdb = stats.stdev(b),
3697 n = values.length;
3698
3699 return (dot - n*mua*mub) / ((n-1) * sda * sdb);
3700 };
3701
3702 // Compute the Spearman rank correlation of two arrays of values.
3703 stats.cor.rank = function(values, a, b) {
3704 var ra = b ? stats.rank(values, util.$(a)) : stats.rank(values),
3705 rb = b ? stats.rank(values, util.$(b)) : stats.rank(a),
3706 n = values.length, i, s, d;
3707
3708 for (i=0, s=0; i<n; ++i) {
3709 d = ra[i] - rb[i];
3710 s += d * d;
3711 }
3712
3713 return 1 - 6*s / (n * (n*n-1));
3714 };
3715
3716 // Compute the distance correlation of two arrays of numbers.
3717 // http://en.wikipedia.org/wiki/Distance_correlation
3718 stats.cor.dist = function(values, a, b) {
3719 var X = b ? values.map(util.$(a)) : values,
3720 Y = b ? values.map(util.$(b)) : a;
3721
3722 var A = stats.dist.mat(X),
3723 B = stats.dist.mat(Y),
3724 n = A.length,
3725 i, aa, bb, ab;
3726
3727 for (i=0, aa=0, bb=0, ab=0; i<n; ++i) {
3728 aa += A[i]*A[i];
3729 bb += B[i]*B[i];
3730 ab += A[i]*B[i];
3731 }
3732
3733 return Math.sqrt(ab / Math.sqrt(aa*bb));
3734 };
3735
3736 // Compute the vector distance between two arrays of numbers.
3737 // Default is Euclidean (exp=2) distance, configurable via exp argument.
3738 stats.dist = function(values, a, b, exp) {
3739 var f = util.isFunction(b) || util.isString(b),
3740 X = values,
3741 Y = f ? values : a,
3742 e = f ? exp : b,
3743 L2 = e === 2 || e == null,
3744 n = values.length, s = 0, d, i;
3745 if (f) {
3746 a = util.$(a);
3747 b = util.$(b);
3748 }
3749 for (i=0; i<n; ++i) {
3750 d = f ? (a(X[i])-b(Y[i])) : (X[i]-Y[i]);
3751 s += L2 ? d*d : Math.pow(Math.abs(d), e);
3752 }
3753 return L2 ? Math.sqrt(s) : Math.pow(s, 1/e);
3754 };
3755
3756 // Construct a mean-centered distance matrix for an array of numbers.
3757 stats.dist.mat = function(X) {
3758 var n = X.length,
3759 m = n*n,
3760 A = Array(m),
3761 R = gen.zeros(n),
3762 M = 0, v, i, j;
3763
3764 for (i=0; i<n; ++i) {
3765 A[i*n+i] = 0;
3766 for (j=i+1; j<n; ++j) {
3767 A[i*n+j] = (v = Math.abs(X[i] - X[j]));
3768 A[j*n+i] = v;
3769 R[i] += v;
3770 R[j] += v;
3771 }
3772 }
3773
3774 for (i=0; i<n; ++i) {
3775 M += R[i];
3776 R[i] /= n;
3777 }
3778 M /= m;
3779
3780 for (i=0; i<n; ++i) {
3781 for (j=i; j<n; ++j) {
3782 A[i*n+j] += M - R[i] - R[j];
3783 A[j*n+i] = A[i*n+j];
3784 }
3785 }
3786
3787 return A;
3788 };
3789
3790 // Compute the Shannon entropy (log base 2) of an array of counts.
3791 stats.entropy = function(counts, f) {
3792 f = util.$(f);
3793 var i, p, s = 0, H = 0, n = counts.length;
3794 for (i=0; i<n; ++i) {
3795 s += (f ? f(counts[i]) : counts[i]);
3796 }
3797 if (s === 0) return 0;
3798 for (i=0; i<n; ++i) {
3799 p = (f ? f(counts[i]) : counts[i]) / s;
3800 if (p) H += p * Math.log(p);
3801 }
3802 return -H / Math.LN2;
3803 };
3804
3805 // Compute the mutual information between two discrete variables.
3806 // Returns an array of the form [MI, MI_distance]
3807 // MI_distance is defined as 1 - I(a,b) / H(a,b).
3808 // http://en.wikipedia.org/wiki/Mutual_information
3809 stats.mutual = function(values, a, b, counts) {
3810 var x = counts ? values.map(util.$(a)) : values,
3811 y = counts ? values.map(util.$(b)) : a,
3812 z = counts ? values.map(util.$(counts)) : b;
3813
3814 var px = {},
3815 py = {},
3816 n = z.length,
3817 s = 0, I = 0, H = 0, p, t, i;
3818
3819 for (i=0; i<n; ++i) {
3820 px[x[i]] = 0;
3821 py[y[i]] = 0;
3822 }
3823
3824 for (i=0; i<n; ++i) {
3825 px[x[i]] += z[i];
3826 py[y[i]] += z[i];
3827 s += z[i];
3828 }
3829
3830 t = 1 / (s * Math.LN2);
3831 for (i=0; i<n; ++i) {
3832 if (z[i] === 0) continue;
3833 p = (s * z[i]) / (px[x[i]] * py[y[i]]);
3834 I += z[i] * t * Math.log(p);
3835 H += z[i] * t * Math.log(z[i]/s);
3836 }
3837
3838 return [I, 1 + I/H];
3839 };
3840
3841 // Compute the mutual information between two discrete variables.
3842 stats.mutual.info = function(values, a, b, counts) {
3843 return stats.mutual(values, a, b, counts)[0];
3844 };
3845
3846 // Compute the mutual information distance between two discrete variables.
3847 // MI_distance is defined as 1 - I(a,b) / H(a,b).
3848 stats.mutual.dist = function(values, a, b, counts) {
3849 return stats.mutual(values, a, b, counts)[1];
3850 };
3851
3852 // Compute a profile of summary statistics for a variable.
3853 stats.profile = function(values, f) {
3854 var mean = 0,
3855 valid = 0,
3856 missing = 0,
3857 distinct = 0,
3858 min = null,
3859 max = null,
3860 M2 = 0,
3861 vals = [],
3862 u = {}, delta, sd, i, v, x;
3863
3864 // compute summary stats
3865 for (i=0; i<values.length; ++i) {
3866 v = f ? f(values[i]) : values[i];
3867
3868 // update unique values
3869 u[v] = (v in u) ? u[v] + 1 : (distinct += 1, 1);
3870
3871 if (v == null) {
3872 ++missing;
3873 } else if (util.isValid(v)) {
3874 // update stats
3875 x = (typeof v === 'string') ? v.length : v;
3876 if (min===null || x < min) min = x;
3877 if (max===null || x > max) max = x;
3878 delta = x - mean;
3879 mean = mean + delta / (++valid);
3880 M2 = M2 + delta * (x - mean);
3881 vals.push(x);
3882 }
3883 }
3884 M2 = M2 / (valid - 1);
3885 sd = Math.sqrt(M2);
3886
3887 // sort values for median and iqr
3888 vals.sort(util.cmp);
3889
3890 return {
3891 type: type(values, f),
3892 unique: u,
3893 count: values.length,
3894 valid: valid,
3895 missing: missing,
3896 distinct: distinct,
3897 min: min,
3898 max: max,
3899 mean: mean,
3900 stdev: sd,
3901 median: (v = stats.quantile(vals, 0.5)),
3902 q1: stats.quantile(vals, 0.25),
3903 q3: stats.quantile(vals, 0.75),
3904 modeskew: sd === 0 ? 0 : (mean - v) / sd
3905 };
3906 };
3907
3908 // Compute profiles for all variables in a data set.
3909 stats.summary = function(data, fields) {
3910 fields = fields || util.keys(data[0]);
3911 var s = fields.map(function(f) {
3912 var p = stats.profile(data, util.$(f));
3913 return (p.field = f, p);
3914 });
3915 return (s.__summary__ = true, s);
3916 };
3917
3918 module.exports = stats;
3919 },{"./generate":14,"./import/type":23,"./util":29}],27:[function(require,module,exports){
3920 var util = require('./util'),
3921 format = require('./format');
3922
3923 var context = {
3924 formats: [],
3925 format_map: {},
3926 truncate: util.truncate,
3927 pad: util.pad
3928 };
3929
3930 function template(text) {
3931 var src = source(text, 'd');
3932 src = 'var __t; return ' + src + ';';
3933
3934 /* jshint evil: true */
3935 return (new Function('d', src)).bind(context);
3936 }
3937
3938 template.source = source;
3939 template.context = context;
3940 module.exports = template;
3941
3942 // Clear cache of format objects.
3943 // This can *break* prior template functions, so invoke with care!
3944 template.clearFormatCache = function() {
3945 context.formats = [];
3946 context.format_map = {};
3947 };
3948
3949 // Generate property access code for use within template source.
3950 // object: the name of the object (variable) containing template data
3951 // property: the property access string, verbatim from template tag
3952 template.property = function(object, property) {
3953 var src = util.field(property).map(util.str).join('][');
3954 return object + '[' + src + ']';
3955 };
3956
3957 // Generate source code for a template function.
3958 // text: the template text
3959 // variable: the name of the data object variable ('obj' by default)
3960 // properties: optional hash for collecting all accessed properties
3961 function source(text, variable, properties) {
3962 variable = variable || 'obj';
3963 var index = 0;
3964 var src = '\'';
3965 var regex = template_re;
3966
3967 // Compile the template source, escaping string literals appropriately.
3968 text.replace(regex, function(match, interpolate, offset) {
3969 src += text
3970 .slice(index, offset)
3971 .replace(template_escaper, template_escapeChar);
3972 index = offset + match.length;
3973
3974 if (interpolate) {
3975 src += '\'\n+((__t=(' +
3976 template_var(interpolate, variable, properties) +
3977 '))==null?\'\':__t)+\n\'';
3978 }
3979
3980 // Adobe VMs need the match returned to produce the correct offest.
3981 return match;
3982 });
3983 return src + '\'';
3984 }
3985
3986 function template_var(text, variable, properties) {
3987 var filters = text.match(filter_re);
3988 var prop = filters.shift().trim();
3989 var stringCast = true;
3990
3991 function strcall(fn) {
3992 fn = fn || '';
3993 if (stringCast) {
3994 stringCast = false;
3995 src = 'String(' + src + ')' + fn;
3996 } else {
3997 src += fn;
3998 }
3999 return src;
4000 }
4001
4002 function date() {
4003 return '(typeof ' + src + '==="number"?new Date('+src+'):'+src+')';
4004 }
4005
4006 function number_format(fmt, key) {
4007 a = template_format(args[0], key, fmt);
4008 stringCast = false;
4009 src = 'this.formats['+a+']('+src+')';
4010 }
4011
4012 function time_format(fmt, key) {
4013 a = template_format(args[0], key, fmt);
4014 stringCast = false;
4015 src = 'this.formats['+a+']('+date()+')';
4016 }
4017
4018 if (properties) properties[prop] = 1;
4019 var src = template.property(variable, prop);
4020
4021 for (var i=0; i<filters.length; ++i) {
4022 var f = filters[i], args = null, pidx, a, b;
4023
4024 if ((pidx=f.indexOf(':')) > 0) {
4025 f = f.slice(0, pidx);
4026 args = filters[i].slice(pidx+1)
4027 .match(args_re)
4028 .map(function(s) { return s.trim(); });
4029 }
4030 f = f.trim();
4031
4032 switch (f) {
4033 case 'length':
4034 strcall('.length');
4035 break;
4036 case 'lower':
4037 strcall('.toLowerCase()');
4038 break;
4039 case 'upper':
4040 strcall('.toUpperCase()');
4041 break;
4042 case 'lower-locale':
4043 strcall('.toLocaleLowerCase()');
4044 break;
4045 case 'upper-locale':
4046 strcall('.toLocaleUpperCase()');
4047 break;
4048 case 'trim':
4049 strcall('.trim()');
4050 break;
4051 case 'left':
4052 a = util.number(args[0]);
4053 strcall('.slice(0,' + a + ')');
4054 break;
4055 case 'right':
4056 a = util.number(args[0]);
4057 strcall('.slice(-' + a +')');
4058 break;
4059 case 'mid':
4060 a = util.number(args[0]);
4061 b = a + util.number(args[1]);
4062 strcall('.slice(+'+a+','+b+')');
4063 break;
4064 case 'slice':
4065 a = util.number(args[0]);
4066 strcall('.slice('+ a +
4067 (args.length > 1 ? ',' + util.number(args[1]) : '') +
4068 ')');
4069 break;
4070 case 'truncate':
4071 a = util.number(args[0]);
4072 b = args[1];
4073 b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b;
4074 src = 'this.truncate(' + strcall() + ',' + a + ',\'' + b + '\')';
4075 break;
4076 case 'pad':
4077 a = util.number(args[0]);
4078 b = args[1];
4079 b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b;
4080 src = 'this.pad(' + strcall() + ',' + a + ',\'' + b + '\')';
4081 break;
4082 case 'number':
4083 number_format(format.number, 'number');
4084 break;
4085 case 'time':
4086 time_format(format.time, 'time');
4087 break;
4088 case 'time-utc':
4089 time_format(format.utc, 'time-utc');
4090 break;
4091 default:
4092 throw Error('Unrecognized template filter: ' + f);
4093 }
4094 }
4095
4096 return src;
4097 }
4098
4099 var template_re = /\{\{(.+?)\}\}|$/g,
4100 filter_re = /(?:"[^"]*"|\'[^\']*\'|[^\|"]+|[^\|\']+)+/g,
4101 args_re = /(?:"[^"]*"|\'[^\']*\'|[^,"]+|[^,\']+)+/g;
4102
4103 // Certain characters need to be escaped so that they can be put into a
4104 // string literal.
4105 var template_escapes = {
4106 '\'': '\'',
4107 '\\': '\\',
4108 '\r': 'r',
4109 '\n': 'n',
4110 '\u2028': 'u2028',
4111 '\u2029': 'u2029'
4112 };
4113
4114 var template_escaper = /\\|'|\r|\n|\u2028|\u2029/g;
4115
4116 function template_escapeChar(match) {
4117 return '\\' + template_escapes[match];
4118 }
4119
4120 function template_format(pattern, key, fmt) {
4121 if ((pattern[0] === '\'' && pattern[pattern.length-1] === '\'') ||
4122 (pattern[0] === '"' && pattern[pattern.length-1] === '"')) {
4123 pattern = pattern.slice(1, -1);
4124 } else {
4125 throw Error('Format pattern must be quoted: ' + pattern);
4126 }
4127 key = key + ':' + pattern;
4128 if (!context.format_map[key]) {
4129 var f = fmt(pattern);
4130 var i = context.formats.length;
4131 context.formats.push(f);
4132 context.format_map[key] = i;
4133 }
4134 return context.format_map[key];
4135 }
4136
4137 },{"./format":13,"./util":29}],28:[function(require,module,exports){
4138 var d3_time = require('d3-time');
4139
4140 var tempDate = new Date(),
4141 baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD
4142 utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0);
4143
4144 function date(d) {
4145 return (tempDate.setTime(+d), tempDate);
4146 }
4147
4148 // create a time unit entry
4149 function entry(type, date, unit, step, min, max) {
4150 var e = {
4151 type: type,
4152 date: date,
4153 unit: unit
4154 };
4155 if (step) {
4156 e.step = step;
4157 } else {
4158 e.minstep = 1;
4159 }
4160 if (min != null) e.min = min;
4161 if (max != null) e.max = max;
4162 return e;
4163 }
4164
4165 function create(type, unit, base, step, min, max) {
4166 return entry(type,
4167 function(d) { return unit.offset(base, d); },
4168 function(d) { return unit.count(base, d); },
4169 step, min, max);
4170 }
4171
4172 var locale = [
4173 create('second', d3_time.second, baseDate),
4174 create('minute', d3_time.minute, baseDate),
4175 create('hour', d3_time.hour, baseDate),
4176 create('day', d3_time.day, baseDate, [1, 7]),
4177 create('month', d3_time.month, baseDate, [1, 3, 6]),
4178 create('year', d3_time.year, baseDate),
4179
4180 // periodic units
4181 entry('seconds',
4182 function(d) { return new Date(1970, 0, 1, 0, 0, d); },
4183 function(d) { return date(d).getSeconds(); },
4184 null, 0, 59
4185 ),
4186 entry('minutes',
4187 function(d) { return new Date(1970, 0, 1, 0, d); },
4188 function(d) { return date(d).getMinutes(); },
4189 null, 0, 59
4190 ),
4191 entry('hours',
4192 function(d) { return new Date(1970, 0, 1, d); },
4193 function(d) { return date(d).getHours(); },
4194 null, 0, 23
4195 ),
4196 entry('weekdays',
4197 function(d) { return new Date(1970, 0, 4+d); },
4198 function(d) { return date(d).getDay(); },
4199 [1], 0, 6
4200 ),
4201 entry('dates',
4202 function(d) { return new Date(1970, 0, d); },
4203 function(d) { return date(d).getDate(); },
4204 [1], 1, 31
4205 ),
4206 entry('months',
4207 function(d) { return new Date(1970, d % 12, 1); },
4208 function(d) { return date(d).getMonth(); },
4209 [1], 0, 11
4210 )
4211 ];
4212
4213 var utc = [
4214 create('second', d3_time.utcSecond, utcBaseDate),
4215 create('minute', d3_time.utcMinute, utcBaseDate),
4216 create('hour', d3_time.utcHour, utcBaseDate),
4217 create('day', d3_time.utcDay, utcBaseDate, [1, 7]),
4218 create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]),
4219 create('year', d3_time.utcYear, utcBaseDate),
4220
4221 // periodic units
4222 entry('seconds',
4223 function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); },
4224 function(d) { return date(d).getUTCSeconds(); },
4225 null, 0, 59
4226 ),
4227 entry('minutes',
4228 function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); },
4229 function(d) { return date(d).getUTCMinutes(); },
4230 null, 0, 59
4231 ),
4232 entry('hours',
4233 function(d) { return new Date(Date.UTC(1970, 0, 1, d)); },
4234 function(d) { return date(d).getUTCHours(); },
4235 null, 0, 23
4236 ),
4237 entry('weekdays',
4238 function(d) { return new Date(Date.UTC(1970, 0, 4+d)); },
4239 function(d) { return date(d).getUTCDay(); },
4240 [1], 0, 6
4241 ),
4242 entry('dates',
4243 function(d) { return new Date(Date.UTC(1970, 0, d)); },
4244 function(d) { return date(d).getUTCDate(); },
4245 [1], 1, 31
4246 ),
4247 entry('months',
4248 function(d) { return new Date(Date.UTC(1970, d % 12, 1)); },
4249 function(d) { return date(d).getUTCMonth(); },
4250 [1], 0, 11
4251 )
4252 ];
4253
4254 var STEPS = [
4255 [31536e6, 5], // 1-year
4256 [7776e6, 4], // 3-month
4257 [2592e6, 4], // 1-month
4258 [12096e5, 3], // 2-week
4259 [6048e5, 3], // 1-week
4260 [1728e5, 3], // 2-day
4261 [864e5, 3], // 1-day
4262 [432e5, 2], // 12-hour
4263 [216e5, 2], // 6-hour
4264 [108e5, 2], // 3-hour
4265 [36e5, 2], // 1-hour
4266 [18e5, 1], // 30-minute
4267 [9e5, 1], // 15-minute
4268 [3e5, 1], // 5-minute
4269 [6e4, 1], // 1-minute
4270 [3e4, 0], // 30-second
4271 [15e3, 0], // 15-second
4272 [5e3, 0], // 5-second
4273 [1e3, 0] // 1-second
4274 ];
4275
4276 function find(units, span, minb, maxb) {
4277 var step = STEPS[0], i, n, bins;
4278
4279 for (i=1, n=STEPS.length; i<n; ++i) {
4280 step = STEPS[i];
4281 if (span > step[0]) {
4282 bins = span / step[0];
4283 if (bins > maxb) {
4284 return units[STEPS[i-1][1]];
4285 }
4286 if (bins >= minb) {
4287 return units[step[1]];
4288 }
4289 }
4290 }
4291 return units[STEPS[n-1][1]];
4292 }
4293
4294 function toUnitMap(units) {
4295 var map = {}, i, n;
4296 for (i=0, n=units.length; i<n; ++i) {
4297 map[units[i].type] = units[i];
4298 }
4299 map.find = function(span, minb, maxb) {
4300 return find(units, span, minb, maxb);
4301 };
4302 return map;
4303 }
4304
4305 module.exports = toUnitMap(locale);
4306 module.exports.utc = toUnitMap(utc);
4307
4308 },{"d3-time":6}],29:[function(require,module,exports){
4309 var buffer = require('buffer'),
4310 time = require('./time'),
4311 utc = time.utc;
4312
4313 var u = module.exports = {};
4314
4315 // utility functions
4316
4317 var FNAME = '__name__';
4318
4319 u.namedfunc = function(name, f) { return (f[FNAME] = name, f); };
4320
4321 u.name = function(f) { return f==null ? null : f[FNAME]; };
4322
4323 u.identity = function(x) { return x; };
4324
4325 u.true = u.namedfunc('true', function() { return true; });
4326
4327 u.false = u.namedfunc('false', function() { return false; });
4328
4329 u.duplicate = function(obj) {
4330 return JSON.parse(JSON.stringify(obj));
4331 };
4332
4333 u.equal = function(a, b) {
4334 return JSON.stringify(a) === JSON.stringify(b);
4335 };
4336
4337 u.extend = function(obj) {
4338 for (var x, name, i=1, len=arguments.length; i<len; ++i) {
4339 x = arguments[i];
4340 for (name in x) { obj[name] = x[name]; }
4341 }
4342 return obj;
4343 };
4344
4345 u.length = function(x) {
4346 return x != null && x.length != null ? x.length : null;
4347 };
4348
4349 u.keys = function(x) {
4350 var keys = [], k;
4351 for (k in x) keys.push(k);
4352 return keys;
4353 };
4354
4355 u.vals = function(x) {
4356 var vals = [], k;
4357 for (k in x) vals.push(x[k]);
4358 return vals;
4359 };
4360
4361 u.toMap = function(list, f) {
4362 return (f = u.$(f)) ?
4363 list.reduce(function(obj, x) { return (obj[f(x)] = 1, obj); }, {}) :
4364 list.reduce(function(obj, x) { return (obj[x] = 1, obj); }, {});
4365 };
4366
4367 u.keystr = function(values) {
4368 // use to ensure consistent key generation across modules
4369 var n = values.length;
4370 if (!n) return '';
4371 for (var s=String(values[0]), i=1; i<n; ++i) {
4372 s += '|' + String(values[i]);
4373 }
4374 return s;
4375 };
4376
4377 // type checking functions
4378
4379 var toString = Object.prototype.toString;
4380
4381 u.isObject = function(obj) {
4382 return obj === Object(obj);
4383 };
4384
4385 u.isFunction = function(obj) {
4386 return toString.call(obj) === '[object Function]';
4387 };
4388
4389 u.isString = function(obj) {
4390 return typeof value === 'string' || toString.call(obj) === '[object String]';
4391 };
4392
4393 u.isArray = Array.isArray || function(obj) {
4394 return toString.call(obj) === '[object Array]';
4395 };
4396
4397 u.isNumber = function(obj) {
4398 return typeof obj === 'number' || toString.call(obj) === '[object Number]';
4399 };
4400
4401 u.isBoolean = function(obj) {
4402 return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
4403 };
4404
4405 u.isDate = function(obj) {
4406 return toString.call(obj) === '[object Date]';
4407 };
4408
4409 u.isValid = function(obj) {
4410 return obj != null && obj === obj;
4411 };
4412
4413 u.isBuffer = (buffer.Buffer && buffer.Buffer.isBuffer) || u.false;
4414
4415 // type coercion functions
4416
4417 u.number = function(s) {
4418 return s == null || s === '' ? null : +s;
4419 };
4420
4421 u.boolean = function(s) {
4422 return s == null || s === '' ? null : s==='false' ? false : !!s;
4423 };
4424
4425 u.date = function(s) {
4426 return s == null || s === '' ? null : Date.parse(s);
4427 };
4428
4429 u.array = function(x) {
4430 return x != null ? (u.isArray(x) ? x : [x]) : [];
4431 };
4432
4433 u.str = function(x) {
4434 return u.isArray(x) ? '[' + x.map(u.str) + ']'
4435 : u.isObject(x) ? JSON.stringify(x)
4436 : u.isString(x) ? ('\''+util_escape_str(x)+'\'') : x;
4437 };
4438
4439 var escape_str_re = /(^|[^\\])'/g;
4440
4441 function util_escape_str(x) {
4442 return x.replace(escape_str_re, '$1\\\'');
4443 }
4444
4445 // data access functions
4446
4447 var field_re = /\[(.*?)\]|[^.\[]+/g;
4448
4449 u.field = function(f) {
4450 return String(f).match(field_re).map(function(d) {
4451 return d[0] !== '[' ? d :
4452 d[1] !== "'" && d[1] !== '"' ? d.slice(1, -1) :
4453 d.slice(2, -2).replace(/\\(["'])/g, '$1');
4454 });
4455 };
4456
4457 u.accessor = function(f) {
4458 var s;
4459 return f==null || u.isFunction(f) ? f :
4460 u.namedfunc(f, (s = u.field(f)).length > 1 ?
4461 function(x) { return s.reduce(function(x,f) { return x[f]; }, x); } :
4462 function(x) { return x[f]; }
4463 );
4464 };
4465
4466 // short-cut for accessor
4467 u.$ = u.accessor;
4468
4469 u.mutator = function(f) {
4470 var s;
4471 return u.isString(f) && (s=u.field(f)).length > 1 ?
4472 function(x, v) {
4473 for (var i=0; i<s.length-1; ++i) x = x[s[i]];
4474 x[s[i]] = v;
4475 } :
4476 function(x, v) { x[f] = v; };
4477 };
4478
4479
4480 u.$func = function(name, op) {
4481 return function(f) {
4482 f = u.$(f) || u.identity;
4483 var n = name + (u.name(f) ? '_'+u.name(f) : '');
4484 return u.namedfunc(n, function(d) { return op(f(d)); });
4485 };
4486 };
4487
4488 u.$valid = u.$func('valid', u.isValid);
4489 u.$length = u.$func('length', u.length);
4490
4491 u.$in = function(f, values) {
4492 f = u.$(f);
4493 var map = u.isArray(values) ? u.toMap(values) : values;
4494 return function(d) { return !!map[f(d)]; };
4495 };
4496
4497 u.$year = u.$func('year', time.year.unit);
4498 u.$month = u.$func('month', time.months.unit);
4499 u.$date = u.$func('date', time.dates.unit);
4500 u.$day = u.$func('day', time.weekdays.unit);
4501 u.$hour = u.$func('hour', time.hours.unit);
4502 u.$minute = u.$func('minute', time.minutes.unit);
4503 u.$second = u.$func('second', time.seconds.unit);
4504
4505 u.$utcYear = u.$func('utcYear', utc.year.unit);
4506 u.$utcMonth = u.$func('utcMonth', utc.months.unit);
4507 u.$utcDate = u.$func('utcDate', utc.dates.unit);
4508 u.$utcDay = u.$func('utcDay', utc.weekdays.unit);
4509 u.$utcHour = u.$func('utcHour', utc.hours.unit);
4510 u.$utcMinute = u.$func('utcMinute', utc.minutes.unit);
4511 u.$utcSecond = u.$func('utcSecond', utc.seconds.unit);
4512
4513 // comparison / sorting functions
4514
4515 u.comparator = function(sort) {
4516 var sign = [];
4517 if (sort === undefined) sort = [];
4518 sort = u.array(sort).map(function(f) {
4519 var s = 1;
4520 if (f[0] === '-') { s = -1; f = f.slice(1); }
4521 else if (f[0] === '+') { s = +1; f = f.slice(1); }
4522 sign.push(s);
4523 return u.accessor(f);
4524 });
4525 return function(a,b) {
4526 var i, n, f, x, y;
4527 for (i=0, n=sort.length; i<n; ++i) {
4528 f = sort[i]; x = f(a); y = f(b);
4529 if (x < y) return -1 * sign[i];
4530 if (x > y) return sign[i];
4531 }
4532 return 0;
4533 };
4534 };
4535
4536 u.cmp = function(a, b) {
4537 if (a < b) {
4538 return -1;
4539 } else if (a > b) {
4540 return 1;
4541 } else if (a >= b) {
4542 return 0;
4543 } else if (a === null) {
4544 return -1;
4545 } else if (b === null) {
4546 return 1;
4547 }
4548 return NaN;
4549 };
4550
4551 u.numcmp = function(a, b) { return a - b; };
4552
4553 u.stablesort = function(array, sortBy, keyFn) {
4554 var indices = array.reduce(function(idx, v, i) {
4555 return (idx[keyFn(v)] = i, idx);
4556 }, {});
4557
4558 array.sort(function(a, b) {
4559 var sa = sortBy(a),
4560 sb = sortBy(b);
4561 return sa < sb ? -1 : sa > sb ? 1
4562 : (indices[keyFn(a)] - indices[keyFn(b)]);
4563 });
4564
4565 return array;
4566 };
4567
4568
4569 // string functions
4570
4571 u.pad = function(s, length, pos, padchar) {
4572 padchar = padchar || " ";
4573 var d = length - s.length;
4574 if (d <= 0) return s;
4575 switch (pos) {
4576 case 'left':
4577 return strrep(d, padchar) + s;
4578 case 'middle':
4579 case 'center':
4580 return strrep(Math.floor(d/2), padchar) +
4581 s + strrep(Math.ceil(d/2), padchar);
4582 default:
4583 return s + strrep(d, padchar);
4584 }
4585 };
4586
4587 function strrep(n, str) {
4588 var s = "", i;
4589 for (i=0; i<n; ++i) s += str;
4590 return s;
4591 }
4592
4593 u.truncate = function(s, length, pos, word, ellipsis) {
4594 var len = s.length;
4595 if (len <= length) return s;
4596 ellipsis = ellipsis !== undefined ? String(ellipsis) : '\u2026';
4597 var l = Math.max(0, length - ellipsis.length);
4598
4599 switch (pos) {
4600 case 'left':
4601 return ellipsis + (word ? truncateOnWord(s,l,1) : s.slice(len-l));
4602 case 'middle':
4603 case 'center':
4604 var l1 = Math.ceil(l/2), l2 = Math.floor(l/2);
4605 return (word ? truncateOnWord(s,l1) : s.slice(0,l1)) +
4606 ellipsis + (word ? truncateOnWord(s,l2,1) : s.slice(len-l2));
4607 default:
4608 return (word ? truncateOnWord(s,l) : s.slice(0,l)) + ellipsis;
4609 }
4610 };
4611
4612 function truncateOnWord(s, len, rev) {
4613 var cnt = 0, tok = s.split(truncate_word_re);
4614 if (rev) {
4615 s = (tok = tok.reverse())
4616 .filter(function(w) { cnt += w.length; return cnt <= len; })
4617 .reverse();
4618 } else {
4619 s = tok.filter(function(w) { cnt += w.length; return cnt <= len; });
4620 }
4621 return s.length ? s.join('').trim() : tok[0].slice(0, len);
4622 }
4623
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])/;
4625
4626 },{"./time":28,"buffer":2}],30:[function(require,module,exports){
4627 var DEPS = require('./Dependencies').ALL;
4628
4629 function create(cs, reflow) {
4630 var out = {};
4631 copy(cs, out);
4632
4633 out.add = [];
4634 out.mod = [];
4635 out.rem = [];
4636
4637 out.reflow = reflow;
4638
4639 return out;
4640 }
4641
4642 function copy(a, b) {
4643 b.stamp = a ? a.stamp : 0;
4644 b.sort = a ? a.sort : null;
4645 b.facet = a ? a.facet : null;
4646 b.trans = a ? a.trans : null;
4647 b.dirty = a ? a.dirty : [];
4648 b.request = a ? a.request : null;
4649 for (var d, i=0, n=DEPS.length; i<n; ++i) {
4650 b[d=DEPS[i]] = a ? a[d] : {};
4651 }
4652 }
4653
4654 module.exports = {
4655 create: create,
4656 copy: copy
4657 };
4658 },{"./Dependencies":33}],31:[function(require,module,exports){
4659 var log = require('vega-logging'),
4660 Tuple = require('./Tuple'),
4661 Base = require('./Node').prototype;
4662
4663 function Collector(graph) {
4664 Base.init.call(this, graph);
4665 this._data = [];
4666 this.router(true).collector(true);
4667 }
4668
4669 var prototype = (Collector.prototype = Object.create(Base));
4670 prototype.constructor = Collector;
4671
4672 prototype.data = function() {
4673 return this._data;
4674 };
4675
4676 prototype.evaluate = function(input) {
4677 log.debug(input, ["collecting"]);
4678
4679 if (input.rem.length) {
4680 this._data = Tuple.idFilter(this._data, input.rem);
4681 }
4682
4683 if (input.add.length) {
4684 this._data = this._data.length ? this._data.concat(input.add) : input.add;
4685 }
4686
4687 if (input.sort) {
4688 this._data.sort(input.sort);
4689 }
4690
4691 if (input.reflow) {
4692 input.mod = input.mod.concat(
4693 Tuple.idFilter(this._data, input.add, input.mod, input.rem));
4694 input.reflow = false;
4695 }
4696
4697 return input;
4698 };
4699
4700 module.exports = Collector;
4701 },{"./Node":36,"./Tuple":38,"vega-logging":45}],32:[function(require,module,exports){
4702 var log = require('vega-logging'),
4703 ChangeSet = require('./ChangeSet'),
4704 Collector = require('./Collector'),
4705 Tuple = require('./Tuple'),
4706 Node = require('./Node'); // jshint ignore:line
4707
4708 function DataSource(graph, name, facet) {
4709 this._graph = graph;
4710 this._name = name;
4711 this._data = [];
4712 this._source = null;
4713 this._facet = facet;
4714 this._input = ChangeSet.create();
4715 this._output = null; // Output changeset
4716
4717 this._inputNode = null;
4718 this._outputNode = null;
4719 this._pipeline = null; // Pipeline of transformations.
4720 this._collector = null; // Collector to materialize output of pipeline.
4721 this._mutates = false; // Does any pipeline operator mutate tuples?
4722 }
4723
4724 var prototype = DataSource.prototype;
4725
4726 prototype.name = function(name) {
4727 if (!arguments.length) return this._name;
4728 return (this._name = name, this);
4729 };
4730
4731 prototype.source = function(src) {
4732 if (!arguments.length) return this._source;
4733 return (this._source = this._graph.data(src));
4734 };
4735
4736 prototype.insert = function(tuples) {
4737 this._input.add = this._input.add.concat(tuples.map(Tuple.ingest));
4738 return this;
4739 };
4740
4741 prototype.remove = function(where) {
4742 var remove = this._data.filter(where);
4743 this._input.rem = this._input.rem.concat(remove);
4744 return this;
4745 };
4746
4747 prototype.update = function(where, field, func) {
4748 var mod = this._input.mod,
4749 ids = Tuple.idMap(mod);
4750
4751 this._input.fields[field] = 1;
4752
4753 this._data.filter(where).forEach(function(x) {
4754 var prev = x[field],
4755 next = func(x);
4756 if (prev !== next) {
4757 Tuple.set(x, field, next);
4758 if (ids[x._id] !== 1) {
4759 mod.push(x);
4760 ids[x._id] = 1;
4761 }
4762 }
4763 });
4764
4765 return this;
4766 };
4767
4768 prototype.values = function(data) {
4769 if (!arguments.length) return this._collector.data();
4770
4771 // Replace backing data
4772 this._input.rem = this._data.slice();
4773 if (data) { this.insert(data); }
4774 return this;
4775 };
4776
4777 prototype.mutates = function(m) {
4778 if (!arguments.length) return this._mutates;
4779 this._mutates = this._mutates || m;
4780 return this;
4781 };
4782
4783 prototype.last = function() {
4784 return this._output;
4785 };
4786
4787 prototype.fire = function(input) {
4788 if (input) this._input = input;
4789 this._graph.propagate(this._input, this._pipeline[0]);
4790 return this;
4791 };
4792
4793 prototype.pipeline = function(pipeline) {
4794 if (!arguments.length) return this._pipeline;
4795
4796 var graph = this._graph,
4797 status;
4798
4799 pipeline.unshift(this._inputNode = DataSourceInput(this));
4800 status = graph.preprocess(pipeline);
4801
4802 if (status.router) {
4803 pipeline.push(status.collector = new Collector(graph));
4804 }
4805
4806 pipeline.push(this._outputNode = DataSourceOutput(this));
4807 this._collector = status.collector;
4808 this._mutates = !!status.mutates;
4809 graph.connect(this._pipeline = pipeline);
4810
4811 return this;
4812 };
4813
4814 prototype.synchronize = function() {
4815 this._graph.synchronize(this._pipeline);
4816 return this;
4817 };
4818
4819 prototype.listener = function() {
4820 return DataSourceListener(this).addListener(this._inputNode);
4821 };
4822
4823 prototype.addListener = function(l) {
4824 if (l instanceof DataSource) {
4825 this._collector.addListener(l.listener());
4826 } else {
4827 this._outputNode.addListener(l);
4828 }
4829 return this;
4830 };
4831
4832 prototype.removeListener = function(l) {
4833 this._outputNode.removeListener(l);
4834 };
4835
4836 prototype.listeners = function(ds) {
4837 return (ds ? this._collector : this._outputNode).listeners();
4838 };
4839
4840 // Input node applies the datasource's delta, and propagates it to
4841 // the rest of the pipeline. It receives touches to reflow data.
4842 function DataSourceInput(ds) {
4843 var input = new Node(ds._graph)
4844 .router(true)
4845 .collector(true);
4846
4847 input.data = function() {
4848 return ds._data;
4849 };
4850
4851 input.evaluate = function(input) {
4852 log.debug(input, ['input', ds._name]);
4853
4854 var delta = ds._input,
4855 out = ChangeSet.create(input), f;
4856
4857 // Delta might contain fields updated through API
4858 for (f in delta.fields) {
4859 out.fields[f] = 1;
4860 }
4861
4862 // update data
4863 if (delta.rem.length) {
4864 ds._data = Tuple.idFilter(ds._data, delta.rem);
4865 }
4866
4867 if (delta.add.length) {
4868 ds._data = ds._data.concat(delta.add);
4869 }
4870
4871 // if reflowing, add any other tuples not currently in changeset
4872 if (input.reflow) {
4873 delta.mod = delta.mod.concat(
4874 Tuple.idFilter(ds._data, delta.add, delta.mod, delta.rem));
4875 }
4876
4877 // reset change list
4878 ds._input = ChangeSet.create();
4879
4880 out.add = delta.add;
4881 out.mod = delta.mod;
4882 out.rem = delta.rem;
4883 out.facet = ds._facet;
4884 return out;
4885 };
4886
4887 return input;
4888 }
4889
4890 // Output node captures the last changeset seen by this datasource
4891 // (needed for joins and builds) and materializes any nested data.
4892 // If this datasource is faceted, materializes the values in the facet.
4893 function DataSourceOutput(ds) {
4894 var output = new Node(ds._graph)
4895 .router(true)
4896 .reflows(true)
4897 .collector(true);
4898
4899 output.data = function() {
4900 return ds._collector ? ds._collector.data() : ds._data;
4901 };
4902
4903 output.evaluate = function(input) {
4904 log.debug(input, ['output', ds._name]);
4905
4906 var out = ChangeSet.create(input, true);
4907
4908 if (ds._facet) {
4909 ds._facet.values = ds.values();
4910 input.facet = null;
4911 }
4912
4913 ds._output = input;
4914 out.data[ds._name] = 1;
4915 return out;
4916 };
4917
4918 return output;
4919 }
4920
4921 function DataSourceListener(ds) {
4922 var l = new Node(ds._graph).router(true);
4923
4924 l.evaluate = function(input) {
4925 // Tuple derivation carries a cost. So only derive if the pipeline has
4926 // operators that mutate, and thus would override the source data.
4927 if (ds.mutates()) {
4928 var map = ds._srcMap || (ds._srcMap = {}), // to propagate tuples correctly
4929 output = ChangeSet.create(input);
4930
4931 output.add = input.add.map(function(t) {
4932 return (map[t._id] = Tuple.derive(t));
4933 });
4934
4935 output.mod = input.mod.map(function(t) {
4936 return Tuple.rederive(t, map[t._id]);
4937 });
4938
4939 output.rem = input.rem.map(function(t) {
4940 var o = map[t._id];
4941 return (map[t._id] = null, o);
4942 });
4943
4944 return (ds._input = output);
4945 } else {
4946 return (ds._input = input);
4947 }
4948 };
4949
4950 return l;
4951 }
4952
4953 module.exports = DataSource;
4954
4955 },{"./ChangeSet":30,"./Collector":31,"./Node":36,"./Tuple":38,"vega-logging":45}],33:[function(require,module,exports){
4956 var deps = module.exports = {
4957 ALL: ['data', 'fields', 'scales', 'signals']
4958 };
4959 deps.ALL.forEach(function(k) { deps[k.toUpperCase()] = k; });
4960
4961 },{}],34:[function(require,module,exports){
4962 var dl = require('datalib'),
4963 Heap = require('./Heap'),
4964 ChangeSet = require('./ChangeSet'),
4965 DataSource = require('./DataSource'),
4966 Collector = require('./Collector'),
4967 Tuple = require('./Tuple'),
4968 Signal = require('./Signal'),
4969 Deps = require('./Dependencies');
4970
4971 function Graph() {
4972 }
4973
4974 var prototype = Graph.prototype;
4975
4976 prototype.init = function() {
4977 this._stamp = 0;
4978 this._rank = 0;
4979
4980 this._data = {};
4981 this._signals = {};
4982
4983 this.doNotPropagate = {};
4984 };
4985
4986 prototype.rank = function() {
4987 return ++this._rank;
4988 };
4989
4990 prototype.values = function(type, names, hash) {
4991 var data = (type === Deps.SIGNALS ? this._signals : this._data),
4992 n = (names !== undefined ? names : dl.keys(data)),
4993 vals, i;
4994
4995 if (Array.isArray(n)) {
4996 vals = hash || {};
4997 for (i=0; i<n.length; ++i) {
4998 vals[n[i]] = data[n[i]].values();
4999 }
5000 return vals;
5001 } else {
5002 return data[n].values();
5003 }
5004 };
5005
5006 // Retain for backwards-compatibility
5007 prototype.dataValues = function(names) {
5008 return this.values(Deps.DATA, names);
5009 };
5010
5011 // Retain for backwards-compatibility
5012 prototype.signalValues = function(names) {
5013 return this.values(Deps.SIGNALS, names);
5014 };
5015
5016 prototype.data = function(name, pipeline, facet) {
5017 var db = this._data;
5018 if (!arguments.length) {
5019 var all = [], key;
5020 for (key in db) { all.push(db[key]); }
5021 return all;
5022 } else if (arguments.length === 1) {
5023 return db[name];
5024 } else {
5025 return (db[name] = new DataSource(this, name, facet).pipeline(pipeline));
5026 }
5027 };
5028
5029 prototype.signal = function(name, init) {
5030 if (arguments.length === 1) {
5031 var m = this;
5032 return Array.isArray(name) ?
5033 name.map(function(n) { return m._signals[n]; }) :
5034 this._signals[name];
5035 } else {
5036 return (this._signals[name] = new Signal(this, name, init));
5037 }
5038 };
5039
5040 prototype.signalRef = function(ref) {
5041 if (!Array.isArray(ref)) {
5042 ref = dl.field(ref);
5043 }
5044
5045 var value = this.signal(ref[0]).value();
5046 if (ref.length > 1) {
5047 for (var i=1, n=ref.length; i<n; ++i) {
5048 value = value[ref[i]];
5049 }
5050 }
5051 return value;
5052 };
5053
5054 // Stamp should be specified with caution. It is necessary for inline datasources,
5055 // which need to be populated during the same cycle even though propagation has
5056 // passed that part of the dataflow graph.
5057 prototype.propagate = function(pulse, node, stamp) {
5058 var pulses = {},
5059 listeners, next, nplse, tpls, ntpls, i, len;
5060
5061 // new PQ with each propagation cycle so that we can pulse branches
5062 // of the dataflow graph during a propagation (e.g., when creating
5063 // a new inline datasource).
5064 var pq = new Heap(function(a, b) {
5065 // Sort on qrank (queue-rank).
5066 // Rank can change during propagation due to rewiring.
5067 return a._qrank - b._qrank;
5068 });
5069
5070 if (pulse.stamp) throw Error('Pulse already has a non-zero stamp.');
5071
5072 pulse.stamp = stamp || ++this._stamp;
5073 pulses[node._id] = pulse;
5074 pq.push(node.qrank(true));
5075
5076 while (pq.size() > 0) {
5077 node = pq.peek();
5078 pulse = pulses[node._id];
5079
5080 if (node.rank() !== node.qrank()) {
5081 // A node's rank might change during a propagation. Re-queue if so.
5082 pq.replace(node.qrank(true));
5083 } else {
5084 // Evaluate node and propagate pulse.
5085 pq.pop();
5086 pulses[node._id] = null;
5087 listeners = node._listeners;
5088 pulse = this.evaluate(pulse, node);
5089
5090 // Propagate the pulse.
5091 if (pulse !== this.doNotPropagate) {
5092 // Ensure reflow pulses always send reflow pulses even if skipped.
5093 if (!pulse.reflow && node.reflows()) {
5094 pulse = ChangeSet.create(pulse, true);
5095 }
5096
5097 for (i=0, len=listeners.length; i<len; ++i) {
5098 next = listeners[i];
5099
5100 if ((nplse = pulses[next._id]) !== undefined) {
5101 if (nplse === null) throw Error('Already propagated to node.');
5102 if (nplse === pulse) continue; // Re-queueing the same pulse.
5103
5104 // We've already queued this node. Ensure there should be at most one
5105 // pulse with tuples (add/mod/rem), and the remainder will be reflows.
5106 tpls = pulse.add.length || pulse.mod.length || pulse.rem.length;
5107 ntpls = nplse.add.length || nplse.mod.length || nplse.rem.length;
5108
5109 if (tpls && ntpls) throw Error('Multiple changeset pulses to same node');
5110
5111 // Combine reflow and tuples into a single pulse.
5112 pulses[next._id] = tpls ? pulse : nplse;
5113 pulses[next._id].reflow = pulse.reflow || nplse.reflow;
5114 } else {
5115 // First time we're seeing this node, queue it for propagation.
5116 pq.push(next.qrank(true));
5117 pulses[next._id] = pulse;
5118 }
5119 }
5120 }
5121 }
5122 }
5123 };
5124
5125 // Process a new branch of the dataflow graph prior to connection:
5126 // (1) Insert new Collector nodes as needed.
5127 // (2) Track + return mutation/routing status of the branch.
5128 prototype.preprocess = function(branch) {
5129 var graph = this,
5130 mutates = 0,
5131 node, router, collector, collects;
5132
5133 for (var i=0; i<branch.length; ++i) {
5134 node = branch[i];
5135
5136 // Batch nodes need access to a materialized dataset.
5137 if (node.batch() && !node._collector) {
5138 if (router || !collector) {
5139 node = new Collector(graph);
5140 branch.splice(i, 0, node);
5141 router = false;
5142 } else {
5143 node._collector = collector;
5144 }
5145 }
5146
5147 if ((collects = node.collector())) collector = node;
5148 router = router || node.router() && !collects;
5149 mutates = mutates || node.mutates();
5150
5151 // A collector needs to be inserted after tuple-producing
5152 // nodes for correct previous value tracking.
5153 if (node.produces()) {
5154 branch.splice(i+1, 0, new Collector(graph));
5155 router = false;
5156 }
5157 }
5158
5159 return {router: router, collector: collector, mutates: mutates};
5160 };
5161
5162 prototype.connect = function(branch) {
5163 var collector, node, data, signals, i, n, j, m;
5164
5165 // connect the pipeline
5166 for (i=0, n=branch.length; i<n; ++i) {
5167 node = branch[i];
5168 if (node.collector()) collector = node;
5169
5170 data = node.dependency(Deps.DATA);
5171 for (j=0, m=data.length; j<m; ++j) {
5172 this.data(data[j]).addListener(collector);
5173 }
5174
5175 signals = node.dependency(Deps.SIGNALS);
5176 for (j=0, m=signals.length; j<m; ++j) {
5177 this.signal(signals[j]).addListener(collector);
5178 }
5179
5180 if (i > 0) branch[i-1].addListener(node);
5181 }
5182
5183 return branch;
5184 };
5185
5186 prototype.disconnect = function(branch) {
5187 var collector, node, data, signals, i, n, j, m;
5188
5189 for (i=0, n=branch.length; i<n; ++i) {
5190 node = branch[i];
5191 if (node.collector()) collector = node;
5192
5193 data = node.dependency(Deps.DATA);
5194 for (j=0, m=data.length; j<m; ++j) {
5195 this.data(data[j]).removeListener(collector);
5196 }
5197
5198 signals = node.dependency(Deps.SIGNALS);
5199 for (j=0, m=signals.length; j<m; ++j) {
5200 this.signal(signals[j]).removeListener(collector);
5201 }
5202
5203 node.disconnect();
5204 }
5205
5206 return branch;
5207 };
5208
5209 prototype.synchronize = function(branch) {
5210 var ids = {},
5211 node, data, i, n, j, m, d, id;
5212
5213 for (i=0, n=branch.length; i<n; ++i) {
5214 node = branch[i];
5215 if (!node.collector()) continue;
5216
5217 for (j=0, data=node.data(), m=data.length; j<m; ++j) {
5218 id = (d = data[j])._id;
5219 if (ids[id]) continue;
5220 Tuple.prev_update(d);
5221 ids[id] = 1;
5222 }
5223 }
5224
5225 return this;
5226 };
5227
5228 prototype.reevaluate = function(pulse, node) {
5229 var reflowed = pulse.reflow && node.last() >= pulse.stamp,
5230 run = node.router() || pulse.add.length || pulse.rem.length;
5231
5232 return run || !reflowed || node.reevaluate(pulse);
5233 };
5234
5235 prototype.evaluate = function(pulse, node) {
5236 if (!this.reevaluate(pulse, node)) return pulse;
5237 pulse = node.evaluate(pulse);
5238 node.last(pulse.stamp);
5239 return pulse;
5240 };
5241
5242 module.exports = Graph;
5243
5244 },{"./ChangeSet":30,"./Collector":31,"./DataSource":32,"./Dependencies":33,"./Heap":35,"./Signal":37,"./Tuple":38,"datalib":24}],35:[function(require,module,exports){
5245 function Heap(comparator) {
5246 this.cmp = comparator;
5247 this.nodes = [];
5248 }
5249
5250 var prototype = Heap.prototype;
5251
5252 prototype.size = function() {
5253 return this.nodes.length;
5254 };
5255
5256 prototype.clear = function() {
5257 return (this.nodes = [], this);
5258 };
5259
5260 prototype.peek = function() {
5261 return this.nodes[0];
5262 };
5263
5264 prototype.push = function(x) {
5265 var array = this.nodes;
5266 array.push(x);
5267 return _siftdown(array, 0, array.length-1, this.cmp);
5268 };
5269
5270 prototype.pop = function() {
5271 var array = this.nodes,
5272 last = array.pop(),
5273 item;
5274
5275 if (array.length) {
5276 item = array[0];
5277 array[0] = last;
5278 _siftup(array, 0, this.cmp);
5279 } else {
5280 item = last;
5281 }
5282 return item;
5283 };
5284
5285 prototype.replace = function(item) {
5286 var array = this.nodes,
5287 retval = array[0];
5288 array[0] = item;
5289 _siftup(array, 0, this.cmp);
5290 return retval;
5291 };
5292
5293 prototype.pushpop = function(item) {
5294 var array = this.nodes, ref = array[0];
5295 if (array.length && this.cmp(ref, item) < 0) {
5296 array[0] = item;
5297 item = ref;
5298 _siftup(array, 0, this.cmp);
5299 }
5300 return item;
5301 };
5302
5303 function _siftdown(array, start, idx, cmp) {
5304 var item, parent, pidx;
5305
5306 item = array[idx];
5307 while (idx > start) {
5308 pidx = (idx - 1) >> 1;
5309 parent = array[pidx];
5310 if (cmp(item, parent) < 0) {
5311 array[idx] = parent;
5312 idx = pidx;
5313 continue;
5314 }
5315 break;
5316 }
5317 return (array[idx] = item);
5318 }
5319
5320 function _siftup(array, idx, cmp) {
5321 var start = idx,
5322 end = array.length,
5323 item = array[idx],
5324 cidx = 2 * idx + 1, ridx;
5325
5326 while (cidx < end) {
5327 ridx = cidx + 1;
5328 if (ridx < end && cmp(array[cidx], array[ridx]) >= 0) {
5329 cidx = ridx;
5330 }
5331 array[idx] = array[cidx];
5332 idx = cidx;
5333 cidx = 2 * idx + 1;
5334 }
5335 array[idx] = item;
5336 return _siftdown(array, start, idx, cmp);
5337 }
5338
5339 module.exports = Heap;
5340
5341 },{}],36:[function(require,module,exports){
5342 var DEPS = require('./Dependencies').ALL,
5343 nodeID = 0;
5344
5345 function Node(graph) {
5346 if (graph) this.init(graph);
5347 }
5348
5349 var Flags = Node.Flags = {
5350 Router: 0x01, // Responsible for propagating tuples, cannot be skipped.
5351 Collector: 0x02, // Holds a materialized dataset, pulse node to reflow.
5352 Produces: 0x04, // Produces new tuples.
5353 Mutates: 0x08, // Sets properties of incoming tuples.
5354 Reflows: 0x10, // Forwards a reflow pulse.
5355 Batch: 0x20 // Performs batch data processing, needs collector.
5356 };
5357
5358 var prototype = Node.prototype;
5359
5360 prototype.init = function(graph) {
5361 this._id = ++nodeID;
5362 this._graph = graph;
5363 this._rank = graph.rank(); // Topological sort by rank
5364 this._qrank = null; // Rank when enqueued for propagation
5365 this._stamp = 0; // Last stamp seen
5366
5367 this._listeners = [];
5368 this._listeners._ids = {}; // To prevent duplicate listeners
5369
5370 // Initialize dependencies.
5371 this._deps = {};
5372 for (var i=0, n=DEPS.length; i<n; ++i) {
5373 this._deps[DEPS[i]] = [];
5374 }
5375
5376 // Initialize status flags.
5377 this._flags = 0;
5378
5379 return this;
5380 };
5381
5382 prototype.rank = function() {
5383 return this._rank;
5384 };
5385
5386 prototype.qrank = function(/* set */) {
5387 if (!arguments.length) return this._qrank;
5388 return (this._qrank = this._rank, this);
5389 };
5390
5391 prototype.last = function(stamp) {
5392 if (!arguments.length) return this._stamp;
5393 return (this._stamp = stamp, this);
5394 };
5395
5396 // -- status flags ---
5397
5398 prototype._setf = function(v, b) {
5399 if (b) { this._flags |= v; } else { this._flags &= ~v; }
5400 return this;
5401 };
5402
5403 prototype.router = function(state) {
5404 if (!arguments.length) return (this._flags & Flags.Router);
5405 return this._setf(Flags.Router, state);
5406 };
5407
5408 prototype.collector = function(state) {
5409 if (!arguments.length) return (this._flags & Flags.Collector);
5410 return this._setf(Flags.Collector, state);
5411 };
5412
5413 prototype.produces = function(state) {
5414 if (!arguments.length) return (this._flags & Flags.Produces);
5415 return this._setf(Flags.Produces, state);
5416 };
5417
5418 prototype.mutates = function(state) {
5419 if (!arguments.length) return (this._flags & Flags.Mutates);
5420 return this._setf(Flags.Mutates, state);
5421 };
5422
5423 prototype.reflows = function(state) {
5424 if (!arguments.length) return (this._flags & Flags.Reflows);
5425 return this._setf(Flags.Reflows, state);
5426 };
5427
5428 prototype.batch = function(state) {
5429 if (!arguments.length) return (this._flags & Flags.Batch);
5430 return this._setf(Flags.Batch, state);
5431 };
5432
5433 prototype.dependency = function(type, deps) {
5434 var d = this._deps[type],
5435 n = d._names || (d._names = {}); // To prevent dupe deps
5436
5437 // Get dependencies of the given type
5438 if (arguments.length === 1) {
5439 return d;
5440 }
5441
5442 if (deps === null) {
5443 // Clear dependencies of the given type
5444 d.splice(0, d.length);
5445 d._names = {};
5446 } else if (!Array.isArray(deps)) {
5447 // Separate this case to avoid cost of array creation
5448 if (n[deps]) return this;
5449 d.push(deps);
5450 n[deps] = 1;
5451 } else {
5452 for (var i=0, len=deps.length, dep; i<len; ++i) {
5453 dep = deps[i];
5454 if (n[dep]) continue;
5455 d.push(dep);
5456 n[dep] = 1;
5457 }
5458 }
5459
5460 return this;
5461 };
5462
5463 prototype.listeners = function() {
5464 return this._listeners;
5465 };
5466
5467 prototype.addListener = function(l) {
5468 if (!(l instanceof Node)) {
5469 throw Error('Listener is not a Node');
5470 }
5471 if (this._listeners._ids[l._id]) return this;
5472
5473 this._listeners.push(l);
5474 this._listeners._ids[l._id] = 1;
5475 if (this._rank > l._rank) {
5476 var q = [l],
5477 g = this._graph, cur;
5478 while (q.length) {
5479 cur = q.shift();
5480 cur._rank = g.rank();
5481 q.unshift.apply(q, cur.listeners());
5482 }
5483 }
5484
5485 return this;
5486 };
5487
5488 prototype.removeListener = function(l) {
5489 if (!this._listeners._ids[l._id]) return false;
5490
5491 var idx = this._listeners.indexOf(l),
5492 b = idx >= 0;
5493
5494 if (b) {
5495 this._listeners.splice(idx, 1);
5496 this._listeners._ids[l._id] = null;
5497 }
5498 return b;
5499 };
5500
5501 prototype.disconnect = function() {
5502 this._listeners = [];
5503 this._listeners._ids = {};
5504 };
5505
5506 // Evaluate this dataflow node for the current pulse.
5507 // Subclasses should override to perform custom processing.
5508 prototype.evaluate = function(pulse) {
5509 return pulse;
5510 };
5511
5512 // Should this node be re-evaluated for the current pulse?
5513 // Searches pulse to see if any dependencies have updated.
5514 prototype.reevaluate = function(pulse) {
5515 var prop, dep, i, n, j, m;
5516
5517 for (i=0, n=DEPS.length; i<n; ++i) {
5518 prop = DEPS[i];
5519 dep = this._deps[prop];
5520 for (j=0, m=dep.length; j<m; ++j) {
5521 if (pulse[prop][dep[j]]) return true;
5522 }
5523 }
5524
5525 return false;
5526 };
5527
5528 Node.reset = function() { nodeID = 0; };
5529
5530 module.exports = Node;
5531
5532 },{"./Dependencies":33}],37:[function(require,module,exports){
5533 var ChangeSet = require('./ChangeSet'),
5534 Node = require('./Node'), // jshint ignore:line
5535 Base = Node.prototype;
5536
5537 function Signal(graph, name, initialValue) {
5538 Base.init.call(this, graph);
5539 this._name = name;
5540 this._value = initialValue;
5541 this._verbose = false; // Verbose signals re-pulse the graph even if prev === val.
5542 this._handlers = [];
5543 return this;
5544 }
5545
5546 var prototype = (Signal.prototype = Object.create(Base));
5547 prototype.constructor = Signal;
5548
5549 prototype.name = function() {
5550 return this._name;
5551 };
5552
5553 prototype.value = function(val) {
5554 if (!arguments.length) return this._value;
5555 return (this._value = val, this);
5556 };
5557
5558 // Alias to value, for shared API with DataSource
5559 prototype.values = prototype.value;
5560
5561 prototype.verbose = function(v) {
5562 if (!arguments.length) return this._verbose;
5563 return (this._verbose = !!v, this);
5564 };
5565
5566 prototype.evaluate = function(input) {
5567 return input.signals[this._name] ? input : this._graph.doNotPropagate;
5568 };
5569
5570 prototype.fire = function(cs) {
5571 if (!cs) cs = ChangeSet.create(null, true);
5572 cs.signals[this._name] = 1;
5573 this._graph.propagate(cs, this);
5574 };
5575
5576 prototype.on = function(handler) {
5577 var signal = this,
5578 node = new Node(this._graph);
5579
5580 node.evaluate = function(input) {
5581 handler(signal.name(), signal.value());
5582 return input;
5583 };
5584
5585 this._handlers.push({
5586 handler: handler,
5587 node: node
5588 });
5589
5590 return this.addListener(node);
5591 };
5592
5593 prototype.off = function(handler) {
5594 var h = this._handlers, i, x;
5595
5596 for (i=h.length; --i>=0;) {
5597 if (!handler || h[i].handler === handler) {
5598 x = h.splice(i, 1)[0];
5599 this.removeListener(x.node);
5600 }
5601 }
5602
5603 return this;
5604 };
5605
5606 module.exports = Signal;
5607
5608 },{"./ChangeSet":30,"./Node":36}],38:[function(require,module,exports){
5609 var tupleID = 0;
5610
5611 function ingest(datum) {
5612 datum = (datum === Object(datum)) ? datum : {data: datum};
5613 datum._id = ++tupleID;
5614 if (datum._prev) datum._prev = null;
5615 return datum;
5616 }
5617
5618 function idMap(a, ids) {
5619 ids = ids || {};
5620 for (var i=0, n=a.length; i<n; ++i) {
5621 ids[a[i]._id] = 1;
5622 }
5623 return ids;
5624 }
5625
5626 function copy(t, c) {
5627 c = c || {};
5628 for (var k in t) {
5629 if (k !== '_prev' && k !== '_id') c[k] = t[k];
5630 }
5631 return c;
5632 }
5633
5634 module.exports = {
5635 ingest: ingest,
5636 idMap: idMap,
5637
5638 derive: function(d) {
5639 return ingest(copy(d));
5640 },
5641
5642 rederive: function(d, t) {
5643 return copy(d, t);
5644 },
5645
5646 set: function(t, k, v) {
5647 return t[k] === v ? 0 : (t[k] = v, 1);
5648 },
5649
5650 prev: function(t) {
5651 return t._prev || t;
5652 },
5653
5654 prev_init: function(t) {
5655 if (!t._prev) { t._prev = {_id: t._id}; }
5656 },
5657
5658 prev_update: function(t) {
5659 var p = t._prev, k, v;
5660 if (p) for (k in t) {
5661 if (k !== '_prev' && k !== '_id') {
5662 p[k] = ((v=t[k]) instanceof Object && v._prev) ? v._prev : v;
5663 }
5664 }
5665 },
5666
5667 reset: function() { tupleID = 0; },
5668
5669 idFilter: function(data) {
5670 var ids = {};
5671 for (var i=arguments.length; --i>0;) {
5672 idMap(arguments[i], ids);
5673 }
5674 return data.filter(function(x) { return !ids[x._id]; });
5675 }
5676 };
5677
5678 },{}],39:[function(require,module,exports){
5679 module.exports = {
5680 ChangeSet: require('./ChangeSet'),
5681 Collector: require('./Collector'),
5682 DataSource: require('./DataSource'),
5683 Dependencies: require('./Dependencies'),
5684 Graph: require('./Graph'),
5685 Node: require('./Node'),
5686 Signal: require('./Signal'),
5687 Tuple: require('./Tuple'),
5688 debug: require('vega-logging').debug
5689 };
5690
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){
5692 function toMap(list) {
5693 var map = {}, i, n;
5694 for (i=0, n=list.length; i<n; ++i) map[list[i]] = 1;
5695 return map;
5696 }
5697
5698 function keys(object) {
5699 var list = [], k;
5700 for (k in object) list.push(k);
5701 return list;
5702 }
5703
5704 module.exports = function(opt) {
5705 opt = opt || {};
5706 var constants = opt.constants || require('./constants'),
5707 functions = (opt.functions || require('./functions'))(codegen),
5708 idWhiteList = opt.idWhiteList ? toMap(opt.idWhiteList) : null,
5709 idBlackList = opt.idBlackList ? toMap(opt.idBlackList) : null,
5710 memberDepth = 0,
5711 FIELD_VAR = opt.fieldVar || 'datum',
5712 GLOBAL_VAR = opt.globalVar || 'signals',
5713 globals = {},
5714 fields = {};
5715
5716 function codegen_wrap(ast) {
5717 var retval = {
5718 code: codegen(ast),
5719 globals: keys(globals),
5720 fields: keys(fields)
5721 };
5722 globals = {};
5723 fields = {};
5724 return retval;
5725 }
5726
5727 function lookupGlobal(id) {
5728 return GLOBAL_VAR + '["' + id + '"]';
5729 }
5730
5731 function codegen(ast) {
5732 if (typeof ast === 'string') return ast;
5733 var generator = CODEGEN_TYPES[ast.type];
5734 if (generator == null) {
5735 throw new Error('Unsupported type: ' + ast.type);
5736 }
5737 return generator(ast);
5738 }
5739
5740 var CODEGEN_TYPES = {
5741 'Literal': function(n) {
5742 return n.raw;
5743 },
5744 'Identifier': function(n) {
5745 var id = n.name;
5746 if (memberDepth > 0) {
5747 return id;
5748 }
5749 if (constants.hasOwnProperty(id)) {
5750 return constants[id];
5751 }
5752 if (idWhiteList) {
5753 if (idWhiteList.hasOwnProperty(id)) {
5754 return id;
5755 } else {
5756 globals[id] = 1;
5757 return lookupGlobal(id);
5758 }
5759 }
5760 if (idBlackList && idBlackList.hasOwnProperty(id)) {
5761 throw new Error('Illegal identifier: ' + id);
5762 }
5763 return id;
5764 },
5765 'Program': function(n) {
5766 return n.body.map(codegen).join('\n');
5767 },
5768 'MemberExpression': function(n) {
5769 var d = !n.computed;
5770 var o = codegen(n.object);
5771 if (d) memberDepth += 1;
5772 var p = codegen(n.property);
5773 if (o === FIELD_VAR) { fields[p] = 1; } // HACKish...
5774 if (d) memberDepth -= 1;
5775 return o + (d ? '.'+p : '['+p+']');
5776 },
5777 'CallExpression': function(n) {
5778 if (n.callee.type !== 'Identifier') {
5779 throw new Error('Illegal callee type: ' + n.callee.type);
5780 }
5781 var callee = n.callee.name;
5782 var args = n.arguments;
5783 var fn = functions.hasOwnProperty(callee) && functions[callee];
5784 if (!fn) throw new Error('Unrecognized function: ' + callee);
5785 return fn instanceof Function ?
5786 fn(args) :
5787 fn + '(' + args.map(codegen).join(',') + ')';
5788 },
5789 'ArrayExpression': function(n) {
5790 return '[' + n.elements.map(codegen).join(',') + ']';
5791 },
5792 'BinaryExpression': function(n) {
5793 return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')';
5794 },
5795 'UnaryExpression': function(n) {
5796 return '(' + n.operator + codegen(n.argument) + ')';
5797 },
5798 'ConditionalExpression': function(n) {
5799 return '(' + codegen(n.test) +
5800 '?' + codegen(n.consequent) +
5801 ':' + codegen(n.alternate) +
5802 ')';
5803 },
5804 'LogicalExpression': function(n) {
5805 return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')';
5806 },
5807 'ObjectExpression': function(n) {
5808 return '{' + n.properties.map(codegen).join(',') + '}';
5809 },
5810 'Property': function(n) {
5811 memberDepth += 1;
5812 var k = codegen(n.key);
5813 memberDepth -= 1;
5814 return k + ':' + codegen(n.value);
5815 },
5816 'ExpressionStatement': function(n) {
5817 return codegen(n.expression);
5818 }
5819 };
5820
5821 codegen_wrap.functions = functions;
5822 codegen_wrap.constants = constants;
5823 return codegen_wrap;
5824 };
5825
5826 },{"./constants":41,"./functions":42}],41:[function(require,module,exports){
5827 module.exports = {
5828 'NaN': 'NaN',
5829 'E': 'Math.E',
5830 'LN2': 'Math.LN2',
5831 'LN10': 'Math.LN10',
5832 'LOG2E': 'Math.LOG2E',
5833 'LOG10E': 'Math.LOG10E',
5834 'PI': 'Math.PI',
5835 'SQRT1_2': 'Math.SQRT1_2',
5836 'SQRT2': 'Math.SQRT2'
5837 };
5838 },{}],42:[function(require,module,exports){
5839 module.exports = function(codegen) {
5840
5841 function fncall(name, args, cast, type) {
5842 var obj = codegen(args[0]);
5843 if (cast) {
5844 obj = cast + '(' + obj + ')';
5845 if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
5846 }
5847 return obj + '.' + name + (type < 0 ? '' : type === 0 ?
5848 '()' :
5849 '(' + args.slice(1).map(codegen).join(',') + ')');
5850 }
5851
5852 function fn(name, cast, type) {
5853 return function(args) {
5854 return fncall(name, args, cast, type);
5855 };
5856 }
5857
5858 var DATE = 'new Date',
5859 STRING = 'String',
5860 REGEXP = 'RegExp';
5861
5862 return {
5863 // MATH functions
5864 'isNaN': 'isNaN',
5865 'isFinite': 'isFinite',
5866 'abs': 'Math.abs',
5867 'acos': 'Math.acos',
5868 'asin': 'Math.asin',
5869 'atan': 'Math.atan',
5870 'atan2': 'Math.atan2',
5871 'ceil': 'Math.ceil',
5872 'cos': 'Math.cos',
5873 'exp': 'Math.exp',
5874 'floor': 'Math.floor',
5875 'log': 'Math.log',
5876 'max': 'Math.max',
5877 'min': 'Math.min',
5878 'pow': 'Math.pow',
5879 'random': 'Math.random',
5880 'round': 'Math.round',
5881 'sin': 'Math.sin',
5882 'sqrt': 'Math.sqrt',
5883 'tan': 'Math.tan',
5884
5885 'clamp': function(args) {
5886 if (args.length < 3)
5887 throw new Error('Missing arguments to clamp function.');
5888 if (args.length > 3)
5889 throw new Error('Too many arguments to clamp function.');
5890 var a = args.map(codegen);
5891 return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))';
5892 },
5893
5894 // DATE functions
5895 'now': 'Date.now',
5896 'datetime': DATE,
5897 'date': fn('getDate', DATE, 0),
5898 'day': fn('getDay', DATE, 0),
5899 'year': fn('getFullYear', DATE, 0),
5900 'month': fn('getMonth', DATE, 0),
5901 'hours': fn('getHours', DATE, 0),
5902 'minutes': fn('getMinutes', DATE, 0),
5903 'seconds': fn('getSeconds', DATE, 0),
5904 'milliseconds': fn('getMilliseconds', DATE, 0),
5905 'time': fn('getTime', DATE, 0),
5906 'timezoneoffset': fn('getTimezoneOffset', DATE, 0),
5907 'utcdate': fn('getUTCDate', DATE, 0),
5908 'utcday': fn('getUTCDay', DATE, 0),
5909 'utcyear': fn('getUTCFullYear', DATE, 0),
5910 'utcmonth': fn('getUTCMonth', DATE, 0),
5911 'utchours': fn('getUTCHours', DATE, 0),
5912 'utcminutes': fn('getUTCMinutes', DATE, 0),
5913 'utcseconds': fn('getUTCSeconds', DATE, 0),
5914 'utcmilliseconds': fn('getUTCMilliseconds', DATE, 0),
5915
5916 // shared sequence functions
5917 'length': fn('length', null, -1),
5918 'indexof': fn('indexOf', null),
5919 'lastindexof': fn('lastIndexOf', null),
5920
5921 // STRING functions
5922 'parseFloat': 'parseFloat',
5923 'parseInt': 'parseInt',
5924 'upper': fn('toUpperCase', STRING, 0),
5925 'lower': fn('toLowerCase', STRING, 0),
5926 'slice': fn('slice', STRING),
5927 'substring': fn('substring', STRING),
5928
5929 // REGEXP functions
5930 'regexp': REGEXP,
5931 'test': fn('test', REGEXP),
5932
5933 // Control Flow functions
5934 'if': function(args) {
5935 if (args.length < 3)
5936 throw new Error('Missing arguments to if function.');
5937 if (args.length > 3)
5938 throw new Error('Too many arguments to if function.');
5939 var a = args.map(codegen);
5940 return a[0]+'?'+a[1]+':'+a[2];
5941 }
5942 };
5943 };
5944 },{}],43:[function(require,module,exports){
5945 var parser = require('./parser'),
5946 codegen = require('./codegen');
5947
5948 var expr = module.exports = {
5949 parse: function(input, opt) {
5950 return parser.parse('('+input+')', opt);
5951 },
5952 code: function(opt) {
5953 return codegen(opt);
5954 },
5955 compiler: function(args, opt) {
5956 args = args.slice();
5957 var generator = codegen(opt),
5958 len = args.length,
5959 compile = function(str) {
5960 var value = generator(expr.parse(str));
5961 args[len] = '"use strict"; return (' + value.code + ');';
5962 value.fn = Function.apply(null, args);
5963 return value;
5964 };
5965 compile.codegen = generator;
5966 return compile;
5967 },
5968 functions: require('./functions'),
5969 constants: require('./constants')
5970 };
5971
5972 },{"./codegen":40,"./constants":41,"./functions":42,"./parser":44}],44:[function(require,module,exports){
5973 /*
5974 The following expression parser is based on Esprima (http://esprima.org/).
5975 Original header comment and license for Esprima is included here:
5976
5977 Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
5978 Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
5979 Copyright (C) 2013 Mathias Bynens <mathias@qiwi.be>
5980 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
5981 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
5982 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
5983 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
5984 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
5985 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
5986 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
5987
5988 Redistribution and use in source and binary forms, with or without
5989 modification, are permitted provided that the following conditions are met:
5990
5991 * Redistributions of source code must retain the above copyright
5992 notice, this list of conditions and the following disclaimer.
5993 * Redistributions in binary form must reproduce the above copyright
5994 notice, this list of conditions and the following disclaimer in the
5995 documentation and/or other materials provided with the distribution.
5996
5997 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5998 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5999 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6000 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
6001 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6002 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6003 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6004 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6005 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
6006 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6007 */
6008 /* istanbul ignore next */
6009 module.exports = (function() {
6010 'use strict';
6011
6012 var Token,
6013 TokenName,
6014 Syntax,
6015 PropertyKind,
6016 Messages,
6017 Regex,
6018 source,
6019 strict,
6020 index,
6021 lineNumber,
6022 lineStart,
6023 length,
6024 lookahead,
6025 state,
6026 extra;
6027
6028 Token = {
6029 BooleanLiteral: 1,
6030 EOF: 2,
6031 Identifier: 3,
6032 Keyword: 4,
6033 NullLiteral: 5,
6034 NumericLiteral: 6,
6035 Punctuator: 7,
6036 StringLiteral: 8,
6037 RegularExpression: 9
6038 };
6039
6040 TokenName = {};
6041 TokenName[Token.BooleanLiteral] = 'Boolean';
6042 TokenName[Token.EOF] = '<end>';
6043 TokenName[Token.Identifier] = 'Identifier';
6044 TokenName[Token.Keyword] = 'Keyword';
6045 TokenName[Token.NullLiteral] = 'Null';
6046 TokenName[Token.NumericLiteral] = 'Numeric';
6047 TokenName[Token.Punctuator] = 'Punctuator';
6048 TokenName[Token.StringLiteral] = 'String';
6049 TokenName[Token.RegularExpression] = 'RegularExpression';
6050
6051 Syntax = {
6052 AssignmentExpression: 'AssignmentExpression',
6053 ArrayExpression: 'ArrayExpression',
6054 BinaryExpression: 'BinaryExpression',
6055 CallExpression: 'CallExpression',
6056 ConditionalExpression: 'ConditionalExpression',
6057 ExpressionStatement: 'ExpressionStatement',
6058 Identifier: 'Identifier',
6059 Literal: 'Literal',
6060 LogicalExpression: 'LogicalExpression',
6061 MemberExpression: 'MemberExpression',
6062 ObjectExpression: 'ObjectExpression',
6063 Program: 'Program',
6064 Property: 'Property',
6065 UnaryExpression: 'UnaryExpression'
6066 };
6067
6068 PropertyKind = {
6069 Data: 1,
6070 Get: 2,
6071 Set: 4
6072 };
6073
6074 // Error messages should be identical to V8.
6075 Messages = {
6076 UnexpectedToken: 'Unexpected token %0',
6077 UnexpectedNumber: 'Unexpected number',
6078 UnexpectedString: 'Unexpected string',
6079 UnexpectedIdentifier: 'Unexpected identifier',
6080 UnexpectedReserved: 'Unexpected reserved word',
6081 UnexpectedEOS: 'Unexpected end of input',
6082 NewlineAfterThrow: 'Illegal newline after throw',
6083 InvalidRegExp: 'Invalid regular expression',
6084 UnterminatedRegExp: 'Invalid regular expression: missing /',
6085 InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
6086 InvalidLHSInForIn: 'Invalid left-hand side in for-in',
6087 MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
6088 NoCatchOrFinally: 'Missing catch or finally after try',
6089 UnknownLabel: 'Undefined label \'%0\'',
6090 Redeclaration: '%0 \'%1\' has already been declared',
6091 IllegalContinue: 'Illegal continue statement',
6092 IllegalBreak: 'Illegal break statement',
6093 IllegalReturn: 'Illegal return statement',
6094 StrictModeWith: 'Strict mode code may not include a with statement',
6095 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
6096 StrictVarName: 'Variable name may not be eval or arguments in strict mode',
6097 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
6098 StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
6099 StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
6100 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
6101 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
6102 StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
6103 AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
6104 AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
6105 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
6106 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
6107 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
6108 StrictReservedWord: 'Use of future reserved word in strict mode'
6109 };
6110
6111 // See also tools/generate-unicode-regex.py.
6112 Regex = {
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]'),
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]')
6115 };
6116
6117 // Ensure the condition is true, otherwise throw an error.
6118 // This is only to have a better contract semantic, i.e. another safety net
6119 // to catch a logic error. The condition shall be fulfilled in normal case.
6120 // Do NOT use this to enforce a certain condition on any user input.
6121
6122 function assert(condition, message) {
6123 if (!condition) {
6124 throw new Error('ASSERT: ' + message);
6125 }
6126 }
6127
6128 function isDecimalDigit(ch) {
6129 return (ch >= 0x30 && ch <= 0x39); // 0..9
6130 }
6131
6132 function isHexDigit(ch) {
6133 return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
6134 }
6135
6136 function isOctalDigit(ch) {
6137 return '01234567'.indexOf(ch) >= 0;
6138 }
6139
6140 // 7.2 White Space
6141
6142 function isWhiteSpace(ch) {
6143 return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
6144 (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
6145 }
6146
6147 // 7.3 Line Terminators
6148
6149 function isLineTerminator(ch) {
6150 return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
6151 }
6152
6153 // 7.6 Identifier Names and Identifiers
6154
6155 function isIdentifierStart(ch) {
6156 return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
6157 (ch >= 0x41 && ch <= 0x5A) || // A..Z
6158 (ch >= 0x61 && ch <= 0x7A) || // a..z
6159 (ch === 0x5C) || // \ (backslash)
6160 ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
6161 }
6162
6163 function isIdentifierPart(ch) {
6164 return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
6165 (ch >= 0x41 && ch <= 0x5A) || // A..Z
6166 (ch >= 0x61 && ch <= 0x7A) || // a..z
6167 (ch >= 0x30 && ch <= 0x39) || // 0..9
6168 (ch === 0x5C) || // \ (backslash)
6169 ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
6170 }
6171
6172 // 7.6.1.2 Future Reserved Words
6173
6174 function isFutureReservedWord(id) {
6175 switch (id) {
6176 case 'class':
6177 case 'enum':
6178 case 'export':
6179 case 'extends':
6180 case 'import':
6181 case 'super':
6182 return true;
6183 default:
6184 return false;
6185 }
6186 }
6187
6188 function isStrictModeReservedWord(id) {
6189 switch (id) {
6190 case 'implements':
6191 case 'interface':
6192 case 'package':
6193 case 'private':
6194 case 'protected':
6195 case 'public':
6196 case 'static':
6197 case 'yield':
6198 case 'let':
6199 return true;
6200 default:
6201 return false;
6202 }
6203 }
6204
6205 // 7.6.1.1 Keywords
6206
6207 function isKeyword(id) {
6208 if (strict && isStrictModeReservedWord(id)) {
6209 return true;
6210 }
6211
6212 // 'const' is specialized as Keyword in V8.
6213 // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
6214 // Some others are from future reserved words.
6215
6216 switch (id.length) {
6217 case 2:
6218 return (id === 'if') || (id === 'in') || (id === 'do');
6219 case 3:
6220 return (id === 'var') || (id === 'for') || (id === 'new') ||
6221 (id === 'try') || (id === 'let');
6222 case 4:
6223 return (id === 'this') || (id === 'else') || (id === 'case') ||
6224 (id === 'void') || (id === 'with') || (id === 'enum');
6225 case 5:
6226 return (id === 'while') || (id === 'break') || (id === 'catch') ||
6227 (id === 'throw') || (id === 'const') || (id === 'yield') ||
6228 (id === 'class') || (id === 'super');
6229 case 6:
6230 return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
6231 (id === 'switch') || (id === 'export') || (id === 'import');
6232 case 7:
6233 return (id === 'default') || (id === 'finally') || (id === 'extends');
6234 case 8:
6235 return (id === 'function') || (id === 'continue') || (id === 'debugger');
6236 case 10:
6237 return (id === 'instanceof');
6238 default:
6239 return false;
6240 }
6241 }
6242
6243 function skipComment() {
6244 var ch, start;
6245
6246 start = (index === 0);
6247 while (index < length) {
6248 ch = source.charCodeAt(index);
6249
6250 if (isWhiteSpace(ch)) {
6251 ++index;
6252 } else if (isLineTerminator(ch)) {
6253 ++index;
6254 if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
6255 ++index;
6256 }
6257 ++lineNumber;
6258 lineStart = index;
6259 start = true;
6260 } else {
6261 break;
6262 }
6263 }
6264 }
6265
6266 function scanHexEscape(prefix) {
6267 var i, len, ch, code = 0;
6268
6269 len = (prefix === 'u') ? 4 : 2;
6270 for (i = 0; i < len; ++i) {
6271 if (index < length && isHexDigit(source[index])) {
6272 ch = source[index++];
6273 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
6274 } else {
6275 return '';
6276 }
6277 }
6278 return String.fromCharCode(code);
6279 }
6280
6281 function scanUnicodeCodePointEscape() {
6282 var ch, code, cu1, cu2;
6283
6284 ch = source[index];
6285 code = 0;
6286
6287 // At least, one hex digit is required.
6288 if (ch === '}') {
6289 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6290 }
6291
6292 while (index < length) {
6293 ch = source[index++];
6294 if (!isHexDigit(ch)) {
6295 break;
6296 }
6297 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
6298 }
6299
6300 if (code > 0x10FFFF || ch !== '}') {
6301 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6302 }
6303
6304 // UTF-16 Encoding
6305 if (code <= 0xFFFF) {
6306 return String.fromCharCode(code);
6307 }
6308 cu1 = ((code - 0x10000) >> 10) + 0xD800;
6309 cu2 = ((code - 0x10000) & 1023) + 0xDC00;
6310 return String.fromCharCode(cu1, cu2);
6311 }
6312
6313 function getEscapedIdentifier() {
6314 var ch, id;
6315
6316 ch = source.charCodeAt(index++);
6317 id = String.fromCharCode(ch);
6318
6319 // '\u' (U+005C, U+0075) denotes an escaped character.
6320 if (ch === 0x5C) {
6321 if (source.charCodeAt(index) !== 0x75) {
6322 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6323 }
6324 ++index;
6325 ch = scanHexEscape('u');
6326 if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
6327 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6328 }
6329 id = ch;
6330 }
6331
6332 while (index < length) {
6333 ch = source.charCodeAt(index);
6334 if (!isIdentifierPart(ch)) {
6335 break;
6336 }
6337 ++index;
6338 id += String.fromCharCode(ch);
6339
6340 // '\u' (U+005C, U+0075) denotes an escaped character.
6341 if (ch === 0x5C) {
6342 id = id.substr(0, id.length - 1);
6343 if (source.charCodeAt(index) !== 0x75) {
6344 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6345 }
6346 ++index;
6347 ch = scanHexEscape('u');
6348 if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
6349 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6350 }
6351 id += ch;
6352 }
6353 }
6354
6355 return id;
6356 }
6357
6358 function getIdentifier() {
6359 var start, ch;
6360
6361 start = index++;
6362 while (index < length) {
6363 ch = source.charCodeAt(index);
6364 if (ch === 0x5C) {
6365 // Blackslash (U+005C) marks Unicode escape sequence.
6366 index = start;
6367 return getEscapedIdentifier();
6368 }
6369 if (isIdentifierPart(ch)) {
6370 ++index;
6371 } else {
6372 break;
6373 }
6374 }
6375
6376 return source.slice(start, index);
6377 }
6378
6379 function scanIdentifier() {
6380 var start, id, type;
6381
6382 start = index;
6383
6384 // Backslash (U+005C) starts an escaped character.
6385 id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier();
6386
6387 // There is no keyword or literal with only one character.
6388 // Thus, it must be an identifier.
6389 if (id.length === 1) {
6390 type = Token.Identifier;
6391 } else if (isKeyword(id)) {
6392 type = Token.Keyword;
6393 } else if (id === 'null') {
6394 type = Token.NullLiteral;
6395 } else if (id === 'true' || id === 'false') {
6396 type = Token.BooleanLiteral;
6397 } else {
6398 type = Token.Identifier;
6399 }
6400
6401 return {
6402 type: type,
6403 value: id,
6404 lineNumber: lineNumber,
6405 lineStart: lineStart,
6406 start: start,
6407 end: index
6408 };
6409 }
6410
6411 // 7.7 Punctuators
6412
6413 function scanPunctuator() {
6414 var start = index,
6415 code = source.charCodeAt(index),
6416 code2,
6417 ch1 = source[index],
6418 ch2,
6419 ch3,
6420 ch4;
6421
6422 switch (code) {
6423
6424 // Check for most common single-character punctuators.
6425 case 0x2E: // . dot
6426 case 0x28: // ( open bracket
6427 case 0x29: // ) close bracket
6428 case 0x3B: // ; semicolon
6429 case 0x2C: // , comma
6430 case 0x7B: // { open curly brace
6431 case 0x7D: // } close curly brace
6432 case 0x5B: // [
6433 case 0x5D: // ]
6434 case 0x3A: // :
6435 case 0x3F: // ?
6436 case 0x7E: // ~
6437 ++index;
6438 if (extra.tokenize) {
6439 if (code === 0x28) {
6440 extra.openParenToken = extra.tokens.length;
6441 } else if (code === 0x7B) {
6442 extra.openCurlyToken = extra.tokens.length;
6443 }
6444 }
6445 return {
6446 type: Token.Punctuator,
6447 value: String.fromCharCode(code),
6448 lineNumber: lineNumber,
6449 lineStart: lineStart,
6450 start: start,
6451 end: index
6452 };
6453
6454 default:
6455 code2 = source.charCodeAt(index + 1);
6456
6457 // '=' (U+003D) marks an assignment or comparison operator.
6458 if (code2 === 0x3D) {
6459 switch (code) {
6460 case 0x2B: // +
6461 case 0x2D: // -
6462 case 0x2F: // /
6463 case 0x3C: // <
6464 case 0x3E: // >
6465 case 0x5E: // ^
6466 case 0x7C: // |
6467 case 0x25: // %
6468 case 0x26: // &
6469 case 0x2A: // *
6470 index += 2;
6471 return {
6472 type: Token.Punctuator,
6473 value: String.fromCharCode(code) + String.fromCharCode(code2),
6474 lineNumber: lineNumber,
6475 lineStart: lineStart,
6476 start: start,
6477 end: index
6478 };
6479
6480 case 0x21: // !
6481 case 0x3D: // =
6482 index += 2;
6483
6484 // !== and ===
6485 if (source.charCodeAt(index) === 0x3D) {
6486 ++index;
6487 }
6488 return {
6489 type: Token.Punctuator,
6490 value: source.slice(start, index),
6491 lineNumber: lineNumber,
6492 lineStart: lineStart,
6493 start: start,
6494 end: index
6495 };
6496 }
6497 }
6498 }
6499
6500 // 4-character punctuator: >>>=
6501
6502 ch4 = source.substr(index, 4);
6503
6504 if (ch4 === '>>>=') {
6505 index += 4;
6506 return {
6507 type: Token.Punctuator,
6508 value: ch4,
6509 lineNumber: lineNumber,
6510 lineStart: lineStart,
6511 start: start,
6512 end: index
6513 };
6514 }
6515
6516 // 3-character punctuators: === !== >>> <<= >>=
6517
6518 ch3 = ch4.substr(0, 3);
6519
6520 if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') {
6521 index += 3;
6522 return {
6523 type: Token.Punctuator,
6524 value: ch3,
6525 lineNumber: lineNumber,
6526 lineStart: lineStart,
6527 start: start,
6528 end: index
6529 };
6530 }
6531
6532 // Other 2-character punctuators: ++ -- << >> && ||
6533 ch2 = ch3.substr(0, 2);
6534
6535 if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') {
6536 index += 2;
6537 return {
6538 type: Token.Punctuator,
6539 value: ch2,
6540 lineNumber: lineNumber,
6541 lineStart: lineStart,
6542 start: start,
6543 end: index
6544 };
6545 }
6546
6547 // 1-character punctuators: < > = ! + - * % & | ^ /
6548
6549 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
6550 ++index;
6551 return {
6552 type: Token.Punctuator,
6553 value: ch1,
6554 lineNumber: lineNumber,
6555 lineStart: lineStart,
6556 start: start,
6557 end: index
6558 };
6559 }
6560
6561 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6562 }
6563
6564 // 7.8.3 Numeric Literals
6565
6566 function scanHexLiteral(start) {
6567 var number = '';
6568
6569 while (index < length) {
6570 if (!isHexDigit(source[index])) {
6571 break;
6572 }
6573 number += source[index++];
6574 }
6575
6576 if (number.length === 0) {
6577 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6578 }
6579
6580 if (isIdentifierStart(source.charCodeAt(index))) {
6581 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6582 }
6583
6584 return {
6585 type: Token.NumericLiteral,
6586 value: parseInt('0x' + number, 16),
6587 lineNumber: lineNumber,
6588 lineStart: lineStart,
6589 start: start,
6590 end: index
6591 };
6592 }
6593
6594 function scanOctalLiteral(start) {
6595 var number = '0' + source[index++];
6596 while (index < length) {
6597 if (!isOctalDigit(source[index])) {
6598 break;
6599 }
6600 number += source[index++];
6601 }
6602
6603 if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
6604 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6605 }
6606
6607 return {
6608 type: Token.NumericLiteral,
6609 value: parseInt(number, 8),
6610 octal: true,
6611 lineNumber: lineNumber,
6612 lineStart: lineStart,
6613 start: start,
6614 end: index
6615 };
6616 }
6617
6618 function scanNumericLiteral() {
6619 var number, start, ch;
6620
6621 ch = source[index];
6622 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
6623 'Numeric literal must start with a decimal digit or a decimal point');
6624
6625 start = index;
6626 number = '';
6627 if (ch !== '.') {
6628 number = source[index++];
6629 ch = source[index];
6630
6631 // Hex number starts with '0x'.
6632 // Octal number starts with '0'.
6633 if (number === '0') {
6634 if (ch === 'x' || ch === 'X') {
6635 ++index;
6636 return scanHexLiteral(start);
6637 }
6638 if (isOctalDigit(ch)) {
6639 return scanOctalLiteral(start);
6640 }
6641
6642 // decimal number starts with '0' such as '09' is illegal.
6643 if (ch && isDecimalDigit(ch.charCodeAt(0))) {
6644 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6645 }
6646 }
6647
6648 while (isDecimalDigit(source.charCodeAt(index))) {
6649 number += source[index++];
6650 }
6651 ch = source[index];
6652 }
6653
6654 if (ch === '.') {
6655 number += source[index++];
6656 while (isDecimalDigit(source.charCodeAt(index))) {
6657 number += source[index++];
6658 }
6659 ch = source[index];
6660 }
6661
6662 if (ch === 'e' || ch === 'E') {
6663 number += source[index++];
6664
6665 ch = source[index];
6666 if (ch === '+' || ch === '-') {
6667 number += source[index++];
6668 }
6669 if (isDecimalDigit(source.charCodeAt(index))) {
6670 while (isDecimalDigit(source.charCodeAt(index))) {
6671 number += source[index++];
6672 }
6673 } else {
6674 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6675 }
6676 }
6677
6678 if (isIdentifierStart(source.charCodeAt(index))) {
6679 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6680 }
6681
6682 return {
6683 type: Token.NumericLiteral,
6684 value: parseFloat(number),
6685 lineNumber: lineNumber,
6686 lineStart: lineStart,
6687 start: start,
6688 end: index
6689 };
6690 }
6691
6692 // 7.8.4 String Literals
6693
6694 function scanStringLiteral() {
6695 var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart;
6696 startLineNumber = lineNumber;
6697 startLineStart = lineStart;
6698
6699 quote = source[index];
6700 assert((quote === '\'' || quote === '"'),
6701 'String literal must starts with a quote');
6702
6703 start = index;
6704 ++index;
6705
6706 while (index < length) {
6707 ch = source[index++];
6708
6709 if (ch === quote) {
6710 quote = '';
6711 break;
6712 } else if (ch === '\\') {
6713 ch = source[index++];
6714 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
6715 switch (ch) {
6716 case 'u':
6717 case 'x':
6718 if (source[index] === '{') {
6719 ++index;
6720 str += scanUnicodeCodePointEscape();
6721 } else {
6722 restore = index;
6723 unescaped = scanHexEscape(ch);
6724 if (unescaped) {
6725 str += unescaped;
6726 } else {
6727 index = restore;
6728 str += ch;
6729 }
6730 }
6731 break;
6732 case 'n':
6733 str += '\n';
6734 break;
6735 case 'r':
6736 str += '\r';
6737 break;
6738 case 't':
6739 str += '\t';
6740 break;
6741 case 'b':
6742 str += '\b';
6743 break;
6744 case 'f':
6745 str += '\f';
6746 break;
6747 case 'v':
6748 str += '\x0B';
6749 break;
6750
6751 default:
6752 if (isOctalDigit(ch)) {
6753 code = '01234567'.indexOf(ch);
6754
6755 // \0 is not octal escape sequence
6756 if (code !== 0) {
6757 octal = true;
6758 }
6759
6760 if (index < length && isOctalDigit(source[index])) {
6761 octal = true;
6762 code = code * 8 + '01234567'.indexOf(source[index++]);
6763
6764 // 3 digits are only allowed when string starts
6765 // with 0, 1, 2, 3
6766 if ('0123'.indexOf(ch) >= 0 &&
6767 index < length &&
6768 isOctalDigit(source[index])) {
6769 code = code * 8 + '01234567'.indexOf(source[index++]);
6770 }
6771 }
6772 str += String.fromCharCode(code);
6773 } else {
6774 str += ch;
6775 }
6776 break;
6777 }
6778 } else {
6779 ++lineNumber;
6780 if (ch === '\r' && source[index] === '\n') {
6781 ++index;
6782 }
6783 lineStart = index;
6784 }
6785 } else if (isLineTerminator(ch.charCodeAt(0))) {
6786 break;
6787 } else {
6788 str += ch;
6789 }
6790 }
6791
6792 if (quote !== '') {
6793 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6794 }
6795
6796 return {
6797 type: Token.StringLiteral,
6798 value: str,
6799 octal: octal,
6800 startLineNumber: startLineNumber,
6801 startLineStart: startLineStart,
6802 lineNumber: lineNumber,
6803 lineStart: lineStart,
6804 start: start,
6805 end: index
6806 };
6807 }
6808
6809 function testRegExp(pattern, flags) {
6810 var tmp = pattern,
6811 value;
6812
6813 if (flags.indexOf('u') >= 0) {
6814 // Replace each astral symbol and every Unicode code point
6815 // escape sequence with a single ASCII symbol to avoid throwing on
6816 // regular expressions that are only valid in combination with the
6817 // `/u` flag.
6818 // Note: replacing with the ASCII symbol `x` might cause false
6819 // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
6820 // perfectly valid pattern that is equivalent to `[a-b]`, but it
6821 // would be replaced by `[x-b]` which throws an error.
6822 tmp = tmp
6823 .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
6824 if (parseInt($1, 16) <= 0x10FFFF) {
6825 return 'x';
6826 }
6827 throwError({}, Messages.InvalidRegExp);
6828 })
6829 .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
6830 }
6831
6832 // First, detect invalid regular expressions.
6833 try {
6834 value = new RegExp(tmp);
6835 } catch (e) {
6836 throwError({}, Messages.InvalidRegExp);
6837 }
6838
6839 // Return a regular expression object for this pattern-flag pair, or
6840 // `null` in case the current environment doesn't support the flags it
6841 // uses.
6842 try {
6843 return new RegExp(pattern, flags);
6844 } catch (exception) {
6845 return null;
6846 }
6847 }
6848
6849 function scanRegExpBody() {
6850 var ch, str, classMarker, terminated, body;
6851
6852 ch = source[index];
6853 assert(ch === '/', 'Regular expression literal must start with a slash');
6854 str = source[index++];
6855
6856 classMarker = false;
6857 terminated = false;
6858 while (index < length) {
6859 ch = source[index++];
6860 str += ch;
6861 if (ch === '\\') {
6862 ch = source[index++];
6863 // ECMA-262 7.8.5
6864 if (isLineTerminator(ch.charCodeAt(0))) {
6865 throwError({}, Messages.UnterminatedRegExp);
6866 }
6867 str += ch;
6868 } else if (isLineTerminator(ch.charCodeAt(0))) {
6869 throwError({}, Messages.UnterminatedRegExp);
6870 } else if (classMarker) {
6871 if (ch === ']') {
6872 classMarker = false;
6873 }
6874 } else {
6875 if (ch === '/') {
6876 terminated = true;
6877 break;
6878 } else if (ch === '[') {
6879 classMarker = true;
6880 }
6881 }
6882 }
6883
6884 if (!terminated) {
6885 throwError({}, Messages.UnterminatedRegExp);
6886 }
6887
6888 // Exclude leading and trailing slash.
6889 body = str.substr(1, str.length - 2);
6890 return {
6891 value: body,
6892 literal: str
6893 };
6894 }
6895
6896 function scanRegExpFlags() {
6897 var ch, str, flags, restore;
6898
6899 str = '';
6900 flags = '';
6901 while (index < length) {
6902 ch = source[index];
6903 if (!isIdentifierPart(ch.charCodeAt(0))) {
6904 break;
6905 }
6906
6907 ++index;
6908 if (ch === '\\' && index < length) {
6909 ch = source[index];
6910 if (ch === 'u') {
6911 ++index;
6912 restore = index;
6913 ch = scanHexEscape('u');
6914 if (ch) {
6915 flags += ch;
6916 for (str += '\\u'; restore < index; ++restore) {
6917 str += source[restore];
6918 }
6919 } else {
6920 index = restore;
6921 flags += 'u';
6922 str += '\\u';
6923 }
6924 throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
6925 } else {
6926 str += '\\';
6927 throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
6928 }
6929 } else {
6930 flags += ch;
6931 str += ch;
6932 }
6933 }
6934
6935 return {
6936 value: flags,
6937 literal: str
6938 };
6939 }
6940
6941 function scanRegExp() {
6942 var start, body, flags, value;
6943
6944 lookahead = null;
6945 skipComment();
6946 start = index;
6947
6948 body = scanRegExpBody();
6949 flags = scanRegExpFlags();
6950 value = testRegExp(body.value, flags.value);
6951
6952 if (extra.tokenize) {
6953 return {
6954 type: Token.RegularExpression,
6955 value: value,
6956 regex: {
6957 pattern: body.value,
6958 flags: flags.value
6959 },
6960 lineNumber: lineNumber,
6961 lineStart: lineStart,
6962 start: start,
6963 end: index
6964 };
6965 }
6966
6967 return {
6968 literal: body.literal + flags.literal,
6969 value: value,
6970 regex: {
6971 pattern: body.value,
6972 flags: flags.value
6973 },
6974 start: start,
6975 end: index
6976 };
6977 }
6978
6979 function collectRegex() {
6980 var pos, loc, regex, token;
6981
6982 skipComment();
6983
6984 pos = index;
6985 loc = {
6986 start: {
6987 line: lineNumber,
6988 column: index - lineStart
6989 }
6990 };
6991
6992 regex = scanRegExp();
6993
6994 loc.end = {
6995 line: lineNumber,
6996 column: index - lineStart
6997 };
6998
6999 if (!extra.tokenize) {
7000 // Pop the previous token, which is likely '/' or '/='
7001 if (extra.tokens.length > 0) {
7002 token = extra.tokens[extra.tokens.length - 1];
7003 if (token.range[0] === pos && token.type === 'Punctuator') {
7004 if (token.value === '/' || token.value === '/=') {
7005 extra.tokens.pop();
7006 }
7007 }
7008 }
7009
7010 extra.tokens.push({
7011 type: 'RegularExpression',
7012 value: regex.literal,
7013 regex: regex.regex,
7014 range: [pos, index],
7015 loc: loc
7016 });
7017 }
7018
7019 return regex;
7020 }
7021
7022 function isIdentifierName(token) {
7023 return token.type === Token.Identifier ||
7024 token.type === Token.Keyword ||
7025 token.type === Token.BooleanLiteral ||
7026 token.type === Token.NullLiteral;
7027 }
7028
7029 function advanceSlash() {
7030 var prevToken,
7031 checkToken;
7032 // Using the following algorithm:
7033 // https://github.com/mozilla/sweet.js/wiki/design
7034 prevToken = extra.tokens[extra.tokens.length - 1];
7035 if (!prevToken) {
7036 // Nothing before that: it cannot be a division.
7037 return collectRegex();
7038 }
7039 if (prevToken.type === 'Punctuator') {
7040 if (prevToken.value === ']') {
7041 return scanPunctuator();
7042 }
7043 if (prevToken.value === ')') {
7044 checkToken = extra.tokens[extra.openParenToken - 1];
7045 if (checkToken &&
7046 checkToken.type === 'Keyword' &&
7047 (checkToken.value === 'if' ||
7048 checkToken.value === 'while' ||
7049 checkToken.value === 'for' ||
7050 checkToken.value === 'with')) {
7051 return collectRegex();
7052 }
7053 return scanPunctuator();
7054 }
7055 if (prevToken.value === '}') {
7056 // Dividing a function by anything makes little sense,
7057 // but we have to check for that.
7058 if (extra.tokens[extra.openCurlyToken - 3] &&
7059 extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
7060 // Anonymous function.
7061 checkToken = extra.tokens[extra.openCurlyToken - 4];
7062 if (!checkToken) {
7063 return scanPunctuator();
7064 }
7065 } else if (extra.tokens[extra.openCurlyToken - 4] &&
7066 extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
7067 // Named function.
7068 checkToken = extra.tokens[extra.openCurlyToken - 5];
7069 if (!checkToken) {
7070 return collectRegex();
7071 }
7072 } else {
7073 return scanPunctuator();
7074 }
7075 return scanPunctuator();
7076 }
7077 return collectRegex();
7078 }
7079 if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
7080 return collectRegex();
7081 }
7082 return scanPunctuator();
7083 }
7084
7085 function advance() {
7086 var ch;
7087
7088 skipComment();
7089
7090 if (index >= length) {
7091 return {
7092 type: Token.EOF,
7093 lineNumber: lineNumber,
7094 lineStart: lineStart,
7095 start: index,
7096 end: index
7097 };
7098 }
7099
7100 ch = source.charCodeAt(index);
7101
7102 if (isIdentifierStart(ch)) {
7103 return scanIdentifier();
7104 }
7105
7106 // Very common: ( and ) and ;
7107 if (ch === 0x28 || ch === 0x29 || ch === 0x3B) {
7108 return scanPunctuator();
7109 }
7110
7111 // String literal starts with single quote (U+0027) or double quote (U+0022).
7112 if (ch === 0x27 || ch === 0x22) {
7113 return scanStringLiteral();
7114 }
7115
7116
7117 // Dot (.) U+002E can also start a floating-point number, hence the need
7118 // to check the next character.
7119 if (ch === 0x2E) {
7120 if (isDecimalDigit(source.charCodeAt(index + 1))) {
7121 return scanNumericLiteral();
7122 }
7123 return scanPunctuator();
7124 }
7125
7126 if (isDecimalDigit(ch)) {
7127 return scanNumericLiteral();
7128 }
7129
7130 // Slash (/) U+002F can also start a regex.
7131 if (extra.tokenize && ch === 0x2F) {
7132 return advanceSlash();
7133 }
7134
7135 return scanPunctuator();
7136 }
7137
7138 function collectToken() {
7139 var loc, token, value, entry;
7140
7141 skipComment();
7142 loc = {
7143 start: {
7144 line: lineNumber,
7145 column: index - lineStart
7146 }
7147 };
7148
7149 token = advance();
7150 loc.end = {
7151 line: lineNumber,
7152 column: index - lineStart
7153 };
7154
7155 if (token.type !== Token.EOF) {
7156 value = source.slice(token.start, token.end);
7157 entry = {
7158 type: TokenName[token.type],
7159 value: value,
7160 range: [token.start, token.end],
7161 loc: loc
7162 };
7163 if (token.regex) {
7164 entry.regex = {
7165 pattern: token.regex.pattern,
7166 flags: token.regex.flags
7167 };
7168 }
7169 extra.tokens.push(entry);
7170 }
7171
7172 return token;
7173 }
7174
7175 function lex() {
7176 var token;
7177
7178 token = lookahead;
7179 index = token.end;
7180 lineNumber = token.lineNumber;
7181 lineStart = token.lineStart;
7182
7183 lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
7184
7185 index = token.end;
7186 lineNumber = token.lineNumber;
7187 lineStart = token.lineStart;
7188
7189 return token;
7190 }
7191
7192 function peek() {
7193 var pos, line, start;
7194
7195 pos = index;
7196 line = lineNumber;
7197 start = lineStart;
7198 lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
7199 index = pos;
7200 lineNumber = line;
7201 lineStart = start;
7202 }
7203
7204 function Position() {
7205 this.line = lineNumber;
7206 this.column = index - lineStart;
7207 }
7208
7209 function SourceLocation() {
7210 this.start = new Position();
7211 this.end = null;
7212 }
7213
7214 function WrappingSourceLocation(startToken) {
7215 if (startToken.type === Token.StringLiteral) {
7216 this.start = {
7217 line: startToken.startLineNumber,
7218 column: startToken.start - startToken.startLineStart
7219 };
7220 } else {
7221 this.start = {
7222 line: startToken.lineNumber,
7223 column: startToken.start - startToken.lineStart
7224 };
7225 }
7226 this.end = null;
7227 }
7228
7229 function Node() {
7230 // Skip comment.
7231 index = lookahead.start;
7232 if (lookahead.type === Token.StringLiteral) {
7233 lineNumber = lookahead.startLineNumber;
7234 lineStart = lookahead.startLineStart;
7235 } else {
7236 lineNumber = lookahead.lineNumber;
7237 lineStart = lookahead.lineStart;
7238 }
7239 if (extra.range) {
7240 this.range = [index, 0];
7241 }
7242 if (extra.loc) {
7243 this.loc = new SourceLocation();
7244 }
7245 }
7246
7247 function WrappingNode(startToken) {
7248 if (extra.range) {
7249 this.range = [startToken.start, 0];
7250 }
7251 if (extra.loc) {
7252 this.loc = new WrappingSourceLocation(startToken);
7253 }
7254 }
7255
7256 WrappingNode.prototype = Node.prototype = {
7257
7258 finish: function () {
7259 if (extra.range) {
7260 this.range[1] = index;
7261 }
7262 if (extra.loc) {
7263 this.loc.end = new Position();
7264 if (extra.source) {
7265 this.loc.source = extra.source;
7266 }
7267 }
7268 },
7269
7270 finishArrayExpression: function (elements) {
7271 this.type = Syntax.ArrayExpression;
7272 this.elements = elements;
7273 this.finish();
7274 return this;
7275 },
7276
7277 finishAssignmentExpression: function (operator, left, right) {
7278 this.type = Syntax.AssignmentExpression;
7279 this.operator = operator;
7280 this.left = left;
7281 this.right = right;
7282 this.finish();
7283 return this;
7284 },
7285
7286 finishBinaryExpression: function (operator, left, right) {
7287 this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
7288 this.operator = operator;
7289 this.left = left;
7290 this.right = right;
7291 this.finish();
7292 return this;
7293 },
7294
7295 finishCallExpression: function (callee, args) {
7296 this.type = Syntax.CallExpression;
7297 this.callee = callee;
7298 this.arguments = args;
7299 this.finish();
7300 return this;
7301 },
7302
7303 finishConditionalExpression: function (test, consequent, alternate) {
7304 this.type = Syntax.ConditionalExpression;
7305 this.test = test;
7306 this.consequent = consequent;
7307 this.alternate = alternate;
7308 this.finish();
7309 return this;
7310 },
7311
7312 finishExpressionStatement: function (expression) {
7313 this.type = Syntax.ExpressionStatement;
7314 this.expression = expression;
7315 this.finish();
7316 return this;
7317 },
7318
7319 finishIdentifier: function (name) {
7320 this.type = Syntax.Identifier;
7321 this.name = name;
7322 this.finish();
7323 return this;
7324 },
7325
7326 finishLiteral: function (token) {
7327 this.type = Syntax.Literal;
7328 this.value = token.value;
7329 this.raw = source.slice(token.start, token.end);
7330 if (token.regex) {
7331 if (this.raw == '//') {
7332 this.raw = '/(?:)/';
7333 }
7334 this.regex = token.regex;
7335 }
7336 this.finish();
7337 return this;
7338 },
7339
7340 finishMemberExpression: function (accessor, object, property) {
7341 this.type = Syntax.MemberExpression;
7342 this.computed = accessor === '[';
7343 this.object = object;
7344 this.property = property;
7345 this.finish();
7346 return this;
7347 },
7348
7349 finishObjectExpression: function (properties) {
7350 this.type = Syntax.ObjectExpression;
7351 this.properties = properties;
7352 this.finish();
7353 return this;
7354 },
7355
7356 finishProgram: function (body) {
7357 this.type = Syntax.Program;
7358 this.body = body;
7359 this.finish();
7360 return this;
7361 },
7362
7363 finishProperty: function (kind, key, value) {
7364 this.type = Syntax.Property;
7365 this.key = key;
7366 this.value = value;
7367 this.kind = kind;
7368 this.finish();
7369 return this;
7370 },
7371
7372 finishUnaryExpression: function (operator, argument) {
7373 this.type = Syntax.UnaryExpression;
7374 this.operator = operator;
7375 this.argument = argument;
7376 this.prefix = true;
7377 this.finish();
7378 return this;
7379 }
7380 };
7381
7382 // Return true if there is a line terminator before the next token.
7383
7384 function peekLineTerminator() {
7385 var pos, line, start, found;
7386
7387 pos = index;
7388 line = lineNumber;
7389 start = lineStart;
7390 skipComment();
7391 found = lineNumber !== line;
7392 index = pos;
7393 lineNumber = line;
7394 lineStart = start;
7395
7396 return found;
7397 }
7398
7399 // Throw an exception
7400
7401 function throwError(token, messageFormat) {
7402 var error,
7403 args = Array.prototype.slice.call(arguments, 2),
7404 msg = messageFormat.replace(
7405 /%(\d)/g,
7406 function (whole, index) {
7407 assert(index < args.length, 'Message reference must be in range');
7408 return args[index];
7409 }
7410 );
7411
7412 if (typeof token.lineNumber === 'number') {
7413 error = new Error('Line ' + token.lineNumber + ': ' + msg);
7414 error.index = token.start;
7415 error.lineNumber = token.lineNumber;
7416 error.column = token.start - lineStart + 1;
7417 } else {
7418 error = new Error('Line ' + lineNumber + ': ' + msg);
7419 error.index = index;
7420 error.lineNumber = lineNumber;
7421 error.column = index - lineStart + 1;
7422 }
7423
7424 error.description = msg;
7425 throw error;
7426 }
7427
7428 function throwErrorTolerant() {
7429 try {
7430 throwError.apply(null, arguments);
7431 } catch (e) {
7432 if (extra.errors) {
7433 extra.errors.push(e);
7434 } else {
7435 throw e;
7436 }
7437 }
7438 }
7439
7440
7441 // Throw an exception because of the token.
7442
7443 function throwUnexpected(token) {
7444 if (token.type === Token.EOF) {
7445 throwError(token, Messages.UnexpectedEOS);
7446 }
7447
7448 if (token.type === Token.NumericLiteral) {
7449 throwError(token, Messages.UnexpectedNumber);
7450 }
7451
7452 if (token.type === Token.StringLiteral) {
7453 throwError(token, Messages.UnexpectedString);
7454 }
7455
7456 if (token.type === Token.Identifier) {
7457 throwError(token, Messages.UnexpectedIdentifier);
7458 }
7459
7460 if (token.type === Token.Keyword) {
7461 if (isFutureReservedWord(token.value)) {
7462 throwError(token, Messages.UnexpectedReserved);
7463 } else if (strict && isStrictModeReservedWord(token.value)) {
7464 throwErrorTolerant(token, Messages.StrictReservedWord);
7465 return;
7466 }
7467 throwError(token, Messages.UnexpectedToken, token.value);
7468 }
7469
7470 // BooleanLiteral, NullLiteral, or Punctuator.
7471 throwError(token, Messages.UnexpectedToken, token.value);
7472 }
7473
7474 // Expect the next token to match the specified punctuator.
7475 // If not, an exception will be thrown.
7476
7477 function expect(value) {
7478 var token = lex();
7479 if (token.type !== Token.Punctuator || token.value !== value) {
7480 throwUnexpected(token);
7481 }
7482 }
7483
7484 /**
7485 * @name expectTolerant
7486 * @description Quietly expect the given token value when in tolerant mode, otherwise delegates
7487 * to <code>expect(value)</code>
7488 * @param {String} value The value we are expecting the lookahead token to have
7489 * @since 2.0
7490 */
7491 function expectTolerant(value) {
7492 if (extra.errors) {
7493 var token = lookahead;
7494 if (token.type !== Token.Punctuator && token.value !== value) {
7495 throwErrorTolerant(token, Messages.UnexpectedToken, token.value);
7496 } else {
7497 lex();
7498 }
7499 } else {
7500 expect(value);
7501 }
7502 }
7503
7504 // Return true if the next token matches the specified punctuator.
7505
7506 function match(value) {
7507 return lookahead.type === Token.Punctuator && lookahead.value === value;
7508 }
7509
7510 // Return true if the next token matches the specified keyword
7511
7512 function matchKeyword(keyword) {
7513 return lookahead.type === Token.Keyword && lookahead.value === keyword;
7514 }
7515
7516 function consumeSemicolon() {
7517 var line;
7518
7519 // Catch the very common case first: immediately a semicolon (U+003B).
7520 if (source.charCodeAt(index) === 0x3B || match(';')) {
7521 lex();
7522 return;
7523 }
7524
7525 line = lineNumber;
7526 skipComment();
7527 if (lineNumber !== line) {
7528 return;
7529 }
7530
7531 if (lookahead.type !== Token.EOF && !match('}')) {
7532 throwUnexpected(lookahead);
7533 }
7534 }
7535
7536 // 11.1.4 Array Initialiser
7537
7538 function parseArrayInitialiser() {
7539 var elements = [], node = new Node();
7540
7541 expect('[');
7542
7543 while (!match(']')) {
7544 if (match(',')) {
7545 lex();
7546 elements.push(null);
7547 } else {
7548 elements.push(parseAssignmentExpression());
7549
7550 if (!match(']')) {
7551 expect(',');
7552 }
7553 }
7554 }
7555
7556 lex();
7557
7558 return node.finishArrayExpression(elements);
7559 }
7560
7561 // 11.1.5 Object Initialiser
7562
7563 function parseObjectPropertyKey() {
7564 var token, node = new Node();
7565
7566 token = lex();
7567
7568 // Note: This function is called only from parseObjectProperty(), where
7569 // EOF and Punctuator tokens are already filtered out.
7570
7571 if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
7572 if (strict && token.octal) {
7573 throwErrorTolerant(token, Messages.StrictOctalLiteral);
7574 }
7575 return node.finishLiteral(token);
7576 }
7577
7578 return node.finishIdentifier(token.value);
7579 }
7580
7581 function parseObjectProperty() {
7582 var token, key, id, value, node = new Node();
7583
7584 token = lookahead;
7585
7586 if (token.type === Token.Identifier) {
7587 id = parseObjectPropertyKey();
7588 expect(':');
7589 value = parseAssignmentExpression();
7590 return node.finishProperty('init', id, value);
7591 }
7592 if (token.type === Token.EOF || token.type === Token.Punctuator) {
7593 throwUnexpected(token);
7594 } else {
7595 key = parseObjectPropertyKey();
7596 expect(':');
7597 value = parseAssignmentExpression();
7598 return node.finishProperty('init', key, value);
7599 }
7600 }
7601
7602 function parseObjectInitialiser() {
7603 var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node();
7604
7605 expect('{');
7606
7607 while (!match('}')) {
7608 property = parseObjectProperty();
7609
7610 if (property.key.type === Syntax.Identifier) {
7611 name = property.key.name;
7612 } else {
7613 name = toString(property.key.value);
7614 }
7615 kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
7616
7617 key = '$' + name;
7618 if (Object.prototype.hasOwnProperty.call(map, key)) {
7619 if (map[key] === PropertyKind.Data) {
7620 if (strict && kind === PropertyKind.Data) {
7621 throwErrorTolerant({}, Messages.StrictDuplicateProperty);
7622 } else if (kind !== PropertyKind.Data) {
7623 throwErrorTolerant({}, Messages.AccessorDataProperty);
7624 }
7625 } else {
7626 if (kind === PropertyKind.Data) {
7627 throwErrorTolerant({}, Messages.AccessorDataProperty);
7628 } else if (map[key] & kind) {
7629 throwErrorTolerant({}, Messages.AccessorGetSet);
7630 }
7631 }
7632 map[key] |= kind;
7633 } else {
7634 map[key] = kind;
7635 }
7636
7637 properties.push(property);
7638
7639 if (!match('}')) {
7640 expectTolerant(',');
7641 }
7642 }
7643
7644 expect('}');
7645
7646 return node.finishObjectExpression(properties);
7647 }
7648
7649 // 11.1.6 The Grouping Operator
7650
7651 function parseGroupExpression() {
7652 var expr;
7653
7654 expect('(');
7655
7656 ++state.parenthesisCount;
7657
7658 expr = parseExpression();
7659
7660 expect(')');
7661
7662 return expr;
7663 }
7664
7665
7666 // 11.1 Primary Expressions
7667
7668 var legalKeywords = {"if":1, "this":1};
7669
7670 function parsePrimaryExpression() {
7671 var type, token, expr, node;
7672
7673 if (match('(')) {
7674 return parseGroupExpression();
7675 }
7676
7677 if (match('[')) {
7678 return parseArrayInitialiser();
7679 }
7680
7681 if (match('{')) {
7682 return parseObjectInitialiser();
7683 }
7684
7685 type = lookahead.type;
7686 node = new Node();
7687
7688 if (type === Token.Identifier || legalKeywords[lookahead.value]) {
7689 expr = node.finishIdentifier(lex().value);
7690 } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
7691 if (strict && lookahead.octal) {
7692 throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
7693 }
7694 expr = node.finishLiteral(lex());
7695 } else if (type === Token.Keyword) {
7696 throw new Error("Disabled.");
7697 } else if (type === Token.BooleanLiteral) {
7698 token = lex();
7699 token.value = (token.value === 'true');
7700 expr = node.finishLiteral(token);
7701 } else if (type === Token.NullLiteral) {
7702 token = lex();
7703 token.value = null;
7704 expr = node.finishLiteral(token);
7705 } else if (match('/') || match('/=')) {
7706 if (typeof extra.tokens !== 'undefined') {
7707 expr = node.finishLiteral(collectRegex());
7708 } else {
7709 expr = node.finishLiteral(scanRegExp());
7710 }
7711 peek();
7712 } else {
7713 throwUnexpected(lex());
7714 }
7715
7716 return expr;
7717 }
7718
7719 // 11.2 Left-Hand-Side Expressions
7720
7721 function parseArguments() {
7722 var args = [];
7723
7724 expect('(');
7725
7726 if (!match(')')) {
7727 while (index < length) {
7728 args.push(parseAssignmentExpression());
7729 if (match(')')) {
7730 break;
7731 }
7732 expectTolerant(',');
7733 }
7734 }
7735
7736 expect(')');
7737
7738 return args;
7739 }
7740
7741 function parseNonComputedProperty() {
7742 var token, node = new Node();
7743
7744 token = lex();
7745
7746 if (!isIdentifierName(token)) {
7747 throwUnexpected(token);
7748 }
7749
7750 return node.finishIdentifier(token.value);
7751 }
7752
7753 function parseNonComputedMember() {
7754 expect('.');
7755
7756 return parseNonComputedProperty();
7757 }
7758
7759 function parseComputedMember() {
7760 var expr;
7761
7762 expect('[');
7763
7764 expr = parseExpression();
7765
7766 expect(']');
7767
7768 return expr;
7769 }
7770
7771 function parseLeftHandSideExpressionAllowCall() {
7772 var expr, args, property, startToken, previousAllowIn = state.allowIn;
7773
7774 startToken = lookahead;
7775 state.allowIn = true;
7776 expr = parsePrimaryExpression();
7777
7778 for (;;) {
7779 if (match('.')) {
7780 property = parseNonComputedMember();
7781 expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
7782 } else if (match('(')) {
7783 args = parseArguments();
7784 expr = new WrappingNode(startToken).finishCallExpression(expr, args);
7785 } else if (match('[')) {
7786 property = parseComputedMember();
7787 expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
7788 } else {
7789 break;
7790 }
7791 }
7792 state.allowIn = previousAllowIn;
7793
7794 return expr;
7795 }
7796
7797 // 11.3 Postfix Expressions
7798
7799 function parsePostfixExpression() {
7800 var expr = parseLeftHandSideExpressionAllowCall();
7801
7802 if (lookahead.type === Token.Punctuator) {
7803 if ((match('++') || match('--')) && !peekLineTerminator()) {
7804 throw new Error("Disabled.");
7805 }
7806 }
7807
7808 return expr;
7809 }
7810
7811 // 11.4 Unary Operators
7812
7813 function parseUnaryExpression() {
7814 var token, expr, startToken;
7815
7816 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
7817 expr = parsePostfixExpression();
7818 } else if (match('++') || match('--')) {
7819 throw new Error("Disabled.");
7820 } else if (match('+') || match('-') || match('~') || match('!')) {
7821 startToken = lookahead;
7822 token = lex();
7823 expr = parseUnaryExpression();
7824 expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
7825 } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
7826 throw new Error("Disabled.");
7827 } else {
7828 expr = parsePostfixExpression();
7829 }
7830
7831 return expr;
7832 }
7833
7834 function binaryPrecedence(token, allowIn) {
7835 var prec = 0;
7836
7837 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
7838 return 0;
7839 }
7840
7841 switch (token.value) {
7842 case '||':
7843 prec = 1;
7844 break;
7845
7846 case '&&':
7847 prec = 2;
7848 break;
7849
7850 case '|':
7851 prec = 3;
7852 break;
7853
7854 case '^':
7855 prec = 4;
7856 break;
7857
7858 case '&':
7859 prec = 5;
7860 break;
7861
7862 case '==':
7863 case '!=':
7864 case '===':
7865 case '!==':
7866 prec = 6;
7867 break;
7868
7869 case '<':
7870 case '>':
7871 case '<=':
7872 case '>=':
7873 case 'instanceof':
7874 prec = 7;
7875 break;
7876
7877 case 'in':
7878 prec = allowIn ? 7 : 0;
7879 break;
7880
7881 case '<<':
7882 case '>>':
7883 case '>>>':
7884 prec = 8;
7885 break;
7886
7887 case '+':
7888 case '-':
7889 prec = 9;
7890 break;
7891
7892 case '*':
7893 case '/':
7894 case '%':
7895 prec = 11;
7896 break;
7897
7898 default:
7899 break;
7900 }
7901
7902 return prec;
7903 }
7904
7905 // 11.5 Multiplicative Operators
7906 // 11.6 Additive Operators
7907 // 11.7 Bitwise Shift Operators
7908 // 11.8 Relational Operators
7909 // 11.9 Equality Operators
7910 // 11.10 Binary Bitwise Operators
7911 // 11.11 Binary Logical Operators
7912
7913 function parseBinaryExpression() {
7914 var marker, markers, expr, token, prec, stack, right, operator, left, i;
7915
7916 marker = lookahead;
7917 left = parseUnaryExpression();
7918
7919 token = lookahead;
7920 prec = binaryPrecedence(token, state.allowIn);
7921 if (prec === 0) {
7922 return left;
7923 }
7924 token.prec = prec;
7925 lex();
7926
7927 markers = [marker, lookahead];
7928 right = parseUnaryExpression();
7929
7930 stack = [left, token, right];
7931
7932 while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
7933
7934 // Reduce: make a binary expression from the three topmost entries.
7935 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
7936 right = stack.pop();
7937 operator = stack.pop().value;
7938 left = stack.pop();
7939 markers.pop();
7940 expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
7941 stack.push(expr);
7942 }
7943
7944 // Shift.
7945 token = lex();
7946 token.prec = prec;
7947 stack.push(token);
7948 markers.push(lookahead);
7949 expr = parseUnaryExpression();
7950 stack.push(expr);
7951 }
7952
7953 // Final reduce to clean-up the stack.
7954 i = stack.length - 1;
7955 expr = stack[i];
7956 markers.pop();
7957 while (i > 1) {
7958 expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
7959 i -= 2;
7960 }
7961
7962 return expr;
7963 }
7964
7965 // 11.12 Conditional Operator
7966
7967 function parseConditionalExpression() {
7968 var expr, previousAllowIn, consequent, alternate, startToken;
7969
7970 startToken = lookahead;
7971
7972 expr = parseBinaryExpression();
7973
7974 if (match('?')) {
7975 lex();
7976 previousAllowIn = state.allowIn;
7977 state.allowIn = true;
7978 consequent = parseAssignmentExpression();
7979 state.allowIn = previousAllowIn;
7980 expect(':');
7981 alternate = parseAssignmentExpression();
7982
7983 expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
7984 }
7985
7986 return expr;
7987 }
7988
7989 // 11.13 Assignment Operators
7990
7991 function parseAssignmentExpression() {
7992 var oldParenthesisCount, token, expr, startToken;
7993
7994 oldParenthesisCount = state.parenthesisCount;
7995
7996 startToken = lookahead;
7997 token = lookahead;
7998
7999 expr = parseConditionalExpression();
8000
8001 return expr;
8002 }
8003
8004 // 11.14 Comma Operator
8005
8006 function parseExpression() {
8007 var expr = parseAssignmentExpression();
8008
8009 if (match(',')) {
8010 throw new Error("Disabled."); // no sequence expressions
8011 }
8012
8013 return expr;
8014 }
8015
8016 // 12.4 Expression Statement
8017
8018 function parseExpressionStatement(node) {
8019 var expr = parseExpression();
8020 consumeSemicolon();
8021 return node.finishExpressionStatement(expr);
8022 }
8023
8024 // 12 Statements
8025
8026 function parseStatement() {
8027 var type = lookahead.type,
8028 expr,
8029 node;
8030
8031 if (type === Token.EOF) {
8032 throwUnexpected(lookahead);
8033 }
8034
8035 if (type === Token.Punctuator && lookahead.value === '{') {
8036 throw new Error("Disabled."); // block statement
8037 }
8038
8039 node = new Node();
8040
8041 if (type === Token.Punctuator) {
8042 switch (lookahead.value) {
8043 case ';':
8044 throw new Error("Disabled."); // empty statement
8045 case '(':
8046 return parseExpressionStatement(node);
8047 default:
8048 break;
8049 }
8050 } else if (type === Token.Keyword) {
8051 throw new Error("Disabled."); // keyword
8052 }
8053
8054 expr = parseExpression();
8055 consumeSemicolon();
8056 return node.finishExpressionStatement(expr);
8057 }
8058
8059 // 14 Program
8060
8061 function parseSourceElement() {
8062 if (lookahead.type === Token.Keyword) {
8063 switch (lookahead.value) {
8064 case 'const':
8065 case 'let':
8066 throw new Error("Disabled.");
8067 case 'function':
8068 throw new Error("Disabled.");
8069 default:
8070 return parseStatement();
8071 }
8072 }
8073
8074 if (lookahead.type !== Token.EOF) {
8075 return parseStatement();
8076 }
8077 }
8078
8079 function parseSourceElements() {
8080 var sourceElement, sourceElements = [], token, directive, firstRestricted;
8081
8082 while (index < length) {
8083 token = lookahead;
8084 if (token.type !== Token.StringLiteral) {
8085 break;
8086 }
8087
8088 sourceElement = parseSourceElement();
8089 sourceElements.push(sourceElement);
8090 if (sourceElement.expression.type !== Syntax.Literal) {
8091 // this is not directive
8092 break;
8093 }
8094 directive = source.slice(token.start + 1, token.end - 1);
8095 if (directive === 'use strict') {
8096 strict = true;
8097 if (firstRestricted) {
8098 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
8099 }
8100 } else {
8101 if (!firstRestricted && token.octal) {
8102 firstRestricted = token;
8103 }
8104 }
8105 }
8106
8107 while (index < length) {
8108 sourceElement = parseSourceElement();
8109 if (typeof sourceElement === 'undefined') {
8110 break;
8111 }
8112 sourceElements.push(sourceElement);
8113 }
8114 return sourceElements;
8115 }
8116
8117 function parseProgram() {
8118 var body, node;
8119
8120 skipComment();
8121 peek();
8122 node = new Node();
8123 strict = true; // assume strict
8124
8125 body = parseSourceElements();
8126 return node.finishProgram(body);
8127 }
8128
8129 function filterTokenLocation() {
8130 var i, entry, token, tokens = [];
8131
8132 for (i = 0; i < extra.tokens.length; ++i) {
8133 entry = extra.tokens[i];
8134 token = {
8135 type: entry.type,
8136 value: entry.value
8137 };
8138 if (entry.regex) {
8139 token.regex = {
8140 pattern: entry.regex.pattern,
8141 flags: entry.regex.flags
8142 };
8143 }
8144 if (extra.range) {
8145 token.range = entry.range;
8146 }
8147 if (extra.loc) {
8148 token.loc = entry.loc;
8149 }
8150 tokens.push(token);
8151 }
8152
8153 extra.tokens = tokens;
8154 }
8155
8156 function tokenize(code, options) {
8157 var toString,
8158 tokens;
8159
8160 toString = String;
8161 if (typeof code !== 'string' && !(code instanceof String)) {
8162 code = toString(code);
8163 }
8164
8165 source = code;
8166 index = 0;
8167 lineNumber = (source.length > 0) ? 1 : 0;
8168 lineStart = 0;
8169 length = source.length;
8170 lookahead = null;
8171 state = {
8172 allowIn: true,
8173 labelSet: {},
8174 inFunctionBody: false,
8175 inIteration: false,
8176 inSwitch: false,
8177 lastCommentStart: -1
8178 };
8179
8180 extra = {};
8181
8182 // Options matching.
8183 options = options || {};
8184
8185 // Of course we collect tokens here.
8186 options.tokens = true;
8187 extra.tokens = [];
8188 extra.tokenize = true;
8189 // The following two fields are necessary to compute the Regex tokens.
8190 extra.openParenToken = -1;
8191 extra.openCurlyToken = -1;
8192
8193 extra.range = (typeof options.range === 'boolean') && options.range;
8194 extra.loc = (typeof options.loc === 'boolean') && options.loc;
8195
8196 if (typeof options.tolerant === 'boolean' && options.tolerant) {
8197 extra.errors = [];
8198 }
8199
8200 try {
8201 peek();
8202 if (lookahead.type === Token.EOF) {
8203 return extra.tokens;
8204 }
8205
8206 lex();
8207 while (lookahead.type !== Token.EOF) {
8208 try {
8209 lex();
8210 } catch (lexError) {
8211 if (extra.errors) {
8212 extra.errors.push(lexError);
8213 // We have to break on the first error
8214 // to avoid infinite loops.
8215 break;
8216 } else {
8217 throw lexError;
8218 }
8219 }
8220 }
8221
8222 filterTokenLocation();
8223 tokens = extra.tokens;
8224 if (typeof extra.errors !== 'undefined') {
8225 tokens.errors = extra.errors;
8226 }
8227 } catch (e) {
8228 throw e;
8229 } finally {
8230 extra = {};
8231 }
8232 return tokens;
8233 }
8234
8235 function parse(code, options) {
8236 var program, toString;
8237
8238 toString = String;
8239 if (typeof code !== 'string' && !(code instanceof String)) {
8240 code = toString(code);
8241 }
8242
8243 source = code;
8244 index = 0;
8245 lineNumber = (source.length > 0) ? 1 : 0;
8246 lineStart = 0;
8247 length = source.length;
8248 lookahead = null;
8249 state = {
8250 allowIn: true,
8251 labelSet: {},
8252 parenthesisCount: 0,
8253 inFunctionBody: false,
8254 inIteration: false,
8255 inSwitch: false,
8256 lastCommentStart: -1
8257 };
8258
8259 extra = {};
8260 if (typeof options !== 'undefined') {
8261 extra.range = (typeof options.range === 'boolean') && options.range;
8262 extra.loc = (typeof options.loc === 'boolean') && options.loc;
8263
8264 if (extra.loc && options.source !== null && options.source !== undefined) {
8265 extra.source = toString(options.source);
8266 }
8267
8268 if (typeof options.tokens === 'boolean' && options.tokens) {
8269 extra.tokens = [];
8270 }
8271 if (typeof options.tolerant === 'boolean' && options.tolerant) {
8272 extra.errors = [];
8273 }
8274 }
8275
8276 try {
8277 program = parseProgram();
8278 if (typeof extra.tokens !== 'undefined') {
8279 filterTokenLocation();
8280 program.tokens = extra.tokens;
8281 }
8282 if (typeof extra.errors !== 'undefined') {
8283 program.errors = extra.errors;
8284 }
8285 } catch (e) {
8286 throw e;
8287 } finally {
8288 extra = {};
8289 }
8290
8291 return program;
8292 }
8293
8294 return {
8295 tokenize: tokenize,
8296 parse: parse
8297 };
8298
8299 })();
8300 },{}],45:[function(require,module,exports){
8301 var ts = Date.now();
8302
8303 function write(msg) {
8304 msg = '[Vega Log] ' + msg;
8305 console.log(msg);
8306 }
8307
8308 function error(msg) {
8309 msg = '[Vega Err] ' + msg;
8310 console.error(msg);
8311 }
8312
8313 function debug(input, args) {
8314 if (!debug.enable) return;
8315 var log = Function.prototype.bind.call(console.log, console);
8316 var state = {
8317 prevTime: Date.now() - ts,
8318 stamp: input.stamp
8319 };
8320
8321 if (input.add) {
8322 state.add = input.add.length;
8323 state.mod = input.mod.length;
8324 state.rem = input.rem.length;
8325 state.reflow = !!input.reflow;
8326 }
8327
8328 log.apply(console, (args.push(JSON.stringify(state)), args));
8329 ts = Date.now();
8330 }
8331
8332 module.exports = {
8333 log: write,
8334 error: error,
8335 debug: (debug.enable = false, debug)
8336 };
8337
8338 },{}],46:[function(require,module,exports){
8339 module.exports = {
8340 path: require('./path'),
8341 render: require('./render'),
8342 Item: require('./util/Item'),
8343 bound: require('./util/bound'),
8344 Bounds: require('./util/Bounds'),
8345 Gradient: require('./util/Gradient'),
8346 toJSON: require('./util/scene').toJSON,
8347 fromJSON: require('./util/scene').fromJSON
8348 };
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){
8350 var segmentCache = {},
8351 bezierCache = {},
8352 join = [].join;
8353
8354 // Copied from Inkscape svgtopdf, thanks!
8355 function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) {
8356 var key = join.call(arguments);
8357 if (segmentCache[key]) {
8358 return segmentCache[key];
8359 }
8360
8361 var th = rotateX * (Math.PI/180);
8362 var sin_th = Math.sin(th);
8363 var cos_th = Math.cos(th);
8364 rx = Math.abs(rx);
8365 ry = Math.abs(ry);
8366 var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5;
8367 var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5;
8368 var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry);
8369 if (pl > 1) {
8370 pl = Math.sqrt(pl);
8371 rx *= pl;
8372 ry *= pl;
8373 }
8374
8375 var a00 = cos_th / rx;
8376 var a01 = sin_th / rx;
8377 var a10 = (-sin_th) / ry;
8378 var a11 = (cos_th) / ry;
8379 var x0 = a00 * ox + a01 * oy;
8380 var y0 = a10 * ox + a11 * oy;
8381 var x1 = a00 * x + a01 * y;
8382 var y1 = a10 * x + a11 * y;
8383
8384 var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0);
8385 var sfactor_sq = 1 / d - 0.25;
8386 if (sfactor_sq < 0) sfactor_sq = 0;
8387 var sfactor = Math.sqrt(sfactor_sq);
8388 if (sweep == large) sfactor = -sfactor;
8389 var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0);
8390 var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0);
8391
8392 var th0 = Math.atan2(y0-yc, x0-xc);
8393 var th1 = Math.atan2(y1-yc, x1-xc);
8394
8395 var th_arc = th1-th0;
8396 if (th_arc < 0 && sweep === 1){
8397 th_arc += 2 * Math.PI;
8398 } else if (th_arc > 0 && sweep === 0) {
8399 th_arc -= 2 * Math.PI;
8400 }
8401
8402 var segs = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001)));
8403 var result = [];
8404 for (var i=0; i<segs; ++i) {
8405 var th2 = th0 + i * th_arc / segs;
8406 var th3 = th0 + (i+1) * th_arc / segs;
8407 result[i] = [xc, yc, th2, th3, rx, ry, sin_th, cos_th];
8408 }
8409
8410 return (segmentCache[key] = result);
8411 }
8412
8413 function bezier(params) {
8414 var key = join.call(params);
8415 if (bezierCache[key]) {
8416 return bezierCache[key];
8417 }
8418
8419 var cx = params[0],
8420 cy = params[1],
8421 th0 = params[2],
8422 th1 = params[3],
8423 rx = params[4],
8424 ry = params[5],
8425 sin_th = params[6],
8426 cos_th = params[7];
8427
8428 var a00 = cos_th * rx;
8429 var a01 = -sin_th * ry;
8430 var a10 = sin_th * rx;
8431 var a11 = cos_th * ry;
8432
8433 var cos_th0 = Math.cos(th0);
8434 var sin_th0 = Math.sin(th0);
8435 var cos_th1 = Math.cos(th1);
8436 var sin_th1 = Math.sin(th1);
8437
8438 var th_half = 0.5 * (th1 - th0);
8439 var sin_th_h2 = Math.sin(th_half * 0.5);
8440 var t = (8/3) * sin_th_h2 * sin_th_h2 / Math.sin(th_half);
8441 var x1 = cx + cos_th0 - t * sin_th0;
8442 var y1 = cy + sin_th0 + t * cos_th0;
8443 var x3 = cx + cos_th1;
8444 var y3 = cy + sin_th1;
8445 var x2 = x3 + t * sin_th1;
8446 var y2 = y3 - t * cos_th1;
8447
8448 return (bezierCache[key] = [
8449 a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
8450 a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
8451 a00 * x3 + a01 * y3, a10 * x3 + a11 * y3
8452 ]);
8453 }
8454
8455 module.exports = {
8456 segments: segments,
8457 bezier: bezier,
8458 cache: {
8459 segments: segmentCache,
8460 bezier: bezierCache
8461 }
8462 };
8463
8464 },{}],48:[function(require,module,exports){
8465 module.exports = {
8466 parse: require('./parse'),
8467 render: require('./render')
8468 };
8469
8470 },{"./parse":49,"./render":50}],49:[function(require,module,exports){
8471 // Path parsing and rendering code adapted from fabric.js -- Thanks!
8472 var cmdlen = { m:2, l:2, h:1, v:1, c:6, s:4, q:4, t:2, a:7 },
8473 regexp = [/([MLHVCSQTAZmlhvcsqtaz])/g, /###/, /(\d)([-+])/g, /\s|,|###/];
8474
8475 module.exports = function(pathstr) {
8476 var result = [],
8477 path,
8478 curr,
8479 chunks,
8480 parsed, param,
8481 cmd, len, i, j, n, m;
8482
8483 // First, break path into command sequence
8484 path = pathstr
8485 .slice()
8486 .replace(regexp[0], '###$1')
8487 .split(regexp[1])
8488 .slice(1);
8489
8490 // Next, parse each command in turn
8491 for (i=0, n=path.length; i<n; ++i) {
8492 curr = path[i];
8493 chunks = curr
8494 .slice(1)
8495 .trim()
8496 .replace(regexp[2],'$1###$2')
8497 .split(regexp[3]);
8498 cmd = curr.charAt(0);
8499
8500 parsed = [cmd];
8501 for (j=0, m=chunks.length; j<m; ++j) {
8502 if ((param = +chunks[j]) === param) { // not NaN
8503 parsed.push(param);
8504 }
8505 }
8506
8507 len = cmdlen[cmd.toLowerCase()];
8508 if (parsed.length-1 > len) {
8509 for (j=1, m=parsed.length; j<m; j+=len) {
8510 result.push([cmd].concat(parsed.slice(j, j+len)));
8511 }
8512 }
8513 else {
8514 result.push(parsed);
8515 }
8516 }
8517
8518 return result;
8519 };
8520
8521 },{}],50:[function(require,module,exports){
8522 var arc = require('./arc');
8523
8524 module.exports = function(g, path, l, t) {
8525 var current, // current instruction
8526 previous = null,
8527 x = 0, // current x
8528 y = 0, // current y
8529 controlX = 0, // current control point x
8530 controlY = 0, // current control point y
8531 tempX,
8532 tempY,
8533 tempControlX,
8534 tempControlY;
8535
8536 if (l == null) l = 0;
8537 if (t == null) t = 0;
8538
8539 g.beginPath();
8540
8541 for (var i=0, len=path.length; i<len; ++i) {
8542 current = path[i];
8543
8544 switch (current[0]) { // first letter
8545
8546 case 'l': // lineto, relative
8547 x += current[1];
8548 y += current[2];
8549 g.lineTo(x + l, y + t);
8550 break;
8551
8552 case 'L': // lineto, absolute
8553 x = current[1];
8554 y = current[2];
8555 g.lineTo(x + l, y + t);
8556 break;
8557
8558 case 'h': // horizontal lineto, relative
8559 x += current[1];
8560 g.lineTo(x + l, y + t);
8561 break;
8562
8563 case 'H': // horizontal lineto, absolute
8564 x = current[1];
8565 g.lineTo(x + l, y + t);
8566 break;
8567
8568 case 'v': // vertical lineto, relative
8569 y += current[1];
8570 g.lineTo(x + l, y + t);
8571 break;
8572
8573 case 'V': // verical lineto, absolute
8574 y = current[1];
8575 g.lineTo(x + l, y + t);
8576 break;
8577
8578 case 'm': // moveTo, relative
8579 x += current[1];
8580 y += current[2];
8581 g.moveTo(x + l, y + t);
8582 break;
8583
8584 case 'M': // moveTo, absolute
8585 x = current[1];
8586 y = current[2];
8587 g.moveTo(x + l, y + t);
8588 break;
8589
8590 case 'c': // bezierCurveTo, relative
8591 tempX = x + current[5];
8592 tempY = y + current[6];
8593 controlX = x + current[3];
8594 controlY = y + current[4];
8595 g.bezierCurveTo(
8596 x + current[1] + l, // x1
8597 y + current[2] + t, // y1
8598 controlX + l, // x2
8599 controlY + t, // y2
8600 tempX + l,
8601 tempY + t
8602 );
8603 x = tempX;
8604 y = tempY;
8605 break;
8606
8607 case 'C': // bezierCurveTo, absolute
8608 x = current[5];
8609 y = current[6];
8610 controlX = current[3];
8611 controlY = current[4];
8612 g.bezierCurveTo(
8613 current[1] + l,
8614 current[2] + t,
8615 controlX + l,
8616 controlY + t,
8617 x + l,
8618 y + t
8619 );
8620 break;
8621
8622 case 's': // shorthand cubic bezierCurveTo, relative
8623 // transform to absolute x,y
8624 tempX = x + current[3];
8625 tempY = y + current[4];
8626 // calculate reflection of previous control points
8627 controlX = 2 * x - controlX;
8628 controlY = 2 * y - controlY;
8629 g.bezierCurveTo(
8630 controlX + l,
8631 controlY + t,
8632 x + current[1] + l,
8633 y + current[2] + t,
8634 tempX + l,
8635 tempY + t
8636 );
8637
8638 // set control point to 2nd one of this command
8639 // the first control point is assumed to be the reflection of
8640 // the second control point on the previous command relative
8641 // to the current point.
8642 controlX = x + current[1];
8643 controlY = y + current[2];
8644
8645 x = tempX;
8646 y = tempY;
8647 break;
8648
8649 case 'S': // shorthand cubic bezierCurveTo, absolute
8650 tempX = current[3];
8651 tempY = current[4];
8652 // calculate reflection of previous control points
8653 controlX = 2*x - controlX;
8654 controlY = 2*y - controlY;
8655 g.bezierCurveTo(
8656 controlX + l,
8657 controlY + t,
8658 current[1] + l,
8659 current[2] + t,
8660 tempX + l,
8661 tempY + t
8662 );
8663 x = tempX;
8664 y = tempY;
8665 // set control point to 2nd one of this command
8666 // the first control point is assumed to be the reflection of
8667 // the second control point on the previous command relative
8668 // to the current point.
8669 controlX = current[1];
8670 controlY = current[2];
8671
8672 break;
8673
8674 case 'q': // quadraticCurveTo, relative
8675 // transform to absolute x,y
8676 tempX = x + current[3];
8677 tempY = y + current[4];
8678
8679 controlX = x + current[1];
8680 controlY = y + current[2];
8681
8682 g.quadraticCurveTo(
8683 controlX + l,
8684 controlY + t,
8685 tempX + l,
8686 tempY + t
8687 );
8688 x = tempX;
8689 y = tempY;
8690 break;
8691
8692 case 'Q': // quadraticCurveTo, absolute
8693 tempX = current[3];
8694 tempY = current[4];
8695
8696 g.quadraticCurveTo(
8697 current[1] + l,
8698 current[2] + t,
8699 tempX + l,
8700 tempY + t
8701 );
8702 x = tempX;
8703 y = tempY;
8704 controlX = current[1];
8705 controlY = current[2];
8706 break;
8707
8708 case 't': // shorthand quadraticCurveTo, relative
8709
8710 // transform to absolute x,y
8711 tempX = x + current[1];
8712 tempY = y + current[2];
8713
8714 if (previous[0].match(/[QqTt]/) === null) {
8715 // If there is no previous command or if the previous command was not a Q, q, T or t,
8716 // assume the control point is coincident with the current point
8717 controlX = x;
8718 controlY = y;
8719 }
8720 else if (previous[0] === 't') {
8721 // calculate reflection of previous control points for t
8722 controlX = 2 * x - tempControlX;
8723 controlY = 2 * y - tempControlY;
8724 }
8725 else if (previous[0] === 'q') {
8726 // calculate reflection of previous control points for q
8727 controlX = 2 * x - controlX;
8728 controlY = 2 * y - controlY;
8729 }
8730
8731 tempControlX = controlX;
8732 tempControlY = controlY;
8733
8734 g.quadraticCurveTo(
8735 controlX + l,
8736 controlY + t,
8737 tempX + l,
8738 tempY + t
8739 );
8740 x = tempX;
8741 y = tempY;
8742 controlX = x + current[1];
8743 controlY = y + current[2];
8744 break;
8745
8746 case 'T':
8747 tempX = current[1];
8748 tempY = current[2];
8749
8750 // calculate reflection of previous control points
8751 controlX = 2 * x - controlX;
8752 controlY = 2 * y - controlY;
8753 g.quadraticCurveTo(
8754 controlX + l,
8755 controlY + t,
8756 tempX + l,
8757 tempY + t
8758 );
8759 x = tempX;
8760 y = tempY;
8761 break;
8762
8763 case 'a':
8764 drawArc(g, x + l, y + t, [
8765 current[1],
8766 current[2],
8767 current[3],
8768 current[4],
8769 current[5],
8770 current[6] + x + l,
8771 current[7] + y + t
8772 ]);
8773 x += current[6];
8774 y += current[7];
8775 break;
8776
8777 case 'A':
8778 drawArc(g, x + l, y + t, [
8779 current[1],
8780 current[2],
8781 current[3],
8782 current[4],
8783 current[5],
8784 current[6] + l,
8785 current[7] + t
8786 ]);
8787 x = current[6];
8788 y = current[7];
8789 break;
8790
8791 case 'z':
8792 case 'Z':
8793 g.closePath();
8794 break;
8795 }
8796 previous = current;
8797 }
8798 };
8799
8800 function drawArc(g, x, y, coords) {
8801 var seg = arc.segments(
8802 coords[5], // end x
8803 coords[6], // end y
8804 coords[0], // radius x
8805 coords[1], // radius y
8806 coords[3], // large flag
8807 coords[4], // sweep flag
8808 coords[2], // rotation
8809 x, y
8810 );
8811 for (var i=0; i<seg.length; ++i) {
8812 var bez = arc.bezier(seg[i]);
8813 g.bezierCurveTo.apply(g, bez);
8814 }
8815 }
8816
8817 },{"./arc":47}],51:[function(require,module,exports){
8818 function Handler() {
8819 this._active = null;
8820 this._handlers = {};
8821 }
8822
8823 var prototype = Handler.prototype;
8824
8825 prototype.initialize = function(el, pad, obj) {
8826 this._el = el;
8827 this._obj = obj || null;
8828 return this.padding(pad);
8829 };
8830
8831 prototype.element = function() {
8832 return this._el;
8833 };
8834
8835 prototype.padding = function(pad) {
8836 this._padding = pad || {top:0, left:0, bottom:0, right:0};
8837 return this;
8838 };
8839
8840 prototype.scene = function(scene) {
8841 if (!arguments.length) return this._scene;
8842 this._scene = scene;
8843 return this;
8844 };
8845
8846 // add an event handler
8847 // subclasses should override
8848 prototype.on = function(/*type, handler*/) {};
8849
8850 // remove an event handler
8851 // subclasses should override
8852 prototype.off = function(/*type, handler*/) {};
8853
8854 // return an array with all registered event handlers
8855 prototype.handlers = function() {
8856 var h = this._handlers, a = [], k;
8857 for (k in h) { a.push.apply(a, h[k]); }
8858 return a;
8859 };
8860
8861 prototype.eventName = function(name) {
8862 var i = name.indexOf('.');
8863 return i < 0 ? name : name.slice(0,i);
8864 };
8865
8866 module.exports = Handler;
8867 },{}],52:[function(require,module,exports){
8868 function Renderer() {
8869 this._el = null;
8870 this._bgcolor = null;
8871 }
8872
8873 var prototype = Renderer.prototype;
8874
8875 prototype.initialize = function(el, width, height, padding) {
8876 this._el = el;
8877 return this.resize(width, height, padding);
8878 };
8879
8880 // Returns the parent container element for a visualization
8881 prototype.element = function() {
8882 return this._el;
8883 };
8884
8885 // Returns the scene element (e.g., canvas or SVG) of the visualization
8886 // Subclasses must override if the first child is not the scene element
8887 prototype.scene = function() {
8888 return this._el && this._el.firstChild;
8889 };
8890
8891 prototype.background = function(bgcolor) {
8892 if (arguments.length === 0) return this._bgcolor;
8893 this._bgcolor = bgcolor;
8894 return this;
8895 };
8896
8897 prototype.resize = function(width, height, padding) {
8898 this._width = width;
8899 this._height = height;
8900 this._padding = padding || {top:0, left:0, bottom:0, right:0};
8901 return this;
8902 };
8903
8904 prototype.render = function(/*scene, items*/) {
8905 return this;
8906 };
8907
8908 module.exports = Renderer;
8909 },{}],53:[function(require,module,exports){
8910 var DOM = require('../../util/dom'),
8911 Handler = require('../Handler'),
8912 marks = require('./marks');
8913
8914 function CanvasHandler() {
8915 Handler.call(this);
8916 this._down = null;
8917 this._touch = null;
8918 this._first = true;
8919 }
8920
8921 var base = Handler.prototype;
8922 var prototype = (CanvasHandler.prototype = Object.create(base));
8923 prototype.constructor = CanvasHandler;
8924
8925 prototype.initialize = function(el, pad, obj) {
8926 // add event listeners
8927 var canvas = this._canvas = DOM.find(el, 'canvas'),
8928 that = this;
8929 this.events.forEach(function(type) {
8930 canvas.addEventListener(type, function(evt) {
8931 if (prototype[type]) {
8932 prototype[type].call(that, evt);
8933 } else {
8934 that.fire(type, evt);
8935 }
8936 });
8937 });
8938
8939 return base.initialize.call(this, el, pad, obj);
8940 };
8941
8942 prototype.canvas = function() {
8943 return this._canvas;
8944 };
8945
8946 // retrieve the current canvas context
8947 prototype.context = function() {
8948 return this._canvas.getContext('2d');
8949 };
8950
8951 // supported events
8952 prototype.events = [
8953 'keydown',
8954 'keypress',
8955 'keyup',
8956 'mousedown',
8957 'mouseup',
8958 'mousemove',
8959 'mouseout',
8960 'mouseover',
8961 'click',
8962 'dblclick',
8963 'wheel',
8964 'mousewheel',
8965 'touchstart',
8966 'touchmove',
8967 'touchend'
8968 ];
8969
8970 // to keep firefox happy
8971 prototype.DOMMouseScroll = function(evt) {
8972 this.fire('mousewheel', evt);
8973 };
8974
8975 prototype.mousemove = function(evt) {
8976 var a = this._active,
8977 p = this.pickEvent(evt);
8978
8979 if (p === a) {
8980 // active item and picked item are the same
8981 this.fire('mousemove', evt); // fire move
8982 } else {
8983 // active item and picked item are different
8984 this.fire('mouseout', evt); // fire out for prior active item
8985 this._active = p; // set new active item
8986 this.fire('mouseover', evt); // fire over for new active item
8987 this.fire('mousemove', evt); // fire move for new active item
8988 }
8989 };
8990
8991 prototype.mouseout = function(evt) {
8992 this.fire('mouseout', evt);
8993 this._active = null;
8994 };
8995
8996 prototype.mousedown = function(evt) {
8997 this._down = this._active;
8998 this.fire('mousedown', evt);
8999 };
9000
9001 prototype.click = function(evt) {
9002 if (this._down === this._active) {
9003 this.fire('click', evt);
9004 this._down = null;
9005 }
9006 };
9007
9008 prototype.touchstart = function(evt) {
9009 this._touch = this.pickEvent(evt.changedTouches[0]);
9010
9011 if (this._first) {
9012 this._active = this._touch;
9013 this._first = false;
9014 }
9015
9016 this.fire('touchstart', evt, true);
9017 };
9018
9019 prototype.touchmove = function(evt) {
9020 this.fire('touchmove', evt, true);
9021 };
9022
9023 prototype.touchend = function(evt) {
9024 this.fire('touchend', evt, true);
9025 this._touch = null;
9026 };
9027
9028 // fire an event
9029 prototype.fire = function(type, evt, touch) {
9030 var a = touch ? this._touch : this._active,
9031 h = this._handlers[type], i, len;
9032 if (h) {
9033 evt.vegaType = type;
9034 for (i=0, len=h.length; i<len; ++i) {
9035 h[i].handler.call(this._obj, evt, a);
9036 }
9037 }
9038 };
9039
9040 // add an event handler
9041 prototype.on = function(type, handler) {
9042 var name = this.eventName(type),
9043 h = this._handlers;
9044 (h[name] || (h[name] = [])).push({
9045 type: type,
9046 handler: handler
9047 });
9048 return this;
9049 };
9050
9051 // remove an event handler
9052 prototype.off = function(type, handler) {
9053 var name = this.eventName(type),
9054 h = this._handlers[name], i;
9055 if (!h) return;
9056 for (i=h.length; --i>=0;) {
9057 if (h[i].type !== type) continue;
9058 if (!handler || h[i].handler === handler) h.splice(i, 1);
9059 }
9060 return this;
9061 };
9062
9063 prototype.pickEvent = function(evt) {
9064 var rect = this._canvas.getBoundingClientRect(),
9065 pad = this._padding, x, y;
9066 return this.pick(this._scene,
9067 x = (evt.clientX - rect.left),
9068 y = (evt.clientY - rect.top),
9069 x - pad.left, y - pad.top);
9070 };
9071
9072 // find the scenegraph item at the current mouse position
9073 // x, y -- the absolute x, y mouse coordinates on the canvas element
9074 // gx, gy -- the relative coordinates within the current group
9075 prototype.pick = function(scene, x, y, gx, gy) {
9076 var g = this.context(),
9077 mark = marks[scene.marktype];
9078 return mark.pick.call(this, g, scene, x, y, gx, gy);
9079 };
9080
9081 module.exports = CanvasHandler;
9082
9083 },{"../../util/dom":81,"../Handler":51,"./marks":60}],54:[function(require,module,exports){
9084 var DOM = require('../../util/dom'),
9085 Bounds = require('../../util/Bounds'),
9086 ImageLoader = require('../../util/ImageLoader'),
9087 Canvas = require('../../util/canvas'),
9088 Renderer = require('../Renderer'),
9089 marks = require('./marks');
9090
9091 function CanvasRenderer(loadConfig) {
9092 Renderer.call(this);
9093 this._loader = new ImageLoader(loadConfig);
9094 }
9095
9096 CanvasRenderer.RETINA = true;
9097
9098 var base = Renderer.prototype;
9099 var prototype = (CanvasRenderer.prototype = Object.create(base));
9100 prototype.constructor = CanvasRenderer;
9101
9102 prototype.initialize = function(el, width, height, padding) {
9103 this._canvas = Canvas.instance(width, height);
9104 if (el) {
9105 DOM.clear(el, 0).appendChild(this._canvas);
9106 this._canvas.setAttribute('class', 'marks');
9107 }
9108 return base.initialize.call(this, el, width, height, padding);
9109 };
9110
9111 prototype.resize = function(width, height, padding) {
9112 base.resize.call(this, width, height, padding);
9113 Canvas.resize(this._canvas, this._width, this._height,
9114 this._padding, CanvasRenderer.RETINA);
9115 return this;
9116 };
9117
9118 prototype.canvas = function() {
9119 return this._canvas;
9120 };
9121
9122 prototype.context = function() {
9123 return this._canvas ? this._canvas.getContext('2d') : null;
9124 };
9125
9126 prototype.pendingImages = function() {
9127 return this._loader.pending();
9128 };
9129
9130 function clipToBounds(g, items) {
9131 if (!items) return null;
9132
9133 var b = new Bounds(), i, n, item, mark, group;
9134 for (i=0, n=items.length; i<n; ++i) {
9135 item = items[i];
9136 mark = item.mark;
9137 group = mark.group;
9138 item = marks[mark.marktype].nested ? mark : item;
9139 b.union(translate(item.bounds, group));
9140 if (item['bounds:prev']) {
9141 b.union(translate(item['bounds:prev'], group));
9142 }
9143 }
9144 b.round();
9145
9146 g.beginPath();
9147 g.rect(b.x1, b.y1, b.width(), b.height());
9148 g.clip();
9149
9150 return b;
9151 }
9152
9153 function translate(bounds, group) {
9154 if (group == null) return bounds;
9155 var b = bounds.clone();
9156 for (; group != null; group = group.mark.group) {
9157 b.translate(group.x || 0, group.y || 0);
9158 }
9159 return b;
9160 }
9161
9162 prototype.render = function(scene, items) {
9163 var g = this.context(),
9164 p = this._padding,
9165 w = this._width + p.left + p.right,
9166 h = this._height + p.top + p.bottom,
9167 b;
9168
9169 // setup
9170 this._scene = scene; // cache scene for async redraw
9171 g.save();
9172 b = clipToBounds(g, items);
9173 this.clear(-p.left, -p.top, w, h);
9174
9175 // render
9176 this.draw(g, scene, b);
9177
9178 // takedown
9179 g.restore();
9180 this._scene = null; // clear scene cache
9181
9182 return this;
9183 };
9184
9185 prototype.draw = function(ctx, scene, bounds) {
9186 var mark = marks[scene.marktype];
9187 mark.draw.call(this, ctx, scene, bounds);
9188 };
9189
9190 prototype.clear = function(x, y, w, h) {
9191 var g = this.context();
9192 g.clearRect(x, y, w, h);
9193 if (this._bgcolor != null) {
9194 g.fillStyle = this._bgcolor;
9195 g.fillRect(x, y, w, h);
9196 }
9197 };
9198
9199 prototype.loadImage = function(uri) {
9200 var renderer = this,
9201 scene = this._scene;
9202 return this._loader.loadImage(uri, function() {
9203 renderer.renderAsync(scene);
9204 });
9205 };
9206
9207 prototype.renderAsync = function(scene) {
9208 // TODO make safe for multiple scene rendering?
9209 var renderer = this;
9210 if (renderer._async_id) {
9211 clearTimeout(renderer._async_id);
9212 }
9213 renderer._async_id = setTimeout(function() {
9214 renderer.render(scene);
9215 delete renderer._async_id;
9216 }, 10);
9217 };
9218
9219 module.exports = CanvasRenderer;
9220
9221 },{"../../util/Bounds":74,"../../util/ImageLoader":77,"../../util/canvas":80,"../../util/dom":81,"../Renderer":52,"./marks":60}],55:[function(require,module,exports){
9222 module.exports = {
9223 Handler: require('./CanvasHandler'),
9224 Renderer: require('./CanvasRenderer')
9225 };
9226 },{"./CanvasHandler":53,"./CanvasRenderer":54}],56:[function(require,module,exports){
9227 var util = require('./util');
9228 var halfpi = Math.PI / 2;
9229
9230 function path(g, o) {
9231 var x = o.x || 0,
9232 y = o.y || 0,
9233 ir = o.innerRadius || 0,
9234 or = o.outerRadius || 0,
9235 sa = (o.startAngle || 0) - halfpi,
9236 ea = (o.endAngle || 0) - halfpi;
9237 g.beginPath();
9238 if (ir === 0) g.moveTo(x, y);
9239 else g.arc(x, y, ir, sa, ea, 0);
9240 g.arc(x, y, or, ea, sa, 1);
9241 g.closePath();
9242 }
9243
9244 module.exports = {
9245 draw: util.drawAll(path),
9246 pick: util.pickPath(path)
9247 };
9248 },{"./util":67}],57:[function(require,module,exports){
9249 var util = require('./util'),
9250 parse = require('../../../path/parse'),
9251 render = require('../../../path/render'),
9252 areaPath = require('../../../util/svg').path.area;
9253
9254 function path(g, items) {
9255 var o = items[0],
9256 p = o.pathCache || (o.pathCache = parse(areaPath(items)));
9257 render(g, p);
9258 }
9259
9260 function pick(g, scene, x, y, gx, gy) {
9261 var items = scene.items,
9262 b = scene.bounds;
9263
9264 if (!items || !items.length || b && !b.contains(gx, gy)) {
9265 return null;
9266 }
9267
9268 if (g.pixelratio != null && g.pixelratio !== 1) {
9269 x *= g.pixelratio;
9270 y *= g.pixelratio;
9271 }
9272 return hit(g, items, x, y) ? items[0] : null;
9273 }
9274
9275 var hit = util.testPath(path);
9276
9277 module.exports = {
9278 draw: util.drawOne(path),
9279 pick: pick,
9280 nested: true
9281 };
9282
9283 },{"../../../path/parse":49,"../../../path/render":50,"../../../util/svg":83,"./util":67}],58:[function(require,module,exports){
9284 var util = require('./util'),
9285 rect = require('./rect');
9286
9287 function draw(g, scene, bounds) {
9288 if (!scene.items || !scene.items.length) return;
9289
9290 var groups = scene.items,
9291 renderer = this,
9292 group, items, axes, legends, gx, gy, i, n, j, m;
9293
9294 rect.draw.call(renderer, g, scene, bounds);
9295
9296 for (i=0, n=groups.length; i<n; ++i) {
9297 group = groups[i];
9298 axes = group.axisItems || [];
9299 items = group.items || [];
9300 legends = group.legendItems || [];
9301 gx = group.x || 0;
9302 gy = group.y || 0;
9303
9304 // render group contents
9305 g.save();
9306 g.translate(gx, gy);
9307 if (group.clip) {
9308 g.beginPath();
9309 g.rect(0, 0, group.width || 0, group.height || 0);
9310 g.clip();
9311 }
9312
9313 if (bounds) bounds.translate(-gx, -gy);
9314
9315 for (j=0, m=axes.length; j<m; ++j) {
9316 if (axes[j].layer === 'back') {
9317 renderer.draw(g, axes[j], bounds);
9318 }
9319 }
9320 for (j=0, m=items.length; j<m; ++j) {
9321 renderer.draw(g, items[j], bounds);
9322 }
9323 for (j=0, m=axes.length; j<m; ++j) {
9324 if (axes[j].layer !== 'back') {
9325 renderer.draw(g, axes[j], bounds);
9326 }
9327 }
9328 for (j=0, m=legends.length; j<m; ++j) {
9329 renderer.draw(g, legends[j], bounds);
9330 }
9331
9332 if (bounds) bounds.translate(gx, gy);
9333 g.restore();
9334 }
9335 }
9336
9337 function hit(g, o) {
9338 return o.fill || o.stroke;
9339 }
9340
9341 function pick(g, scene, x, y, gx, gy) {
9342 if (scene.bounds && !scene.bounds.contains(gx, gy)) {
9343 return null;
9344 }
9345 var items = scene.items || [],
9346 subscene, group, hits, dx, dy, i, j;
9347
9348 for (i=items.length; --i>=0;) {
9349 group = items[i];
9350 dx = group.x || 0;
9351 dy = group.y || 0;
9352
9353 g.save();
9354 g.translate(dx, dy);
9355 for (j=group.items.length; --j >= 0;) {
9356 subscene = group.items[j];
9357 if (subscene.interactive === false) continue;
9358 hits = this.pick(subscene, x, y, gx-dx, gy-dy);
9359 if (hits) {
9360 g.restore();
9361 return hits;
9362 }
9363 }
9364 g.restore();
9365 }
9366
9367 return scene.interactive !== false ? pickSelf(g, scene, x, y, gx, gy) : null;
9368 }
9369
9370 var pickSelf = util.pick(hit);
9371
9372 module.exports = {
9373 draw: draw,
9374 pick: pick
9375 };
9376
9377 },{"./rect":63,"./util":67}],59:[function(require,module,exports){
9378 var util = require('./util');
9379
9380 function draw(g, scene, bounds) {
9381 if (!scene.items || !scene.items.length) return;
9382
9383 var renderer = this,
9384 items = scene.items, o;
9385
9386 for (var i=0, len=items.length; i<len; ++i) {
9387 o = items[i];
9388 if (bounds && !bounds.intersects(o.bounds))
9389 continue; // bounds check
9390
9391 if (!(o.image && o.image.url === o.url)) {
9392 o.image = renderer.loadImage(o.url);
9393 o.image.url = o.url;
9394 }
9395
9396 var x = o.x || 0,
9397 y = o.y || 0,
9398 w = o.width || (o.image && o.image.width) || 0,
9399 h = o.height || (o.image && o.image.height) || 0,
9400 opac;
9401 x = x - (o.align==='center' ? w/2 : o.align==='right' ? w : 0);
9402 y = y - (o.baseline==='middle' ? h/2 : o.baseline==='bottom' ? h : 0);
9403
9404 if (o.image.loaded) {
9405 g.globalAlpha = (opac = o.opacity) != null ? opac : 1;
9406 g.drawImage(o.image, x, y, w, h);
9407 }
9408 }
9409 }
9410
9411 module.exports = {
9412 draw: draw,
9413 pick: util.pick()
9414 };
9415 },{"./util":67}],60:[function(require,module,exports){
9416 module.exports = {
9417 arc: require('./arc'),
9418 area: require('./area'),
9419 group: require('./group'),
9420 image: require('./image'),
9421 line: require('./line'),
9422 path: require('./path'),
9423 rect: require('./rect'),
9424 rule: require('./rule'),
9425 symbol: require('./symbol'),
9426 text: require('./text')
9427 };
9428
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){
9430 var util = require('./util'),
9431 parse = require('../../../path/parse'),
9432 render = require('../../../path/render'),
9433 linePath = require('../../../util/svg').path.line;
9434
9435 function path(g, items) {
9436 var o = items[0],
9437 p = o.pathCache || (o.pathCache = parse(linePath(items)));
9438 render(g, p);
9439 }
9440
9441 function pick(g, scene, x, y, gx, gy) {
9442 var items = scene.items,
9443 b = scene.bounds;
9444
9445 if (!items || !items.length || b && !b.contains(gx, gy)) {
9446 return null;
9447 }
9448
9449 if (g.pixelratio != null && g.pixelratio !== 1) {
9450 x *= g.pixelratio;
9451 y *= g.pixelratio;
9452 }
9453 return hit(g, items, x, y) ? items[0] : null;
9454 }
9455
9456 var hit = util.testPath(path, false);
9457
9458 module.exports = {
9459 draw: util.drawOne(path),
9460 pick: pick,
9461 nested: true
9462 };
9463
9464 },{"../../../path/parse":49,"../../../path/render":50,"../../../util/svg":83,"./util":67}],62:[function(require,module,exports){
9465 var util = require('./util'),
9466 parse = require('../../../path/parse'),
9467 render = require('../../../path/render');
9468
9469 function path(g, o) {
9470 if (o.path == null) return true;
9471 var p = o.pathCache || (o.pathCache = parse(o.path));
9472 render(g, p, o.x, o.y);
9473 }
9474
9475 module.exports = {
9476 draw: util.drawAll(path),
9477 pick: util.pickPath(path)
9478 };
9479
9480 },{"../../../path/parse":49,"../../../path/render":50,"./util":67}],63:[function(require,module,exports){
9481 var util = require('./util');
9482
9483 function draw(g, scene, bounds) {
9484 if (!scene.items || !scene.items.length) return;
9485
9486 var items = scene.items,
9487 o, opac, x, y, w, h;
9488
9489 for (var i=0, len=items.length; i<len; ++i) {
9490 o = items[i];
9491 if (bounds && !bounds.intersects(o.bounds))
9492 continue; // bounds check
9493
9494 opac = o.opacity == null ? 1 : o.opacity;
9495 if (opac === 0) continue;
9496
9497 x = o.x || 0;
9498 y = o.y || 0;
9499 w = o.width || 0;
9500 h = o.height || 0;
9501
9502 if (o.fill && util.fill(g, o, opac)) {
9503 g.fillRect(x, y, w, h);
9504 }
9505 if (o.stroke && util.stroke(g, o, opac)) {
9506 g.strokeRect(x, y, w, h);
9507 }
9508 }
9509 }
9510
9511 module.exports = {
9512 draw: draw,
9513 pick: util.pick()
9514 };
9515 },{"./util":67}],64:[function(require,module,exports){
9516 var util = require('./util');
9517
9518 function draw(g, scene, bounds) {
9519 if (!scene.items || !scene.items.length) return;
9520
9521 var items = scene.items,
9522 o, opac, x1, y1, x2, y2;
9523
9524 for (var i=0, len=items.length; i<len; ++i) {
9525 o = items[i];
9526 if (bounds && !bounds.intersects(o.bounds))
9527 continue; // bounds check
9528
9529 opac = o.opacity == null ? 1 : o.opacity;
9530 if (opac === 0) continue;
9531
9532 x1 = o.x || 0;
9533 y1 = o.y || 0;
9534 x2 = o.x2 != null ? o.x2 : x1;
9535 y2 = o.y2 != null ? o.y2 : y1;
9536
9537 if (o.stroke && util.stroke(g, o, opac)) {
9538 g.beginPath();
9539 g.moveTo(x1, y1);
9540 g.lineTo(x2, y2);
9541 g.stroke();
9542 }
9543 }
9544 }
9545
9546 function stroke(g, o) {
9547 var x1 = o.x || 0,
9548 y1 = o.y || 0,
9549 x2 = o.x2 != null ? o.x2 : x1,
9550 y2 = o.y2 != null ? o.y2 : y1,
9551 lw = o.strokeWidth,
9552 lc = o.strokeCap;
9553
9554 g.lineWidth = lw != null ? lw : 1;
9555 g.lineCap = lc != null ? lc : 'butt';
9556 g.beginPath();
9557 g.moveTo(x1, y1);
9558 g.lineTo(x2, y2);
9559 }
9560
9561 function hit(g, o, x, y) {
9562 if (!g.isPointInStroke) return false;
9563 stroke(g, o);
9564 return g.isPointInStroke(x, y);
9565 }
9566
9567 module.exports = {
9568 draw: draw,
9569 pick: util.pick(hit)
9570 };
9571
9572 },{"./util":67}],65:[function(require,module,exports){
9573 var util = require('./util');
9574
9575 var sqrt3 = Math.sqrt(3),
9576 tan30 = Math.tan(30 * Math.PI / 180);
9577
9578 function path(g, o) {
9579 var size = o.size != null ? o.size : 100,
9580 x = o.x, y = o.y, r, t, rx, ry;
9581
9582 g.beginPath();
9583
9584 if (o.shape == null || o.shape === 'circle') {
9585 r = Math.sqrt(size / Math.PI);
9586 g.arc(x, y, r, 0, 2*Math.PI, 0);
9587 g.closePath();
9588 return;
9589 }
9590
9591 switch (o.shape) {
9592 case 'cross':
9593 r = Math.sqrt(size / 5) / 2;
9594 t = 3*r;
9595 g.moveTo(x-t, y-r);
9596 g.lineTo(x-r, y-r);
9597 g.lineTo(x-r, y-t);
9598 g.lineTo(x+r, y-t);
9599 g.lineTo(x+r, y-r);
9600 g.lineTo(x+t, y-r);
9601 g.lineTo(x+t, y+r);
9602 g.lineTo(x+r, y+r);
9603 g.lineTo(x+r, y+t);
9604 g.lineTo(x-r, y+t);
9605 g.lineTo(x-r, y+r);
9606 g.lineTo(x-t, y+r);
9607 break;
9608
9609 case 'diamond':
9610 ry = Math.sqrt(size / (2 * tan30));
9611 rx = ry * tan30;
9612 g.moveTo(x, y-ry);
9613 g.lineTo(x+rx, y);
9614 g.lineTo(x, y+ry);
9615 g.lineTo(x-rx, y);
9616 break;
9617
9618 case 'square':
9619 t = Math.sqrt(size);
9620 r = t / 2;
9621 g.rect(x-r, y-r, t, t);
9622 break;
9623
9624 case 'triangle-down':
9625 rx = Math.sqrt(size / sqrt3);
9626 ry = rx * sqrt3 / 2;
9627 g.moveTo(x, y+ry);
9628 g.lineTo(x+rx, y-ry);
9629 g.lineTo(x-rx, y-ry);
9630 break;
9631
9632 case 'triangle-up':
9633 rx = Math.sqrt(size / sqrt3);
9634 ry = rx * sqrt3 / 2;
9635 g.moveTo(x, y-ry);
9636 g.lineTo(x+rx, y+ry);
9637 g.lineTo(x-rx, y+ry);
9638 }
9639 g.closePath();
9640 }
9641
9642 module.exports = {
9643 draw: util.drawAll(path),
9644 pick: util.pickPath(path)
9645 };
9646 },{"./util":67}],66:[function(require,module,exports){
9647 var Bounds = require('../../../util/Bounds'),
9648 textBounds = require('../../../util/bound').text,
9649 text = require('../../../util/text'),
9650 util = require('./util'),
9651 tempBounds = new Bounds();
9652
9653 function draw(g, scene, bounds) {
9654 if (!scene.items || !scene.items.length) return;
9655
9656 var items = scene.items,
9657 o, opac, x, y, r, t, str;
9658
9659 for (var i=0, len=items.length; i<len; ++i) {
9660 o = items[i];
9661 if (bounds && !bounds.intersects(o.bounds))
9662 continue; // bounds check
9663
9664 str = text.value(o.text);
9665 if (!str) continue;
9666 opac = o.opacity == null ? 1 : o.opacity;
9667 if (opac === 0) continue;
9668
9669 g.font = text.font(o);
9670 g.textAlign = o.align || 'left';
9671
9672 x = (o.x || 0);
9673 y = (o.y || 0);
9674 if ((r = o.radius)) {
9675 t = (o.theta || 0) - Math.PI/2;
9676 x += r * Math.cos(t);
9677 y += r * Math.sin(t);
9678 }
9679
9680 if (o.angle) {
9681 g.save();
9682 g.translate(x, y);
9683 g.rotate(o.angle * Math.PI/180);
9684 x = y = 0; // reset x, y
9685 }
9686 x += (o.dx || 0);
9687 y += (o.dy || 0) + text.offset(o);
9688
9689 if (o.fill && util.fill(g, o, opac)) {
9690 g.fillText(str, x, y);
9691 }
9692 if (o.stroke && util.stroke(g, o, opac)) {
9693 g.strokeText(str, x, y);
9694 }
9695 if (o.angle) g.restore();
9696 }
9697 }
9698
9699 function hit(g, o, x, y, gx, gy) {
9700 if (o.fontSize <= 0) return false;
9701 if (!o.angle) return true; // bounds sufficient if no rotation
9702
9703 // project point into space of unrotated bounds
9704 var b = textBounds(o, tempBounds, true),
9705 a = -o.angle * Math.PI / 180,
9706 cos = Math.cos(a),
9707 sin = Math.sin(a),
9708 ox = o.x,
9709 oy = o.y,
9710 px = cos*gx - sin*gy + (ox - ox*cos + oy*sin),
9711 py = sin*gx + cos*gy + (oy - ox*sin - oy*cos);
9712
9713 return b.contains(px, py);
9714 }
9715
9716 module.exports = {
9717 draw: draw,
9718 pick: util.pick(hit)
9719 };
9720
9721 },{"../../../util/Bounds":74,"../../../util/bound":79,"../../../util/text":84,"./util":67}],67:[function(require,module,exports){
9722 function drawPathOne(path, g, o, items) {
9723 if (path(g, items)) return;
9724
9725 var opac = o.opacity == null ? 1 : o.opacity;
9726 if (opac===0) return;
9727
9728 if (o.fill && fill(g, o, opac)) { g.fill(); }
9729 if (o.stroke && stroke(g, o, opac)) { g.stroke(); }
9730 }
9731
9732 function drawPathAll(path, g, scene, bounds) {
9733 var i, len, item;
9734 for (i=0, len=scene.items.length; i<len; ++i) {
9735 item = scene.items[i];
9736 if (!bounds || bounds.intersects(item.bounds)) {
9737 drawPathOne(path, g, item, item);
9738 }
9739 }
9740 }
9741
9742 function drawAll(pathFunc) {
9743 return function(g, scene, bounds) {
9744 drawPathAll(pathFunc, g, scene, bounds);
9745 };
9746 }
9747
9748 function drawOne(pathFunc) {
9749 return function(g, scene, bounds) {
9750 if (!scene.items.length) return;
9751 if (!bounds || bounds.intersects(scene.bounds)) {
9752 drawPathOne(pathFunc, g, scene.items[0], scene.items);
9753 }
9754 };
9755 }
9756
9757 var trueFunc = function() { return true; };
9758
9759 function pick(test) {
9760 if (!test) test = trueFunc;
9761
9762 return function(g, scene, x, y, gx, gy) {
9763 if (!scene.items.length) return null;
9764
9765 var o, b, i;
9766
9767 if (g.pixelratio != null && g.pixelratio !== 1) {
9768 x *= g.pixelratio;
9769 y *= g.pixelratio;
9770 }
9771
9772 for (i=scene.items.length; --i >= 0;) {
9773 o = scene.items[i]; b = o.bounds;
9774 // first hit test against bounding box
9775 if ((b && !b.contains(gx, gy)) || !b) continue;
9776 // if in bounding box, perform more careful test
9777 if (test(g, o, x, y, gx, gy)) return o;
9778 }
9779 return null;
9780 };
9781 }
9782
9783 function testPath(path, filled) {
9784 return function(g, o, x, y) {
9785 var item = Array.isArray(o) ? o[0] : o,
9786 fill = (filled == null) ? item.fill : filled,
9787 stroke = item.stroke && g.isPointInStroke, lw, lc;
9788
9789 if (stroke) {
9790 lw = item.strokeWidth;
9791 lc = item.strokeCap;
9792 g.lineWidth = lw != null ? lw : 1;
9793 g.lineCap = lc != null ? lc : 'butt';
9794 }
9795
9796 return path(g, o) ? false :
9797 (fill && g.isPointInPath(x, y)) ||
9798 (stroke && g.isPointInStroke(x, y));
9799 };
9800 }
9801
9802 function pickPath(path) {
9803 return pick(testPath(path));
9804 }
9805
9806 function fill(g, o, opacity) {
9807 opacity *= (o.fillOpacity==null ? 1 : o.fillOpacity);
9808 if (opacity > 0) {
9809 g.globalAlpha = opacity;
9810 g.fillStyle = color(g, o, o.fill);
9811 return true;
9812 } else {
9813 return false;
9814 }
9815 }
9816
9817 function stroke(g, o, opacity) {
9818 var lw = (lw = o.strokeWidth) != null ? lw : 1, lc;
9819 if (lw <= 0) return false;
9820
9821 opacity *= (o.strokeOpacity==null ? 1 : o.strokeOpacity);
9822 if (opacity > 0) {
9823 g.globalAlpha = opacity;
9824 g.strokeStyle = color(g, o, o.stroke);
9825 g.lineWidth = lw;
9826 g.lineCap = (lc = o.strokeCap) != null ? lc : 'butt';
9827 g.vgLineDash(o.strokeDash || null);
9828 g.vgLineDashOffset(o.strokeDashOffset || 0);
9829 return true;
9830 } else {
9831 return false;
9832 }
9833 }
9834
9835 function color(g, o, value) {
9836 return (value.id) ?
9837 gradient(g, value, o.bounds) :
9838 value;
9839 }
9840
9841 function gradient(g, p, b) {
9842 var w = b.width(),
9843 h = b.height(),
9844 x1 = b.x1 + p.x1 * w,
9845 y1 = b.y1 + p.y1 * h,
9846 x2 = b.x1 + p.x2 * w,
9847 y2 = b.y1 + p.y2 * h,
9848 grad = g.createLinearGradient(x1, y1, x2, y2),
9849 stop = p.stops,
9850 i, n;
9851
9852 for (i=0, n=stop.length; i<n; ++i) {
9853 grad.addColorStop(stop[i].offset, stop[i].color);
9854 }
9855 return grad;
9856 }
9857
9858 module.exports = {
9859 drawOne: drawOne,
9860 drawAll: drawAll,
9861 pick: pick,
9862 pickPath: pickPath,
9863 testPath: testPath,
9864 stroke: stroke,
9865 fill: fill,
9866 color: color,
9867 gradient: gradient
9868 };
9869
9870 },{}],68:[function(require,module,exports){
9871 module.exports = {
9872 'canvas': require('./canvas'),
9873 'svg': require('./svg')
9874 };
9875
9876 },{"./canvas":55,"./svg":72}],69:[function(require,module,exports){
9877 var DOM = require('../../util/dom'),
9878 Handler = require('../Handler');
9879
9880 function SVGHandler() {
9881 Handler.call(this);
9882 }
9883
9884 var base = Handler.prototype;
9885 var prototype = (SVGHandler.prototype = Object.create(base));
9886 prototype.constructor = SVGHandler;
9887
9888 prototype.initialize = function(el, pad, obj) {
9889 this._svg = DOM.find(el, 'svg');
9890 return base.initialize.call(this, el, pad, obj);
9891 };
9892
9893 prototype.svg = function() {
9894 return this._svg;
9895 };
9896
9897 // wrap an event listener for the SVG DOM
9898 prototype.listener = function(handler) {
9899 var that = this;
9900 return function(evt) {
9901 var target = evt.target,
9902 item = target.__data__;
9903 evt.vegaType = evt.type;
9904 item = Array.isArray(item) ? item[0] : item;
9905 handler.call(that._obj, evt, item);
9906 };
9907 };
9908
9909 // add an event handler
9910 prototype.on = function(type, handler) {
9911 var name = this.eventName(type),
9912 svg = this._svg,
9913 h = this._handlers,
9914 x = {
9915 type: type,
9916 handler: handler,
9917 listener: this.listener(handler)
9918 };
9919
9920 (h[name] || (h[name] = [])).push(x);
9921 svg.addEventListener(name, x.listener);
9922 return this;
9923 };
9924
9925 // remove an event handler
9926 prototype.off = function(type, handler) {
9927 var name = this.eventName(type),
9928 svg = this._svg,
9929 h = this._handlers[name], i;
9930 if (!h) return;
9931 for (i=h.length; --i>=0;) {
9932 if (h[i].type === type && !handler || h[i].handler === handler) {
9933 svg.removeEventListener(name, h[i].listener);
9934 h.splice(i, 1);
9935 }
9936 }
9937 return this;
9938 };
9939
9940 module.exports = SVGHandler;
9941
9942 },{"../../util/dom":81,"../Handler":51}],70:[function(require,module,exports){
9943 var ImageLoader = require('../../util/ImageLoader'),
9944 Renderer = require('../Renderer'),
9945 text = require('../../util/text'),
9946 DOM = require('../../util/dom'),
9947 SVG = require('../../util/svg'),
9948 ns = SVG.metadata.xmlns,
9949 marks = require('./marks');
9950
9951 function SVGRenderer(loadConfig) {
9952 Renderer.call(this);
9953 this._loader = new ImageLoader(loadConfig);
9954 this._dirtyID = 0;
9955 }
9956
9957 var base = Renderer.prototype;
9958 var prototype = (SVGRenderer.prototype = Object.create(base));
9959 prototype.constructor = SVGRenderer;
9960
9961 prototype.initialize = function(el, width, height, padding) {
9962 if (el) {
9963 this._svg = DOM.child(el, 0, 'svg', ns, 'marks');
9964 DOM.clear(el, 1);
9965 // set the svg root group
9966 this._root = DOM.child(this._svg, 0, 'g', ns);
9967 DOM.clear(this._svg, 1);
9968 }
9969
9970 // create the svg definitions cache
9971 this._defs = {
9972 clip_id: 1,
9973 gradient: {},
9974 clipping: {}
9975 };
9976
9977 // set background color if defined
9978 this.background(this._bgcolor);
9979
9980 return base.initialize.call(this, el, width, height, padding);
9981 };
9982
9983 prototype.background = function(bgcolor) {
9984 if (arguments.length && this._svg) {
9985 this._svg.style.setProperty('background-color', bgcolor);
9986 }
9987 return base.background.apply(this, arguments);
9988 };
9989
9990 prototype.resize = function(width, height, padding) {
9991 base.resize.call(this, width, height, padding);
9992
9993 if (this._svg) {
9994 var w = this._width,
9995 h = this._height,
9996 p = this._padding;
9997
9998 this._svg.setAttribute('width', w + p.left + p.right);
9999 this._svg.setAttribute('height', h + p.top + p.bottom);
10000
10001 this._root.setAttribute('transform', 'translate('+p.left+','+p.top+')');
10002 }
10003
10004 return this;
10005 };
10006
10007 prototype.svg = function() {
10008 if (!this._svg) return null;
10009
10010 var attr = {
10011 'class': 'marks',
10012 'width': this._width + this._padding.left + this._padding.right,
10013 'height': this._height + this._padding.top + this._padding.bottom,
10014 };
10015 for (var key in SVG.metadata) {
10016 attr[key] = SVG.metadata[key];
10017 }
10018
10019 return DOM.openTag('svg', attr) + this._svg.innerHTML + DOM.closeTag('svg');
10020 };
10021
10022 prototype.imageURL = function(url) {
10023 return this._loader.imageURL(url);
10024 };
10025
10026
10027 // -- Render entry point --
10028
10029 prototype.render = function(scene, items) {
10030 if (this._dirtyCheck(items)) {
10031 if (this._dirtyAll) this._resetDefs();
10032 this.draw(this._root, scene, -1);
10033 DOM.clear(this._root, 1);
10034 }
10035 this.updateDefs();
10036 return this;
10037 };
10038
10039 prototype.draw = function(el, scene, index) {
10040 this.drawMark(el, scene, index, marks[scene.marktype]);
10041 };
10042
10043
10044 // -- Manage SVG definitions ('defs') block --
10045
10046 prototype.updateDefs = function() {
10047 var svg = this._svg,
10048 defs = this._defs,
10049 el = defs.el,
10050 index = 0, id;
10051
10052 for (id in defs.gradient) {
10053 if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns));
10054 updateGradient(el, defs.gradient[id], index++);
10055 }
10056
10057 for (id in defs.clipping) {
10058 if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns));
10059 updateClipping(el, defs.clipping[id], index++);
10060 }
10061
10062 // clean-up
10063 if (el) {
10064 if (index === 0) {
10065 svg.removeChild(el);
10066 defs.el = null;
10067 } else {
10068 DOM.clear(el, index);
10069 }
10070 }
10071 };
10072
10073 function updateGradient(el, grad, index) {
10074 var i, n, stop;
10075
10076 el = DOM.child(el, index, 'linearGradient', ns);
10077 el.setAttribute('id', grad.id);
10078 el.setAttribute('x1', grad.x1);
10079 el.setAttribute('x2', grad.x2);
10080 el.setAttribute('y1', grad.y1);
10081 el.setAttribute('y2', grad.y2);
10082
10083 for (i=0, n=grad.stops.length; i<n; ++i) {
10084 stop = DOM.child(el, i, 'stop', ns);
10085 stop.setAttribute('offset', grad.stops[i].offset);
10086 stop.setAttribute('stop-color', grad.stops[i].color);
10087 }
10088 DOM.clear(el, i);
10089 }
10090
10091 function updateClipping(el, clip, index) {
10092 var rect;
10093
10094 el = DOM.child(el, index, 'clipPath', ns);
10095 el.setAttribute('id', clip.id);
10096 rect = DOM.child(el, 0, 'rect', ns);
10097 rect.setAttribute('x', 0);
10098 rect.setAttribute('y', 0);
10099 rect.setAttribute('width', clip.width);
10100 rect.setAttribute('height', clip.height);
10101 }
10102
10103 prototype._resetDefs = function() {
10104 var def = this._defs;
10105 def.clip_id = 1;
10106 def.gradient = {};
10107 def.clipping = {};
10108 };
10109
10110
10111 // -- Manage rendering of items marked as dirty --
10112
10113 prototype.isDirty = function(item) {
10114 return this._dirtyAll || item.dirty === this._dirtyID;
10115 };
10116
10117 prototype._dirtyCheck = function(items) {
10118 this._dirtyAll = true;
10119 if (!items) return true;
10120
10121 var id = ++this._dirtyID,
10122 item, mark, type, mdef, i, n, o;
10123
10124 for (i=0, n=items.length; i<n; ++i) {
10125 item = items[i];
10126 mark = item.mark;
10127 if (mark.marktype !== type) {
10128 // memoize mark instance lookup
10129 type = mark.marktype;
10130 mdef = marks[type];
10131 }
10132
10133 if (item.status === 'exit') { // EXIT
10134 if (item._svg) {
10135 if (mdef.nest && item.mark.items.length) {
10136 // if nested mark with remaining points, update instead
10137 this._update(mdef, item._svg, item.mark.items[0]);
10138 o = item.mark.items[0];
10139 o._svg = item._svg;
10140 o._update = id;
10141 } else {
10142 // otherwise remove from DOM
10143 DOM.remove(item._svg);
10144 }
10145 item._svg = null;
10146 }
10147 continue;
10148 }
10149
10150 item = (mdef.nest ? mark.items[0] : item);
10151 if (item._update === id) { // Already processed
10152 continue;
10153 } else if (item._svg) { // UPDATE
10154 this._update(mdef, item._svg, item);
10155 } else { // ENTER
10156 this._dirtyAll = false;
10157 dirtyParents(item, id);
10158 }
10159 item._update = id;
10160 }
10161 return !this._dirtyAll;
10162 };
10163
10164 function dirtyParents(item, id) {
10165 for (; item && item.dirty !== id; item=item.mark.group) {
10166 item.dirty = id;
10167 if (item.mark && item.mark.dirty !== id) {
10168 item.mark.dirty = id;
10169 } else return;
10170 }
10171 }
10172
10173
10174 // -- Construct & maintain scenegraph to SVG mapping ---
10175
10176 // Draw a mark container.
10177 prototype.drawMark = function(el, scene, index, mdef) {
10178 if (!this.isDirty(scene)) return;
10179
10180 var items = mdef.nest ?
10181 (scene.items && scene.items.length ? [scene.items[0]] : []) :
10182 scene.items || [],
10183 events = scene.interactive === false ? 'none' : null,
10184 isGroup = (mdef.tag === 'g'),
10185 className = DOM.cssClass(scene),
10186 p, i, n, c, d, insert;
10187
10188 p = DOM.child(el, index+1, 'g', ns, className);
10189 p.setAttribute('class', className);
10190 scene._svg = p;
10191 if (!isGroup && events) {
10192 p.style.setProperty('pointer-events', events);
10193 }
10194
10195 for (i=0, n=items.length; i<n; ++i) {
10196 if (this.isDirty(d = items[i])) {
10197 insert = !(this._dirtyAll || d._svg);
10198 c = insert ? bind(p, mdef, d, i, true)
10199 : (p.childNodes[i] || bind(p, mdef, d, i));
10200 this._update(mdef, c, d);
10201 if (isGroup) {
10202 if (insert) this._dirtyAll = true;
10203 this._recurse(c, d);
10204 if (insert) this._dirtyAll = false;
10205 }
10206 }
10207 }
10208 DOM.clear(p, i);
10209 return p;
10210 };
10211
10212 // Recursively process group contents.
10213 prototype._recurse = function(el, group) {
10214 var items = group.items || [],
10215 legends = group.legendItems || [],
10216 axes = group.axisItems || [],
10217 idx = 0, j, m;
10218
10219 for (j=0, m=axes.length; j<m; ++j) {
10220 if (axes[j].layer === 'back') {
10221 this.drawMark(el, axes[j], idx++, marks.group);
10222 }
10223 }
10224 for (j=0, m=items.length; j<m; ++j) {
10225 this.draw(el, items[j], idx++);
10226 }
10227 for (j=0, m=axes.length; j<m; ++j) {
10228 if (axes[j].layer !== 'back') {
10229 this.drawMark(el, axes[j], idx++, marks.group);
10230 }
10231 }
10232 for (j=0, m=legends.length; j<m; ++j) {
10233 this.drawMark(el, legends[j], idx++, marks.group);
10234 }
10235
10236 // remove any extraneous DOM elements
10237 DOM.clear(el, 1 + idx);
10238 };
10239
10240 // Bind a scenegraph item to an SVG DOM element.
10241 // Create new SVG elements as needed.
10242 function bind(el, mdef, item, index, insert) {
10243 // create svg element, bind item data for D3 compatibility
10244 var node = DOM.child(el, index, mdef.tag, ns, null, insert);
10245 node.__data__ = item;
10246 node.__values__ = {fill: 'default'};
10247
10248 // create background rect
10249 if (mdef.tag === 'g') {
10250 var bg = DOM.child(node, 0, 'rect', ns, 'background');
10251 bg.__data__ = item;
10252 }
10253
10254 // add pointer from scenegraph item to svg element
10255 return (item._svg = node);
10256 }
10257
10258
10259 // -- Set attributes & styles on SVG elements ---
10260
10261 var href = (typeof window !== 'undefined' ? window.location.href : ''),
10262 element = null, // temp var for current SVG element
10263 values = null; // temp var for current values hash
10264
10265 // Extra configuration for certain mark types
10266 var mark_extras = {
10267 group: function(mdef, el, item) {
10268 element = el.childNodes[0];
10269 values = el.__values__; // use parent's values hash
10270 mdef.background(emit, item, this);
10271
10272 var value = item.mark.interactive === false ? 'none' : null;
10273 if (value !== values.events) {
10274 element.style.setProperty('pointer-events', value);
10275 values.events = value;
10276 }
10277 },
10278 text: function(mdef, el, item) {
10279 var str = text.value(item.text);
10280 if (str !== values.text) {
10281 el.textContent = str;
10282 values.text = str;
10283 }
10284 str = text.font(item);
10285 if (str !== values.font) {
10286 el.style.setProperty('font', str);
10287 values.font = str;
10288 }
10289 }
10290 };
10291
10292 prototype._update = function(mdef, el, item) {
10293 // set dom element and values cache
10294 // provides access to emit method
10295 element = el;
10296 values = el.__values__;
10297
10298 // apply svg attributes
10299 mdef.attr(emit, item, this);
10300
10301 // some marks need special treatment
10302 var extra = mark_extras[mdef.type];
10303 if (extra) extra(mdef, el, item);
10304
10305 // apply svg css styles
10306 // note: element may be modified by 'extra' method
10307 this.style(element, item);
10308 };
10309
10310 function emit(name, value, ns) {
10311 // early exit if value is unchanged
10312 if (value === values[name]) return;
10313
10314 if (value != null) {
10315 // if value is provided, update DOM attribute
10316 if (ns) {
10317 element.setAttributeNS(ns, name, value);
10318 } else {
10319 element.setAttribute(name, value);
10320 }
10321 } else {
10322 // else remove DOM attribute
10323 if (ns) {
10324 element.removeAttributeNS(ns, name);
10325 } else {
10326 element.removeAttribute(name);
10327 }
10328 }
10329
10330 // note current value for future comparison
10331 values[name] = value;
10332 }
10333
10334 prototype.style = function(el, o) {
10335 if (o == null) return;
10336 var i, n, prop, name, value;
10337
10338 for (i=0, n=SVG.styleProperties.length; i<n; ++i) {
10339 prop = SVG.styleProperties[i];
10340 value = o[prop];
10341 if (value === values[prop]) continue;
10342
10343 name = SVG.styles[prop];
10344 if (value == null) {
10345 if (name === 'fill') {
10346 el.style.setProperty(name, 'none');
10347 } else {
10348 el.style.removeProperty(name);
10349 }
10350 } else {
10351 if (value.id) {
10352 // ensure definition is included
10353 this._defs.gradient[value.id] = value;
10354 value = 'url(' + href + '#' + value.id + ')';
10355 }
10356 el.style.setProperty(name, value+'');
10357 }
10358
10359 values[prop] = value;
10360 }
10361 };
10362
10363 module.exports = SVGRenderer;
10364
10365 },{"../../util/ImageLoader":77,"../../util/dom":81,"../../util/svg":83,"../../util/text":84,"../Renderer":52,"./marks":73}],71:[function(require,module,exports){
10366 var Renderer = require('../Renderer'),
10367 ImageLoader = require('../../util/ImageLoader'),
10368 SVG = require('../../util/svg'),
10369 text = require('../../util/text'),
10370 DOM = require('../../util/dom'),
10371 openTag = DOM.openTag,
10372 closeTag = DOM.closeTag,
10373 MARKS = require('./marks');
10374
10375 function SVGStringRenderer(loadConfig) {
10376 Renderer.call(this);
10377
10378 this._loader = new ImageLoader(loadConfig);
10379
10380 this._text = {
10381 head: '',
10382 root: '',
10383 foot: '',
10384 defs: '',
10385 body: ''
10386 };
10387
10388 this._defs = {
10389 clip_id: 1,
10390 gradient: {},
10391 clipping: {}
10392 };
10393 }
10394
10395 var base = Renderer.prototype;
10396 var prototype = (SVGStringRenderer.prototype = Object.create(base));
10397 prototype.constructor = SVGStringRenderer;
10398
10399 prototype.resize = function(width, height, padding) {
10400 base.resize.call(this, width, height, padding);
10401 var p = this._padding,
10402 t = this._text;
10403
10404 var attr = {
10405 'class': 'marks',
10406 'width': this._width + p.left + p.right,
10407 'height': this._height + p.top + p.bottom,
10408 };
10409 for (var key in SVG.metadata) {
10410 attr[key] = SVG.metadata[key];
10411 }
10412
10413 t.head = openTag('svg', attr);
10414 t.root = openTag('g', {
10415 transform: 'translate(' + p.left + ',' + p.top + ')'
10416 });
10417 t.foot = closeTag('g') + closeTag('svg');
10418
10419 return this;
10420 };
10421
10422 prototype.svg = function() {
10423 var t = this._text;
10424 return t.head + t.defs + t.root + t.body + t.foot;
10425 };
10426
10427 prototype.render = function(scene) {
10428 this._text.body = this.mark(scene);
10429 this._text.defs = this.buildDefs();
10430 return this;
10431 };
10432
10433 prototype.reset = function() {
10434 this._defs.clip_id = 0;
10435 return this;
10436 };
10437
10438 prototype.buildDefs = function() {
10439 var all = this._defs,
10440 defs = '',
10441 i, id, def, stops;
10442
10443 for (id in all.gradient) {
10444 def = all.gradient[id];
10445 stops = def.stops;
10446
10447 defs += openTag('linearGradient', {
10448 id: id,
10449 x1: def.x1,
10450 x2: def.x2,
10451 y1: def.y1,
10452 y2: def.y2
10453 });
10454
10455 for (i=0; i<stops.length; ++i) {
10456 defs += openTag('stop', {
10457 offset: stops[i].offset,
10458 'stop-color': stops[i].color
10459 }) + closeTag('stop');
10460 }
10461
10462 defs += closeTag('linearGradient');
10463 }
10464
10465 for (id in all.clipping) {
10466 def = all.clipping[id];
10467
10468 defs += openTag('clipPath', {id: id});
10469
10470 defs += openTag('rect', {
10471 x: 0,
10472 y: 0,
10473 width: def.width,
10474 height: def.height
10475 }) + closeTag('rect');
10476
10477 defs += closeTag('clipPath');
10478 }
10479
10480 return (defs.length > 0) ? openTag('defs') + defs + closeTag('defs') : '';
10481 };
10482
10483 prototype.imageURL = function(url) {
10484 return this._loader.imageURL(url);
10485 };
10486
10487 var object;
10488
10489 function emit(name, value, ns, prefixed) {
10490 object[prefixed || name] = value;
10491 }
10492
10493 prototype.attributes = function(attr, item) {
10494 object = {};
10495 attr(emit, item, this);
10496 return object;
10497 };
10498
10499 prototype.mark = function(scene) {
10500 var mdef = MARKS[scene.marktype],
10501 tag = mdef.tag,
10502 attr = mdef.attr,
10503 nest = mdef.nest || false,
10504 data = nest ?
10505 (scene.items && scene.items.length ? [scene.items[0]] : []) :
10506 (scene.items || []),
10507 defs = this._defs,
10508 str = '',
10509 style, i, item;
10510
10511 if (tag !== 'g' && scene.interactive === false) {
10512 style = 'style="pointer-events: none;"';
10513 }
10514
10515 // render opening group tag
10516 str += openTag('g', {
10517 'class': DOM.cssClass(scene)
10518 }, style);
10519
10520 // render contained elements
10521 for (i=0; i<data.length; ++i) {
10522 item = data[i];
10523 style = (tag !== 'g') ? styles(item, scene, tag, defs) : null;
10524 str += openTag(tag, this.attributes(attr, item), style);
10525 if (tag === 'text') {
10526 str += escape_text(text.value(item.text));
10527 } else if (tag === 'g') {
10528 str += openTag('rect',
10529 this.attributes(mdef.background, item),
10530 styles(item, scene, 'bgrect', defs)) + closeTag('rect');
10531 str += this.markGroup(item);
10532 }
10533 str += closeTag(tag);
10534 }
10535
10536 // render closing group tag
10537 return str + closeTag('g');
10538 };
10539
10540 prototype.markGroup = function(scene) {
10541 var str = '',
10542 axes = scene.axisItems || [],
10543 items = scene.items || [],
10544 legends = scene.legendItems || [],
10545 j, m;
10546
10547 for (j=0, m=axes.length; j<m; ++j) {
10548 if (axes[j].layer === 'back') {
10549 str += this.mark(axes[j]);
10550 }
10551 }
10552 for (j=0, m=items.length; j<m; ++j) {
10553 str += this.mark(items[j]);
10554 }
10555 for (j=0, m=axes.length; j<m; ++j) {
10556 if (axes[j].layer !== 'back') {
10557 str += this.mark(axes[j]);
10558 }
10559 }
10560 for (j=0, m=legends.length; j<m; ++j) {
10561 str += this.mark(legends[j]);
10562 }
10563
10564 return str;
10565 };
10566
10567 function styles(o, mark, tag, defs) {
10568 if (o == null) return '';
10569 var i, n, prop, name, value, s = '';
10570
10571 if (tag === 'bgrect' && mark.interactive === false) {
10572 s += 'pointer-events: none;';
10573 }
10574
10575 if (tag === 'text') {
10576 s += 'font: ' + text.font(o) + ';';
10577 }
10578
10579 for (i=0, n=SVG.styleProperties.length; i<n; ++i) {
10580 prop = SVG.styleProperties[i];
10581 name = SVG.styles[prop];
10582 value = o[prop];
10583
10584 if (value == null) {
10585 if (name === 'fill') {
10586 s += (s.length ? ' ' : '') + 'fill: none;';
10587 }
10588 } else {
10589 if (value.id) {
10590 // ensure definition is included
10591 defs.gradient[value.id] = value;
10592 value = 'url(#' + value.id + ')';
10593 }
10594 s += (s.length ? ' ' : '') + name + ': ' + value + ';';
10595 }
10596 }
10597
10598 return s ? 'style="' + s + '"' : null;
10599 }
10600
10601 function escape_text(s) {
10602 return s.replace(/&/g, '&amp;')
10603 .replace(/</g, '&lt;')
10604 .replace(/>/g, '&gt;');
10605 }
10606
10607 module.exports = SVGStringRenderer;
10608
10609 },{"../../util/ImageLoader":77,"../../util/dom":81,"../../util/svg":83,"../../util/text":84,"../Renderer":52,"./marks":73}],72:[function(require,module,exports){
10610 module.exports = {
10611 Handler: require('./SVGHandler'),
10612 Renderer: require('./SVGRenderer'),
10613 string: {
10614 Renderer : require('./SVGStringRenderer')
10615 }
10616 };
10617 },{"./SVGHandler":69,"./SVGRenderer":70,"./SVGStringRenderer":71}],73:[function(require,module,exports){
10618 var text = require('../../util/text'),
10619 SVG = require('../../util/svg'),
10620 textAlign = SVG.textAlign,
10621 path = SVG.path;
10622
10623 function translateItem(o) {
10624 return translate(o.x || 0, o.y || 0);
10625 }
10626
10627 function translate(x, y) {
10628 return 'translate(' + x + ',' + y + ')';
10629 }
10630
10631 module.exports = {
10632 arc: {
10633 tag: 'path',
10634 type: 'arc',
10635 attr: function(emit, o) {
10636 emit('transform', translateItem(o));
10637 emit('d', path.arc(o));
10638 }
10639 },
10640 area: {
10641 tag: 'path',
10642 type: 'area',
10643 nest: true,
10644 attr: function(emit, o) {
10645 var items = o.mark.items;
10646 if (items.length) emit('d', path.area(items));
10647 }
10648 },
10649 group: {
10650 tag: 'g',
10651 type: 'group',
10652 attr: function(emit, o, renderer) {
10653 var id = null, defs, c;
10654 emit('transform', translateItem(o));
10655 if (o.clip) {
10656 defs = renderer._defs;
10657 id = o.clip_id || (o.clip_id = 'clip' + defs.clip_id++);
10658 c = defs.clipping[id] || (defs.clipping[id] = {id: id});
10659 c.width = o.width || 0;
10660 c.height = o.height || 0;
10661 }
10662 emit('clip-path', id ? ('url(#' + id + ')') : null);
10663 },
10664 background: function(emit, o) {
10665 emit('class', 'background');
10666 emit('width', o.width || 0);
10667 emit('height', o.height || 0);
10668 }
10669 },
10670 image: {
10671 tag: 'image',
10672 type: 'image',
10673 attr: function(emit, o, renderer) {
10674 var x = o.x || 0,
10675 y = o.y || 0,
10676 w = o.width || 0,
10677 h = o.height || 0,
10678 url = renderer.imageURL(o.url);
10679
10680 x = x - (o.align === 'center' ? w/2 : o.align === 'right' ? w : 0);
10681 y = y - (o.baseline === 'middle' ? h/2 : o.baseline === 'bottom' ? h : 0);
10682
10683 emit('href', url, 'http://www.w3.org/1999/xlink', 'xlink:href');
10684 emit('transform', translate(x, y));
10685 emit('width', w);
10686 emit('height', h);
10687 }
10688 },
10689 line: {
10690 tag: 'path',
10691 type: 'line',
10692 nest: true,
10693 attr: function(emit, o) {
10694 var items = o.mark.items;
10695 if (items.length) emit('d', path.line(items));
10696 }
10697 },
10698 path: {
10699 tag: 'path',
10700 type: 'path',
10701 attr: function(emit, o) {
10702 emit('transform', translateItem(o));
10703 emit('d', o.path);
10704 }
10705 },
10706 rect: {
10707 tag: 'rect',
10708 type: 'rect',
10709 nest: false,
10710 attr: function(emit, o) {
10711 emit('transform', translateItem(o));
10712 emit('width', o.width || 0);
10713 emit('height', o.height || 0);
10714 }
10715 },
10716 rule: {
10717 tag: 'line',
10718 type: 'rule',
10719 attr: function(emit, o) {
10720 emit('transform', translateItem(o));
10721 emit('x2', o.x2 != null ? o.x2 - (o.x||0) : 0);
10722 emit('y2', o.y2 != null ? o.y2 - (o.y||0) : 0);
10723 }
10724 },
10725 symbol: {
10726 tag: 'path',
10727 type: 'symbol',
10728 attr: function(emit, o) {
10729 emit('transform', translateItem(o));
10730 emit('d', path.symbol(o));
10731 }
10732 },
10733 text: {
10734 tag: 'text',
10735 type: 'text',
10736 nest: false,
10737 attr: function(emit, o) {
10738 var dx = (o.dx || 0),
10739 dy = (o.dy || 0) + text.offset(o),
10740 x = (o.x || 0),
10741 y = (o.y || 0),
10742 a = o.angle || 0,
10743 r = o.radius || 0, t;
10744
10745 if (r) {
10746 t = (o.theta || 0) - Math.PI/2;
10747 x += r * Math.cos(t);
10748 y += r * Math.sin(t);
10749 }
10750
10751 emit('text-anchor', textAlign[o.align] || 'start');
10752
10753 if (a) {
10754 t = translate(x, y) + ' rotate('+a+')';
10755 if (dx || dy) t += ' ' + translate(dx, dy);
10756 } else {
10757 t = translate(x+dx, y+dy);
10758 }
10759 emit('transform', t);
10760 }
10761 }
10762 };
10763
10764 },{"../../util/svg":83,"../../util/text":84}],74:[function(require,module,exports){
10765 function Bounds(b) {
10766 this.clear();
10767 if (b) this.union(b);
10768 }
10769
10770 var prototype = Bounds.prototype;
10771
10772 prototype.clone = function() {
10773 return new Bounds(this);
10774 };
10775
10776 prototype.clear = function() {
10777 this.x1 = +Number.MAX_VALUE;
10778 this.y1 = +Number.MAX_VALUE;
10779 this.x2 = -Number.MAX_VALUE;
10780 this.y2 = -Number.MAX_VALUE;
10781 return this;
10782 };
10783
10784 prototype.set = function(x1, y1, x2, y2) {
10785 this.x1 = x1;
10786 this.y1 = y1;
10787 this.x2 = x2;
10788 this.y2 = y2;
10789 return this;
10790 };
10791
10792 prototype.add = function(x, y) {
10793 if (x < this.x1) this.x1 = x;
10794 if (y < this.y1) this.y1 = y;
10795 if (x > this.x2) this.x2 = x;
10796 if (y > this.y2) this.y2 = y;
10797 return this;
10798 };
10799
10800 prototype.expand = function(d) {
10801 this.x1 -= d;
10802 this.y1 -= d;
10803 this.x2 += d;
10804 this.y2 += d;
10805 return this;
10806 };
10807
10808 prototype.round = function() {
10809 this.x1 = Math.floor(this.x1);
10810 this.y1 = Math.floor(this.y1);
10811 this.x2 = Math.ceil(this.x2);
10812 this.y2 = Math.ceil(this.y2);
10813 return this;
10814 };
10815
10816 prototype.translate = function(dx, dy) {
10817 this.x1 += dx;
10818 this.x2 += dx;
10819 this.y1 += dy;
10820 this.y2 += dy;
10821 return this;
10822 };
10823
10824 prototype.rotate = function(angle, x, y) {
10825 var cos = Math.cos(angle),
10826 sin = Math.sin(angle),
10827 cx = x - x*cos + y*sin,
10828 cy = y - x*sin - y*cos,
10829 x1 = this.x1, x2 = this.x2,
10830 y1 = this.y1, y2 = this.y2;
10831
10832 return this.clear()
10833 .add(cos*x1 - sin*y1 + cx, sin*x1 + cos*y1 + cy)
10834 .add(cos*x1 - sin*y2 + cx, sin*x1 + cos*y2 + cy)
10835 .add(cos*x2 - sin*y1 + cx, sin*x2 + cos*y1 + cy)
10836 .add(cos*x2 - sin*y2 + cx, sin*x2 + cos*y2 + cy);
10837 };
10838
10839 prototype.union = function(b) {
10840 if (b.x1 < this.x1) this.x1 = b.x1;
10841 if (b.y1 < this.y1) this.y1 = b.y1;
10842 if (b.x2 > this.x2) this.x2 = b.x2;
10843 if (b.y2 > this.y2) this.y2 = b.y2;
10844 return this;
10845 };
10846
10847 prototype.encloses = function(b) {
10848 return b && (
10849 this.x1 <= b.x1 &&
10850 this.x2 >= b.x2 &&
10851 this.y1 <= b.y1 &&
10852 this.y2 >= b.y2
10853 );
10854 };
10855
10856 prototype.intersects = function(b) {
10857 return b && !(
10858 this.x2 < b.x1 ||
10859 this.x1 > b.x2 ||
10860 this.y2 < b.y1 ||
10861 this.y1 > b.y2
10862 );
10863 };
10864
10865 prototype.contains = function(x, y) {
10866 return !(
10867 x < this.x1 ||
10868 x > this.x2 ||
10869 y < this.y1 ||
10870 y > this.y2
10871 );
10872 };
10873
10874 prototype.width = function() {
10875 return this.x2 - this.x1;
10876 };
10877
10878 prototype.height = function() {
10879 return this.y2 - this.y1;
10880 };
10881
10882 module.exports = Bounds;
10883
10884 },{}],75:[function(require,module,exports){
10885 module.exports = function(b) {
10886 function noop() { }
10887 function add(x,y) { b.add(x, y); }
10888
10889 return {
10890 bounds: function(_) {
10891 if (!arguments.length) return b;
10892 return (b = _, this);
10893 },
10894 beginPath: noop,
10895 closePath: noop,
10896 moveTo: add,
10897 lineTo: add,
10898 quadraticCurveTo: function(x1, y1, x2, y2) {
10899 b.add(x1, y1);
10900 b.add(x2, y2);
10901 },
10902 bezierCurveTo: function(x1, y1, x2, y2, x3, y3) {
10903 b.add(x1, y1);
10904 b.add(x2, y2);
10905 b.add(x3, y3);
10906 }
10907 };
10908 };
10909
10910 },{}],76:[function(require,module,exports){
10911 var gradient_id = 0;
10912
10913 function Gradient(type) {
10914 this.id = 'gradient_' + (gradient_id++);
10915 this.type = type || 'linear';
10916 this.stops = [];
10917 this.x1 = 0;
10918 this.x2 = 1;
10919 this.y1 = 0;
10920 this.y2 = 0;
10921 }
10922
10923 var prototype = Gradient.prototype;
10924
10925 prototype.stop = function(offset, color) {
10926 this.stops.push({
10927 offset: offset,
10928 color: color
10929 });
10930 return this;
10931 };
10932
10933 module.exports = Gradient;
10934 },{}],77:[function(require,module,exports){
10935 (function (global){
10936 var load = require('datalib/src/import/load');
10937
10938 function ImageLoader(loadConfig) {
10939 this._pending = 0;
10940 this._config = loadConfig || ImageLoader.Config;
10941 }
10942
10943 // Overridable global default load configuration
10944 ImageLoader.Config = null;
10945
10946 var prototype = ImageLoader.prototype;
10947
10948 prototype.pending = function() {
10949 return this._pending;
10950 };
10951
10952 prototype.params = function(uri) {
10953 var p = {url: uri}, k;
10954 for (k in this._config) { p[k] = this._config[k]; }
10955 return p;
10956 };
10957
10958 prototype.imageURL = function(uri) {
10959 return load.sanitizeUrl(this.params(uri));
10960 };
10961
10962 function browser(uri, callback) {
10963 var url = load.sanitizeUrl(this.params(uri));
10964 if (!url) { // error
10965 if (callback) callback(uri, null);
10966 return null;
10967 }
10968
10969 var loader = this,
10970 image = new Image();
10971
10972 loader._pending += 1;
10973
10974 image.onload = function() {
10975 loader._pending -= 1;
10976 image.loaded = true;
10977 if (callback) callback(null, image);
10978 };
10979 image.src = url;
10980
10981 return image;
10982 }
10983
10984 function server(uri, callback) {
10985 var loader = this,
10986 image = new ((typeof window !== "undefined" ? window['canvas'] : typeof global !== "undefined" ? global['canvas'] : null).Image)();
10987
10988 loader._pending += 1;
10989
10990 load(this.params(uri), function(err, data) {
10991 loader._pending -= 1;
10992 if (err) {
10993 if (callback) callback(err, null);
10994 return null;
10995 }
10996 image.src = data;
10997 image.loaded = true;
10998 if (callback) callback(null, image);
10999 });
11000
11001 return image;
11002 }
11003
11004 prototype.loadImage = function(uri, callback) {
11005 return load.useXHR ?
11006 browser.call(this, uri, callback) :
11007 server.call(this, uri, callback);
11008 };
11009
11010 module.exports = ImageLoader;
11011
11012 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
11013
11014 },{"datalib/src/import/load":20}],78:[function(require,module,exports){
11015 function Item(mark) {
11016 this.mark = mark;
11017 }
11018
11019 var prototype = Item.prototype;
11020
11021 prototype.hasPropertySet = function(name) {
11022 var props = this.mark.def.properties;
11023 return props && props[name] != null;
11024 };
11025
11026 prototype.cousin = function(offset, index) {
11027 if (offset === 0) return this;
11028 offset = offset || -1;
11029 var mark = this.mark,
11030 group = mark.group,
11031 iidx = index==null ? mark.items.indexOf(this) : index,
11032 midx = group.items.indexOf(mark) + offset;
11033 return group.items[midx].items[iidx];
11034 };
11035
11036 prototype.sibling = function(offset) {
11037 if (offset === 0) return this;
11038 offset = offset || -1;
11039 var mark = this.mark,
11040 iidx = mark.items.indexOf(this) + offset;
11041 return mark.items[iidx];
11042 };
11043
11044 prototype.remove = function() {
11045 var item = this,
11046 list = item.mark.items,
11047 i = list.indexOf(item);
11048 if (i >= 0) {
11049 if (i===list.length-1) {
11050 list.pop();
11051 } else {
11052 list.splice(i, 1);
11053 }
11054 }
11055 return item;
11056 };
11057
11058 prototype.touch = function() {
11059 if (this.pathCache) this.pathCache = null;
11060 };
11061
11062 module.exports = Item;
11063 },{}],79:[function(require,module,exports){
11064 var BoundsContext = require('./BoundsContext'),
11065 Bounds = require('./Bounds'),
11066 canvas = require('./canvas'),
11067 svg = require('./svg'),
11068 text = require('./text'),
11069 paths = require('../path'),
11070 parse = paths.parse,
11071 drawPath = paths.render,
11072 areaPath = svg.path.area,
11073 linePath = svg.path.line,
11074 halfpi = Math.PI / 2,
11075 sqrt3 = Math.sqrt(3),
11076 tan30 = Math.tan(30 * Math.PI / 180),
11077 g2D = null,
11078 bc = BoundsContext();
11079
11080 function context() {
11081 return g2D || (g2D = canvas.instance(1,1).getContext('2d'));
11082 }
11083
11084 function strokeBounds(o, bounds) {
11085 if (o.stroke && o.opacity !== 0 && o.stokeOpacity !== 0) {
11086 bounds.expand(o.strokeWidth != null ? o.strokeWidth : 1);
11087 }
11088 return bounds;
11089 }
11090
11091 function pathBounds(o, path, bounds, x, y) {
11092 if (path == null) {
11093 bounds.set(0, 0, 0, 0);
11094 } else {
11095 drawPath(bc.bounds(bounds), path, x, y);
11096 strokeBounds(o, bounds);
11097 }
11098 return bounds;
11099 }
11100
11101 function path(o, bounds) {
11102 var p = o.path ? o.pathCache || (o.pathCache = parse(o.path)) : null;
11103 return pathBounds(o, p, bounds, o.x, o.y);
11104 }
11105
11106 function area(mark, bounds) {
11107 if (mark.items.length === 0) return bounds;
11108 var items = mark.items,
11109 item = items[0],
11110 p = item.pathCache || (item.pathCache = parse(areaPath(items)));
11111 return pathBounds(item, p, bounds);
11112 }
11113
11114 function line(mark, bounds) {
11115 if (mark.items.length === 0) return bounds;
11116 var items = mark.items,
11117 item = items[0],
11118 p = item.pathCache || (item.pathCache = parse(linePath(items)));
11119 return pathBounds(item, p, bounds);
11120 }
11121
11122 function rect(o, bounds) {
11123 var x, y;
11124 return strokeBounds(o, bounds.set(
11125 x = o.x || 0,
11126 y = o.y || 0,
11127 (x + o.width) || 0,
11128 (y + o.height) || 0
11129 ));
11130 }
11131
11132 function image(o, bounds) {
11133 var x = o.x || 0,
11134 y = o.y || 0,
11135 w = o.width || 0,
11136 h = o.height || 0;
11137 x = x - (o.align === 'center' ? w/2 : (o.align === 'right' ? w : 0));
11138 y = y - (o.baseline === 'middle' ? h/2 : (o.baseline === 'bottom' ? h : 0));
11139 return bounds.set(x, y, x+w, y+h);
11140 }
11141
11142 function rule(o, bounds) {
11143 var x1, y1;
11144 return strokeBounds(o, bounds.set(
11145 x1 = o.x || 0,
11146 y1 = o.y || 0,
11147 o.x2 != null ? o.x2 : x1,
11148 o.y2 != null ? o.y2 : y1
11149 ));
11150 }
11151
11152 function arc(o, bounds) {
11153 var cx = o.x || 0,
11154 cy = o.y || 0,
11155 ir = o.innerRadius || 0,
11156 or = o.outerRadius || 0,
11157 sa = (o.startAngle || 0) - halfpi,
11158 ea = (o.endAngle || 0) - halfpi,
11159 xmin = Infinity, xmax = -Infinity,
11160 ymin = Infinity, ymax = -Infinity,
11161 a, i, n, x, y, ix, iy, ox, oy;
11162
11163 var angles = [sa, ea],
11164 s = sa - (sa % halfpi);
11165 for (i=0; i<4 && s<ea; ++i, s+=halfpi) {
11166 angles.push(s);
11167 }
11168
11169 for (i=0, n=angles.length; i<n; ++i) {
11170 a = angles[i];
11171 x = Math.cos(a); ix = ir*x; ox = or*x;
11172 y = Math.sin(a); iy = ir*y; oy = or*y;
11173 xmin = Math.min(xmin, ix, ox);
11174 xmax = Math.max(xmax, ix, ox);
11175 ymin = Math.min(ymin, iy, oy);
11176 ymax = Math.max(ymax, iy, oy);
11177 }
11178
11179 return strokeBounds(o, bounds.set(
11180 cx + xmin,
11181 cy + ymin,
11182 cx + xmax,
11183 cy + ymax
11184 ));
11185 }
11186
11187 function symbol(o, bounds) {
11188 var size = o.size != null ? o.size : 100,
11189 x = o.x || 0,
11190 y = o.y || 0,
11191 r, t, rx, ry;
11192
11193 switch (o.shape) {
11194 case 'cross':
11195 t = 3 * Math.sqrt(size / 5) / 2;
11196 bounds.set(x-t, y-t, x+t, y+t);
11197 break;
11198
11199 case 'diamond':
11200 ry = Math.sqrt(size / (2 * tan30));
11201 rx = ry * tan30;
11202 bounds.set(x-rx, y-ry, x+rx, y+ry);
11203 break;
11204
11205 case 'square':
11206 t = Math.sqrt(size);
11207 r = t / 2;
11208 bounds.set(x-r, y-r, x+r, y+r);
11209 break;
11210
11211 case 'triangle-down':
11212 rx = Math.sqrt(size / sqrt3);
11213 ry = rx * sqrt3 / 2;
11214 bounds.set(x-rx, y-ry, x+rx, y+ry);
11215 break;
11216
11217 case 'triangle-up':
11218 rx = Math.sqrt(size / sqrt3);
11219 ry = rx * sqrt3 / 2;
11220 bounds.set(x-rx, y-ry, x+rx, y+ry);
11221 break;
11222
11223 default:
11224 r = Math.sqrt(size/Math.PI);
11225 bounds.set(x-r, y-r, x+r, y+r);
11226 }
11227
11228 return strokeBounds(o, bounds);
11229 }
11230
11231 function textMark(o, bounds, noRotate) {
11232 var g = context(),
11233 h = text.size(o),
11234 a = o.align,
11235 r = o.radius || 0,
11236 x = (o.x || 0),
11237 y = (o.y || 0),
11238 dx = (o.dx || 0),
11239 dy = (o.dy || 0) + text.offset(o) - Math.round(0.8*h), // use 4/5 offset
11240 w, t;
11241
11242 if (r) {
11243 t = (o.theta || 0) - Math.PI/2;
11244 x += r * Math.cos(t);
11245 y += r * Math.sin(t);
11246 }
11247
11248 // horizontal alignment
11249 g.font = text.font(o);
11250 w = g.measureText(text.value(o.text)).width;
11251 if (a === 'center') {
11252 dx -= (w / 2);
11253 } else if (a === 'right') {
11254 dx -= w;
11255 } else {
11256 // left by default, do nothing
11257 }
11258
11259 bounds.set(dx+=x, dy+=y, dx+w, dy+h);
11260 if (o.angle && !noRotate) {
11261 bounds.rotate(o.angle*Math.PI/180, x, y);
11262 }
11263 return bounds.expand(noRotate ? 0 : 1);
11264 }
11265
11266 function group(g, bounds, includeLegends) {
11267 var axes = g.axisItems || [],
11268 items = g.items || [],
11269 legends = g.legendItems || [],
11270 j, m;
11271
11272 for (j=0, m=axes.length; j<m; ++j) {
11273 bounds.union(axes[j].bounds);
11274 }
11275 for (j=0, m=items.length; j<m; ++j) {
11276 bounds.union(items[j].bounds);
11277 }
11278 if (includeLegends) {
11279 for (j=0, m=legends.length; j<m; ++j) {
11280 bounds.union(legends[j].bounds);
11281 }
11282 }
11283 if (g.width || g.height) {
11284 strokeBounds(g, bounds
11285 .add(0, 0)
11286 .add(g.width || 0, g.height || 0));
11287 }
11288 return bounds.translate(g.x || 0, g.y || 0);
11289 }
11290
11291 var methods = {
11292 group: group,
11293 symbol: symbol,
11294 image: image,
11295 rect: rect,
11296 rule: rule,
11297 arc: arc,
11298 text: textMark,
11299 path: path,
11300 area: area,
11301 line: line
11302 };
11303 methods.area.nest = true;
11304 methods.line.nest = true;
11305
11306 function itemBounds(item, func, opt) {
11307 var type = item.mark.marktype;
11308 func = func || methods[type];
11309 if (func.nest) item = item.mark;
11310
11311 var curr = item.bounds,
11312 prev = item['bounds:prev'] || (item['bounds:prev'] = new Bounds());
11313
11314 if (curr) {
11315 prev.clear().union(curr);
11316 curr.clear();
11317 } else {
11318 item.bounds = new Bounds();
11319 }
11320 func(item, item.bounds, opt);
11321 if (!curr) prev.clear().union(item.bounds);
11322 return item.bounds;
11323 }
11324
11325 var DUMMY_ITEM = {mark: null};
11326
11327 function markBounds(mark, bounds, opt) {
11328 var type = mark.marktype,
11329 func = methods[type],
11330 items = mark.items,
11331 hasi = items && items.length,
11332 i, n, o, b;
11333
11334 if (func.nest) {
11335 o = hasi ? items[0]
11336 : (DUMMY_ITEM.mark = mark, DUMMY_ITEM); // no items, so fake it
11337 b = itemBounds(o, func, opt);
11338 bounds = bounds && bounds.union(b) || b;
11339 return bounds;
11340 }
11341
11342 bounds = bounds || mark.bounds && mark.bounds.clear() || new Bounds();
11343 if (hasi) {
11344 for (i=0, n=items.length; i<n; ++i) {
11345 bounds.union(itemBounds(items[i], func, opt));
11346 }
11347 }
11348 return (mark.bounds = bounds);
11349 }
11350
11351 module.exports = {
11352 mark: markBounds,
11353 item: itemBounds,
11354 text: textMark,
11355 group: group
11356 };
11357
11358 },{"../path":48,"./Bounds":74,"./BoundsContext":75,"./canvas":80,"./svg":83,"./text":84}],80:[function(require,module,exports){
11359 (function (global){
11360 function instance(w, h) {
11361 w = w || 1;
11362 h = h || 1;
11363 var canvas;
11364
11365 if (typeof document !== 'undefined' && document.createElement) {
11366 canvas = document.createElement('canvas');
11367 canvas.width = w;
11368 canvas.height = h;
11369 } else {
11370 var Canvas = (typeof window !== "undefined" ? window['canvas'] : typeof global !== "undefined" ? global['canvas'] : null);
11371 if (!Canvas.prototype) return null;
11372 canvas = new Canvas(w, h);
11373 }
11374 return lineDash(canvas);
11375 }
11376
11377 function resize(canvas, w, h, p, retina) {
11378 var g = this._ctx = canvas.getContext('2d'),
11379 s = 1;
11380
11381 canvas.width = w + p.left + p.right;
11382 canvas.height = h + p.top + p.bottom;
11383
11384 // if browser canvas, attempt to modify for retina display
11385 if (retina && typeof HTMLElement !== 'undefined' &&
11386 canvas instanceof HTMLElement)
11387 {
11388 g.pixelratio = (s = pixelRatio(canvas) || 1);
11389 }
11390
11391 g.setTransform(s, 0, 0, s, s*p.left, s*p.top);
11392 return canvas;
11393 }
11394
11395 function pixelRatio(canvas) {
11396 var g = canvas.getContext('2d');
11397
11398 // get canvas pixel data
11399 var devicePixelRatio = window && window.devicePixelRatio || 1,
11400 backingStoreRatio = (
11401 g.webkitBackingStorePixelRatio ||
11402 g.mozBackingStorePixelRatio ||
11403 g.msBackingStorePixelRatio ||
11404 g.oBackingStorePixelRatio ||
11405 g.backingStorePixelRatio) || 1,
11406 ratio = devicePixelRatio / backingStoreRatio;
11407
11408 if (devicePixelRatio !== backingStoreRatio) {
11409 // set actual and visible canvas size
11410 var w = canvas.width,
11411 h = canvas.height;
11412 canvas.width = w * ratio;
11413 canvas.height = h * ratio;
11414 canvas.style.width = w + 'px';
11415 canvas.style.height = h + 'px';
11416 }
11417
11418 return ratio;
11419 }
11420
11421 function lineDash(canvas) {
11422 var g = canvas.getContext('2d');
11423 if (g.vgLineDash) return; // already initialized!
11424
11425 var NOOP = function() {},
11426 NODASH = [];
11427
11428 if (g.setLineDash) {
11429 g.vgLineDash = function(dash) { this.setLineDash(dash || NODASH); };
11430 g.vgLineDashOffset = function(off) { this.lineDashOffset = off; };
11431 } else if (g.webkitLineDash !== undefined) {
11432 g.vgLineDash = function(dash) { this.webkitLineDash = dash || NODASH; };
11433 g.vgLineDashOffset = function(off) { this.webkitLineDashOffset = off; };
11434 } else if (g.mozDash !== undefined) {
11435 g.vgLineDash = function(dash) { this.mozDash = dash; };
11436 g.vgLineDashOffset = NOOP;
11437 } else {
11438 g.vgLineDash = NOOP;
11439 g.vgLineDashOffset = NOOP;
11440 }
11441 return canvas;
11442 }
11443
11444 module.exports = {
11445 instance: instance,
11446 resize: resize,
11447 lineDash: lineDash
11448 };
11449
11450 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
11451
11452 },{}],81:[function(require,module,exports){
11453 // create a new DOM element
11454 function create(doc, tag, ns) {
11455 return ns ? doc.createElementNS(ns, tag) : doc.createElement(tag);
11456 }
11457
11458 // remove element from DOM
11459 // recursively remove parent elements if empty
11460 function remove(el) {
11461 if (!el) return;
11462 var p = el.parentNode;
11463 if (p) {
11464 p.removeChild(el);
11465 if (!p.childNodes || !p.childNodes.length) remove(p);
11466 }
11467 }
11468
11469 module.exports = {
11470 // find first child element with matching tag
11471 find: function(el, tag) {
11472 tag = tag.toLowerCase();
11473 for (var i=0, n=el.childNodes.length; i<n; ++i) {
11474 if (el.childNodes[i].tagName.toLowerCase() === tag) {
11475 return el.childNodes[i];
11476 }
11477 }
11478 },
11479 // retrieve child element at given index
11480 // create & insert if doesn't exist or if tag/className do not match
11481 child: function(el, index, tag, ns, className, insert) {
11482 var a, b;
11483 a = b = el.childNodes[index];
11484 if (!a || insert ||
11485 a.tagName.toLowerCase() !== tag.toLowerCase() ||
11486 className && a.getAttribute('class') != className) {
11487 a = create(el.ownerDocument, tag, ns);
11488 el.insertBefore(a, b);
11489 if (className) a.setAttribute('class', className);
11490 }
11491 return a;
11492 },
11493 // remove all child elements at or above the given index
11494 clear: function(el, index) {
11495 var curr = el.childNodes.length;
11496 while (curr > index) {
11497 el.removeChild(el.childNodes[--curr]);
11498 }
11499 return el;
11500 },
11501 remove: remove,
11502 // generate css class name for mark
11503 cssClass: function(mark) {
11504 return 'mark-' + mark.marktype + (mark.name ? ' '+mark.name : '');
11505 },
11506 // generate string for an opening xml tag
11507 // tag: the name of the xml tag
11508 // attr: hash of attribute name-value pairs to include
11509 // raw: additional raw string to include in tag markup
11510 openTag: function(tag, attr, raw) {
11511 var s = '<' + tag, key, val;
11512 if (attr) {
11513 for (key in attr) {
11514 val = attr[key];
11515 if (val != null) {
11516 s += ' ' + key + '="' + val + '"';
11517 }
11518 }
11519 }
11520 if (raw) s += ' ' + raw;
11521 return s + '>';
11522 },
11523 // generate string for closing xml tag
11524 // tag: the name of the xml tag
11525 closeTag: function(tag) {
11526 return '</' + tag + '>';
11527 }
11528 };
11529
11530 },{}],82:[function(require,module,exports){
11531 var bound = require('../util/bound');
11532
11533 var sets = [
11534 'items',
11535 'axisItems',
11536 'legendItems'
11537 ];
11538
11539 var keys = [
11540 'marktype', 'name', 'interactive', 'clip',
11541 'items', 'axisItems', 'legendItems', 'layer',
11542 'x', 'y', 'width', 'height', 'align', 'baseline', // layout
11543 'fill', 'fillOpacity', 'opacity', // fill
11544 'stroke', 'strokeOpacity', 'strokeWidth', 'strokeCap', // stroke
11545 'strokeDash', 'strokeDashOffset', // stroke dash
11546 'startAngle', 'endAngle', 'innerRadius', 'outerRadius', // arc
11547 'interpolate', 'tension', 'orient', // area, line
11548 'url', // image
11549 'path', // path
11550 'x2', 'y2', // rule
11551 'size', 'shape', // symbol
11552 'text', 'angle', 'theta', 'radius', 'dx', 'dy', // text
11553 'font', 'fontSize', 'fontWeight', 'fontStyle', 'fontVariant' // font
11554 ];
11555
11556 function toJSON(scene, indent) {
11557 return JSON.stringify(scene, keys, indent);
11558 }
11559
11560 function fromJSON(json) {
11561 var scene = (typeof json === 'string' ? JSON.parse(json) : json);
11562 return initialize(scene);
11563 }
11564
11565 function initialize(scene) {
11566 var type = scene.marktype,
11567 i, n, s, m, items;
11568
11569 for (s=0, m=sets.length; s<m; ++s) {
11570 if ((items = scene[sets[s]])) {
11571 for (i=0, n=items.length; i<n; ++i) {
11572 items[i][type ? 'mark' : 'group'] = scene;
11573 if (!type || type === 'group') {
11574 initialize(items[i]);
11575 }
11576 }
11577 }
11578 }
11579
11580 if (type) bound.mark(scene);
11581 return scene;
11582 }
11583
11584 module.exports = {
11585 toJSON: toJSON,
11586 fromJSON: fromJSON
11587 };
11588 },{"../util/bound":79}],83:[function(require,module,exports){
11589 (function (global){
11590 var d3_svg = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null).svg;
11591
11592 function x(o) { return o.x || 0; }
11593 function y(o) { return o.y || 0; }
11594 function xw(o) { return (o.x || 0) + (o.width || 0); }
11595 function yh(o) { return (o.y || 0) + (o.height || 0); }
11596 function size(o) { return o.size == null ? 100 : o.size; }
11597 function shape(o) { return o.shape || 'circle'; }
11598
11599 var areav = d3_svg.area().x(x).y1(y).y0(yh),
11600 areah = d3_svg.area().y(y).x1(x).x0(xw),
11601 line = d3_svg.line().x(x).y(y);
11602
11603 module.exports = {
11604 metadata: {
11605 'version': '1.1',
11606 'xmlns': 'http://www.w3.org/2000/svg',
11607 'xmlns:xlink': 'http://www.w3.org/1999/xlink'
11608 },
11609 path: {
11610 arc: d3_svg.arc(),
11611 symbol: d3_svg.symbol().type(shape).size(size),
11612 area: function(items) {
11613 var o = items[0];
11614 return (o.orient === 'horizontal' ? areah : areav)
11615 .interpolate(o.interpolate || 'linear')
11616 .tension(o.tension || 0.7)
11617 (items);
11618 },
11619 line: function(items) {
11620 var o = items[0];
11621 return line
11622 .interpolate(o.interpolate || 'linear')
11623 .tension(o.tension || 0.7)
11624 (items);
11625 }
11626 },
11627 textAlign: {
11628 'left': 'start',
11629 'center': 'middle',
11630 'right': 'end'
11631 },
11632 textBaseline: {
11633 'top': 'before-edge',
11634 'bottom': 'after-edge',
11635 'middle': 'central'
11636 },
11637 styles: {
11638 'fill': 'fill',
11639 'fillOpacity': 'fill-opacity',
11640 'stroke': 'stroke',
11641 'strokeWidth': 'stroke-width',
11642 'strokeOpacity': 'stroke-opacity',
11643 'strokeCap': 'stroke-linecap',
11644 'strokeDash': 'stroke-dasharray',
11645 'strokeDashOffset': 'stroke-dashoffset',
11646 'opacity': 'opacity'
11647 },
11648 styleProperties: [
11649 'fill',
11650 'fillOpacity',
11651 'stroke',
11652 'strokeWidth',
11653 'strokeOpacity',
11654 'strokeCap',
11655 'strokeDash',
11656 'strokeDashOffset',
11657 'opacity'
11658 ]
11659 };
11660
11661 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
11662
11663 },{}],84:[function(require,module,exports){
11664 function size(item) {
11665 return item.fontSize != null ? item.fontSize : 11;
11666 }
11667
11668 module.exports = {
11669 size: size,
11670 value: function(s) {
11671 return s != null ? String(s) : '';
11672 },
11673 font: function(item, quote) {
11674 var font = item.font;
11675 if (quote && font) {
11676 font = String(font).replace(/\"/g, '\'');
11677 }
11678 return '' +
11679 (item.fontStyle ? item.fontStyle + ' ' : '') +
11680 (item.fontVariant ? item.fontVariant + ' ' : '') +
11681 (item.fontWeight ? item.fontWeight + ' ' : '') +
11682 size(item) + 'px ' +
11683 (font || 'sans-serif');
11684 },
11685 offset: function(item) {
11686 // perform our own font baseline calculation
11687 // why? not all browsers support SVG 1.1 'alignment-baseline' :(
11688 var baseline = item.baseline,
11689 h = size(item);
11690 return Math.round(
11691 baseline === 'top' ? 0.93*h :
11692 baseline === 'middle' ? 0.30*h :
11693 baseline === 'bottom' ? -0.21*h : 0
11694 );
11695 }
11696 };
11697
11698 },{}],85:[function(require,module,exports){
11699 var sg = require('vega-scenegraph').render,
11700 canvas = sg.canvas,
11701 svg = sg.svg.string,
11702 View = require('./View');
11703
11704 function HeadlessView(width, height, model) {
11705 View.call(null, width, height, model);
11706 this._type = 'canvas';
11707 this._renderers = {canvas: canvas, svg: svg};
11708 }
11709
11710 var prototype = (HeadlessView.prototype = new View());
11711
11712 prototype.renderer = function(type) {
11713 if(type) this._type = type;
11714 return View.prototype.renderer.apply(this, arguments);
11715 };
11716
11717 prototype.canvas = function() {
11718 return (this._type === 'canvas') ? this._renderer.canvas() : null;
11719 };
11720
11721 prototype.canvasAsync = function(callback) {
11722 var r = this._renderer, view = this;
11723
11724 function wait() {
11725 if (r.pendingImages() === 0) {
11726 view.render(); // re-render with all images
11727 callback(view.canvas());
11728 } else {
11729 setTimeout(wait, 10);
11730 }
11731 }
11732
11733 // if images loading, poll until ready
11734 if (this._type !== 'canvas') return null;
11735 if (r.pendingImages() > 0) { wait(); } else { callback(this.canvas()); }
11736 };
11737
11738 prototype.svg = function() {
11739 return (this._type === 'svg') ? this._renderer.svg() : null;
11740 };
11741
11742 prototype.initialize = function() {
11743 var w = this._width,
11744 h = this._height,
11745 bg = this._bgcolor,
11746 pad = this._padding,
11747 config = this.model().config();
11748
11749 if (this._viewport) {
11750 w = this._viewport[0] - (pad ? pad.left + pad.right : 0);
11751 h = this._viewport[1] - (pad ? pad.top + pad.bottom : 0);
11752 }
11753
11754 this._renderer = (this._renderer || new this._io.Renderer(config.load))
11755 .initialize(null, w, h, pad)
11756 .background(bg);
11757
11758 return this;
11759 };
11760
11761 module.exports = HeadlessView;
11762 },{"./View":87,"vega-scenegraph":46}],86:[function(require,module,exports){
11763 var dl = require('datalib'),
11764 df = require('vega-dataflow'),
11765 ChangeSet = df.ChangeSet,
11766 Base = df.Graph.prototype,
11767 Node = df.Node, // jshint ignore:line
11768 GroupBuilder = require('../scene/GroupBuilder'),
11769 visit = require('../scene/visit'),
11770 config = require('./config');
11771
11772 function Model(cfg) {
11773 this._defs = {};
11774 this._predicates = {};
11775 this._scene = null;
11776
11777 this._node = null;
11778 this._builder = null; // Top-level scenegraph builder
11779
11780 this._reset = {axes: false, legends: false};
11781
11782 this.config(cfg);
11783 Base.init.call(this);
11784 }
11785
11786 var prototype = (Model.prototype = Object.create(Base));
11787 prototype.constructor = Model;
11788
11789 prototype.defs = function(defs) {
11790 if (!arguments.length) return this._defs;
11791 this._defs = defs;
11792 return this;
11793 };
11794
11795 prototype.config = function(cfg) {
11796 if (!arguments.length) return this._config;
11797 this._config = Object.create(config);
11798 for (var name in cfg) {
11799 var x = cfg[name], y = this._config[name];
11800 if (dl.isObject(x) && dl.isObject(y)) {
11801 dl.extend(y, x);
11802 } else {
11803 this._config[name] = x;
11804 }
11805 }
11806
11807 return this;
11808 };
11809
11810 prototype.width = function(width) {
11811 if (this._defs) this._defs.width = width;
11812 if (this._defs && this._defs.marks) this._defs.marks.width = width;
11813 if (this._scene) {
11814 this._scene.items[0].width = width;
11815 this._scene.items[0]._dirty = true;
11816 }
11817 this._reset.axes = true;
11818 return this;
11819 };
11820
11821 prototype.height = function(height) {
11822 if (this._defs) this._defs.height = height;
11823 if (this._defs && this._defs.marks) this._defs.marks.height = height;
11824 if (this._scene) {
11825 this._scene.items[0].height = height;
11826 this._scene.items[0]._dirty = true;
11827 }
11828 this._reset.axes = true;
11829 return this;
11830 };
11831
11832 prototype.node = function() {
11833 return this._node || (this._node = new Node(this));
11834 };
11835
11836 prototype.data = function() {
11837 var data = Base.data.apply(this, arguments);
11838 if (arguments.length > 1) { // new Datasource
11839 this.node().addListener(data.pipeline()[0]);
11840 }
11841 return data;
11842 };
11843
11844 function predicates(name) {
11845 var m = this, pred = {};
11846 if (!dl.isArray(name)) return this._predicates[name];
11847 name.forEach(function(n) { pred[n] = m._predicates[n]; });
11848 return pred;
11849 }
11850
11851 prototype.predicate = function(name, predicate) {
11852 if (arguments.length === 1) return predicates.call(this, name);
11853 return (this._predicates[name] = predicate);
11854 };
11855
11856 prototype.predicates = function() { return this._predicates; };
11857
11858 prototype.scene = function(renderer) {
11859 if (!arguments.length) return this._scene;
11860 if (this._builder) this.node().removeListener(this._builder.disconnect());
11861 this._builder = new GroupBuilder(this, this._defs.marks, this._scene={});
11862 this.node().addListener(this._builder.connect());
11863 var p = this._builder.pipeline();
11864 p[p.length-1].addListener(renderer);
11865 return this;
11866 };
11867
11868 prototype.reset = function() {
11869 if (this._scene && this._reset.axes) {
11870 visit(this._scene, function(item) {
11871 if (item.axes) item.axes.forEach(function(axis) { axis.reset(); });
11872 });
11873 this._reset.axes = false;
11874 }
11875 if (this._scene && this._reset.legends) {
11876 visit(this._scene, function(item) {
11877 if (item.legends) item.legends.forEach(function(l) { l.reset(); });
11878 });
11879 this._reset.legends = false;
11880 }
11881 return this;
11882 };
11883
11884 prototype.addListener = function(l) {
11885 this.node().addListener(l);
11886 };
11887
11888 prototype.removeListener = function(l) {
11889 this.node().removeListener(l);
11890 };
11891
11892 prototype.fire = function(cs) {
11893 if (!cs) cs = ChangeSet.create();
11894 this.propagate(cs, this.node());
11895 };
11896
11897 module.exports = Model;
11898 },{"../scene/GroupBuilder":110,"../scene/visit":115,"./config":88,"datalib":24,"vega-dataflow":39}],87:[function(require,module,exports){
11899 (function (global){
11900 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
11901 dl = require('datalib'),
11902 df = require('vega-dataflow'),
11903 sg = require('vega-scenegraph').render,
11904 log = require('vega-logging'),
11905 Deps = df.Dependencies,
11906 parseStreams = require('../parse/streams'),
11907 Encoder = require('../scene/Encoder'),
11908 Transition = require('../scene/Transition');
11909
11910 function View(el, width, height) {
11911 this._el = null;
11912 this._model = null;
11913 this._width = this.__width = width || 500;
11914 this._height = this.__height = height || 300;
11915 this._bgcolor = null;
11916 this._autopad = 1;
11917 this._padding = {top:0, left:0, bottom:0, right:0};
11918 this._viewport = null;
11919 this._renderer = null;
11920 this._handler = null;
11921 this._streamer = null; // Targeted update for streaming changes
11922 this._changeset = null;
11923 this._repaint = true; // Full re-render on every re-init
11924 this._renderers = sg;
11925 this._io = null;
11926 this._api = {}; // Stash streaming data API sandboxes.
11927 }
11928
11929 var prototype = View.prototype;
11930
11931 prototype.model = function(model) {
11932 if (!arguments.length) return this._model;
11933 if (this._model !== model) {
11934 this._model = model;
11935 this._streamer = new df.Node(model);
11936 this._streamer._rank = -1; // HACK: To reduce re-ranking churn.
11937 this._changeset = df.ChangeSet.create();
11938 if (this._handler) this._handler.model(model);
11939 }
11940 return this;
11941 };
11942
11943 // Sandboxed streaming data API
11944 function streaming(src) {
11945 var view = this,
11946 ds = this._model.data(src),
11947 name = ds.name(),
11948 listener = ds.pipeline()[0],
11949 streamer = this._streamer,
11950 api = {};
11951
11952 // If we have it stashed, don't create a new closure.
11953 if (this._api[src]) return this._api[src];
11954
11955 api.insert = function(vals) {
11956 ds.insert(dl.duplicate(vals)); // Don't pollute the environment
11957 streamer.addListener(listener);
11958 view._changeset.data[name] = 1;
11959 return api;
11960 };
11961
11962 api.update = function() {
11963 streamer.addListener(listener);
11964 view._changeset.data[name] = 1;
11965 return (ds.update.apply(ds, arguments), api);
11966 };
11967
11968 api.remove = function() {
11969 streamer.addListener(listener);
11970 view._changeset.data[name] = 1;
11971 return (ds.remove.apply(ds, arguments), api);
11972 };
11973
11974 api.values = function() { return ds.values(); };
11975
11976 return (this._api[src] = api);
11977 }
11978
11979 prototype.data = function(data) {
11980 var v = this;
11981 if (!arguments.length) return v._model.values();
11982 else if (dl.isString(data)) return streaming.call(v, data);
11983 else if (dl.isObject(data)) {
11984 dl.keys(data).forEach(function(k) {
11985 var api = streaming.call(v, k);
11986 data[k](api);
11987 });
11988 }
11989 return this;
11990 };
11991
11992 prototype.signal = function(name, value) {
11993 var m = this._model,
11994 cs = this._changeset,
11995 streamer = this._streamer,
11996 setter = name;
11997
11998 if (!arguments.length) {
11999 return m.values(Deps.SIGNALS);
12000 } else if (arguments.length == 1 && dl.isString(name)) {
12001 return m.values(Deps.SIGNALS, name);
12002 }
12003
12004 if (arguments.length == 2) {
12005 setter = {};
12006 setter[name] = value;
12007 }
12008
12009 dl.keys(setter).forEach(function(k) {
12010 streamer.addListener(m.signal(k).value(setter[k]));
12011 cs.signals[k] = 1;
12012 cs.reflow = true;
12013 });
12014
12015 return this;
12016 };
12017
12018 prototype.width = function(width) {
12019 if (!arguments.length) return this.__width;
12020 if (this.__width !== width) {
12021 this._width = this.__width = width;
12022 this.model().width(width);
12023 this.initialize();
12024 if (this._strict) this._autopad = 1;
12025 }
12026 return this;
12027 };
12028
12029 prototype.height = function(height) {
12030 if (!arguments.length) return this.__height;
12031 if (this.__height !== height) {
12032 this._height = this.__height = height;
12033 this.model().height(height);
12034 this.initialize();
12035 if (this._strict) this._autopad = 1;
12036 }
12037 return this;
12038 };
12039
12040 prototype.background = function(bgcolor) {
12041 if (!arguments.length) return this._bgcolor;
12042 if (this._bgcolor !== bgcolor) {
12043 this._bgcolor = bgcolor;
12044 this.initialize();
12045 }
12046 return this;
12047 };
12048
12049 prototype.padding = function(pad) {
12050 if (!arguments.length) return this._padding;
12051 if (this._padding !== pad) {
12052 if (dl.isString(pad)) {
12053 this._autopad = 1;
12054 this._padding = {top:0, left:0, bottom:0, right:0};
12055 this._strict = (pad === 'strict');
12056 } else {
12057 this._autopad = 0;
12058 this._padding = pad;
12059 this._strict = false;
12060 }
12061 if (this._renderer) this._renderer.resize(this._width, this._height, pad);
12062 if (this._handler) this._handler.padding(pad);
12063 }
12064 return (this._repaint = true, this);
12065 };
12066
12067 prototype.autopad = function(opt) {
12068 if (this._autopad < 1) return this;
12069 else this._autopad = 0;
12070
12071 var b = this.model().scene().bounds,
12072 pad = this._padding,
12073 config = this.model().config(),
12074 inset = config.autopadInset,
12075 l = b.x1 < 0 ? Math.ceil(-b.x1) + inset : 0,
12076 t = b.y1 < 0 ? Math.ceil(-b.y1) + inset : 0,
12077 r = b.x2 > this._width ? Math.ceil(+b.x2 - this._width) + inset : 0;
12078 b = b.y2 > this._height ? Math.ceil(+b.y2 - this._height) + inset : 0;
12079 pad = {left:l, top:t, right:r, bottom:b};
12080
12081 if (this._strict) {
12082 this._autopad = 0;
12083 this._padding = pad;
12084 this._width = Math.max(0, this.__width - (l+r));
12085 this._height = Math.max(0, this.__height - (t+b));
12086
12087 this._model.width(this._width)
12088 .height(this._height).reset();
12089
12090 this.initialize()
12091 .update({props:'enter'}).update({props:'update'});
12092 } else {
12093 this.padding(pad).update(opt);
12094 }
12095 return this;
12096 };
12097
12098 prototype.viewport = function(size) {
12099 if (!arguments.length) return this._viewport;
12100 if (this._viewport !== size) {
12101 this._viewport = size;
12102 this.initialize();
12103 }
12104 return this;
12105 };
12106
12107 prototype.renderer = function(type) {
12108 if (!arguments.length) return this._renderer;
12109 if (this._renderers[type]) type = this._renderers[type];
12110 else if (dl.isString(type)) throw new Error('Unknown renderer: ' + type);
12111 else if (!type) throw new Error('No renderer specified');
12112
12113 if (this._io !== type) {
12114 this._io = type;
12115 this._renderer = null;
12116 this.initialize();
12117 if (this._build) this.render();
12118 }
12119 return this;
12120 };
12121
12122 prototype.initialize = function(el) {
12123 var v = this, prevHandler,
12124 w = v._width, h = v._height, pad = v._padding, bg = v._bgcolor,
12125 config = this.model().config();
12126
12127 if (!arguments.length || el === null) {
12128 el = this._el ? this._el.parentNode : null;
12129 if (!el) return this; // This View cannot init w/o an
12130 }
12131
12132 // clear pre-existing container
12133 d3.select(el).select('div.vega').remove();
12134
12135 // add div container
12136 this._el = el = d3.select(el)
12137 .append('div')
12138 .attr('class', 'vega')
12139 .style('position', 'relative')
12140 .node();
12141 if (v._viewport) {
12142 d3.select(el)
12143 .style('width', (v._viewport[0] || w)+'px')
12144 .style('height', (v._viewport[1] || h)+'px')
12145 .style('overflow', 'auto');
12146 }
12147
12148 // renderer
12149 sg.canvas.Renderer.RETINA = config.render.retina;
12150 v._renderer = (v._renderer || new this._io.Renderer(config.load))
12151 .initialize(el, w, h, pad)
12152 .background(bg);
12153
12154 // input handler
12155 prevHandler = v._handler;
12156 v._handler = new this._io.Handler()
12157 .initialize(el, pad, v);
12158
12159 if (prevHandler) {
12160 prevHandler.handlers().forEach(function(h) {
12161 v._handler.on(h.type, h.handler);
12162 });
12163 } else {
12164 // Register event listeners for signal stream definitions.
12165 v._detach = parseStreams(this);
12166 }
12167
12168 return (this._repaint = true, this);
12169 };
12170
12171 prototype.destroy = function() {
12172 if (this._detach) this._detach();
12173 };
12174
12175 function build() {
12176 var v = this;
12177 v._renderNode = new df.Node(v._model)
12178 .router(true);
12179
12180 v._renderNode.evaluate = function(input) {
12181 log.debug(input, ['rendering']);
12182
12183 var s = v._model.scene(),
12184 h = v._handler;
12185
12186 if (h && h.scene) h.scene(s);
12187
12188 if (input.trans) {
12189 input.trans.start(function(items) { v._renderer.render(s, items); });
12190 } else if (v._repaint) {
12191 v._renderer.render(s);
12192 v._repaint = false;
12193 } else if (input.dirty.length) {
12194 v._renderer.render(s, input.dirty);
12195 }
12196
12197 if (input.dirty.length) {
12198 input.dirty.forEach(function(i) { i._dirty = false; });
12199 s.items[0]._dirty = false;
12200 }
12201
12202 // For all updated datasources, clear their previous values.
12203 for (var d in input.data) { v._model.data(d).synchronize(); }
12204 return input;
12205 };
12206
12207 return (v._model.scene(v._renderNode), true);
12208 }
12209
12210 prototype.update = function(opt) {
12211 opt = opt || {};
12212 var v = this,
12213 trans = opt.duration ? new Transition(opt.duration, opt.ease) : null;
12214
12215 var cs = v._changeset;
12216 if (trans) cs.trans = trans;
12217 if (opt.props !== undefined) {
12218 if (dl.keys(cs.data).length > 0) {
12219 throw Error(
12220 'New data values are not reflected in the visualization.' +
12221 ' Please call view.update() before updating a specified property set.'
12222 );
12223 }
12224
12225 cs.reflow = true;
12226 cs.request = opt.props;
12227 }
12228
12229 var built = v._build;
12230 v._build = v._build || build.call(this);
12231
12232 // If specific items are specified, short-circuit dataflow graph.
12233 // Else-If there are streaming updates, perform a targeted propagation.
12234 // Otherwise, reevaluate the entire model (datasources + scene).
12235 if (opt.items && built) {
12236 Encoder.update(this._model, opt.trans, opt.props, opt.items, cs.dirty);
12237 v._renderNode.evaluate(cs);
12238 } else if (v._streamer.listeners().length && built) {
12239 v._model.propagate(cs, v._streamer);
12240 v._streamer.disconnect();
12241 } else {
12242 v._model.fire(cs);
12243 }
12244
12245 v._changeset = df.ChangeSet.create();
12246
12247 return v.autopad(opt);
12248 };
12249
12250 prototype.toImageURL = function(type) {
12251 var v = this, Renderer;
12252
12253 // lookup appropriate renderer
12254 switch (type || 'png') {
12255 case 'canvas':
12256 case 'png':
12257 Renderer = sg.canvas.Renderer; break;
12258 case 'svg':
12259 Renderer = sg.svg.string.Renderer; break;
12260 default: throw Error('Unrecognized renderer type: ' + type);
12261 }
12262
12263 var retina = sg.canvas.Renderer.RETINA;
12264 sg.canvas.Renderer.RETINA = false; // ignore retina screen
12265
12266 // render the scenegraph
12267 var ren = new Renderer(v._model.config.load)
12268 .initialize(null, v._width, v._height, v._padding)
12269 .render(v._model.scene());
12270
12271 sg.canvas.Renderer.RETINA = retina; // restore retina settings
12272
12273 // return data url
12274 if (type === 'svg') {
12275 var blob = new Blob([ren.svg()], {type: 'image/svg+xml'});
12276 return window.URL.createObjectURL(blob);
12277 } else {
12278 return ren.canvas().toDataURL('image/png');
12279 }
12280 };
12281
12282 prototype.render = function(items) {
12283 this._renderer.render(this._model.scene(), items);
12284 return this;
12285 };
12286
12287 prototype.on = function() {
12288 this._handler.on.apply(this._handler, arguments);
12289 return this;
12290 };
12291
12292 prototype.onSignal = function(name, handler) {
12293 this._model.signal(name).on(handler);
12294 return this;
12295 };
12296
12297 prototype.off = function() {
12298 this._handler.off.apply(this._handler, arguments);
12299 return this;
12300 };
12301
12302 prototype.offSignal = function(name, handler) {
12303 this._model.signal(name).off(handler);
12304 return this;
12305 };
12306
12307 View.factory = function(model) {
12308 var HeadlessView = require('./HeadlessView');
12309 return function(opt) {
12310 opt = opt || {};
12311 var defs = model.defs();
12312 var v = (opt.el ? new View() : new HeadlessView())
12313 .model(model)
12314 .renderer(opt.renderer || 'canvas')
12315 .width(defs.width)
12316 .height(defs.height)
12317 .background(defs.background)
12318 .padding(defs.padding)
12319 .viewport(defs.viewport)
12320 .initialize(opt.el);
12321
12322 if (opt.data) v.data(opt.data);
12323
12324 if (opt.hover !== false && opt.el) {
12325 v.on('mouseover', function(evt, item) {
12326 if (item && item.hasPropertySet('hover')) {
12327 this.update({props:'hover', items:item});
12328 }
12329 })
12330 .on('mouseout', function(evt, item) {
12331 if (item && item.hasPropertySet('hover')) {
12332 this.update({props:'update', items:item});
12333 }
12334 });
12335 }
12336
12337 return v;
12338 };
12339 };
12340
12341 module.exports = View;
12342 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
12343
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){
12345 (function (global){
12346 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
12347 config = {};
12348
12349 config.load = {
12350 // base url for loading external data files
12351 // used only for server-side operation
12352 baseURL: '',
12353 // Allows domain restriction when using data loading via XHR.
12354 // To enable, set it to a list of allowed domains
12355 // e.g., ['wikipedia.org', 'eff.org']
12356 domainWhiteList: false
12357 };
12358
12359 // inset padding for automatic padding calculation
12360 config.autopadInset = 5;
12361
12362 // extensible scale lookup table
12363 // all d3.scale.* instances also supported
12364 config.scale = {
12365 time: d3.time.scale,
12366 utc: d3.time.scale.utc
12367 };
12368
12369 // default rendering settings
12370 config.render = {
12371 retina: true
12372 };
12373
12374 // default axis properties
12375 config.axis = {
12376 orient: 'bottom',
12377 ticks: 10,
12378 padding: 3,
12379 axisColor: '#000',
12380 gridColor: '#000',
12381 gridOpacity: 0.15,
12382 tickColor: '#000',
12383 tickLabelColor: '#000',
12384 axisWidth: 1,
12385 tickWidth: 1,
12386 tickSize: 6,
12387 tickLabelFontSize: 11,
12388 tickLabelFont: 'sans-serif',
12389 titleColor: '#000',
12390 titleFont: 'sans-serif',
12391 titleFontSize: 11,
12392 titleFontWeight: 'bold',
12393 titleOffset: 35
12394 };
12395
12396 // default legend properties
12397 config.legend = {
12398 orient: 'right',
12399 offset: 20,
12400 padding: 3,
12401 gradientStrokeColor: '#888',
12402 gradientStrokeWidth: 1,
12403 gradientHeight: 16,
12404 gradientWidth: 100,
12405 labelColor: '#000',
12406 labelFontSize: 10,
12407 labelFont: 'sans-serif',
12408 labelAlign: 'left',
12409 labelBaseline: 'middle',
12410 labelOffset: 8,
12411 symbolShape: 'circle',
12412 symbolSize: 50,
12413 symbolColor: '#888',
12414 symbolStrokeWidth: 1,
12415 titleColor: '#000',
12416 titleFont: 'sans-serif',
12417 titleFontSize: 11,
12418 titleFontWeight: 'bold'
12419 };
12420
12421 // default color values
12422 config.color = {
12423 rgb: [128, 128, 128],
12424 lab: [50, 0, 0],
12425 hcl: [0, 0, 50],
12426 hsl: [0, 0, 0.5]
12427 };
12428
12429 // default scale ranges
12430 config.range = {
12431 category10: d3.scale.category10().range(),
12432 category20: d3.scale.category20().range(),
12433 category20b: d3.scale.category20b().range(),
12434 category20c: d3.scale.category20c().range(),
12435 shapes: [
12436 'circle',
12437 'cross',
12438 'diamond',
12439 'square',
12440 'triangle-down',
12441 'triangle-up'
12442 ]
12443 };
12444
12445 module.exports = config;
12446 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
12447
12448 },{}],89:[function(require,module,exports){
12449 var dl = require('datalib'),
12450 parse = require('../parse'),
12451 Scale = require('../scene/Scale'),
12452 config = require('./config');
12453
12454 function compile(module, opt, schema) {
12455 var s = module.schema;
12456 if (!s) return;
12457 if (s.refs) dl.extend(schema.refs, s.refs);
12458 if (s.defs) dl.extend(schema.defs, s.defs);
12459 }
12460
12461 module.exports = function(opt) {
12462 var schema = null;
12463 opt = opt || {};
12464
12465 // Compile if we're not loading the schema from a URL.
12466 // Load from a URL to extend the existing base schema.
12467 if (opt.url) {
12468 schema = dl.json(dl.extend({url: opt.url}, config.load));
12469 } else {
12470 schema = {
12471 "$schema": "http://json-schema.org/draft-04/schema#",
12472 "title": "Vega Visualization Specification Language",
12473 "defs": {},
12474 "refs": {},
12475 "$ref": "#/defs/spec"
12476 };
12477
12478 dl.keys(parse).forEach(function(k) { compile(parse[k], opt, schema); });
12479
12480 // Scales aren't in the parser, add schema manually
12481 compile(Scale, opt, schema);
12482 }
12483
12484 // Extend schema to support custom mark properties or property sets.
12485 if (opt.properties) dl.keys(opt.properties).forEach(function(k) {
12486 schema.defs.propset.properties[k] = {"$ref": "#/refs/"+opt.properties[k]+"Value"};
12487 });
12488
12489 if (opt.propertySets) dl.keys(opt.propertySets).forEach(function(k) {
12490 schema.defs.mark.properties.properties.properties[k] = {"$ref": "#/defs/propset"};
12491 });
12492
12493 return schema;
12494 };
12495 },{"../parse":95,"../scene/Scale":111,"./config":88,"datalib":24}],90:[function(require,module,exports){
12496 var dl = require('datalib'),
12497 axs = require('../scene/axis');
12498
12499 var ORIENT = {
12500 "x": "bottom",
12501 "y": "left",
12502 "top": "top",
12503 "bottom": "bottom",
12504 "left": "left",
12505 "right": "right"
12506 };
12507
12508 function parseAxes(model, spec, axes, group) {
12509 var config = model.config();
12510 (spec || []).forEach(function(def, index) {
12511 axes[index] = axes[index] || axs(model);
12512 parseAxis(config, def, index, axes[index], group);
12513 });
12514 }
12515
12516 function parseAxis(config, def, index, axis, group) {
12517 // axis scale
12518 if (def.scale !== undefined) {
12519 axis.scale(group.scale(def.scale));
12520 }
12521
12522 // axis orientation
12523 axis.orient(def.orient || ORIENT[def.type]);
12524 // axis offset
12525 axis.offset(def.offset || 0);
12526 // axis layer
12527 axis.layer(def.layer || "front");
12528 // axis grid lines
12529 axis.grid(def.grid || false);
12530 // axis title
12531 axis.title(def.title || null);
12532 // axis title offset
12533 axis.titleOffset(def.titleOffset != null ?
12534 def.titleOffset : config.axis.titleOffset);
12535 // axis values
12536 axis.tickValues(def.values || null);
12537 // axis label formatting
12538 axis.tickFormat(def.format || null);
12539 axis.tickFormatType(def.formatType || null);
12540 // axis tick subdivision
12541 axis.tickSubdivide(def.subdivide || 0);
12542 // axis tick padding
12543 axis.tickPadding(def.tickPadding || config.axis.padding);
12544
12545 // axis tick size(s)
12546 var size = [];
12547 if (def.tickSize !== undefined) {
12548 for (var i=0; i<3; ++i) size.push(def.tickSize);
12549 } else {
12550 var ts = config.axis.tickSize;
12551 size = [ts, ts, ts];
12552 }
12553 if (def.tickSizeMajor != null) size[0] = def.tickSizeMajor;
12554 if (def.tickSizeMinor != null) size[1] = def.tickSizeMinor;
12555 if (def.tickSizeEnd != null) size[2] = def.tickSizeEnd;
12556 if (size.length) {
12557 axis.tickSize.apply(axis, size);
12558 }
12559
12560 // axis tick count
12561 axis.tickCount(def.ticks || config.axis.ticks);
12562
12563 // style properties
12564 var p = def.properties;
12565 if (p && p.ticks) {
12566 axis.majorTickProperties(p.majorTicks ?
12567 dl.extend({}, p.ticks, p.majorTicks) : p.ticks);
12568 axis.minorTickProperties(p.minorTicks ?
12569 dl.extend({}, p.ticks, p.minorTicks) : p.ticks);
12570 } else {
12571 axis.majorTickProperties(p && p.majorTicks || {});
12572 axis.minorTickProperties(p && p.minorTicks || {});
12573 }
12574 axis.tickLabelProperties(p && p.labels || {});
12575 axis.titleProperties(p && p.title || {});
12576 axis.gridLineProperties(p && p.grid || {});
12577 axis.domainProperties(p && p.axis || {});
12578 }
12579
12580 module.exports = parseAxes;
12581 },{"../scene/axis":113,"datalib":24}],91:[function(require,module,exports){
12582 (function (global){
12583 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null);
12584
12585 function parseBg(bg) {
12586 // return null if input is null or undefined
12587 if (bg == null) return null;
12588 // run through d3 rgb to sanity check
12589 return d3.rgb(bg) + "";
12590 }
12591
12592 module.exports = parseBg;
12593 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
12594
12595 },{}],92:[function(require,module,exports){
12596 var dl = require('datalib'),
12597 log = require('vega-logging'),
12598 parseTransforms = require('./transforms'),
12599 parseModify = require('./modify');
12600
12601 function parseData(model, spec, callback) {
12602 var config = model.config(),
12603 count = 0;
12604
12605 function loaded(d) {
12606 return function(error, data) {
12607 if (error) {
12608 log.error('LOADING FAILED: ' + d.url + ' ' + error);
12609 } else {
12610 model.data(d.name).values(dl.read(data, d.format));
12611 }
12612 if (--count === 0) callback();
12613 };
12614 }
12615
12616 // process each data set definition
12617 (spec || []).forEach(function(d) {
12618 if (d.url) {
12619 count += 1;
12620 dl.load(dl.extend({url: d.url}, config.load), loaded(d));
12621 }
12622 parseData.datasource(model, d);
12623 });
12624
12625 if (count === 0) setTimeout(callback, 1);
12626 return spec;
12627 }
12628
12629 parseData.datasource = function(model, d) {
12630 var transform = (d.transform || []).map(function(t) {
12631 return parseTransforms(model, t);
12632 }),
12633 mod = (d.modify || []).map(function(m) {
12634 return parseModify(model, m, d);
12635 }),
12636 ds = model.data(d.name, mod.concat(transform));
12637
12638 if (d.values) {
12639 ds.values(dl.read(d.values, d.format));
12640 } else if (d.source) {
12641 // Derived ds will be pulsed by its src rather than the model.
12642 ds.source(d.source).addListener(ds);
12643 model.removeListener(ds.pipeline()[0]);
12644 }
12645
12646 return ds;
12647 };
12648
12649 module.exports = parseData;
12650 },{"./modify":99,"./transforms":106,"datalib":24,"vega-logging":45}],93:[function(require,module,exports){
12651 module.exports = (function() {
12652 /*
12653 * Generated by PEG.js 0.8.0.
12654 *
12655 * http://pegjs.majda.cz/
12656 */
12657
12658 function peg$subclass(child, parent) {
12659 function ctor() { this.constructor = child; }
12660 ctor.prototype = parent.prototype;
12661 child.prototype = new ctor();
12662 }
12663
12664 function SyntaxError(message, expected, found, offset, line, column) {
12665 this.message = message;
12666 this.expected = expected;
12667 this.found = found;
12668 this.offset = offset;
12669 this.line = line;
12670 this.column = column;
12671
12672 this.name = "SyntaxError";
12673 }
12674
12675 peg$subclass(SyntaxError, Error);
12676
12677 function parse(input) {
12678 var options = arguments.length > 1 ? arguments[1] : {},
12679
12680 peg$FAILED = {},
12681
12682 peg$startRuleFunctions = { start: peg$parsestart },
12683 peg$startRuleFunction = peg$parsestart,
12684
12685 peg$c0 = peg$FAILED,
12686 peg$c1 = ",",
12687 peg$c2 = { type: "literal", value: ",", description: "\",\"" },
12688 peg$c3 = function(o, m) { return [o].concat(m); },
12689 peg$c4 = function(o) { return [o]; },
12690 peg$c5 = "[",
12691 peg$c6 = { type: "literal", value: "[", description: "\"[\"" },
12692 peg$c7 = "]",
12693 peg$c8 = { type: "literal", value: "]", description: "\"]\"" },
12694 peg$c9 = ">",
12695 peg$c10 = { type: "literal", value: ">", description: "\">\"" },
12696 peg$c11 = function(f1, f2, o) { return {start: f1, end: f2, middle: o}; },
12697 peg$c12 = [],
12698 peg$c13 = function(s, f) { return (s.filters = f, s); },
12699 peg$c14 = function(s) { return s; },
12700 peg$c15 = "(",
12701 peg$c16 = { type: "literal", value: "(", description: "\"(\"" },
12702 peg$c17 = ")",
12703 peg$c18 = { type: "literal", value: ")", description: "\")\"" },
12704 peg$c19 = function(m) { return {stream: m}; },
12705 peg$c20 = "@",
12706 peg$c21 = { type: "literal", value: "@", description: "\"@\"" },
12707 peg$c22 = ":",
12708 peg$c23 = { type: "literal", value: ":", description: "\":\"" },
12709 peg$c24 = function(n, e) { return {event: e, name: n}; },
12710 peg$c25 = function(m, e) { return {event: e, mark: m}; },
12711 peg$c26 = function(t, e) { return {event: e, target: t}; },
12712 peg$c27 = function(e) { return {event: e}; },
12713 peg$c28 = function(s) { return {signal: s}; },
12714 peg$c29 = "rect",
12715 peg$c30 = { type: "literal", value: "rect", description: "\"rect\"" },
12716 peg$c31 = "symbol",
12717 peg$c32 = { type: "literal", value: "symbol", description: "\"symbol\"" },
12718 peg$c33 = "path",
12719 peg$c34 = { type: "literal", value: "path", description: "\"path\"" },
12720 peg$c35 = "arc",
12721 peg$c36 = { type: "literal", value: "arc", description: "\"arc\"" },
12722 peg$c37 = "area",
12723 peg$c38 = { type: "literal", value: "area", description: "\"area\"" },
12724 peg$c39 = "line",
12725 peg$c40 = { type: "literal", value: "line", description: "\"line\"" },
12726 peg$c41 = "rule",
12727 peg$c42 = { type: "literal", value: "rule", description: "\"rule\"" },
12728 peg$c43 = "image",
12729 peg$c44 = { type: "literal", value: "image", description: "\"image\"" },
12730 peg$c45 = "text",
12731 peg$c46 = { type: "literal", value: "text", description: "\"text\"" },
12732 peg$c47 = "group",
12733 peg$c48 = { type: "literal", value: "group", description: "\"group\"" },
12734 peg$c49 = "mousedown",
12735 peg$c50 = { type: "literal", value: "mousedown", description: "\"mousedown\"" },
12736 peg$c51 = "mouseup",
12737 peg$c52 = { type: "literal", value: "mouseup", description: "\"mouseup\"" },
12738 peg$c53 = "click",
12739 peg$c54 = { type: "literal", value: "click", description: "\"click\"" },
12740 peg$c55 = "dblclick",
12741 peg$c56 = { type: "literal", value: "dblclick", description: "\"dblclick\"" },
12742 peg$c57 = "wheel",
12743 peg$c58 = { type: "literal", value: "wheel", description: "\"wheel\"" },
12744 peg$c59 = "keydown",
12745 peg$c60 = { type: "literal", value: "keydown", description: "\"keydown\"" },
12746 peg$c61 = "keypress",
12747 peg$c62 = { type: "literal", value: "keypress", description: "\"keypress\"" },
12748 peg$c63 = "keyup",
12749 peg$c64 = { type: "literal", value: "keyup", description: "\"keyup\"" },
12750 peg$c65 = "mousewheel",
12751 peg$c66 = { type: "literal", value: "mousewheel", description: "\"mousewheel\"" },
12752 peg$c67 = "mousemove",
12753 peg$c68 = { type: "literal", value: "mousemove", description: "\"mousemove\"" },
12754 peg$c69 = "mouseout",
12755 peg$c70 = { type: "literal", value: "mouseout", description: "\"mouseout\"" },
12756 peg$c71 = "mouseover",
12757 peg$c72 = { type: "literal", value: "mouseover", description: "\"mouseover\"" },
12758 peg$c73 = "mouseenter",
12759 peg$c74 = { type: "literal", value: "mouseenter", description: "\"mouseenter\"" },
12760 peg$c75 = "touchstart",
12761 peg$c76 = { type: "literal", value: "touchstart", description: "\"touchstart\"" },
12762 peg$c77 = "touchmove",
12763 peg$c78 = { type: "literal", value: "touchmove", description: "\"touchmove\"" },
12764 peg$c79 = "touchend",
12765 peg$c80 = { type: "literal", value: "touchend", description: "\"touchend\"" },
12766 peg$c81 = function(e) { return e; },
12767 peg$c82 = /^[a-zA-Z0-9_\-]/,
12768 peg$c83 = { type: "class", value: "[a-zA-Z0-9_\\-]", description: "[a-zA-Z0-9_\\-]" },
12769 peg$c84 = function(n) { return n.join(""); },
12770 peg$c85 = /^[a-zA-Z0-9\-_ #.>+~[\]=|\^$*]/,
12771 peg$c86 = { type: "class", value: "[a-zA-Z0-9\\-_ #.>+~[\\]=|\\^$*]", description: "[a-zA-Z0-9\\-_ #.>+~[\\]=|\\^$*]" },
12772 peg$c87 = function(c) { return c.join(""); },
12773 peg$c88 = /^['"a-zA-Z0-9_().><=! \t-&|~]/,
12774 peg$c89 = { type: "class", value: "['\"a-zA-Z0-9_().><=! \\t-&|~]", description: "['\"a-zA-Z0-9_().><=! \\t-&|~]" },
12775 peg$c90 = function(v) { return v.join(""); },
12776 peg$c91 = /^[ \t\r\n]/,
12777 peg$c92 = { type: "class", value: "[ \\t\\r\\n]", description: "[ \\t\\r\\n]" },
12778
12779 peg$currPos = 0,
12780 peg$reportedPos = 0,
12781 peg$cachedPos = 0,
12782 peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
12783 peg$maxFailPos = 0,
12784 peg$maxFailExpected = [],
12785 peg$silentFails = 0,
12786
12787 peg$result;
12788
12789 if ("startRule" in options) {
12790 if (!(options.startRule in peg$startRuleFunctions)) {
12791 throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
12792 }
12793
12794 peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
12795 }
12796
12797 function text() {
12798 return input.substring(peg$reportedPos, peg$currPos);
12799 }
12800
12801 function offset() {
12802 return peg$reportedPos;
12803 }
12804
12805 function line() {
12806 return peg$computePosDetails(peg$reportedPos).line;
12807 }
12808
12809 function column() {
12810 return peg$computePosDetails(peg$reportedPos).column;
12811 }
12812
12813 function expected(description) {
12814 throw peg$buildException(
12815 null,
12816 [{ type: "other", description: description }],
12817 peg$reportedPos
12818 );
12819 }
12820
12821 function error(message) {
12822 throw peg$buildException(message, null, peg$reportedPos);
12823 }
12824
12825 function peg$computePosDetails(pos) {
12826 function advance(details, startPos, endPos) {
12827 var p, ch;
12828
12829 for (p = startPos; p < endPos; p++) {
12830 ch = input.charAt(p);
12831 if (ch === "\n") {
12832 if (!details.seenCR) { details.line++; }
12833 details.column = 1;
12834 details.seenCR = false;
12835 } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
12836 details.line++;
12837 details.column = 1;
12838 details.seenCR = true;
12839 } else {
12840 details.column++;
12841 details.seenCR = false;
12842 }
12843 }
12844 }
12845
12846 if (peg$cachedPos !== pos) {
12847 if (peg$cachedPos > pos) {
12848 peg$cachedPos = 0;
12849 peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
12850 }
12851 advance(peg$cachedPosDetails, peg$cachedPos, pos);
12852 peg$cachedPos = pos;
12853 }
12854
12855 return peg$cachedPosDetails;
12856 }
12857
12858 function peg$fail(expected) {
12859 if (peg$currPos < peg$maxFailPos) { return; }
12860
12861 if (peg$currPos > peg$maxFailPos) {
12862 peg$maxFailPos = peg$currPos;
12863 peg$maxFailExpected = [];
12864 }
12865
12866 peg$maxFailExpected.push(expected);
12867 }
12868
12869 function peg$buildException(message, expected, pos) {
12870 function cleanupExpected(expected) {
12871 var i = 1;
12872
12873 expected.sort(function(a, b) {
12874 if (a.description < b.description) {
12875 return -1;
12876 } else if (a.description > b.description) {
12877 return 1;
12878 } else {
12879 return 0;
12880 }
12881 });
12882
12883 while (i < expected.length) {
12884 if (expected[i - 1] === expected[i]) {
12885 expected.splice(i, 1);
12886 } else {
12887 i++;
12888 }
12889 }
12890 }
12891
12892 function buildMessage(expected, found) {
12893 function stringEscape(s) {
12894 function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
12895
12896 return s
12897 .replace(/\\/g, '\\\\')
12898 .replace(/"/g, '\\"')
12899 .replace(/\x08/g, '\\b')
12900 .replace(/\t/g, '\\t')
12901 .replace(/\n/g, '\\n')
12902 .replace(/\f/g, '\\f')
12903 .replace(/\r/g, '\\r')
12904 .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
12905 .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
12906 .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
12907 .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
12908 }
12909
12910 var expectedDescs = new Array(expected.length),
12911 expectedDesc, foundDesc, i;
12912
12913 for (i = 0; i < expected.length; i++) {
12914 expectedDescs[i] = expected[i].description;
12915 }
12916
12917 expectedDesc = expected.length > 1
12918 ? expectedDescs.slice(0, -1).join(", ")
12919 + " or "
12920 + expectedDescs[expected.length - 1]
12921 : expectedDescs[0];
12922
12923 foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
12924
12925 return "Expected " + expectedDesc + " but " + foundDesc + " found.";
12926 }
12927
12928 var posDetails = peg$computePosDetails(pos),
12929 found = pos < input.length ? input.charAt(pos) : null;
12930
12931 if (expected !== null) {
12932 cleanupExpected(expected);
12933 }
12934
12935 return new SyntaxError(
12936 message !== null ? message : buildMessage(expected, found),
12937 expected,
12938 found,
12939 pos,
12940 posDetails.line,
12941 posDetails.column
12942 );
12943 }
12944
12945 function peg$parsestart() {
12946 var s0;
12947
12948 s0 = peg$parsemerged();
12949
12950 return s0;
12951 }
12952
12953 function peg$parsemerged() {
12954 var s0, s1, s2, s3, s4, s5;
12955
12956 s0 = peg$currPos;
12957 s1 = peg$parseordered();
12958 if (s1 !== peg$FAILED) {
12959 s2 = peg$parsesep();
12960 if (s2 !== peg$FAILED) {
12961 if (input.charCodeAt(peg$currPos) === 44) {
12962 s3 = peg$c1;
12963 peg$currPos++;
12964 } else {
12965 s3 = peg$FAILED;
12966 if (peg$silentFails === 0) { peg$fail(peg$c2); }
12967 }
12968 if (s3 !== peg$FAILED) {
12969 s4 = peg$parsesep();
12970 if (s4 !== peg$FAILED) {
12971 s5 = peg$parsemerged();
12972 if (s5 !== peg$FAILED) {
12973 peg$reportedPos = s0;
12974 s1 = peg$c3(s1, s5);
12975 s0 = s1;
12976 } else {
12977 peg$currPos = s0;
12978 s0 = peg$c0;
12979 }
12980 } else {
12981 peg$currPos = s0;
12982 s0 = peg$c0;
12983 }
12984 } else {
12985 peg$currPos = s0;
12986 s0 = peg$c0;
12987 }
12988 } else {
12989 peg$currPos = s0;
12990 s0 = peg$c0;
12991 }
12992 } else {
12993 peg$currPos = s0;
12994 s0 = peg$c0;
12995 }
12996 if (s0 === peg$FAILED) {
12997 s0 = peg$currPos;
12998 s1 = peg$parseordered();
12999 if (s1 !== peg$FAILED) {
13000 peg$reportedPos = s0;
13001 s1 = peg$c4(s1);
13002 }
13003 s0 = s1;
13004 }
13005
13006 return s0;
13007 }
13008
13009 function peg$parseordered() {
13010 var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
13011
13012 s0 = peg$currPos;
13013 if (input.charCodeAt(peg$currPos) === 91) {
13014 s1 = peg$c5;
13015 peg$currPos++;
13016 } else {
13017 s1 = peg$FAILED;
13018 if (peg$silentFails === 0) { peg$fail(peg$c6); }
13019 }
13020 if (s1 !== peg$FAILED) {
13021 s2 = peg$parsesep();
13022 if (s2 !== peg$FAILED) {
13023 s3 = peg$parsefiltered();
13024 if (s3 !== peg$FAILED) {
13025 s4 = peg$parsesep();
13026 if (s4 !== peg$FAILED) {
13027 if (input.charCodeAt(peg$currPos) === 44) {
13028 s5 = peg$c1;
13029 peg$currPos++;
13030 } else {
13031 s5 = peg$FAILED;
13032 if (peg$silentFails === 0) { peg$fail(peg$c2); }
13033 }
13034 if (s5 !== peg$FAILED) {
13035 s6 = peg$parsesep();
13036 if (s6 !== peg$FAILED) {
13037 s7 = peg$parsefiltered();
13038 if (s7 !== peg$FAILED) {
13039 s8 = peg$parsesep();
13040 if (s8 !== peg$FAILED) {
13041 if (input.charCodeAt(peg$currPos) === 93) {
13042 s9 = peg$c7;
13043 peg$currPos++;
13044 } else {
13045 s9 = peg$FAILED;
13046 if (peg$silentFails === 0) { peg$fail(peg$c8); }
13047 }
13048 if (s9 !== peg$FAILED) {
13049 s10 = peg$parsesep();
13050 if (s10 !== peg$FAILED) {
13051 if (input.charCodeAt(peg$currPos) === 62) {
13052 s11 = peg$c9;
13053 peg$currPos++;
13054 } else {
13055 s11 = peg$FAILED;
13056 if (peg$silentFails === 0) { peg$fail(peg$c10); }
13057 }
13058 if (s11 !== peg$FAILED) {
13059 s12 = peg$parsesep();
13060 if (s12 !== peg$FAILED) {
13061 s13 = peg$parseordered();
13062 if (s13 !== peg$FAILED) {
13063 peg$reportedPos = s0;
13064 s1 = peg$c11(s3, s7, s13);
13065 s0 = s1;
13066 } else {
13067 peg$currPos = s0;
13068 s0 = peg$c0;
13069 }
13070 } else {
13071 peg$currPos = s0;
13072 s0 = peg$c0;
13073 }
13074 } else {
13075 peg$currPos = s0;
13076 s0 = peg$c0;
13077 }
13078 } else {
13079 peg$currPos = s0;
13080 s0 = peg$c0;
13081 }
13082 } else {
13083 peg$currPos = s0;
13084 s0 = peg$c0;
13085 }
13086 } else {
13087 peg$currPos = s0;
13088 s0 = peg$c0;
13089 }
13090 } else {
13091 peg$currPos = s0;
13092 s0 = peg$c0;
13093 }
13094 } else {
13095 peg$currPos = s0;
13096 s0 = peg$c0;
13097 }
13098 } else {
13099 peg$currPos = s0;
13100 s0 = peg$c0;
13101 }
13102 } else {
13103 peg$currPos = s0;
13104 s0 = peg$c0;
13105 }
13106 } else {
13107 peg$currPos = s0;
13108 s0 = peg$c0;
13109 }
13110 } else {
13111 peg$currPos = s0;
13112 s0 = peg$c0;
13113 }
13114 } else {
13115 peg$currPos = s0;
13116 s0 = peg$c0;
13117 }
13118 if (s0 === peg$FAILED) {
13119 s0 = peg$parsefiltered();
13120 }
13121
13122 return s0;
13123 }
13124
13125 function peg$parsefiltered() {
13126 var s0, s1, s2, s3;
13127
13128 s0 = peg$currPos;
13129 s1 = peg$parsestream();
13130 if (s1 !== peg$FAILED) {
13131 s2 = [];
13132 s3 = peg$parsefilter();
13133 if (s3 !== peg$FAILED) {
13134 while (s3 !== peg$FAILED) {
13135 s2.push(s3);
13136 s3 = peg$parsefilter();
13137 }
13138 } else {
13139 s2 = peg$c0;
13140 }
13141 if (s2 !== peg$FAILED) {
13142 peg$reportedPos = s0;
13143 s1 = peg$c13(s1, s2);
13144 s0 = s1;
13145 } else {
13146 peg$currPos = s0;
13147 s0 = peg$c0;
13148 }
13149 } else {
13150 peg$currPos = s0;
13151 s0 = peg$c0;
13152 }
13153 if (s0 === peg$FAILED) {
13154 s0 = peg$currPos;
13155 s1 = peg$parsestream();
13156 if (s1 !== peg$FAILED) {
13157 peg$reportedPos = s0;
13158 s1 = peg$c14(s1);
13159 }
13160 s0 = s1;
13161 }
13162
13163 return s0;
13164 }
13165
13166 function peg$parsestream() {
13167 var s0, s1, s2, s3, s4;
13168
13169 s0 = peg$currPos;
13170 if (input.charCodeAt(peg$currPos) === 40) {
13171 s1 = peg$c15;
13172 peg$currPos++;
13173 } else {
13174 s1 = peg$FAILED;
13175 if (peg$silentFails === 0) { peg$fail(peg$c16); }
13176 }
13177 if (s1 !== peg$FAILED) {
13178 s2 = peg$parsemerged();
13179 if (s2 !== peg$FAILED) {
13180 if (input.charCodeAt(peg$currPos) === 41) {
13181 s3 = peg$c17;
13182 peg$currPos++;
13183 } else {
13184 s3 = peg$FAILED;
13185 if (peg$silentFails === 0) { peg$fail(peg$c18); }
13186 }
13187 if (s3 !== peg$FAILED) {
13188 peg$reportedPos = s0;
13189 s1 = peg$c19(s2);
13190 s0 = s1;
13191 } else {
13192 peg$currPos = s0;
13193 s0 = peg$c0;
13194 }
13195 } else {
13196 peg$currPos = s0;
13197 s0 = peg$c0;
13198 }
13199 } else {
13200 peg$currPos = s0;
13201 s0 = peg$c0;
13202 }
13203 if (s0 === peg$FAILED) {
13204 s0 = peg$currPos;
13205 if (input.charCodeAt(peg$currPos) === 64) {
13206 s1 = peg$c20;
13207 peg$currPos++;
13208 } else {
13209 s1 = peg$FAILED;
13210 if (peg$silentFails === 0) { peg$fail(peg$c21); }
13211 }
13212 if (s1 !== peg$FAILED) {
13213 s2 = peg$parsename();
13214 if (s2 !== peg$FAILED) {
13215 if (input.charCodeAt(peg$currPos) === 58) {
13216 s3 = peg$c22;
13217 peg$currPos++;
13218 } else {
13219 s3 = peg$FAILED;
13220 if (peg$silentFails === 0) { peg$fail(peg$c23); }
13221 }
13222 if (s3 !== peg$FAILED) {
13223 s4 = peg$parseeventType();
13224 if (s4 !== peg$FAILED) {
13225 peg$reportedPos = s0;
13226 s1 = peg$c24(s2, s4);
13227 s0 = s1;
13228 } else {
13229 peg$currPos = s0;
13230 s0 = peg$c0;
13231 }
13232 } else {
13233 peg$currPos = s0;
13234 s0 = peg$c0;
13235 }
13236 } else {
13237 peg$currPos = s0;
13238 s0 = peg$c0;
13239 }
13240 } else {
13241 peg$currPos = s0;
13242 s0 = peg$c0;
13243 }
13244 if (s0 === peg$FAILED) {
13245 s0 = peg$currPos;
13246 s1 = peg$parsemarkType();
13247 if (s1 !== peg$FAILED) {
13248 if (input.charCodeAt(peg$currPos) === 58) {
13249 s2 = peg$c22;
13250 peg$currPos++;
13251 } else {
13252 s2 = peg$FAILED;
13253 if (peg$silentFails === 0) { peg$fail(peg$c23); }
13254 }
13255 if (s2 !== peg$FAILED) {
13256 s3 = peg$parseeventType();
13257 if (s3 !== peg$FAILED) {
13258 peg$reportedPos = s0;
13259 s1 = peg$c25(s1, s3);
13260 s0 = s1;
13261 } else {
13262 peg$currPos = s0;
13263 s0 = peg$c0;
13264 }
13265 } else {
13266 peg$currPos = s0;
13267 s0 = peg$c0;
13268 }
13269 } else {
13270 peg$currPos = s0;
13271 s0 = peg$c0;
13272 }
13273 if (s0 === peg$FAILED) {
13274 s0 = peg$currPos;
13275 s1 = peg$parsecss();
13276 if (s1 !== peg$FAILED) {
13277 if (input.charCodeAt(peg$currPos) === 58) {
13278 s2 = peg$c22;
13279 peg$currPos++;
13280 } else {
13281 s2 = peg$FAILED;
13282 if (peg$silentFails === 0) { peg$fail(peg$c23); }
13283 }
13284 if (s2 !== peg$FAILED) {
13285 s3 = peg$parseeventType();
13286 if (s3 !== peg$FAILED) {
13287 peg$reportedPos = s0;
13288 s1 = peg$c26(s1, s3);
13289 s0 = s1;
13290 } else {
13291 peg$currPos = s0;
13292 s0 = peg$c0;
13293 }
13294 } else {
13295 peg$currPos = s0;
13296 s0 = peg$c0;
13297 }
13298 } else {
13299 peg$currPos = s0;
13300 s0 = peg$c0;
13301 }
13302 if (s0 === peg$FAILED) {
13303 s0 = peg$currPos;
13304 s1 = peg$parseeventType();
13305 if (s1 !== peg$FAILED) {
13306 peg$reportedPos = s0;
13307 s1 = peg$c27(s1);
13308 }
13309 s0 = s1;
13310 if (s0 === peg$FAILED) {
13311 s0 = peg$currPos;
13312 s1 = peg$parsename();
13313 if (s1 !== peg$FAILED) {
13314 peg$reportedPos = s0;
13315 s1 = peg$c28(s1);
13316 }
13317 s0 = s1;
13318 }
13319 }
13320 }
13321 }
13322 }
13323
13324 return s0;
13325 }
13326
13327 function peg$parsemarkType() {
13328 var s0;
13329
13330 if (input.substr(peg$currPos, 4) === peg$c29) {
13331 s0 = peg$c29;
13332 peg$currPos += 4;
13333 } else {
13334 s0 = peg$FAILED;
13335 if (peg$silentFails === 0) { peg$fail(peg$c30); }
13336 }
13337 if (s0 === peg$FAILED) {
13338 if (input.substr(peg$currPos, 6) === peg$c31) {
13339 s0 = peg$c31;
13340 peg$currPos += 6;
13341 } else {
13342 s0 = peg$FAILED;
13343 if (peg$silentFails === 0) { peg$fail(peg$c32); }
13344 }
13345 if (s0 === peg$FAILED) {
13346 if (input.substr(peg$currPos, 4) === peg$c33) {
13347 s0 = peg$c33;
13348 peg$currPos += 4;
13349 } else {
13350 s0 = peg$FAILED;
13351 if (peg$silentFails === 0) { peg$fail(peg$c34); }
13352 }
13353 if (s0 === peg$FAILED) {
13354 if (input.substr(peg$currPos, 3) === peg$c35) {
13355 s0 = peg$c35;
13356 peg$currPos += 3;
13357 } else {
13358 s0 = peg$FAILED;
13359 if (peg$silentFails === 0) { peg$fail(peg$c36); }
13360 }
13361 if (s0 === peg$FAILED) {
13362 if (input.substr(peg$currPos, 4) === peg$c37) {
13363 s0 = peg$c37;
13364 peg$currPos += 4;
13365 } else {
13366 s0 = peg$FAILED;
13367 if (peg$silentFails === 0) { peg$fail(peg$c38); }
13368 }
13369 if (s0 === peg$FAILED) {
13370 if (input.substr(peg$currPos, 4) === peg$c39) {
13371 s0 = peg$c39;
13372 peg$currPos += 4;
13373 } else {
13374 s0 = peg$FAILED;
13375 if (peg$silentFails === 0) { peg$fail(peg$c40); }
13376 }
13377 if (s0 === peg$FAILED) {
13378 if (input.substr(peg$currPos, 4) === peg$c41) {
13379 s0 = peg$c41;
13380 peg$currPos += 4;
13381 } else {
13382 s0 = peg$FAILED;
13383 if (peg$silentFails === 0) { peg$fail(peg$c42); }
13384 }
13385 if (s0 === peg$FAILED) {
13386 if (input.substr(peg$currPos, 5) === peg$c43) {
13387 s0 = peg$c43;
13388 peg$currPos += 5;
13389 } else {
13390 s0 = peg$FAILED;
13391 if (peg$silentFails === 0) { peg$fail(peg$c44); }
13392 }
13393 if (s0 === peg$FAILED) {
13394 if (input.substr(peg$currPos, 4) === peg$c45) {
13395 s0 = peg$c45;
13396 peg$currPos += 4;
13397 } else {
13398 s0 = peg$FAILED;
13399 if (peg$silentFails === 0) { peg$fail(peg$c46); }
13400 }
13401 if (s0 === peg$FAILED) {
13402 if (input.substr(peg$currPos, 5) === peg$c47) {
13403 s0 = peg$c47;
13404 peg$currPos += 5;
13405 } else {
13406 s0 = peg$FAILED;
13407 if (peg$silentFails === 0) { peg$fail(peg$c48); }
13408 }
13409 }
13410 }
13411 }
13412 }
13413 }
13414 }
13415 }
13416 }
13417 }
13418
13419 return s0;
13420 }
13421
13422 function peg$parseeventType() {
13423 var s0;
13424
13425 if (input.substr(peg$currPos, 9) === peg$c49) {
13426 s0 = peg$c49;
13427 peg$currPos += 9;
13428 } else {
13429 s0 = peg$FAILED;
13430 if (peg$silentFails === 0) { peg$fail(peg$c50); }
13431 }
13432 if (s0 === peg$FAILED) {
13433 if (input.substr(peg$currPos, 7) === peg$c51) {
13434 s0 = peg$c51;
13435 peg$currPos += 7;
13436 } else {
13437 s0 = peg$FAILED;
13438 if (peg$silentFails === 0) { peg$fail(peg$c52); }
13439 }
13440 if (s0 === peg$FAILED) {
13441 if (input.substr(peg$currPos, 5) === peg$c53) {
13442 s0 = peg$c53;
13443 peg$currPos += 5;
13444 } else {
13445 s0 = peg$FAILED;
13446 if (peg$silentFails === 0) { peg$fail(peg$c54); }
13447 }
13448 if (s0 === peg$FAILED) {
13449 if (input.substr(peg$currPos, 8) === peg$c55) {
13450 s0 = peg$c55;
13451 peg$currPos += 8;
13452 } else {
13453 s0 = peg$FAILED;
13454 if (peg$silentFails === 0) { peg$fail(peg$c56); }
13455 }
13456 if (s0 === peg$FAILED) {
13457 if (input.substr(peg$currPos, 5) === peg$c57) {
13458 s0 = peg$c57;
13459 peg$currPos += 5;
13460 } else {
13461 s0 = peg$FAILED;
13462 if (peg$silentFails === 0) { peg$fail(peg$c58); }
13463 }
13464 if (s0 === peg$FAILED) {
13465 if (input.substr(peg$currPos, 7) === peg$c59) {
13466 s0 = peg$c59;
13467 peg$currPos += 7;
13468 } else {
13469 s0 = peg$FAILED;
13470 if (peg$silentFails === 0) { peg$fail(peg$c60); }
13471 }
13472 if (s0 === peg$FAILED) {
13473 if (input.substr(peg$currPos, 8) === peg$c61) {
13474 s0 = peg$c61;
13475 peg$currPos += 8;
13476 } else {
13477 s0 = peg$FAILED;
13478 if (peg$silentFails === 0) { peg$fail(peg$c62); }
13479 }
13480 if (s0 === peg$FAILED) {
13481 if (input.substr(peg$currPos, 5) === peg$c63) {
13482 s0 = peg$c63;
13483 peg$currPos += 5;
13484 } else {
13485 s0 = peg$FAILED;
13486 if (peg$silentFails === 0) { peg$fail(peg$c64); }
13487 }
13488 if (s0 === peg$FAILED) {
13489 if (input.substr(peg$currPos, 10) === peg$c65) {
13490 s0 = peg$c65;
13491 peg$currPos += 10;
13492 } else {
13493 s0 = peg$FAILED;
13494 if (peg$silentFails === 0) { peg$fail(peg$c66); }
13495 }
13496 if (s0 === peg$FAILED) {
13497 if (input.substr(peg$currPos, 9) === peg$c67) {
13498 s0 = peg$c67;
13499 peg$currPos += 9;
13500 } else {
13501 s0 = peg$FAILED;
13502 if (peg$silentFails === 0) { peg$fail(peg$c68); }
13503 }
13504 if (s0 === peg$FAILED) {
13505 if (input.substr(peg$currPos, 8) === peg$c69) {
13506 s0 = peg$c69;
13507 peg$currPos += 8;
13508 } else {
13509 s0 = peg$FAILED;
13510 if (peg$silentFails === 0) { peg$fail(peg$c70); }
13511 }
13512 if (s0 === peg$FAILED) {
13513 if (input.substr(peg$currPos, 9) === peg$c71) {
13514 s0 = peg$c71;
13515 peg$currPos += 9;
13516 } else {
13517 s0 = peg$FAILED;
13518 if (peg$silentFails === 0) { peg$fail(peg$c72); }
13519 }
13520 if (s0 === peg$FAILED) {
13521 if (input.substr(peg$currPos, 10) === peg$c73) {
13522 s0 = peg$c73;
13523 peg$currPos += 10;
13524 } else {
13525 s0 = peg$FAILED;
13526 if (peg$silentFails === 0) { peg$fail(peg$c74); }
13527 }
13528 if (s0 === peg$FAILED) {
13529 if (input.substr(peg$currPos, 10) === peg$c75) {
13530 s0 = peg$c75;
13531 peg$currPos += 10;
13532 } else {
13533 s0 = peg$FAILED;
13534 if (peg$silentFails === 0) { peg$fail(peg$c76); }
13535 }
13536 if (s0 === peg$FAILED) {
13537 if (input.substr(peg$currPos, 9) === peg$c77) {
13538 s0 = peg$c77;
13539 peg$currPos += 9;
13540 } else {
13541 s0 = peg$FAILED;
13542 if (peg$silentFails === 0) { peg$fail(peg$c78); }
13543 }
13544 if (s0 === peg$FAILED) {
13545 if (input.substr(peg$currPos, 8) === peg$c79) {
13546 s0 = peg$c79;
13547 peg$currPos += 8;
13548 } else {
13549 s0 = peg$FAILED;
13550 if (peg$silentFails === 0) { peg$fail(peg$c80); }
13551 }
13552 }
13553 }
13554 }
13555 }
13556 }
13557 }
13558 }
13559 }
13560 }
13561 }
13562 }
13563 }
13564 }
13565 }
13566 }
13567
13568 return s0;
13569 }
13570
13571 function peg$parsefilter() {
13572 var s0, s1, s2, s3;
13573
13574 s0 = peg$currPos;
13575 if (input.charCodeAt(peg$currPos) === 91) {
13576 s1 = peg$c5;
13577 peg$currPos++;
13578 } else {
13579 s1 = peg$FAILED;
13580 if (peg$silentFails === 0) { peg$fail(peg$c6); }
13581 }
13582 if (s1 !== peg$FAILED) {
13583 s2 = peg$parseexpr();
13584 if (s2 !== peg$FAILED) {
13585 if (input.charCodeAt(peg$currPos) === 93) {
13586 s3 = peg$c7;
13587 peg$currPos++;
13588 } else {
13589 s3 = peg$FAILED;
13590 if (peg$silentFails === 0) { peg$fail(peg$c8); }
13591 }
13592 if (s3 !== peg$FAILED) {
13593 peg$reportedPos = s0;
13594 s1 = peg$c81(s2);
13595 s0 = s1;
13596 } else {
13597 peg$currPos = s0;
13598 s0 = peg$c0;
13599 }
13600 } else {
13601 peg$currPos = s0;
13602 s0 = peg$c0;
13603 }
13604 } else {
13605 peg$currPos = s0;
13606 s0 = peg$c0;
13607 }
13608
13609 return s0;
13610 }
13611
13612 function peg$parsename() {
13613 var s0, s1, s2;
13614
13615 s0 = peg$currPos;
13616 s1 = [];
13617 if (peg$c82.test(input.charAt(peg$currPos))) {
13618 s2 = input.charAt(peg$currPos);
13619 peg$currPos++;
13620 } else {
13621 s2 = peg$FAILED;
13622 if (peg$silentFails === 0) { peg$fail(peg$c83); }
13623 }
13624 if (s2 !== peg$FAILED) {
13625 while (s2 !== peg$FAILED) {
13626 s1.push(s2);
13627 if (peg$c82.test(input.charAt(peg$currPos))) {
13628 s2 = input.charAt(peg$currPos);
13629 peg$currPos++;
13630 } else {
13631 s2 = peg$FAILED;
13632 if (peg$silentFails === 0) { peg$fail(peg$c83); }
13633 }
13634 }
13635 } else {
13636 s1 = peg$c0;
13637 }
13638 if (s1 !== peg$FAILED) {
13639 peg$reportedPos = s0;
13640 s1 = peg$c84(s1);
13641 }
13642 s0 = s1;
13643
13644 return s0;
13645 }
13646
13647 function peg$parsecss() {
13648 var s0, s1, s2;
13649
13650 s0 = peg$currPos;
13651 s1 = [];
13652 if (peg$c85.test(input.charAt(peg$currPos))) {
13653 s2 = input.charAt(peg$currPos);
13654 peg$currPos++;
13655 } else {
13656 s2 = peg$FAILED;
13657 if (peg$silentFails === 0) { peg$fail(peg$c86); }
13658 }
13659 if (s2 !== peg$FAILED) {
13660 while (s2 !== peg$FAILED) {
13661 s1.push(s2);
13662 if (peg$c85.test(input.charAt(peg$currPos))) {
13663 s2 = input.charAt(peg$currPos);
13664 peg$currPos++;
13665 } else {
13666 s2 = peg$FAILED;
13667 if (peg$silentFails === 0) { peg$fail(peg$c86); }
13668 }
13669 }
13670 } else {
13671 s1 = peg$c0;
13672 }
13673 if (s1 !== peg$FAILED) {
13674 peg$reportedPos = s0;
13675 s1 = peg$c87(s1);
13676 }
13677 s0 = s1;
13678
13679 return s0;
13680 }
13681
13682 function peg$parseexpr() {
13683 var s0, s1, s2;
13684
13685 s0 = peg$currPos;
13686 s1 = [];
13687 if (peg$c88.test(input.charAt(peg$currPos))) {
13688 s2 = input.charAt(peg$currPos);
13689 peg$currPos++;
13690 } else {
13691 s2 = peg$FAILED;
13692 if (peg$silentFails === 0) { peg$fail(peg$c89); }
13693 }
13694 if (s2 !== peg$FAILED) {
13695 while (s2 !== peg$FAILED) {
13696 s1.push(s2);
13697 if (peg$c88.test(input.charAt(peg$currPos))) {
13698 s2 = input.charAt(peg$currPos);
13699 peg$currPos++;
13700 } else {
13701 s2 = peg$FAILED;
13702 if (peg$silentFails === 0) { peg$fail(peg$c89); }
13703 }
13704 }
13705 } else {
13706 s1 = peg$c0;
13707 }
13708 if (s1 !== peg$FAILED) {
13709 peg$reportedPos = s0;
13710 s1 = peg$c90(s1);
13711 }
13712 s0 = s1;
13713
13714 return s0;
13715 }
13716
13717 function peg$parsesep() {
13718 var s0, s1;
13719
13720 s0 = [];
13721 if (peg$c91.test(input.charAt(peg$currPos))) {
13722 s1 = input.charAt(peg$currPos);
13723 peg$currPos++;
13724 } else {
13725 s1 = peg$FAILED;
13726 if (peg$silentFails === 0) { peg$fail(peg$c92); }
13727 }
13728 while (s1 !== peg$FAILED) {
13729 s0.push(s1);
13730 if (peg$c91.test(input.charAt(peg$currPos))) {
13731 s1 = input.charAt(peg$currPos);
13732 peg$currPos++;
13733 } else {
13734 s1 = peg$FAILED;
13735 if (peg$silentFails === 0) { peg$fail(peg$c92); }
13736 }
13737 }
13738
13739 return s0;
13740 }
13741
13742 peg$result = peg$startRuleFunction();
13743
13744 if (peg$result !== peg$FAILED && peg$currPos === input.length) {
13745 return peg$result;
13746 } else {
13747 if (peg$result !== peg$FAILED && peg$currPos < input.length) {
13748 peg$fail({ type: "end", description: "end of input" });
13749 }
13750
13751 throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
13752 }
13753 }
13754
13755 return {
13756 SyntaxError: SyntaxError,
13757 parse: parse
13758 };
13759 })();
13760 },{}],94:[function(require,module,exports){
13761 var expr = require('vega-expression'),
13762 args = ['datum', 'event', 'signals'];
13763
13764 module.exports = expr.compiler(args, {
13765 idWhiteList: args,
13766 fieldVar: args[0],
13767 globalVar: args[2],
13768 functions: function(codegen) {
13769 var fn = expr.functions(codegen);
13770 fn.eventItem = function() { return 'event.vg.item'; };
13771 fn.eventGroup = 'event.vg.getGroup';
13772 fn.eventX = 'event.vg.getX';
13773 fn.eventY = 'event.vg.getY';
13774 fn.open = 'window.open';
13775 return fn;
13776 }
13777 });
13778 },{"vega-expression":43}],95:[function(require,module,exports){
13779 module.exports = {
13780 axes: require('./axes'),
13781 background: require('./background'),
13782 data: require('./data'),
13783 events: require('./events'),
13784 expr: require('./expr'),
13785 legends: require('./legends'),
13786 mark: require('./mark'),
13787 marks: require('./marks'),
13788 modify: require('./modify'),
13789 padding: require('./padding'),
13790 predicates: require('./predicates'),
13791 properties: require('./properties'),
13792 signals: require('./signals'),
13793 spec: require('./spec'),
13794 streams: require('./streams'),
13795 transforms: require('./transforms')
13796 };
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){
13798 var lgnd = require('../scene/legend');
13799
13800 function parseLegends(model, spec, legends, group) {
13801 (spec || []).forEach(function(def, index) {
13802 legends[index] = legends[index] || lgnd(model);
13803 parseLegend(def, index, legends[index], group);
13804 });
13805 }
13806
13807 function parseLegend(def, index, legend, group) {
13808 // legend scales
13809 legend.size (def.size ? group.scale(def.size) : null);
13810 legend.shape (def.shape ? group.scale(def.shape) : null);
13811 legend.fill (def.fill ? group.scale(def.fill) : null);
13812 legend.stroke(def.stroke ? group.scale(def.stroke) : null);
13813
13814 // legend orientation
13815 if (def.orient) legend.orient(def.orient);
13816
13817 // legend offset
13818 if (def.offset != null) legend.offset(def.offset);
13819
13820 // legend title
13821 legend.title(def.title || null);
13822
13823 // legend values
13824 legend.values(def.values || null);
13825
13826 // legend label formatting
13827 legend.format(def.format !== undefined ? def.format : null);
13828
13829 // style properties
13830 var p = def.properties;
13831 legend.titleProperties(p && p.title || {});
13832 legend.labelProperties(p && p.labels || {});
13833 legend.legendProperties(p && p.legend || {});
13834 legend.symbolProperties(p && p.symbols || {});
13835 legend.gradientProperties(p && p.gradient || {});
13836 }
13837
13838 module.exports = parseLegends;
13839 },{"../scene/legend":114}],97:[function(require,module,exports){
13840 var dl = require('datalib'),
13841 parseProperties = require('./properties');
13842
13843 function parseMark(model, mark) {
13844 var props = mark.properties,
13845 group = mark.marks;
13846
13847 // parse mark property definitions
13848 dl.keys(props).forEach(function(k) {
13849 props[k] = parseProperties(model, mark.type, props[k]);
13850 });
13851
13852 // parse delay function
13853 if (mark.delay) {
13854 mark.delay = parseProperties(model, mark.type, {delay: mark.delay});
13855 }
13856
13857 // recurse if group type
13858 if (group) {
13859 mark.marks = group.map(function(g) { return parseMark(model, g); });
13860 }
13861
13862 return mark;
13863 }
13864
13865 module.exports = parseMark;
13866 },{"./properties":102,"datalib":24}],98:[function(require,module,exports){
13867 var parseMark = require('./mark');
13868
13869 function parseRootMark(model, spec, width, height) {
13870 return {
13871 type: "group",
13872 width: width,
13873 height: height,
13874 scales: spec.scales || [],
13875 axes: spec.axes || [],
13876 legends: spec.legends || [],
13877 marks: (spec.marks || []).map(function(m) { return parseMark(model, m); })
13878 };
13879 }
13880
13881 module.exports = parseRootMark;
13882 },{"./mark":97}],99:[function(require,module,exports){
13883 var dl = require('datalib'),
13884 log = require('vega-logging'),
13885 df = require('vega-dataflow'),
13886 Node = df.Node, // jshint ignore:line
13887 Tuple = df.Tuple,
13888 Deps = df.Dependencies;
13889
13890 var Types = {
13891 INSERT: "insert",
13892 REMOVE: "remove",
13893 TOGGLE: "toggle",
13894 CLEAR: "clear"
13895 };
13896
13897 var EMPTY = [];
13898
13899 var filter = function(field, value, src, dest) {
13900 for(var i = src.length-1; i >= 0; --i) {
13901 if (src[i][field] == value)
13902 dest.push.apply(dest, src.splice(i, 1));
13903 }
13904 };
13905
13906 function parseModify(model, def, ds) {
13907 var signal = def.signal ? dl.field(def.signal) : null,
13908 signalName = signal ? signal[0] : null,
13909 predicate = def.predicate ? model.predicate(def.predicate.name || def.predicate) : null,
13910 reeval = (predicate === null),
13911 node = new Node(model).router(def.type === Types.CLEAR);
13912
13913 node.evaluate = function(input) {
13914 if (predicate !== null) { // TODO: predicate args
13915 var db = model.values(Deps.DATA, predicate.data || EMPTY),
13916 sg = model.values(Deps.SIGNALS, predicate.signals || EMPTY);
13917 reeval = predicate.call(predicate, {}, db, sg, model._predicates);
13918 }
13919
13920 log.debug(input, [def.type+"ing", reeval]);
13921 if (!reeval) return input;
13922
13923 var datum = {},
13924 value = signal ? model.signalRef(def.signal) : null,
13925 d = model.data(ds.name),
13926 t = null;
13927
13928 datum[def.field] = value;
13929
13930 // We have to modify ds._data so that subsequent pulses contain
13931 // our dynamic data. W/o modifying ds._data, only the output
13932 // collector will contain dynamic tuples.
13933 if (def.type === Types.INSERT) {
13934 t = Tuple.ingest(datum);
13935 input.add.push(t);
13936 d._data.push(t);
13937 } else if (def.type === Types.REMOVE) {
13938 filter(def.field, value, input.add, input.rem);
13939 filter(def.field, value, input.mod, input.rem);
13940 d._data = d._data.filter(function(x) { return x[def.field] !== value; });
13941 } else if (def.type === Types.TOGGLE) {
13942 var add = [], rem = [];
13943 filter(def.field, value, input.rem, add);
13944 filter(def.field, value, input.add, rem);
13945 filter(def.field, value, input.mod, rem);
13946 if (!(add.length || rem.length)) add.push(Tuple.ingest(datum));
13947
13948 input.add.push.apply(input.add, add);
13949 d._data.push.apply(d._data, add);
13950 input.rem.push.apply(input.rem, rem);
13951 d._data = d._data.filter(function(x) { return rem.indexOf(x) === -1; });
13952 } else if (def.type === Types.CLEAR) {
13953 input.rem.push.apply(input.rem, input.add);
13954 input.rem.push.apply(input.rem, input.mod);
13955 input.add = [];
13956 input.mod = [];
13957 d._data = [];
13958 }
13959
13960 input.fields[def.field] = 1;
13961 return input;
13962 };
13963
13964 if (signalName) node.dependency(Deps.SIGNALS, signalName);
13965
13966 if (predicate) {
13967 node.dependency(Deps.DATA, predicate.data);
13968 node.dependency(Deps.SIGNALS, predicate.signals);
13969 }
13970
13971 return node;
13972 }
13973
13974 module.exports = parseModify;
13975 },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],100:[function(require,module,exports){
13976 var dl = require('datalib');
13977
13978 function parsePadding(pad) {
13979 if (pad == null) return "auto";
13980 else if (dl.isString(pad)) return pad==="strict" ? "strict" : "auto";
13981 else if (dl.isObject(pad)) return pad;
13982 var p = dl.isNumber(pad) ? pad : 20;
13983 return {top:p, left:p, right:p, bottom:p};
13984 }
13985
13986 module.exports = parsePadding;
13987 },{"datalib":24}],101:[function(require,module,exports){
13988 var dl = require('datalib');
13989
13990 var types = {
13991 '=': parseComparator,
13992 '==': parseComparator,
13993 '!=': parseComparator,
13994 '>': parseComparator,
13995 '>=': parseComparator,
13996 '<': parseComparator,
13997 '<=': parseComparator,
13998 'and': parseLogical,
13999 '&&': parseLogical,
14000 'or': parseLogical,
14001 '||': parseLogical,
14002 'in': parseIn
14003 };
14004
14005 var nullScale = function() { return 0; };
14006 nullScale.invert = nullScale;
14007
14008 function parsePredicates(model, spec) {
14009 (spec || []).forEach(function(s) {
14010 var parse = types[s.type](model, s);
14011
14012 /* jshint evil:true */
14013 var pred = Function("args", "db", "signals", "predicates", parse.code);
14014 pred.root = function() { return model.scene().items[0]; }; // For global scales
14015 pred.nullScale = nullScale;
14016 pred.isFunction = dl.isFunction;
14017 pred.signals = parse.signals;
14018 pred.data = parse.data;
14019
14020 model.predicate(s.name, pred);
14021 });
14022
14023 return spec;
14024 }
14025
14026 function parseSignal(signal, signals) {
14027 var s = dl.field(signal),
14028 code = "signals["+s.map(dl.str).join("][")+"]";
14029 signals[s[0]] = 1;
14030 return code;
14031 }
14032
14033 function parseOperands(model, operands) {
14034 var decl = [], defs = [],
14035 signals = {}, db = {};
14036
14037 function setSignal(s) { signals[s] = 1; }
14038 function setData(d) { db[d] = 1; }
14039
14040 dl.array(operands).forEach(function(o, i) {
14041 var name = "o" + i,
14042 def = "";
14043
14044 if (o.value !== undefined) {
14045 def = dl.str(o.value);
14046 } else if (o.arg) {
14047 def = "args["+dl.str(o.arg)+"]";
14048 } else if (o.signal) {
14049 def = parseSignal(o.signal, signals);
14050 } else if (o.predicate) {
14051 var ref = o.predicate,
14052 predName = ref && (ref.name || ref),
14053 pred = model.predicate(predName),
14054 p = "predicates["+dl.str(predName)+"]";
14055
14056 pred.signals.forEach(setSignal);
14057 pred.data.forEach(setData);
14058
14059 if (dl.isObject(ref)) {
14060 dl.keys(ref).forEach(function(k) {
14061 if (k === "name") return;
14062 var i = ref[k];
14063 def += "args["+dl.str(k)+"] = ";
14064 if (i.signal) {
14065 def += parseSignal(i.signal, signals);
14066 } else if (i.arg) {
14067 def += "args["+dl.str(i.arg)+"]";
14068 }
14069 def += ", ";
14070 });
14071 }
14072
14073 def += p+".call("+p+", args, db, signals, predicates)";
14074 }
14075
14076 decl.push(name);
14077 defs.push(name+"=("+def+")");
14078 });
14079
14080 return {
14081 code: "var " + decl.join(", ") + ";\n" + defs.join(";\n") + ";\n",
14082 signals: dl.keys(signals),
14083 data: dl.keys(db)
14084 };
14085 }
14086
14087 function parseComparator(model, spec) {
14088 var ops = parseOperands(model, spec.operands);
14089 if (spec.type === '=') spec.type = '==';
14090
14091 ops.code += "o0 = o0 instanceof Date ? o0.getTime() : o0;\n" +
14092 "o1 = o1 instanceof Date ? o1.getTime() : o1;\n";
14093
14094 return {
14095 code: ops.code + "return " + ["o0", "o1"].join(spec.type) + ";",
14096 signals: ops.signals,
14097 data: ops.data
14098 };
14099 }
14100
14101 function parseLogical(model, spec) {
14102 var ops = parseOperands(model, spec.operands),
14103 o = [], i = 0, len = spec.operands.length;
14104
14105 while (o.push("o"+i++) < len);
14106 if (spec.type === 'and') spec.type = '&&';
14107 else if (spec.type === 'or') spec.type = '||';
14108
14109 return {
14110 code: ops.code + "return " + o.join(spec.type) + ";",
14111 signals: ops.signals,
14112 data: ops.data
14113 };
14114 }
14115
14116 function parseIn(model, spec) {
14117 var o = [spec.item], code = "";
14118 if (spec.range) o.push.apply(o, spec.range);
14119 if (spec.scale) {
14120 code = parseScale(spec.scale, o);
14121 }
14122
14123 var ops = parseOperands(model, o);
14124 code = ops.code + code + "\n var ordSet = null;\n";
14125
14126 if (spec.data) {
14127 var field = dl.field(spec.field).map(dl.str);
14128 code += "var where = function(d) { return d["+field.join("][")+"] == o0 };\n";
14129 code += "return db["+dl.str(spec.data)+"].filter(where).length > 0;";
14130 } else if (spec.range) {
14131 // TODO: inclusive/exclusive range?
14132 if (spec.scale) {
14133 code += "if (scale.length == 2) {\n" + // inverting ordinal scales
14134 " ordSet = scale(o1, o2);\n" +
14135 "} else {\n" +
14136 " o1 = scale(o1);\no2 = scale(o2);\n" +
14137 "}";
14138 }
14139
14140 code += "return ordSet !== null ? ordSet.indexOf(o0) !== -1 :\n" +
14141 " o1 < o2 ? o1 <= o0 && o0 <= o2 : o2 <= o0 && o0 <= o1;";
14142 }
14143
14144 return {
14145 code: code,
14146 signals: ops.signals,
14147 data: ops.data.concat(spec.data ? [spec.data] : [])
14148 };
14149 }
14150
14151 // Populate ops such that ultimate scale/inversion function will be in `scale` var.
14152 function parseScale(spec, ops) {
14153 var code = "var scale = ",
14154 idx = ops.length;
14155
14156 if (dl.isString(spec)) {
14157 ops.push({ value: spec });
14158 code += "this.root().scale(o"+idx+")";
14159 } else if (spec.arg) { // Scale function is being passed as an arg
14160 ops.push(spec);
14161 code += "o"+idx;
14162 } else if (spec.name) { // Full scale parameter {name: ..}
14163 ops.push(dl.isString(spec.name) ? {value: spec.name} : spec.name);
14164 code += "(this.isFunction(o"+idx+") ? o"+idx+" : ";
14165 if (spec.scope) {
14166 ops.push(spec.scope);
14167 code += "((o"+(idx+1)+".scale || this.root().scale)(o"+idx+") || this.nullScale)";
14168 } else {
14169 code += "this.root().scale(o"+idx+")";
14170 }
14171 code += ")";
14172 }
14173
14174 if (spec.invert === true) { // Allow spec.invert.arg?
14175 code += ".invert";
14176 }
14177
14178 return code+";\n";
14179 }
14180
14181 module.exports = parsePredicates;
14182 },{"datalib":24}],102:[function(require,module,exports){
14183 (function (global){
14184 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
14185 dl = require('datalib'),
14186 log = require('vega-logging'),
14187 Tuple = require('vega-dataflow').Tuple;
14188
14189 var DEPS = ["signals", "scales", "data", "fields"];
14190
14191 function properties(model, mark, spec) {
14192 var config = model.config(),
14193 code = "",
14194 names = dl.keys(spec),
14195 i, len, name, ref, vars = {},
14196 deps = {
14197 signals: {},
14198 scales: {},
14199 data: {},
14200 fields: {},
14201 nested: [],
14202 _nRefs: {}, // Temp stash to de-dupe nested refs.
14203 reflow: false
14204 };
14205
14206 code += "var o = trans ? {} : item, d=0, set=this.tpl.set, tmpl=signals||{}, t;\n" +
14207 // Stash for dl.template
14208 "tmpl.datum = item.datum;\n" +
14209 "tmpl.group = group;\n" +
14210 "tmpl.parent = group.datum;\n";
14211
14212 function handleDep(p) {
14213 if (ref[p] == null) return;
14214 var k = dl.array(ref[p]), i, n;
14215 for (i=0, n=k.length; i<n; ++i) {
14216 deps[p][k[i]] = 1;
14217 }
14218 }
14219
14220 function handleNestedRefs(r) {
14221 var k = (r.parent ? "parent_" : "group_")+r.level;
14222 deps._nRefs[k] = r;
14223 }
14224
14225 for (i=0, len=names.length; i<len; ++i) {
14226 ref = spec[name = names[i]];
14227 code += (i > 0) ? "\n " : " ";
14228 if (ref.rule) {
14229 ref = rule(model, name, ref.rule);
14230 code += "\n " + ref.code;
14231 } else {
14232 ref = valueRef(config, name, ref);
14233 code += "d += set(o, "+dl.str(name)+", "+ref.val+");";
14234 }
14235
14236 vars[name] = true;
14237 DEPS.forEach(handleDep);
14238 deps.reflow = deps.reflow || ref.reflow;
14239 if (ref.nested.length) ref.nested.forEach(handleNestedRefs);
14240 }
14241
14242 // If nested references are present, sort them based on their level
14243 // to speed up determination of whether encoders should be reeval'd.
14244 dl.keys(deps._nRefs).forEach(function(k) { deps.nested.push(deps._nRefs[k]); });
14245 deps.nested.sort(function(a, b) {
14246 a = a.level;
14247 b = b.level;
14248 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
14249 });
14250
14251 if (vars.x2) {
14252 if (vars.x) {
14253 code += "\n if (o.x > o.x2) { " +
14254 "\n t = o.x;" +
14255 "\n d += set(o, 'x', o.x2);" +
14256 "\n d += set(o, 'x2', t); " +
14257 "\n };";
14258 code += "\n d += set(o, 'width', (o.x2 - o.x));";
14259 } else if (vars.width) {
14260 code += "\n d += set(o, 'x', (o.x2 - o.width));";
14261 } else {
14262 code += "\n d += set(o, 'x', o.x2);";
14263 }
14264 }
14265
14266 if (vars.xc) {
14267 if (vars.width) {
14268 code += "\n d += set(o, 'x', (o.xc - o.width/2));" ;
14269 } else {
14270 code += "\n d += set(o, 'x', o.xc);" ;
14271 }
14272 }
14273
14274 if (vars.y2) {
14275 if (vars.y) {
14276 code += "\n if (o.y > o.y2) { " +
14277 "\n t = o.y;" +
14278 "\n d += set(o, 'y', o.y2);" +
14279 "\n d += set(o, 'y2', t);" +
14280 "\n };";
14281 code += "\n d += set(o, 'height', (o.y2 - o.y));";
14282 } else if (vars.height) {
14283 code += "\n d += set(o, 'y', (o.y2 - o.height));";
14284 } else {
14285 code += "\n d += set(o, 'y', o.y2);";
14286 }
14287 }
14288
14289 if (vars.yc) {
14290 if (vars.height) {
14291 code += "\n d += set(o, 'y', (o.yc - o.height/2));" ;
14292 } else {
14293 code += "\n d += set(o, 'y', o.yc);" ;
14294 }
14295 }
14296
14297 if (hasPath(mark, vars)) code += "\n d += (item.touch(), 1);";
14298 code += "\n if (trans) trans.interpolate(item, o);";
14299 code += "\n return d > 0;";
14300
14301 try {
14302 /* jshint evil:true */
14303 var encoder = Function('item', 'group', 'trans', 'db',
14304 'signals', 'predicates', code);
14305 encoder.tpl = Tuple;
14306 encoder.util = dl;
14307 encoder.d3 = d3; // For color spaces
14308 dl.extend(encoder, dl.template.context);
14309 return {
14310 encode: encoder,
14311 signals: dl.keys(deps.signals),
14312 scales: dl.keys(deps.scales),
14313 data: dl.keys(deps.data),
14314 fields: dl.keys(deps.fields),
14315 nested: deps.nested,
14316 reflow: deps.reflow
14317 };
14318 } catch (e) {
14319 log.error(e);
14320 log.log(code);
14321 }
14322 }
14323
14324 function dependencies(a, b) {
14325 if (!dl.isObject(a)) {
14326 a = {reflow: false, nested: []};
14327 DEPS.forEach(function(d) { a[d] = []; });
14328 }
14329
14330 if (dl.isObject(b)) {
14331 a.reflow = a.reflow || b.reflow;
14332 a.nested.push.apply(a.nested, b.nested);
14333 DEPS.forEach(function(d) { a[d].push.apply(a[d], b[d]); });
14334 }
14335
14336 return a;
14337 }
14338
14339 function hasPath(mark, vars) {
14340 return vars.path ||
14341 ((mark==='area' || mark==='line') &&
14342 (vars.x || vars.x2 || vars.width ||
14343 vars.y || vars.y2 || vars.height ||
14344 vars.tension || vars.interpolate));
14345 }
14346
14347 function rule(model, name, rules) {
14348 var config = model.config(),
14349 deps = dependencies(),
14350 inputs = [], code = '';
14351
14352 (rules||[]).forEach(function(r, i) {
14353 var def = r.predicate,
14354 predName = def && (def.name || def),
14355 pred = model.predicate(predName),
14356 p = 'predicates['+dl.str(predName)+']',
14357 input = [], args = name+'_arg'+i,
14358 ref;
14359
14360 if (dl.isObject(def)) {
14361 dl.keys(def).forEach(function(k) {
14362 if (k === 'name') return;
14363 var ref = valueRef(config, i, def[k]);
14364 input.push(dl.str(k)+': '+ref.val);
14365 dependencies(deps, ref);
14366 });
14367 }
14368
14369 ref = valueRef(config, name, r);
14370 dependencies(deps, ref);
14371
14372 if (predName) {
14373 deps.signals.push.apply(deps.signals, pred.signals);
14374 deps.data.push.apply(deps.data, pred.data);
14375 inputs.push(args+" = {\n "+input.join(",\n ")+"\n }");
14376 code += "if ("+p+".call("+p+","+args+", db, signals, predicates)) {" +
14377 "\n d += set(o, "+dl.str(name)+", "+ref.val+");";
14378 code += rules[i+1] ? "\n } else " : " }";
14379 } else {
14380 code += "{" +
14381 "\n d += set(o, "+dl.str(name)+", "+ref.val+");"+
14382 "\n }\n";
14383 }
14384 });
14385
14386 code = "var " + inputs.join(",\n ") + ";\n " + code;
14387 return (deps.code = code, deps);
14388 }
14389
14390 function valueRef(config, name, ref) {
14391 if (ref == null) return null;
14392
14393 if (name==='fill' || name==='stroke') {
14394 if (ref.c) {
14395 return colorRef(config, 'hcl', ref.h, ref.c, ref.l);
14396 } else if (ref.h || ref.s) {
14397 return colorRef(config, 'hsl', ref.h, ref.s, ref.l);
14398 } else if (ref.l || ref.a) {
14399 return colorRef(config, 'lab', ref.l, ref.a, ref.b);
14400 } else if (ref.r || ref.g || ref.b) {
14401 return colorRef(config, 'rgb', ref.r, ref.g, ref.b);
14402 }
14403 }
14404
14405 // initialize value
14406 var val = null, scale = null,
14407 deps = dependencies(),
14408 sgRef = null, fRef = null, sRef = null, tmpl = {};
14409
14410 if (ref.template !== undefined) {
14411 val = dl.template.source(ref.template, 'tmpl', tmpl);
14412 dl.keys(tmpl).forEach(function(k) {
14413 var f = dl.field(k),
14414 a = f.shift();
14415 if (a === 'parent' || a === 'group') {
14416 deps.nested.push({
14417 parent: a === 'parent',
14418 group: a === 'group',
14419 level: 1
14420 });
14421 } else if (a === 'datum') {
14422 deps.fields.push(f[0]);
14423 } else {
14424 deps.signals.push(a);
14425 }
14426 });
14427 }
14428
14429 if (ref.value !== undefined) {
14430 val = dl.str(ref.value);
14431 }
14432
14433 if (ref.signal !== undefined) {
14434 sgRef = dl.field(ref.signal);
14435 val = 'signals['+sgRef.map(dl.str).join('][')+']';
14436 deps.signals.push(sgRef.shift());
14437 }
14438
14439 if (ref.field !== undefined) {
14440 ref.field = dl.isString(ref.field) ? {datum: ref.field} : ref.field;
14441 fRef = fieldRef(ref.field);
14442 val = fRef.val;
14443 dependencies(deps, fRef);
14444 }
14445
14446 if (ref.scale !== undefined) {
14447 sRef = scaleRef(ref.scale);
14448 scale = sRef.val;
14449 dependencies(deps, sRef);
14450 deps.scales.push(ref.scale.name || ref.scale);
14451
14452 // run through scale function if val specified.
14453 // if no val, scale function is predicate arg.
14454 if (val !== null || ref.band || ref.mult || ref.offset) {
14455 val = scale + (ref.band ? '.rangeBand()' :
14456 '('+(val !== null ? val : 'item.datum.data')+')');
14457 } else {
14458 val = scale;
14459 }
14460 }
14461
14462 // multiply, offset, return value
14463 val = '(' + (ref.mult?(dl.number(ref.mult)+' * '):'') + val + ')' +
14464 (ref.offset ? ' + ' + dl.number(ref.offset) : '');
14465
14466 // Collate dependencies
14467 return (deps.val = val, deps);
14468 }
14469
14470 function colorRef(config, type, x, y, z) {
14471 var xx = x ? valueRef(config, '', x) : config.color[type][0],
14472 yy = y ? valueRef(config, '', y) : config.color[type][1],
14473 zz = z ? valueRef(config, '', z) : config.color[type][2],
14474 deps = dependencies();
14475
14476 [xx, yy, zz].forEach(function(v) {
14477 if (dl.isArray) return;
14478 dependencies(deps, v);
14479 });
14480
14481 var val = '(this.d3.' + type + '(' + [xx.val, yy.val, zz.val].join(',') + ') + "")';
14482 return (deps.val = val, deps);
14483 }
14484
14485 // {field: {datum: "foo"} } -> item.datum.foo
14486 // {field: {group: "foo"} } -> group.foo
14487 // {field: {parent: "foo"} } -> group.datum.foo
14488 function fieldRef(ref) {
14489 if (dl.isString(ref)) {
14490 return {val: dl.field(ref).map(dl.str).join('][')};
14491 }
14492
14493 // Resolve nesting/parent lookups
14494 var l = ref.level || 1,
14495 nested = (ref.group || ref.parent) && l,
14496 scope = nested ? Array(l).join('group.mark.') : '',
14497 r = fieldRef(ref.datum || ref.group || ref.parent || ref.signal),
14498 val = r.val,
14499 deps = dependencies(null, r);
14500
14501 if (ref.datum) {
14502 val = 'item.datum['+val+']';
14503 deps.fields.push(ref.datum);
14504 } else if (ref.group) {
14505 val = scope+'group['+val+']';
14506 deps.nested.push({ level: l, group: true });
14507 } else if (ref.parent) {
14508 val = scope+'group.datum['+val+']';
14509 deps.nested.push({ level: l, parent: true });
14510 } else if (ref.signal) {
14511 val = 'signals['+val+']';
14512 deps.signals.push(dl.field(ref.signal)[0]);
14513 deps.reflow = true;
14514 }
14515
14516 return (deps.val = val, deps);
14517 }
14518
14519 // {scale: "x"}
14520 // {scale: {name: "x"}},
14521 // {scale: fieldRef}
14522 function scaleRef(ref) {
14523 var scale = null,
14524 fr = null,
14525 deps = dependencies();
14526
14527 if (dl.isString(ref)) {
14528 scale = dl.str(ref);
14529 } else if (ref.name) {
14530 scale = dl.isString(ref.name) ? dl.str(ref.name) : (fr = fieldRef(ref.name)).val;
14531 } else {
14532 scale = (fr = fieldRef(ref)).val;
14533 }
14534
14535 scale = '(item.mark._scaleRefs['+scale+'] = 1, group.scale('+scale+'))';
14536 if (ref.invert) scale += '.invert';
14537
14538 // Mark scale refs as they're dealt with separately in mark._scaleRefs.
14539 if (fr) fr.nested.forEach(function(g) { g.scale = true; });
14540 return fr ? (fr.val = scale, fr) : (deps.val = scale, deps);
14541 }
14542
14543 module.exports = properties;
14544 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
14545
14546 },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],103:[function(require,module,exports){
14547 var dl = require('datalib'),
14548 SIGNALS = require('vega-dataflow').Dependencies.SIGNALS,
14549 expr = require('./expr');
14550
14551 var RESERVED = ['datum', 'event', 'signals']
14552 .concat(dl.keys(expr.codegen.functions));
14553
14554 function parseSignals(model, spec) {
14555 // process each signal definition
14556 (spec || []).forEach(function(s) {
14557 if (RESERVED.indexOf(s.name) !== -1) {
14558 throw Error('Signal name "'+s.name+'" is a '+
14559 'reserved keyword ('+RESERVED.join(', ')+').');
14560 }
14561
14562 var signal = model.signal(s.name, s.init)
14563 .verbose(s.verbose);
14564
14565 if (s.init && s.init.expr) {
14566 s.init.expr = expr(s.init.expr);
14567 signal.value(exprVal(model, s.init));
14568 }
14569
14570 if (s.expr) {
14571 s.expr = expr(s.expr);
14572 signal.evaluate = function(input) {
14573 var val = exprVal(model, s);
14574 if (val !== signal.value() || signal.verbose()) {
14575 signal.value(val);
14576 input.signals[s.name] = 1;
14577 return input;
14578 }
14579 return model.doNotPropagate;
14580 };
14581 signal.dependency(SIGNALS, s.expr.globals);
14582 s.expr.globals.forEach(function(dep) {
14583 model.signal(dep).addListener(signal);
14584 });
14585 }
14586 });
14587
14588 return spec;
14589 }
14590
14591 function exprVal(model, spec) {
14592 var e = spec.expr,
14593 val = e.fn(null, null, model.values(SIGNALS, e.globals));
14594 return spec.scale ? parseSignals.scale(model, spec, val) : val;
14595 }
14596
14597 parseSignals.scale = function scale(model, spec, value, datum, evt) {
14598 var def = spec.scale,
14599 name = def.name || def.signal || def,
14600 scope = def.scope, e;
14601
14602 if (scope) {
14603 if (scope.signal) {
14604 scope = model.signalRef(scope.signal);
14605 } else if (dl.isString(scope)) { // Scope is an expression
14606 e = def._expr = (def._expr || expr(scope));
14607 scope = e.fn(datum, evt, model.values(SIGNALS, e.globals));
14608 }
14609 }
14610
14611 if (!scope || !scope.scale) {
14612 scope = (scope && scope.mark) ? scope.mark.group : model.scene().items[0];
14613 }
14614
14615 var s = scope.scale(name);
14616 return !s ? value : (def.invert ? s.invert(value) : s(value));
14617 };
14618
14619 module.exports = parseSignals;
14620 },{"./expr":94,"datalib":24,"vega-dataflow":39}],104:[function(require,module,exports){
14621 var dl = require('datalib'),
14622 log = require('vega-logging'),
14623 Model = require('../core/Model'),
14624 View = require('../core/View');
14625
14626 function parseSpec(spec, callback) {
14627 var vf = arguments[arguments.length-1],
14628 viewFactory = arguments.length > 2 && dl.isFunction(vf) ? vf : View.factory,
14629 config = arguments[2] !== viewFactory ? arguments[2] : {},
14630 model = new Model(config);
14631
14632 function parse(spec) {
14633 // protect against subsequent spec modification
14634 spec = dl.duplicate(spec);
14635
14636 var parsers = require('./'),
14637 width = spec.width || 500,
14638 height = spec.height || 500,
14639 viewport = spec.viewport || null;
14640
14641 model.defs({
14642 width: width,
14643 height: height,
14644 viewport: viewport,
14645 background: parsers.background(spec.background),
14646 padding: parsers.padding(spec.padding),
14647 signals: parsers.signals(model, spec.signals),
14648 predicates: parsers.predicates(model, spec.predicates),
14649 marks: parsers.marks(model, spec, width, height),
14650 data: parsers.data(model, spec.data, function() {
14651 callback(viewFactory(model));
14652 })
14653 });
14654 }
14655
14656 if (dl.isObject(spec)) {
14657 parse(spec);
14658 } else if (dl.isString(spec)) {
14659 var opts = dl.extend({url: spec}, model.config().load);
14660 dl.load(opts, function(err, data) {
14661 if (err) {
14662 log.error('LOADING SPECIFICATION FAILED: ' + err.statusText);
14663 } else {
14664 try {
14665 parse(JSON.parse(data));
14666 } catch (e) {
14667 log.error('INVALID SPECIFICATION: Must be a valid JSON object. '+e);
14668 }
14669 }
14670 });
14671 } else {
14672 log.error('INVALID SPECIFICATION: Must be a valid JSON object or URL.');
14673 }
14674 }
14675
14676 module.exports = parseSpec;
14677 },{"../core/Model":86,"../core/View":87,"./":95,"datalib":24,"vega-logging":45}],105:[function(require,module,exports){
14678 (function (global){
14679 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
14680 dl = require('datalib'),
14681 df = require('vega-dataflow'),
14682 SIGNALS = df.Dependencies.SIGNALS,
14683 parseSignals = require('./signals'),
14684 selector = require('./events'),
14685 expr = require('./expr');
14686
14687 var GATEKEEPER = '_vgGATEKEEPER';
14688
14689 var vgEvent = {
14690 getGroup: function(name) { return name ? this.name[name] : this.group; },
14691 getXY: function(item) {
14692 var p = {x: this.x, y: this.y};
14693 if (typeof item === 'string') {
14694 item = this.name[item];
14695 }
14696 for (; item; item = item.mark && item.mark.group) {
14697 p.x -= item.x || 0;
14698 p.y -= item.y || 0;
14699 }
14700 return p;
14701 },
14702 getX: function(item) { return this.getXY(item).x; },
14703 getY: function(item) { return this.getXY(item).y; }
14704 };
14705
14706 function parseStreams(view) {
14707 var model = view.model(),
14708 spec = model.defs().signals,
14709 registry = {handlers: {}, nodes: {}},
14710 internal = dl.duplicate(registry), // Internal event processing
14711 external = dl.duplicate(registry); // External event processing
14712
14713 (spec || []).forEach(function(sig) {
14714 var signal = model.signal(sig.name);
14715 if (sig.expr) return; // Cannot have an expr and stream definition.
14716
14717 (sig.streams || []).forEach(function(stream) {
14718 var sel = selector.parse(stream.type),
14719 exp = expr(stream.expr);
14720 mergedStream(signal, sel, exp, stream);
14721 });
14722 });
14723
14724 // We register the event listeners all together so that if multiple
14725 // signals are registered on the same event, they will receive the
14726 // new value on the same pulse.
14727 dl.keys(internal.handlers).forEach(function(type) {
14728 view.on(type, function(evt, item) {
14729 evt.preventDefault(); // stop text selection
14730 extendEvent(evt, item);
14731 fire(internal, type, (item && item.datum) || {}, evt);
14732 });
14733 });
14734
14735 // add external event listeners
14736 dl.keys(external.handlers).forEach(function(type) {
14737 if (typeof window === 'undefined') return; // No external support
14738
14739 var h = external.handlers[type],
14740 t = type.split(':'), // --> no element pseudo-selectors
14741 elt = (t[0] === 'window') ? [window] :
14742 window.document.querySelectorAll(t[0]);
14743
14744 function handler(evt) {
14745 extendEvent(evt);
14746 fire(external, type, d3.select(this).datum(), evt);
14747 }
14748
14749 for (var i=0; i<elt.length; ++i) {
14750 elt[i].addEventListener(t[1], handler);
14751 }
14752
14753 h.elements = elt;
14754 h.listener = handler;
14755 });
14756
14757 // remove external event listeners
14758 external.detach = function() {
14759 dl.keys(external.handlers).forEach(function(type) {
14760 var h = external.handlers[type],
14761 t = type.split(':'),
14762 elt = h.elements || [];
14763
14764 for (var i=0; i<elt.length; ++i) {
14765 elt[i].removeEventListener(t[1], h.listener);
14766 }
14767 });
14768 };
14769
14770 // export detach method
14771 return external.detach;
14772
14773 // -- helper functions -----
14774
14775 function extendEvent(evt, item) {
14776 var mouse = d3.mouse((d3.event=evt, view.renderer().scene())),
14777 pad = view.padding(),
14778 names = {}, mark, group, i;
14779
14780 if (item) {
14781 mark = item.mark;
14782 group = mark.marktype === 'group' ? item : mark.group;
14783 for (i=item; i!=null; i=i.mark.group) {
14784 if (i.mark.def.name) {
14785 names[i.mark.def.name] = i;
14786 }
14787 }
14788 }
14789 names.root = view.model().scene().items[0];
14790
14791 evt.vg = Object.create(vgEvent);
14792 evt.vg.group = group;
14793 evt.vg.item = item || {};
14794 evt.vg.name = names;
14795 evt.vg.x = mouse[0] - pad.left;
14796 evt.vg.y = mouse[1] - pad.top;
14797 }
14798
14799 function fire(registry, type, datum, evt) {
14800 var handlers = registry.handlers[type],
14801 node = registry.nodes[type],
14802 cs = df.ChangeSet.create(null, true),
14803 filtered = false,
14804 val, i, n, h;
14805
14806 function invoke(f) {
14807 return !f.fn(datum, evt, model.values(SIGNALS, f.globals));
14808 }
14809
14810 for (i=0, n=handlers.length; i<n; ++i) {
14811 h = handlers[i];
14812 filtered = h.filters.some(invoke);
14813 if (filtered) continue;
14814
14815 val = h.exp.fn(datum, evt, model.values(SIGNALS, h.exp.globals));
14816 if (h.spec.scale) {
14817 val = parseSignals.scale(model, h.spec, val, datum, evt);
14818 }
14819
14820 if (val !== h.signal.value() || h.signal.verbose()) {
14821 h.signal.value(val);
14822 cs.signals[h.signal.name()] = 1;
14823 }
14824 }
14825
14826 model.propagate(cs, node);
14827 }
14828
14829 function mergedStream(sig, selector, exp, spec) {
14830 selector.forEach(function(s) {
14831 if (s.event) domEvent(sig, s, exp, spec);
14832 else if (s.signal) signal(sig, s, exp, spec);
14833 else if (s.start) orderedStream(sig, s, exp, spec);
14834 else if (s.stream) mergedStream(sig, s.stream, exp, spec);
14835 });
14836 }
14837
14838 function domEvent(sig, selector, exp, spec) {
14839 var evt = selector.event,
14840 name = selector.name,
14841 mark = selector.mark,
14842 target = selector.target,
14843 filters = selector.filters || [],
14844 registry = target ? external : internal,
14845 type = target ? target+':'+evt : evt,
14846 node = registry.nodes[type] || (registry.nodes[type] = new df.Node(model)),
14847 handlers = registry.handlers[type] || (registry.handlers[type] = []);
14848
14849 if (name) {
14850 filters.push('!!event.vg.name["' + name + '"]'); // Mimic event bubbling
14851 } else if (mark) {
14852 filters.push('event.vg.item.mark && event.vg.item.mark.marktype==='+dl.str(mark));
14853 }
14854
14855 handlers.push({
14856 signal: sig,
14857 exp: exp,
14858 spec: spec,
14859 filters: filters.map(function(f) { return expr(f); })
14860 });
14861
14862 node.addListener(sig);
14863 }
14864
14865 function signal(sig, selector, exp, spec) {
14866 var n = new df.Node(model);
14867 n.evaluate = function(input) {
14868 if (!input.signals[selector.signal]) return model.doNotPropagate;
14869 var val = exp.fn(null, null, model.values(SIGNALS, exp.globals));
14870 if (spec.scale) {
14871 val = parseSignals.scale(model, spec, val);
14872 }
14873
14874 if (val !== sig.value() || sig.verbose()) {
14875 sig.value(val);
14876 input.signals[sig.name()] = 1;
14877 input.reflow = true;
14878 }
14879
14880 return input;
14881 };
14882 n.dependency(df.Dependencies.SIGNALS, selector.signal);
14883 n.addListener(sig);
14884 model.signal(selector.signal).addListener(n);
14885 }
14886
14887 function orderedStream(sig, selector, exp, spec) {
14888 var name = sig.name(),
14889 gk = name + GATEKEEPER,
14890 trueFn = expr('true'),
14891 falseFn = expr('false'),
14892 middle = selector.middle,
14893 filters = middle.filters || (middle.filters = []),
14894 gatekeeper = model.signal(gk) || model.signal(gk, false);
14895
14896 // Register an anonymous signal to act as a gatekeeper. Its value is
14897 // true or false depending on whether the start or end streams occur.
14898 // The middle signal then simply filters for the gatekeeper's value.
14899 mergedStream(gatekeeper, [selector.start], trueFn, {});
14900 mergedStream(gatekeeper, [selector.end], falseFn, {});
14901
14902 filters.push(gatekeeper.name());
14903 mergedStream(sig, [selector.middle], exp, spec);
14904 }
14905 }
14906
14907 module.exports = parseStreams;
14908 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
14909
14910 },{"./events":93,"./expr":94,"./signals":103,"datalib":24,"vega-dataflow":39}],106:[function(require,module,exports){
14911 var dl = require('datalib'),
14912 transforms = require('../transforms/index');
14913
14914 function parseTransforms(model, def) {
14915 var tx = new transforms[def.type](model);
14916
14917 // We want to rename output fields before setting any other properties,
14918 // as subsequent properties may require output to be set (e.g. group by).
14919 if(def.output) tx.output(def.output);
14920
14921 dl.keys(def).forEach(function(k) {
14922 if(k === 'type' || k === 'output') return;
14923 tx.param(k, def[k]);
14924 });
14925
14926 return tx;
14927 }
14928
14929 module.exports = parseTransforms;
14930 },{"../transforms/index":139,"datalib":24}],107:[function(require,module,exports){
14931 var dl = require('datalib'),
14932 df = require('vega-dataflow'),
14933 Node = df.Node, // jshint ignore:line
14934 log = require('vega-logging'),
14935 bound = require('vega-scenegraph').bound,
14936 Encoder = require('./Encoder');
14937
14938 function Bounder(graph, mark) {
14939 this._mark = mark;
14940 return Node.prototype.init.call(this, graph)
14941 .router(true)
14942 .reflows(true)
14943 .mutates(true);
14944 }
14945
14946 var proto = (Bounder.prototype = new Node());
14947
14948 proto.evaluate = function(input) {
14949 log.debug(input, ['bounds', this._mark.marktype]);
14950
14951 var type = this._mark.marktype,
14952 isGrp = type === 'group',
14953 items = this._mark.items,
14954 hasLegends = dl.array(this._mark.def.legends).length > 0,
14955 i, ilen, j, jlen, group, legend;
14956
14957 if (input.add.length || input.rem.length || !items.length ||
14958 input.mod.length === items.length ||
14959 type === 'area' || type === 'line') {
14960 bound.mark(this._mark, null, isGrp && !hasLegends);
14961 } else {
14962 input.mod.forEach(function(item) { bound.item(item); });
14963 }
14964
14965 if (isGrp && hasLegends) {
14966 for (i=0, ilen=items.length; i<ilen; ++i) {
14967 group = items[i];
14968 group._legendPositions = null;
14969 for (j=0, jlen=group.legendItems.length; j<jlen; ++j) {
14970 legend = group.legendItems[j];
14971 Encoder.update(this._graph, input.trans, 'vg_legendPosition', legend.items, input.dirty);
14972 bound.mark(legend, null, false);
14973 }
14974 }
14975
14976 bound.mark(this._mark, null, true);
14977 }
14978
14979 return df.ChangeSet.create(input, true);
14980 };
14981
14982 module.exports = Bounder;
14983 },{"./Encoder":109,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],108:[function(require,module,exports){
14984 var dl = require('datalib'),
14985 log = require('vega-logging'),
14986 Item = require('vega-scenegraph').Item,
14987 df = require('vega-dataflow'),
14988 Node = df.Node, // jshint ignore:line
14989 Deps = df.Dependencies,
14990 Tuple = df.Tuple,
14991 ChangeSet = df.ChangeSet,
14992 Sentinel = {},
14993 Encoder = require('./Encoder'),
14994 Bounder = require('./Bounder'),
14995 parseData = require('../parse/data');
14996
14997 function Builder() {
14998 return arguments.length ? this.init.apply(this, arguments) : this;
14999 }
15000
15001 var Status = Builder.STATUS = {
15002 ENTER: 'enter',
15003 UPDATE: 'update',
15004 EXIT: 'exit'
15005 };
15006
15007 var CONNECTED = 1, DISCONNECTED = 2;
15008
15009 var proto = (Builder.prototype = new Node());
15010
15011 proto.init = function(graph, def, mark, parent, parent_id, inheritFrom) {
15012 Node.prototype.init.call(this, graph)
15013 .router(true)
15014 .collector(true);
15015
15016 this._def = def;
15017 this._mark = mark;
15018 this._from = (def.from ? def.from.data : null) || inheritFrom;
15019 this._ds = dl.isString(this._from) ? graph.data(this._from) : null;
15020 this._map = {};
15021 this._status = null; // Connected or disconnected?
15022
15023 mark.def = def;
15024 mark.marktype = def.type;
15025 mark.interactive = (def.interactive !== false);
15026 mark.items = [];
15027 if (dl.isValid(def.name)) mark.name = def.name;
15028
15029 this._parent = parent;
15030 this._parent_id = parent_id;
15031
15032 if (def.from && (def.from.mark || def.from.transform || def.from.modify)) {
15033 inlineDs.call(this);
15034 }
15035
15036 // Non-group mark builders are super nodes. Encoder and Bounder remain
15037 // separate operators but are embedded and called by Builder.evaluate.
15038 this._isSuper = (this._def.type !== 'group');
15039 this._encoder = new Encoder(this._graph, this._mark, this);
15040 this._bounder = new Bounder(this._graph, this._mark);
15041 this._output = null; // Output changeset for reactive geom as Bounder reflows
15042
15043 if (this._ds) { this._encoder.dependency(Deps.DATA, this._from); }
15044
15045 // Since Builders are super nodes, copy over encoder dependencies
15046 // (bounder has no registered dependencies).
15047 this.dependency(Deps.DATA, this._encoder.dependency(Deps.DATA));
15048 this.dependency(Deps.SCALES, this._encoder.dependency(Deps.SCALES));
15049 this.dependency(Deps.SIGNALS, this._encoder.dependency(Deps.SIGNALS));
15050
15051 return this;
15052 };
15053
15054 // Reactive geometry and mark-level transformations are handled here
15055 // because they need their group's data-joined context.
15056 function inlineDs() {
15057 var from = this._def.from,
15058 geom = from.mark,
15059 src, name, spec, sibling, output, input;
15060
15061 if (geom) {
15062 name = ['vg', this._parent_id, geom].join('_');
15063 spec = {
15064 name: name,
15065 transform: from.transform,
15066 modify: from.modify
15067 };
15068 } else {
15069 src = this._graph.data(this._from);
15070 name = ['vg', this._from, this._def.type, src.listeners(true).length].join('_');
15071 spec = {
15072 name: name,
15073 source: this._from,
15074 transform: from.transform,
15075 modify: from.modify
15076 };
15077 }
15078
15079 this._from = name;
15080 this._ds = parseData.datasource(this._graph, spec);
15081 var node;
15082
15083 if (geom) {
15084 sibling = this.sibling(geom);
15085
15086 // Bounder reflows, so we need an intermediary node to propagate
15087 // the output constructed by the Builder.
15088 node = new Node(this._graph).addListener(this._ds.listener());
15089 node.evaluate = function() { return sibling._output; };
15090
15091 if (sibling._isSuper) {
15092 sibling.addListener(node);
15093 } else {
15094 sibling._bounder.addListener(node);
15095 }
15096 } else {
15097 // At this point, we have a new datasource but it is empty as
15098 // the propagation cycle has already crossed the datasources.
15099 // So, we repulse just this datasource. This should be safe
15100 // as the ds isn't connected to the scenegraph yet.
15101 output = this._ds.source().last();
15102 input = ChangeSet.create(output);
15103
15104 input.add = output.add;
15105 input.mod = output.mod;
15106 input.rem = output.rem;
15107 input.stamp = null;
15108 this._graph.propagate(input, this._ds.listener(), output.stamp);
15109 }
15110 }
15111
15112 proto.ds = function() { return this._ds; };
15113 proto.parent = function() { return this._parent; };
15114 proto.encoder = function() { return this._encoder; };
15115 proto.pipeline = function() { return [this]; };
15116
15117 proto.connect = function() {
15118 var builder = this;
15119
15120 this._graph.connect(this.pipeline());
15121 this._encoder._scales.forEach(function(s) {
15122 if (!(s = builder._parent.scale(s))) return;
15123 s.addListener(builder);
15124 });
15125
15126 if (this._parent) {
15127 if (this._isSuper) this.addListener(this._parent._collector);
15128 else this._bounder.addListener(this._parent._collector);
15129 }
15130
15131 return (this._status = CONNECTED, this);
15132 };
15133
15134 proto.disconnect = function() {
15135 var builder = this;
15136 if (!this._listeners.length) return this;
15137
15138 function disconnectScales(scales) {
15139 for(var i=0, len=scales.length, s; i<len; ++i) {
15140 if (!(s = builder._parent.scale(scales[i]))) continue;
15141 s.removeListener(builder);
15142 }
15143 }
15144
15145 Node.prototype.disconnect.call(this);
15146 this._graph.disconnect(this.pipeline());
15147 disconnectScales(this._encoder._scales);
15148 disconnectScales(dl.keys(this._mark._scaleRefs));
15149
15150 return (this._status = DISCONNECTED, this);
15151 };
15152
15153 proto.sibling = function(name) {
15154 return this._parent.child(name, this._parent_id);
15155 };
15156
15157 proto.evaluate = function(input) {
15158 log.debug(input, ['building', (this._from || this._def.from), this._def.type]);
15159
15160 var self = this,
15161 def = this._mark.def,
15162 props = def.properties || {},
15163 update = props.update || {},
15164 output, fullUpdate, fcs, data, name;
15165
15166 if (this._ds) {
15167 output = ChangeSet.create(input);
15168
15169 // We need to determine if any encoder dependencies have been updated.
15170 // However, the encoder's data source will likely be updated, and shouldn't
15171 // trigger all items to mod.
15172 data = output.data[(name=this._ds.name())];
15173 delete output.data[name];
15174 fullUpdate = this._encoder.reevaluate(output);
15175 output.data[name] = data;
15176
15177 // If a scale or signal in the update propset has been updated,
15178 // send forward all items for reencoding if we do an early return.
15179 if (fullUpdate) output.mod = this._mark.items.slice();
15180
15181 fcs = this._ds.last();
15182 if (!fcs) throw Error('Builder evaluated before backing DataSource.');
15183 if (fcs.stamp > this._stamp) {
15184 output = join.call(this, fcs, this._ds.values(), true, fullUpdate);
15185 }
15186 } else {
15187 data = dl.isFunction(this._def.from) ? this._def.from() : [Sentinel];
15188 output = join.call(this, input, data);
15189 }
15190
15191 // Stash output before Bounder for downstream reactive geometry.
15192 this._output = output = this._graph.evaluate(output, this._encoder);
15193
15194 // Add any new scale references to the dependency list, and ensure
15195 // they're connected.
15196 if (update.nested && update.nested.length && this._status === CONNECTED) {
15197 dl.keys(this._mark._scaleRefs).forEach(function(s) {
15198 var scale = self._parent.scale(s);
15199 if (!scale) return;
15200
15201 scale.addListener(self);
15202 self.dependency(Deps.SCALES, s);
15203 self._encoder.dependency(Deps.SCALES, s);
15204 });
15205 }
15206
15207 // Supernodes calculate bounds too, but only on items marked dirty.
15208 if (this._isSuper) {
15209 output.mod = output.mod.filter(function(x) { return x._dirty; });
15210 output = this._graph.evaluate(output, this._bounder);
15211 }
15212
15213 return output;
15214 };
15215
15216 function newItem() {
15217 var item = Tuple.ingest(new Item(this._mark));
15218
15219 // For the root node's item
15220 if (this._def.width) Tuple.set(item, 'width', this._def.width);
15221 if (this._def.height) Tuple.set(item, 'height', this._def.height);
15222 return item;
15223 }
15224
15225 function join(input, data, ds, fullUpdate) {
15226 var output = ChangeSet.create(input),
15227 keyf = keyFunction(this._def.key || (ds ? '_id' : null)),
15228 prev = this._mark.items || [],
15229 rem = ds ? input.rem : prev,
15230 mod = Tuple.idMap((!ds || fullUpdate) ? data : input.mod),
15231 next = [],
15232 i, key, len, item, datum, enter, diff;
15233
15234 // Only mark rems as exiting. Due to keyf, there may be an add/mod
15235 // tuple that replaces it.
15236 for (i=0, len=rem.length; i<len; ++i) {
15237 item = (rem[i] === prev[i]) ? prev[i] :
15238 keyf ? this._map[keyf(rem[i])] : rem[i];
15239 item.status = Status.EXIT;
15240 }
15241
15242 for(i=0, len=data.length; i<len; ++i) {
15243 datum = data[i];
15244 item = keyf ? this._map[key = keyf(datum)] : prev[i];
15245 enter = item ? false : (item = newItem.call(this), true);
15246 item.status = enter ? Status.ENTER : Status.UPDATE;
15247 diff = !enter && item.datum !== datum;
15248 item.datum = datum;
15249
15250 if (keyf) {
15251 Tuple.set(item, 'key', key);
15252 this._map[key] = item;
15253 }
15254
15255 if (enter) {
15256 output.add.push(item);
15257 } else if (diff || mod[datum._id]) {
15258 output.mod.push(item);
15259 }
15260
15261 next.push(item);
15262 }
15263
15264 for (i=0, len=rem.length; i<len; ++i) {
15265 item = (rem[i] === prev[i]) ? prev[i] :
15266 keyf ? this._map[key = keyf(rem[i])] : rem[i];
15267 if (item.status === Status.EXIT) {
15268 item._dirty = true;
15269 input.dirty.push(item);
15270 next.push(item);
15271 output.rem.push(item);
15272 if (keyf) this._map[key] = null;
15273 }
15274 }
15275
15276 return (this._mark.items = next, output);
15277 }
15278
15279 function keyFunction(key) {
15280 if (key == null) return null;
15281 var f = dl.array(key).map(dl.accessor);
15282 return function(d) {
15283 for (var s='', i=0, n=f.length; i<n; ++i) {
15284 if (i>0) s += '|';
15285 s += String(f[i](d));
15286 }
15287 return s;
15288 };
15289 }
15290
15291 module.exports = Builder;
15292 },{"../parse/data":92,"./Bounder":107,"./Encoder":109,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],109:[function(require,module,exports){
15293 var dl = require('datalib'),
15294 log = require('vega-logging'),
15295 df = require('vega-dataflow'),
15296 Node = df.Node, // jshint ignore:line
15297 Deps = df.Dependencies,
15298 bound = require('vega-scenegraph').bound;
15299
15300 var EMPTY = {};
15301
15302 function Encoder(graph, mark, builder) {
15303 var props = mark.def.properties || {},
15304 enter = props.enter,
15305 update = props.update,
15306 exit = props.exit;
15307
15308 Node.prototype.init.call(this, graph);
15309
15310 this._mark = mark;
15311 this._builder = builder;
15312 var s = this._scales = [];
15313
15314 // Only scales used in the 'update' property set are set as
15315 // encoder depedencies to have targeted reevaluations. However,
15316 // we still want scales in 'enter' and 'exit' to be evaluated
15317 // before the encoder.
15318 if (enter) s.push.apply(s, enter.scales);
15319
15320 if (update) {
15321 this.dependency(Deps.DATA, update.data);
15322 this.dependency(Deps.SIGNALS, update.signals);
15323 this.dependency(Deps.FIELDS, update.fields);
15324 this.dependency(Deps.SCALES, update.scales);
15325 s.push.apply(s, update.scales);
15326 }
15327
15328 if (exit) s.push.apply(s, exit.scales);
15329
15330 return this.mutates(true);
15331 }
15332
15333 var proto = (Encoder.prototype = new Node());
15334
15335 proto.evaluate = function(input) {
15336 log.debug(input, ['encoding', this._mark.def.type]);
15337 var graph = this._graph,
15338 props = this._mark.def.properties || {},
15339 items = this._mark.items,
15340 enter = props.enter,
15341 update = props.update,
15342 exit = props.exit,
15343 dirty = input.dirty,
15344 preds = graph.predicates(),
15345 req = input.request,
15346 group = this._mark.group,
15347 guide = group && (group.mark.axis || group.mark.legend),
15348 db = EMPTY, sg = EMPTY, i, len, item, prop;
15349
15350 if (req && !guide) {
15351 if ((prop = props[req]) && input.mod.length) {
15352 db = prop.data ? graph.values(Deps.DATA, prop.data) : null;
15353 sg = prop.signals ? graph.values(Deps.SIGNALS, prop.signals) : null;
15354
15355 for (i=0, len=input.mod.length; i<len; ++i) {
15356 item = input.mod[i];
15357 encode.call(this, prop, item, input.trans, db, sg, preds, dirty);
15358 }
15359 }
15360
15361 return input; // exit early if given request
15362 }
15363
15364 db = values(Deps.DATA, graph, input, props);
15365 sg = values(Deps.SIGNALS, graph, input, props);
15366
15367 // Items marked for removal are at the tail of items. Process them first.
15368 for (i=0, len=input.rem.length; i<len; ++i) {
15369 item = input.rem[i];
15370 if (exit) encode.call(this, exit, item, input.trans, db, sg, preds, dirty);
15371 if (input.trans && !exit) input.trans.interpolate(item, EMPTY);
15372 else if (!input.trans) items.pop();
15373 }
15374
15375 var update_status = require('./Builder').STATUS.UPDATE;
15376 for (i=0, len=input.add.length; i<len; ++i) {
15377 item = input.add[i];
15378 if (enter) encode.call(this, enter, item, input.trans, db, sg, preds, dirty);
15379 if (update) encode.call(this, update, item, input.trans, db, sg, preds, dirty);
15380 item.status = update_status;
15381 }
15382
15383 if (update) {
15384 for (i=0, len=input.mod.length; i<len; ++i) {
15385 item = input.mod[i];
15386 encode.call(this, update, item, input.trans, db, sg, preds, dirty);
15387 }
15388 }
15389
15390 return input;
15391 };
15392
15393 // Only marshal necessary data and signal values
15394 function values(type, graph, input, props) {
15395 var p, x, o, add = input.add.length;
15396 if ((p=props.enter) && (x=p[type]).length && add) {
15397 o = graph.values(type, x, (o=o||{}));
15398 }
15399 if ((p=props.exit) && (x=p[type]).length && input.rem.length) {
15400 o = graph.values(type, x, (o=o||{}));
15401 }
15402 if ((p=props.update) && (x=p[type]).length && (add || input.mod.length)) {
15403 o = graph.values(type, x, (o=o||{}));
15404 }
15405 return o || EMPTY;
15406 }
15407
15408 function encode(prop, item, trans, db, sg, preds, dirty) {
15409 var enc = prop.encode,
15410 wasDirty = item._dirty,
15411 isDirty = enc.call(enc, item, item.mark.group||item, trans, db, sg, preds);
15412
15413 item._dirty = isDirty || wasDirty;
15414 if (isDirty && !wasDirty) dirty.push(item);
15415 }
15416
15417 // If a specified property set called, or update property set
15418 // uses nested fieldrefs, reevaluate all items.
15419 proto.reevaluate = function(pulse) {
15420 var def = this._mark.def,
15421 props = def.properties || {},
15422 reeval = dl.isFunction(def.from) || def.orient || pulse.request ||
15423 Node.prototype.reevaluate.call(this, pulse);
15424
15425 return reeval || (props.update ? nestedRefs.call(this) : false);
15426 };
15427
15428 // Test if any nested refs trigger a reflow of mark items.
15429 function nestedRefs() {
15430 var refs = this._mark.def.properties.update.nested,
15431 parent = this._builder,
15432 level = 0,
15433 i = 0, len = refs.length,
15434 ref, ds, stamp;
15435
15436 for (; i<len; ++i) {
15437 ref = refs[i];
15438
15439 // Scale references are resolved via this._mark._scaleRefs which are
15440 // added to dependency lists + connected in Builder.evaluate.
15441 if (ref.scale) continue;
15442
15443 for (; level<ref.level; ++level) {
15444 parent = parent.parent();
15445 ds = parent.ds();
15446 }
15447
15448 // Compare stamps to determine if a change in a group's properties
15449 // or data should trigger a reeval. We cannot check anything fancier
15450 // (e.g., pulse.fields) as the ref may use item.datum.
15451 stamp = (ref.group ? parent.encoder() : ds.last())._stamp;
15452 if (stamp > this._stamp) return true;
15453 }
15454
15455 return false;
15456 }
15457
15458 // Short-circuit encoder if user specifies items
15459 Encoder.update = function(graph, trans, request, items, dirty) {
15460 items = dl.array(items);
15461 var preds = graph.predicates(),
15462 db = graph.values(Deps.DATA),
15463 sg = graph.values(Deps.SIGNALS),
15464 i, len, item, props, prop;
15465
15466 for (i=0, len=items.length; i<len; ++i) {
15467 item = items[i];
15468 props = item.mark.def.properties;
15469 prop = props && props[request];
15470 if (prop) {
15471 encode.call(null, prop, item, trans, db, sg, preds, dirty);
15472 bound.item(item);
15473 }
15474 }
15475
15476 };
15477
15478 module.exports = Encoder;
15479 },{"./Builder":108,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],110:[function(require,module,exports){
15480 var dl = require('datalib'),
15481 df = require('vega-dataflow'),
15482 Node = df.Node, // jshint ignore:line
15483 Deps = df.Dependencies,
15484 Collector = df.Collector,
15485 log = require('vega-logging'),
15486 Builder = require('./Builder'),
15487 Scale = require('./Scale'),
15488 parseAxes = require('../parse/axes'),
15489 parseLegends = require('../parse/legends');
15490
15491 function GroupBuilder() {
15492 this._children = {};
15493 this._scaler = null;
15494 this._recursor = null;
15495
15496 this._scales = {};
15497 this.scale = scale.bind(this);
15498 return arguments.length ? this.init.apply(this, arguments) : this;
15499 }
15500
15501 var Types = GroupBuilder.TYPES = {
15502 GROUP: "group",
15503 MARK: "mark",
15504 AXIS: "axis",
15505 LEGEND: "legend"
15506 };
15507
15508 var proto = (GroupBuilder.prototype = new Builder());
15509
15510 proto.init = function(graph, def) {
15511 var builder = this, name;
15512
15513 this._scaler = new Node(graph);
15514
15515 (def.scales||[]).forEach(function(s) {
15516 s = builder.scale((name=s.name), new Scale(graph, s, builder));
15517 builder.scale(name+":prev", s);
15518 builder._scaler.addListener(s); // Scales should be computed after group is encoded
15519 });
15520
15521 this._recursor = new Node(graph);
15522 this._recursor.evaluate = recurse.bind(this);
15523
15524 var scales = (def.axes||[]).reduce(function(acc, x) {
15525 return (acc[x.scale] = 1, acc);
15526 }, {});
15527
15528 scales = (def.legends||[]).reduce(function(acc, x) {
15529 return (acc[x.size || x.shape || x.fill || x.stroke], acc);
15530 }, scales);
15531
15532 this._recursor.dependency(Deps.SCALES, dl.keys(scales));
15533
15534 // We only need a collector for up-propagation of bounds calculation,
15535 // so only GroupBuilders, and not regular Builders, have collectors.
15536 this._collector = new Collector(graph);
15537
15538 return Builder.prototype.init.apply(this, arguments);
15539 };
15540
15541 proto.evaluate = function() {
15542 var output = Builder.prototype.evaluate.apply(this, arguments),
15543 builder = this;
15544
15545 output.add.forEach(function(group) { buildGroup.call(builder, output, group); });
15546 return output;
15547 };
15548
15549 proto.pipeline = function() {
15550 return [this, this._scaler, this._recursor, this._collector, this._bounder];
15551 };
15552
15553 proto.disconnect = function() {
15554 var builder = this;
15555 dl.keys(builder._children).forEach(function(group_id) {
15556 builder._children[group_id].forEach(function(c) {
15557 builder._recursor.removeListener(c.builder);
15558 c.builder.disconnect();
15559 });
15560 });
15561
15562 builder._children = {};
15563 return Builder.prototype.disconnect.call(this);
15564 };
15565
15566 proto.child = function(name, group_id) {
15567 var children = this._children[group_id],
15568 i = 0, len = children.length,
15569 child;
15570
15571 for (; i<len; ++i) {
15572 child = children[i];
15573 if (child.type == Types.MARK && child.builder._def.name == name) break;
15574 }
15575
15576 return child.builder;
15577 };
15578
15579 function recurse(input) {
15580 var builder = this,
15581 hasMarks = dl.array(this._def.marks).length > 0,
15582 hasAxes = dl.array(this._def.axes).length > 0,
15583 hasLegends = dl.array(this._def.legends).length > 0,
15584 i, j, c, len, group, pipeline, def, inline = false;
15585
15586 for (i=0, len=input.add.length; i<len; ++i) {
15587 group = input.add[i];
15588 if (hasMarks) buildMarks.call(this, input, group);
15589 if (hasAxes) buildAxes.call(this, input, group);
15590 if (hasLegends) buildLegends.call(this, input, group);
15591 }
15592
15593 // Wire up new children builders in reverse to minimize graph rewrites.
15594 for (i=input.add.length-1; i>=0; --i) {
15595 group = input.add[i];
15596 for (j=this._children[group._id].length-1; j>=0; --j) {
15597 c = this._children[group._id][j];
15598 c.builder.connect();
15599 pipeline = c.builder.pipeline();
15600 def = c.builder._def;
15601
15602 // This new child needs to be built during this propagation cycle.
15603 // We could add its builder as a listener off the _recursor node,
15604 // but try to inline it if we can to minimize graph dispatches.
15605 inline = (def.type !== Types.GROUP);
15606 inline = inline && (this._graph.data(c.from) !== undefined);
15607 inline = inline && (pipeline[pipeline.length-1].listeners().length === 1); // Reactive geom source
15608 inline = inline && (def.from && !def.from.mark); // Reactive geom target
15609 c.inline = inline;
15610
15611 if (inline) this._graph.evaluate(input, c.builder);
15612 else this._recursor.addListener(c.builder);
15613 }
15614 }
15615
15616 function removeTemp(c) {
15617 if (c.type == Types.MARK && !c.inline &&
15618 builder._graph.data(c.from) !== undefined) {
15619 builder._recursor.removeListener(c.builder);
15620 }
15621 }
15622
15623 function updateAxis(a) {
15624 var scale = a.scale();
15625 if (!input.scales[scale.scaleName]) return;
15626 a.reset().def();
15627 }
15628
15629 function updateLegend(l) {
15630 var scale = l.size() || l.shape() || l.fill() || l.stroke();
15631 if (!input.scales[scale.scaleName]) return;
15632 l.reset().def();
15633 }
15634
15635 for (i=0, len=input.mod.length; i<len; ++i) {
15636 group = input.mod[i];
15637
15638 // Remove temporary connection for marks that draw from a source
15639 if (hasMarks) builder._children[group._id].forEach(removeTemp);
15640
15641 // Update axis data defs
15642 if (hasAxes) group.axes.forEach(updateAxis);
15643
15644 // Update legend data defs
15645 if (hasLegends) group.legends.forEach(updateLegend);
15646 }
15647
15648 function disconnectChildren(c) {
15649 builder._recursor.removeListener(c.builder);
15650 c.builder.disconnect();
15651 }
15652
15653 for (i=0, len=input.rem.length; i<len; ++i) {
15654 group = input.rem[i];
15655 // For deleted groups, disconnect their children
15656 builder._children[group._id].forEach(disconnectChildren);
15657 delete builder._children[group._id];
15658 }
15659
15660 return input;
15661 }
15662
15663 function scale(name, x) {
15664 var group = this, s = null;
15665 if (arguments.length === 2) return (group._scales[name] = x, x);
15666 while (s == null) {
15667 s = group._scales[name];
15668 group = group.mark ? group.mark.group : group._parent;
15669 if (!group) break;
15670 }
15671 return s;
15672 }
15673
15674 function buildGroup(input, group) {
15675 log.debug(input, ["building group", group._id]);
15676
15677 group._scales = group._scales || {};
15678 group.scale = scale.bind(group);
15679
15680 group.items = group.items || [];
15681 this._children[group._id] = this._children[group._id] || [];
15682
15683 group.axes = group.axes || [];
15684 group.axisItems = group.axisItems || [];
15685
15686 group.legends = group.legends || [];
15687 group.legendItems = group.legendItems || [];
15688 }
15689
15690 function buildMarks(input, group) {
15691 log.debug(input, ["building children marks #"+group._id]);
15692 var marks = this._def.marks,
15693 mark, from, inherit, i, len, b;
15694
15695 for (i=0, len=marks.length; i<len; ++i) {
15696 mark = marks[i];
15697 from = mark.from || {};
15698 inherit = group.datum._facetID;
15699 group.items[i] = {group: group, _scaleRefs: {}};
15700 b = (mark.type === Types.GROUP) ? new GroupBuilder() : new Builder();
15701 b.init(this._graph, mark, group.items[i], this, group._id, inherit);
15702 this._children[group._id].push({
15703 builder: b,
15704 from: from.data || (from.mark ? ("vg_" + group._id + "_" + from.mark) : inherit),
15705 type: Types.MARK
15706 });
15707 }
15708 }
15709
15710 function buildAxes(input, group) {
15711 var axes = group.axes,
15712 axisItems = group.axisItems,
15713 builder = this;
15714
15715 parseAxes(this._graph, this._def.axes, axes, group);
15716 axes.forEach(function(a, i) {
15717 var scale = builder._def.axes[i].scale,
15718 def = a.def(),
15719 b = null;
15720
15721 axisItems[i] = {group: group, axis: true, layer: def.layer};
15722 b = (def.type === Types.GROUP) ? new GroupBuilder() : new Builder();
15723 b.init(builder._graph, def, axisItems[i], builder)
15724 .dependency(Deps.SCALES, scale);
15725 builder._children[group._id].push({ builder: b, type: Types.AXIS, scale: scale });
15726 });
15727 }
15728
15729 function buildLegends(input, group) {
15730 var legends = group.legends,
15731 legendItems = group.legendItems,
15732 builder = this;
15733
15734 parseLegends(this._graph, this._def.legends, legends, group);
15735 legends.forEach(function(l, i) {
15736 var scale = l.size() || l.shape() || l.fill() || l.stroke(),
15737 def = l.def(),
15738 b = null;
15739
15740 legendItems[i] = {group: group, legend: true};
15741 b = (def.type === Types.GROUP) ? new GroupBuilder() : new Builder();
15742 b.init(builder._graph, def, legendItems[i], builder)
15743 .dependency(Deps.SCALES, scale);
15744 builder._children[group._id].push({ builder: b, type: Types.LEGEND, scale: scale });
15745 });
15746 }
15747
15748 module.exports = GroupBuilder;
15749 },{"../parse/axes":90,"../parse/legends":96,"./Builder":108,"./Scale":111,"datalib":24,"vega-dataflow":39,"vega-logging":45}],111:[function(require,module,exports){
15750 (function (global){
15751 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
15752 dl = require('datalib'),
15753 df = require('vega-dataflow'),
15754 log = require('vega-logging'),
15755 Node = df.Node, // jshint ignore:line
15756 Deps = df.Dependencies,
15757 Aggregate = require('../transforms/Aggregate');
15758
15759 var Properties = {
15760 width: 1,
15761 height: 1
15762 };
15763
15764 var Types = {
15765 LINEAR: 'linear',
15766 ORDINAL: 'ordinal',
15767 LOG: 'log',
15768 POWER: 'pow',
15769 SQRT: 'sqrt',
15770 TIME: 'time',
15771 TIME_UTC: 'utc',
15772 QUANTILE: 'quantile',
15773 QUANTIZE: 'quantize',
15774 THRESHOLD: 'threshold'
15775 };
15776
15777 var DataRef = {
15778 DOMAIN: 'domain',
15779 RANGE: 'range',
15780
15781 COUNT: 'count',
15782 GROUPBY: 'groupby',
15783 MIN: 'min',
15784 MAX: 'max',
15785 VALUE: 'value',
15786
15787 ASC: 'asc',
15788 DESC: 'desc'
15789 };
15790
15791 function Scale(graph, def, parent) {
15792 this._def = def;
15793 this._parent = parent;
15794 this._updated = false;
15795 return Node.prototype.init.call(this, graph).reflows(true);
15796 }
15797
15798 var proto = (Scale.prototype = new Node());
15799
15800 proto.evaluate = function(input) {
15801 var self = this,
15802 fn = function(group) { scale.call(self, group); };
15803
15804 this._updated = false;
15805 input.add.forEach(fn);
15806 input.mod.forEach(fn);
15807
15808 // Scales are at the end of an encoding pipeline, so they should forward a
15809 // reflow pulse. Thus, if multiple scales update in the parent group, we don't
15810 // reevaluate child marks multiple times.
15811 if (this._updated) {
15812 input.scales[this._def.name] = 1;
15813 log.debug(input, ["scale", this._def.name]);
15814 }
15815 return df.ChangeSet.create(input, true);
15816 };
15817
15818 // All of a scale's dependencies are registered during propagation as we parse
15819 // dataRefs. So a scale must be responsible for connecting itself to dependents.
15820 proto.dependency = function(type, deps) {
15821 if (arguments.length == 2) {
15822 var method = (type === Deps.DATA ? 'data' : 'signal');
15823 deps = dl.array(deps);
15824 for (var i=0, len=deps.length; i<len; ++i) {
15825 this._graph[method](deps[i]).addListener(this._parent);
15826 }
15827 }
15828
15829 return Node.prototype.dependency.call(this, type, deps);
15830 };
15831
15832 function scale(group) {
15833 var name = this._def.name,
15834 prev = name + ':prev',
15835 s = instance.call(this, group.scale(name)),
15836 m = s.type===Types.ORDINAL ? ordinal : quantitative,
15837 rng = range.call(this, group);
15838
15839 m.call(this, s, rng, group);
15840
15841 group.scale(name, s);
15842 group.scale(prev, group.scale(prev) || s);
15843
15844 return s;
15845 }
15846
15847 function instance(scale) {
15848 var config = this._graph.config(),
15849 type = this._def.type || Types.LINEAR;
15850 if (!scale || type !== scale.type) {
15851 var ctor = config.scale[type] || d3.scale[type];
15852 if (!ctor) throw Error('Unrecognized scale type: ' + type);
15853 (scale = ctor()).type = scale.type || type;
15854 scale.scaleName = this._def.name;
15855 scale._prev = {};
15856 }
15857 return scale;
15858 }
15859
15860 function ordinal(scale, rng, group) {
15861 var def = this._def,
15862 prev = scale._prev,
15863 dataDrivenRange = false,
15864 pad = signal.call(this, def.padding) || 0,
15865 outer = def.outerPadding == null ? pad : signal.call(this, def.outerPadding),
15866 points = def.points && signal.call(this, def.points),
15867 round = signal.call(this, def.round) || def.round == null,
15868 domain, str;
15869
15870 // range pre-processing for data-driven ranges
15871 if (dl.isObject(def.range) && !dl.isArray(def.range)) {
15872 dataDrivenRange = true;
15873 rng = dataRef.call(this, DataRef.RANGE, def.range, scale, group);
15874 }
15875
15876 // domain
15877 domain = dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group);
15878 if (domain && !dl.equal(prev.domain, domain)) {
15879 scale.domain(domain);
15880 prev.domain = domain;
15881 this._updated = true;
15882 }
15883
15884 // range
15885 if (dl.equal(prev.range, rng)) return;
15886
15887 // width-defined range
15888 if (def.bandWidth) {
15889 var bw = signal.call(this, def.bandWidth),
15890 len = domain.length,
15891 space = def.points ? (pad*bw) : (pad*bw*(len-1) + 2*outer),
15892 start;
15893 if (rng[0] > rng[1]) {
15894 start = rng[1] || 0;
15895 rng = [start + (bw * len + space), start];
15896 } else {
15897 start = rng[0] || 0;
15898 rng = [start, start + (bw * len + space)];
15899 }
15900 }
15901
15902 str = typeof rng[0] === 'string';
15903 if (str || rng.length > 2 || rng.length===1 || dataDrivenRange) {
15904 scale.range(rng); // color or shape values
15905 } else if (points && round) {
15906 scale.rangeRoundPoints(rng, pad);
15907 } else if (points) {
15908 scale.rangePoints(rng, pad);
15909 } else if (round) {
15910 scale.rangeRoundBands(rng, pad, outer);
15911 } else {
15912 scale.rangeBands(rng, pad, outer);
15913 }
15914
15915 if (!scale.invert) {
15916 scale.invert = function(x, y) {
15917 if (arguments.length === 1) {
15918 return scale.domain()[d3.bisect(scale.range(), x) - 1];
15919 } else if (arguments.length === 2) { // Invert extents
15920 if (!dl.isNumber(x) || !dl.isNumber(y)) {
15921 throw Error('Extents to ordinal invert are not numbers ('+x+', '+y+').');
15922 }
15923
15924 var points = [],
15925 rng = scale.range(),
15926 i = 0, len = rng.length, r;
15927
15928 for(; i<len; ++i) {
15929 r = rng[i];
15930 if (x < y ? x <= r && r <= y : y <= r && r <= x) {
15931 points.push(r);
15932 }
15933 }
15934
15935 return points.map(function(p) { return scale.invert(p); });
15936 }
15937 };
15938 }
15939
15940 prev.range = rng;
15941 this._updated = true;
15942 }
15943
15944 function quantitative(scale, rng, group) {
15945 var def = this._def,
15946 prev = scale._prev,
15947 round = signal.call(this, def.round),
15948 exponent = signal.call(this, def.exponent),
15949 clamp = signal.call(this, def.clamp),
15950 nice = signal.call(this, def.nice),
15951 domain, interval;
15952
15953 // domain
15954 domain = (def.type === Types.QUANTILE) ?
15955 dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group) :
15956 domainMinMax.call(this, scale, group);
15957 if (domain && !dl.equal(prev.domain, domain)) {
15958 scale.domain(domain);
15959 prev.domain = domain;
15960 this._updated = true;
15961 }
15962
15963 // range
15964 // vertical scales should flip by default, so use XOR here
15965 if (signal.call(this, def.range) === 'height') rng = rng.reverse();
15966 if (dl.equal(prev.range, rng)) return;
15967 scale[round && scale.rangeRound ? 'rangeRound' : 'range'](rng);
15968 prev.range = rng;
15969 this._updated = true;
15970
15971 // TODO: Support signals for these properties. Until then, only eval
15972 // them once.
15973 if (this._stamp > 0) return;
15974 if (exponent && def.type===Types.POWER) scale.exponent(exponent);
15975 if (clamp) scale.clamp(true);
15976 if (nice) {
15977 if (def.type === Types.TIME) {
15978 interval = d3.time[nice];
15979 if (!interval) log.error('Unrecognized interval: ' + interval);
15980 scale.nice(interval);
15981 } else {
15982 scale.nice();
15983 }
15984 }
15985 }
15986
15987 function isUniques(scale) {
15988 return scale.type === Types.ORDINAL || scale.type === Types.QUANTILE;
15989 }
15990
15991 function getRefs(def) {
15992 return def.fields || dl.array(def);
15993 }
15994
15995 function inherits(refs) {
15996 return refs.some(function(r) {
15997 if (!r.data) return true;
15998 return r.data && dl.array(r.field).some(function(f) {
15999 return f.parent;
16000 });
16001 });
16002 }
16003
16004 function getFields(ref, group) {
16005 return dl.array(ref.field).map(function(f) {
16006 return f.parent ?
16007 dl.accessor(f.parent)(group.datum) :
16008 f; // String or {'signal'}
16009 });
16010 }
16011
16012 // Scale datarefs can be computed over multiple schema types.
16013 // This function determines the type of aggregator created, and
16014 // what data is sent to it: values, tuples, or multi-tuples that must
16015 // be standardized into a consistent schema.
16016 function aggrType(def, scale) {
16017 var refs = getRefs(def);
16018
16019 // If we're operating over only a single domain, send full tuples
16020 // through for efficiency (fewer accessor creations/calls)
16021 if (refs.length == 1 && dl.array(refs[0].field).length == 1) {
16022 return Aggregate.TYPES.TUPLE;
16023 }
16024
16025 // With quantitative scales, we only care about min/max.
16026 if (!isUniques(scale)) return Aggregate.TYPES.VALUE;
16027
16028 // If we don't sort, then we can send values directly to aggrs as well
16029 if (!dl.isObject(def.sort)) return Aggregate.TYPES.VALUE;
16030
16031 return Aggregate.TYPES.MULTI;
16032 }
16033
16034 function getCache(which, def, scale, group) {
16035 var refs = getRefs(def),
16036 inherit = inherits(refs),
16037 atype = aggrType(def, scale),
16038 uniques = isUniques(scale),
16039 sort = def.sort,
16040 ck = '_'+which,
16041 fields = getFields(refs[0], group);
16042
16043 if (scale[ck] || this[ck]) return scale[ck] || this[ck];
16044
16045 var cache = new Aggregate(this._graph).type(atype),
16046 groupby, summarize;
16047
16048 // If a scale's dataref doesn't inherit data from the group, we can
16049 // store the dataref aggregator at the Scale (dataflow node) level.
16050 if (inherit) {
16051 scale[ck] = cache;
16052 } else {
16053 this[ck] = cache;
16054 }
16055
16056 if (uniques) {
16057 if (atype === Aggregate.TYPES.VALUE) {
16058 groupby = [{ name: DataRef.GROUPBY, get: dl.identity }];
16059 summarize = {'*': DataRef.COUNT};
16060 } else if (atype === Aggregate.TYPES.TUPLE) {
16061 groupby = [{ name: DataRef.GROUPBY, get: dl.$(fields[0]) }];
16062 summarize = dl.isObject(sort) ? [{
16063 field: DataRef.VALUE,
16064 get: dl.$(sort.field),
16065 ops: [sort.op]
16066 }] : {'*': DataRef.COUNT};
16067 } else { // atype === Aggregate.TYPES.MULTI
16068 groupby = DataRef.GROUPBY;
16069 summarize = [{ field: DataRef.VALUE, ops: [sort.op] }];
16070 }
16071 } else {
16072 groupby = [];
16073 summarize = [{
16074 field: DataRef.VALUE,
16075 get: (atype == Aggregate.TYPES.TUPLE) ? dl.$(fields[0]) : dl.identity,
16076 ops: [DataRef.MIN, DataRef.MAX],
16077 as: [DataRef.MIN, DataRef.MAX]
16078 }];
16079 }
16080
16081 cache.param('groupby', groupby)
16082 .param('summarize', summarize);
16083
16084 return (cache._lastUpdate = -1, cache);
16085 }
16086
16087 function dataRef(which, def, scale, group) {
16088 if (def == null) { return []; }
16089 if (dl.isArray(def)) return def.map(signal.bind(this));
16090
16091 var self = this, graph = this._graph,
16092 refs = getRefs(def),
16093 inherit = inherits(refs),
16094 atype = aggrType(def, scale),
16095 cache = getCache.apply(this, arguments),
16096 sort = def.sort,
16097 uniques = isUniques(scale),
16098 i, rlen, j, flen, ref, fields, field, data, from, so, cmp;
16099
16100 function addDep(s) {
16101 self.dependency(Deps.SIGNALS, s);
16102 }
16103
16104 if (inherit || (!inherit && cache._lastUpdate < this._stamp)) {
16105 for (i=0, rlen=refs.length; i<rlen; ++i) {
16106 ref = refs[i];
16107 from = ref.data || group.datum._facetID;
16108 data = graph.data(from).last();
16109
16110 if (data.stamp <= this._stamp) continue;
16111
16112 fields = getFields(ref, group);
16113 for (j=0, flen=fields.length; j<flen; ++j) {
16114 field = fields[j];
16115
16116 if (atype === Aggregate.TYPES.VALUE) {
16117 cache.accessors(null, field);
16118 } else if (atype === Aggregate.TYPES.MULTI) {
16119 cache.accessors(field, ref.sort || sort.field);
16120 } // Else (Tuple-case) is handled by the aggregator accessors by default
16121
16122 cache.evaluate(data);
16123 }
16124
16125 this.dependency(Deps.DATA, from);
16126 cache.dependency(Deps.SIGNALS).forEach(addDep);
16127 }
16128
16129 cache._lastUpdate = this._stamp;
16130
16131 data = cache.aggr().result();
16132 if (uniques) {
16133 if (dl.isObject(sort)) {
16134 cmp = (so = sort.order) && so.signal ? graph.signalRef(so.signal) : so;
16135 cmp = (cmp == DataRef.DESC ? '-' : '+') + sort.op + '_' + DataRef.VALUE;
16136 cmp = dl.comparator(cmp);
16137 } else if (sort === true) {
16138 cmp = dl.comparator(DataRef.GROUPBY);
16139 }
16140
16141 if (cmp) data = data.sort(cmp);
16142 cache._values = data.map(function(d) { return d[DataRef.GROUPBY]; });
16143 } else {
16144 data = data[0];
16145 cache._values = !dl.isValid(data) ? [] : [data[DataRef.MIN], data[DataRef.MAX]];
16146 }
16147 }
16148
16149 return cache._values;
16150 }
16151
16152 function signal(v) {
16153 if (!v || !v.signal) return v;
16154 var s = v.signal, ref;
16155 this.dependency(Deps.SIGNALS, (ref = dl.field(s))[0]);
16156 return this._graph.signalRef(ref);
16157 }
16158
16159 function domainMinMax(scale, group) {
16160 var def = this._def,
16161 domain = [null, null], s, z;
16162
16163 if (def.domain !== undefined) {
16164 domain = (!dl.isObject(def.domain)) ? domain :
16165 dataRef.call(this, DataRef.DOMAIN, def.domain, scale, group);
16166 }
16167
16168 z = domain.length - 1;
16169 if (def.domainMin !== undefined) {
16170 if (dl.isObject(def.domainMin)) {
16171 if (def.domainMin.signal) {
16172 domain[0] = dl.isValid(s=signal.call(this, def.domainMin)) ? s : domain[0];
16173 } else {
16174 domain[0] = dataRef.call(this, DataRef.DOMAIN+DataRef.MIN, def.domainMin, scale, group)[0];
16175 }
16176 } else {
16177 domain[0] = def.domainMin;
16178 }
16179 }
16180 if (def.domainMax !== undefined) {
16181 if (dl.isObject(def.domainMax)) {
16182 if (def.domainMax.signal) {
16183 domain[z] = dl.isValid(s=signal.call(this, def.domainMax)) ? s : domain[z];
16184 } else {
16185 domain[z] = dataRef.call(this, DataRef.DOMAIN+DataRef.MAX, def.domainMax, scale, group)[1];
16186 }
16187 } else {
16188 domain[z] = def.domainMax;
16189 }
16190 }
16191 if (def.type !== Types.LOG && def.type !== Types.TIME && (def.zero || def.zero===undefined)) {
16192 domain[0] = Math.min(0, domain[0]);
16193 domain[z] = Math.max(0, domain[z]);
16194 }
16195 return domain;
16196 }
16197
16198 function range(group) {
16199 var def = this._def,
16200 config = this._graph.config(),
16201 rangeVal = signal.call(this, def.range),
16202 rng = [null, null];
16203
16204 if (rangeVal !== undefined) {
16205 if (typeof rangeVal === 'string') {
16206 if (Properties[rangeVal]) {
16207 rng = [0, group[rangeVal]];
16208 } else if (config.range[rangeVal]) {
16209 rng = config.range[rangeVal];
16210 } else {
16211 log.error('Unrecogized range: ' + rangeVal);
16212 return rng;
16213 }
16214 } else if (dl.isArray(rangeVal)) {
16215 rng = dl.duplicate(rangeVal).map(signal.bind(this));
16216 } else if (dl.isObject(rangeVal)) {
16217 return null; // early exit
16218 } else {
16219 rng = [0, rangeVal];
16220 }
16221 }
16222 if (def.rangeMin !== undefined) {
16223 rng[0] = def.rangeMin.signal ?
16224 signal.call(this, def.rangeMin) :
16225 def.rangeMin;
16226 }
16227 if (def.rangeMax !== undefined) {
16228 rng[rng.length-1] = def.rangeMax.signal ?
16229 signal.call(this, def.rangeMax) :
16230 def.rangeMax;
16231 }
16232
16233 if (def.reverse !== undefined) {
16234 var rev = signal.call(this, def.reverse);
16235 if (dl.isObject(rev)) {
16236 rev = dl.accessor(rev.field)(group.datum);
16237 }
16238 if (rev) rng = rng.reverse();
16239 }
16240
16241 return rng;
16242 }
16243
16244 module.exports = Scale;
16245 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
16246
16247 },{"../transforms/Aggregate":116,"datalib":24,"vega-dataflow":39,"vega-logging":45}],112:[function(require,module,exports){
16248 (function (global){
16249 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
16250 bound = require('vega-scenegraph').bound,
16251 Tuple = require('vega-dataflow').Tuple,
16252 Status = require('./Builder').STATUS;
16253
16254 function Transition(duration, ease) {
16255 this.duration = duration || 500;
16256 this.ease = ease && d3.ease(ease) || d3.ease('cubic-in-out');
16257 this.updates = {next: null};
16258 }
16259
16260 var prototype = Transition.prototype;
16261
16262 var skip = {
16263 'text': 1,
16264 'url': 1
16265 };
16266
16267 prototype.interpolate = function(item, values) {
16268 var key, curr, next, interp, list = null;
16269
16270 for (key in values) {
16271 curr = item[key];
16272 next = values[key];
16273 if (curr !== next) {
16274 if (skip[key] || curr === undefined) {
16275 // skip interpolation for specific keys or undefined start values
16276 Tuple.set(item, key, next);
16277 } else if (typeof curr === 'number' && !isFinite(curr)) {
16278 // for NaN or infinite numeric values, skip to final value
16279 Tuple.set(item, key, next);
16280 } else {
16281 // otherwise lookup interpolator
16282 interp = d3.interpolate(curr, next);
16283 interp.property = key;
16284 (list || (list=[])).push(interp);
16285 }
16286 }
16287 }
16288
16289 if (list === null && item.status === Status.EXIT) {
16290 list = []; // ensure exiting items are included
16291 }
16292
16293 if (list != null) {
16294 list.item = item;
16295 list.ease = item.mark.ease || this.ease;
16296 list.next = this.updates.next;
16297 this.updates.next = list;
16298 }
16299 return this;
16300 };
16301
16302 prototype.start = function(callback) {
16303 var t = this, prev = t.updates, curr = prev.next;
16304 for (; curr!=null; prev=curr, curr=prev.next) {
16305 if (curr.item.status === Status.EXIT) {
16306 // Only mark item as exited when it is removed.
16307 curr.item.status = Status.UPDATE;
16308 curr.remove = true;
16309 }
16310 }
16311 t.callback = callback;
16312 d3.timer(function(elapsed) { return step.call(t, elapsed); });
16313 };
16314
16315 function step(elapsed) {
16316 var list = this.updates, prev = list, curr = prev.next,
16317 duration = this.duration,
16318 item, delay, f, e, i, n, stop = true;
16319
16320 for (; curr!=null; prev=curr, curr=prev.next) {
16321 item = curr.item;
16322 delay = item.delay || 0;
16323
16324 f = (elapsed - delay) / duration;
16325 if (f < 0) { stop = false; continue; }
16326 if (f > 1) f = 1;
16327 e = curr.ease(f);
16328
16329 for (i=0, n=curr.length; i<n; ++i) {
16330 item[curr[i].property] = curr[i](e);
16331 }
16332 item.touch();
16333 bound.item(item);
16334
16335 if (f === 1) {
16336 if (curr.remove) {
16337 item.status = Status.EXIT;
16338 item.remove();
16339 }
16340 prev.next = curr.next;
16341 curr = prev;
16342 } else {
16343 stop = false;
16344 }
16345 }
16346
16347 this.callback();
16348 return stop;
16349 }
16350
16351 module.exports = Transition;
16352 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
16353
16354 },{"./Builder":108,"vega-dataflow":39,"vega-scenegraph":46}],113:[function(require,module,exports){
16355 var dl = require('datalib'),
16356 Tuple = require('vega-dataflow').Tuple,
16357 parseMark = require('../parse/mark');
16358
16359 var TIME = 'time',
16360 UTC = 'utc',
16361 STRING = 'string',
16362 ORDINAL = 'ordinal',
16363 NUMBER = 'number';
16364
16365 function axs(model) {
16366 var scale,
16367 config = model.config(),
16368 orient = config.axis.orient,
16369 offset = 0,
16370 titleOffset = config.axis.titleOffset,
16371 axisDef = {},
16372 layer = 'front',
16373 grid = false,
16374 title = null,
16375 tickMajorSize = config.axis.tickSize,
16376 tickMinorSize = config.axis.tickSize,
16377 tickEndSize = config.axis.tickSize,
16378 tickPadding = config.axis.padding,
16379 tickValues = null,
16380 tickFormatString = null,
16381 tickFormatType = null,
16382 tickSubdivide = 0,
16383 tickCount = config.axis.ticks,
16384 gridLineStyle = {},
16385 tickLabelStyle = {},
16386 majorTickStyle = {},
16387 minorTickStyle = {},
16388 titleStyle = {},
16389 domainStyle = {},
16390 m = { // Axis marks as references for updates
16391 gridLines: {},
16392 majorTicks: {},
16393 minorTicks: {},
16394 tickLabels: {},
16395 domain: {},
16396 title: {}
16397 };
16398
16399 var axis = {};
16400
16401 function reset() {
16402 axisDef.type = null;
16403 }
16404
16405 function ingest(d) {
16406 return {data: d};
16407 }
16408
16409 function getTickFormat() {
16410 var formatType = tickFormatType || inferFormatType();
16411 return getFormatter(formatType, tickFormatString);
16412 }
16413
16414 function inferFormatType() {
16415 switch (scale.type) {
16416 case TIME: return TIME;
16417 case UTC: return UTC;
16418 case ORDINAL: return STRING;
16419 default: return NUMBER;
16420 }
16421 }
16422
16423 // Adapted from d3 log scale
16424 // TODO customize? replace with range-size-aware filtering?
16425 function logFilter(domain, count, f) {
16426 if (count == null) return f;
16427 var base = scale.base(),
16428 k = Math.min(base, scale.ticks().length / count),
16429 v = domain[0] > 0 ? (e = 1e-12, Math.ceil) : (e = -1e-12, Math.floor),
16430 e;
16431 function log(x) {
16432 return (domain[0] < 0 ?
16433 -Math.log(x > 0 ? 0 : -x) :
16434 Math.log(x < 0 ? 0 : x)) / Math.log(base);
16435 }
16436 function pow(x) {
16437 return domain[0] < 0 ? -Math.pow(base, -x) : Math.pow(base, x);
16438 }
16439 return function(d) {
16440 return pow(v(log(d) + e)) / d >= k ? f(d) : '';
16441 };
16442 }
16443
16444 function getFormatter(formatType, str) {
16445 var fmt = dl.format,
16446 log = scale.type === 'log',
16447 domain, f;
16448
16449 switch (formatType) {
16450 case NUMBER:
16451 domain = scale.domain();
16452 f = fmt.auto.number(domain, tickCount, str || (log ? '.1r' : null));
16453 return log ? logFilter(domain, tickCount, f) : f;
16454 case TIME: return (str ? fmt : fmt.auto).time(str);
16455 case UTC: return (str ? fmt : fmt.auto).utc(str);
16456 default: return String;
16457 }
16458 }
16459
16460 function getTicks(format) {
16461 var major = tickValues || (scale.ticks ? scale.ticks(tickCount) : scale.domain()),
16462 minor = axisSubdivide(scale, major, tickSubdivide).map(ingest);
16463 major = major.map(function(d) { return (d = ingest(d), d.label = format(d.data), d); });
16464 return [major, minor];
16465 }
16466
16467 axis.def = function() {
16468 if (!axisDef.type) axis_def(scale);
16469
16470 var ticks = getTicks(getTickFormat());
16471 var tdata = title ? [title].map(ingest) : [];
16472
16473 axisDef.marks[0].from = function() { return grid ? ticks[0] : []; };
16474 axisDef.marks[1].from = function() { return ticks[0]; };
16475 axisDef.marks[2].from = function() { return ticks[1]; };
16476 axisDef.marks[3].from = axisDef.marks[1].from;
16477 axisDef.marks[4].from = function() { return [1]; };
16478 axisDef.marks[5].from = function() { return tdata; };
16479 axisDef.offset = offset;
16480 axisDef.orient = orient;
16481 axisDef.layer = layer;
16482
16483 return axisDef;
16484 };
16485
16486 function axis_def(scale) {
16487 // setup scale mapping
16488 var newScale, oldScale, range;
16489 if (scale.type === ORDINAL) {
16490 newScale = {scale: scale.scaleName, offset: 0.5 + scale.rangeBand()/2};
16491 oldScale = newScale;
16492 } else {
16493 newScale = {scale: scale.scaleName, offset: 0.5};
16494 oldScale = {scale: scale.scaleName+':prev', offset: 0.5};
16495 }
16496 range = axisScaleRange(scale);
16497
16498 // setup axis marks
16499 dl.extend(m.gridLines, axisTicks(config));
16500 dl.extend(m.majorTicks, axisTicks(config));
16501 dl.extend(m.minorTicks, axisTicks(config));
16502 dl.extend(m.tickLabels, axisTickLabels(config));
16503 dl.extend(m.domain, axisDomain(config));
16504 dl.extend(m.title, axisTitle(config));
16505 m.gridLines.properties.enter.stroke = {value: config.axis.gridColor};
16506 m.gridLines.properties.enter.strokeOpacity = {value: config.axis.gridOpacity};
16507
16508 // extend axis marks based on axis orientation
16509 axisTicksExtend(orient, m.gridLines, oldScale, newScale, Infinity);
16510 axisTicksExtend(orient, m.majorTicks, oldScale, newScale, tickMajorSize);
16511 axisTicksExtend(orient, m.minorTicks, oldScale, newScale, tickMinorSize);
16512 axisLabelExtend(orient, m.tickLabels, oldScale, newScale, tickMajorSize, tickPadding);
16513
16514 axisDomainExtend(orient, m.domain, range, tickEndSize);
16515 axisTitleExtend(orient, m.title, range, titleOffset); // TODO get offset
16516
16517 // add / override custom style properties
16518 dl.extend(m.gridLines.properties.update, gridLineStyle);
16519 dl.extend(m.majorTicks.properties.update, majorTickStyle);
16520 dl.extend(m.minorTicks.properties.update, minorTickStyle);
16521 dl.extend(m.tickLabels.properties.update, tickLabelStyle);
16522 dl.extend(m.domain.properties.update, domainStyle);
16523 dl.extend(m.title.properties.update, titleStyle);
16524
16525 var marks = [m.gridLines, m.majorTicks, m.minorTicks, m.tickLabels, m.domain, m.title];
16526 dl.extend(axisDef, {
16527 type: 'group',
16528 interactive: false,
16529 properties: {
16530 enter: {
16531 encode: axisUpdate,
16532 scales: [scale.scaleName],
16533 signals: [], data: []
16534 },
16535 update: {
16536 encode: axisUpdate,
16537 scales: [scale.scaleName],
16538 signals: [], data: []
16539 }
16540 }
16541 });
16542
16543 axisDef.marks = marks.map(function(m) { return parseMark(model, m); });
16544 }
16545
16546 axis.scale = function(x) {
16547 if (!arguments.length) return scale;
16548 if (scale !== x) { scale = x; reset(); }
16549 return axis;
16550 };
16551
16552 axis.orient = function(x) {
16553 if (!arguments.length) return orient;
16554 if (orient !== x) {
16555 orient = x in axisOrients ? x + '' : config.axis.orient;
16556 reset();
16557 }
16558 return axis;
16559 };
16560
16561 axis.title = function(x) {
16562 if (!arguments.length) return title;
16563 if (title !== x) { title = x; reset(); }
16564 return axis;
16565 };
16566
16567 axis.tickCount = function(x) {
16568 if (!arguments.length) return tickCount;
16569 tickCount = x;
16570 return axis;
16571 };
16572
16573 axis.tickValues = function(x) {
16574 if (!arguments.length) return tickValues;
16575 tickValues = x;
16576 return axis;
16577 };
16578
16579 axis.tickFormat = function(x) {
16580 if (!arguments.length) return tickFormatString;
16581 if (tickFormatString !== x) {
16582 tickFormatString = x;
16583 reset();
16584 }
16585 return axis;
16586 };
16587
16588 axis.tickFormatType = function(x) {
16589 if (!arguments.length) return tickFormatType;
16590 if (tickFormatType !== x) {
16591 tickFormatType = x;
16592 reset();
16593 }
16594 return axis;
16595 };
16596
16597 axis.tickSize = function(x, y) {
16598 if (!arguments.length) return tickMajorSize;
16599 var n = arguments.length - 1,
16600 major = +x,
16601 minor = n > 1 ? +y : tickMajorSize,
16602 end = n > 0 ? +arguments[n] : tickMajorSize;
16603
16604 if (tickMajorSize !== major ||
16605 tickMinorSize !== minor ||
16606 tickEndSize !== end) {
16607 reset();
16608 }
16609
16610 tickMajorSize = major;
16611 tickMinorSize = minor;
16612 tickEndSize = end;
16613 return axis;
16614 };
16615
16616 axis.tickSubdivide = function(x) {
16617 if (!arguments.length) return tickSubdivide;
16618 tickSubdivide = +x;
16619 return axis;
16620 };
16621
16622 axis.offset = function(x) {
16623 if (!arguments.length) return offset;
16624 offset = dl.isObject(x) ? x : +x;
16625 return axis;
16626 };
16627
16628 axis.tickPadding = function(x) {
16629 if (!arguments.length) return tickPadding;
16630 if (tickPadding !== +x) { tickPadding = +x; reset(); }
16631 return axis;
16632 };
16633
16634 axis.titleOffset = function(x) {
16635 if (!arguments.length) return titleOffset;
16636 if (titleOffset !== +x) { titleOffset = +x; reset(); }
16637 return axis;
16638 };
16639
16640 axis.layer = function(x) {
16641 if (!arguments.length) return layer;
16642 if (layer !== x) { layer = x; reset(); }
16643 return axis;
16644 };
16645
16646 axis.grid = function(x) {
16647 if (!arguments.length) return grid;
16648 if (grid !== x) { grid = x; reset(); }
16649 return axis;
16650 };
16651
16652 axis.gridLineProperties = function(x) {
16653 if (!arguments.length) return gridLineStyle;
16654 if (gridLineStyle !== x) { gridLineStyle = x; }
16655 return axis;
16656 };
16657
16658 axis.majorTickProperties = function(x) {
16659 if (!arguments.length) return majorTickStyle;
16660 if (majorTickStyle !== x) { majorTickStyle = x; }
16661 return axis;
16662 };
16663
16664 axis.minorTickProperties = function(x) {
16665 if (!arguments.length) return minorTickStyle;
16666 if (minorTickStyle !== x) { minorTickStyle = x; }
16667 return axis;
16668 };
16669
16670 axis.tickLabelProperties = function(x) {
16671 if (!arguments.length) return tickLabelStyle;
16672 if (tickLabelStyle !== x) { tickLabelStyle = x; }
16673 return axis;
16674 };
16675
16676 axis.titleProperties = function(x) {
16677 if (!arguments.length) return titleStyle;
16678 if (titleStyle !== x) { titleStyle = x; }
16679 return axis;
16680 };
16681
16682 axis.domainProperties = function(x) {
16683 if (!arguments.length) return domainStyle;
16684 if (domainStyle !== x) { domainStyle = x; }
16685 return axis;
16686 };
16687
16688 axis.reset = function() {
16689 reset();
16690 return axis;
16691 };
16692
16693 return axis;
16694 }
16695
16696 var axisOrients = {top: 1, right: 1, bottom: 1, left: 1};
16697
16698 function axisSubdivide(scale, ticks, m) {
16699 var subticks = [];
16700 if (m && ticks.length > 1) {
16701 var extent = axisScaleExtent(scale.domain()),
16702 i = -1,
16703 n = ticks.length,
16704 d = (ticks[1] - ticks[0]) / ++m,
16705 j,
16706 v;
16707 while (++i < n) {
16708 for (j = m; --j > 0;) {
16709 if ((v = +ticks[i] - j * d) >= extent[0]) {
16710 subticks.push(v);
16711 }
16712 }
16713 }
16714 for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) {
16715 subticks.push(v);
16716 }
16717 }
16718 return subticks;
16719 }
16720
16721 function axisScaleExtent(domain) {
16722 var start = domain[0], stop = domain[domain.length - 1];
16723 return start < stop ? [start, stop] : [stop, start];
16724 }
16725
16726 function axisScaleRange(scale) {
16727 return scale.rangeExtent ?
16728 scale.rangeExtent() :
16729 axisScaleExtent(scale.range());
16730 }
16731
16732 var axisAlign = {
16733 bottom: 'center',
16734 top: 'center',
16735 left: 'right',
16736 right: 'left'
16737 };
16738
16739 var axisBaseline = {
16740 bottom: 'top',
16741 top: 'bottom',
16742 left: 'middle',
16743 right: 'middle'
16744 };
16745
16746 function axisLabelExtend(orient, labels, oldScale, newScale, size, pad) {
16747 size = Math.max(size, 0) + pad;
16748 if (orient === 'left' || orient === 'top') {
16749 size *= -1;
16750 }
16751 if (orient === 'top' || orient === 'bottom') {
16752 dl.extend(labels.properties.enter, {
16753 x: oldScale,
16754 y: {value: size},
16755 });
16756 dl.extend(labels.properties.update, {
16757 x: newScale,
16758 y: {value: size},
16759 align: {value: 'center'},
16760 baseline: {value: axisBaseline[orient]}
16761 });
16762 } else {
16763 dl.extend(labels.properties.enter, {
16764 x: {value: size},
16765 y: oldScale,
16766 });
16767 dl.extend(labels.properties.update, {
16768 x: {value: size},
16769 y: newScale,
16770 align: {value: axisAlign[orient]},
16771 baseline: {value: 'middle'}
16772 });
16773 }
16774 }
16775
16776 function axisTicksExtend(orient, ticks, oldScale, newScale, size) {
16777 var sign = (orient === 'left' || orient === 'top') ? -1 : 1;
16778 if (size === Infinity) {
16779 size = (orient === 'top' || orient === 'bottom') ?
16780 {field: {group: 'height', level: 2}, mult: -sign} :
16781 {field: {group: 'width', level: 2}, mult: -sign};
16782 } else {
16783 size = {value: sign * size};
16784 }
16785 if (orient === 'top' || orient === 'bottom') {
16786 dl.extend(ticks.properties.enter, {
16787 x: oldScale,
16788 y: {value: 0},
16789 y2: size
16790 });
16791 dl.extend(ticks.properties.update, {
16792 x: newScale,
16793 y: {value: 0},
16794 y2: size
16795 });
16796 dl.extend(ticks.properties.exit, {
16797 x: newScale,
16798 });
16799 } else {
16800 dl.extend(ticks.properties.enter, {
16801 x: {value: 0},
16802 x2: size,
16803 y: oldScale
16804 });
16805 dl.extend(ticks.properties.update, {
16806 x: {value: 0},
16807 x2: size,
16808 y: newScale
16809 });
16810 dl.extend(ticks.properties.exit, {
16811 y: newScale,
16812 });
16813 }
16814 }
16815
16816 function axisTitleExtend(orient, title, range, offset) {
16817 var mid = ~~((range[0] + range[1]) / 2),
16818 sign = (orient === 'top' || orient === 'left') ? -1 : 1;
16819
16820 if (orient === 'bottom' || orient === 'top') {
16821 dl.extend(title.properties.update, {
16822 x: {value: mid},
16823 y: {value: sign*offset},
16824 angle: {value: 0}
16825 });
16826 } else {
16827 dl.extend(title.properties.update, {
16828 x: {value: sign*offset},
16829 y: {value: mid},
16830 angle: {value: orient === 'left' ? -90 : 90}
16831 });
16832 }
16833 }
16834
16835 function axisDomainExtend(orient, domain, range, size) {
16836 var path;
16837 if (orient === 'top' || orient === 'left') {
16838 size = -1 * size;
16839 }
16840 if (orient === 'bottom' || orient === 'top') {
16841 path = 'M' + range[0] + ',' + size + 'V0H' + range[1] + 'V' + size;
16842 } else {
16843 path = 'M' + size + ',' + range[0] + 'H0V' + range[1] + 'H' + size;
16844 }
16845 domain.properties.update.path = {value: path};
16846 }
16847
16848 function axisUpdate(item, group, trans) {
16849 var o = trans ? {} : item,
16850 offset = item.mark.def.offset,
16851 orient = item.mark.def.orient,
16852 width = group.width,
16853 height = group.height; // TODO fallback to global w,h?
16854
16855 if (dl.isArray(offset)) {
16856 var ofx = offset[0],
16857 ofy = offset[1];
16858
16859 switch (orient) {
16860 case 'left': { Tuple.set(o, 'x', -ofx); Tuple.set(o, 'y', ofy); break; }
16861 case 'right': { Tuple.set(o, 'x', width + ofx); Tuple.set(o, 'y', ofy); break; }
16862 case 'bottom': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', height + ofy); break; }
16863 case 'top': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', -ofy); break; }
16864 default: { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', ofy); }
16865 }
16866 } else {
16867 if (dl.isObject(offset)) {
16868 offset = -group.scale(offset.scale)(offset.value);
16869 }
16870
16871 switch (orient) {
16872 case 'left': { Tuple.set(o, 'x', -offset); Tuple.set(o, 'y', 0); break; }
16873 case 'right': { Tuple.set(o, 'x', width + offset); Tuple.set(o, 'y', 0); break; }
16874 case 'bottom': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', height + offset); break; }
16875 case 'top': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', -offset); break; }
16876 default: { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', 0); }
16877 }
16878 }
16879
16880 if (trans) trans.interpolate(item, o);
16881 return true;
16882 }
16883
16884 function axisTicks(config) {
16885 return {
16886 type: 'rule',
16887 interactive: false,
16888 key: 'data',
16889 properties: {
16890 enter: {
16891 stroke: {value: config.axis.tickColor},
16892 strokeWidth: {value: config.axis.tickWidth},
16893 opacity: {value: 1e-6}
16894 },
16895 exit: { opacity: {value: 1e-6} },
16896 update: { opacity: {value: 1} }
16897 }
16898 };
16899 }
16900
16901 function axisTickLabels(config) {
16902 return {
16903 type: 'text',
16904 interactive: true,
16905 key: 'data',
16906 properties: {
16907 enter: {
16908 fill: {value: config.axis.tickLabelColor},
16909 font: {value: config.axis.tickLabelFont},
16910 fontSize: {value: config.axis.tickLabelFontSize},
16911 opacity: {value: 1e-6},
16912 text: {field: 'label'}
16913 },
16914 exit: { opacity: {value: 1e-6} },
16915 update: { opacity: {value: 1} }
16916 }
16917 };
16918 }
16919
16920 function axisTitle(config) {
16921 return {
16922 type: 'text',
16923 interactive: true,
16924 properties: {
16925 enter: {
16926 font: {value: config.axis.titleFont},
16927 fontSize: {value: config.axis.titleFontSize},
16928 fontWeight: {value: config.axis.titleFontWeight},
16929 fill: {value: config.axis.titleColor},
16930 align: {value: 'center'},
16931 baseline: {value: 'middle'},
16932 text: {field: 'data'}
16933 },
16934 update: {}
16935 }
16936 };
16937 }
16938
16939 function axisDomain(config) {
16940 return {
16941 type: 'path',
16942 interactive: false,
16943 properties: {
16944 enter: {
16945 x: {value: 0.5},
16946 y: {value: 0.5},
16947 stroke: {value: config.axis.axisColor},
16948 strokeWidth: {value: config.axis.axisWidth}
16949 },
16950 update: {}
16951 }
16952 };
16953 }
16954
16955 module.exports = axs;
16956 },{"../parse/mark":97,"datalib":24,"vega-dataflow":39}],114:[function(require,module,exports){
16957 (function (global){
16958 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
16959 dl = require('datalib'),
16960 Gradient = require('vega-scenegraph').Gradient,
16961 parseProperties = require('../parse/properties'),
16962 parseMark = require('../parse/mark');
16963
16964 function lgnd(model) {
16965 var size = null,
16966 shape = null,
16967 fill = null,
16968 stroke = null,
16969 spacing = null,
16970 values = null,
16971 format = null,
16972 formatString = null,
16973 config = model.config(),
16974 title,
16975 orient = 'right',
16976 offset = config.legend.offset,
16977 padding = config.legend.padding,
16978 tickArguments = [5],
16979 legendStyle = {},
16980 symbolStyle = {},
16981 gradientStyle = {},
16982 titleStyle = {},
16983 labelStyle = {},
16984 m = { // Legend marks as references for updates
16985 titles: {},
16986 symbols: {},
16987 labels: {},
16988 gradient: {}
16989 };
16990
16991 var legend = {},
16992 legendDef = {};
16993
16994 function reset() { legendDef.type = null; }
16995 function ingest(d, i) { return {data: d, index: i}; }
16996
16997 legend.def = function() {
16998 var scale = size || shape || fill || stroke;
16999
17000 format = !formatString ? null : ((scale.type === 'time') ?
17001 dl.format.time(formatString) : dl.format.number(formatString));
17002
17003 if (!legendDef.type) {
17004 legendDef = (scale===fill || scale===stroke) && !discrete(scale.type) ?
17005 quantDef(scale) : ordinalDef(scale);
17006 }
17007 legendDef.orient = orient;
17008 legendDef.offset = offset;
17009 legendDef.padding = padding;
17010 return legendDef;
17011 };
17012
17013 function discrete(type) {
17014 return type==='ordinal' || type==='quantize' ||
17015 type==='quantile' || type==='threshold';
17016 }
17017
17018 function ordinalDef(scale) {
17019 var def = o_legend_def(size, shape, fill, stroke);
17020
17021 // generate data
17022 var data = (values == null ?
17023 (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) :
17024 values).map(ingest);
17025 var fmt = format==null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : String) : format;
17026
17027 // determine spacing between legend entries
17028 var fs, range, offset, pad=5, domain = d3.range(data.length);
17029 if (size) {
17030 range = data.map(function(x) { return Math.sqrt(size(x.data)); });
17031 offset = d3.max(range);
17032 range = range.reduce(function(a,b,i,z) {
17033 if (i > 0) a[i] = a[i-1] + z[i-1]/2 + pad;
17034 return (a[i] += b/2, a); }, [0]).map(Math.round);
17035 } else {
17036 offset = Math.round(Math.sqrt(config.legend.symbolSize));
17037 range = spacing ||
17038 (fs = labelStyle.fontSize) && (fs.value + pad) ||
17039 (config.legend.labelFontSize + pad);
17040 range = domain.map(function(d,i) {
17041 return Math.round(offset/2 + i*range);
17042 });
17043 }
17044
17045 // account for padding and title size
17046 var sz = padding, ts;
17047 if (title) {
17048 ts = titleStyle.fontSize;
17049 sz += 5 + ((ts && ts.value) || config.legend.titleFontSize);
17050 }
17051 for (var i=0, n=range.length; i<n; ++i) range[i] += sz;
17052
17053 // build scale for label layout
17054 var scaleSpec = {
17055 name: 'legend',
17056 type: 'ordinal',
17057 points: true,
17058 domain: domain,
17059 range: range
17060 };
17061
17062 // update legend def
17063 var tdata = (title ? [title] : []).map(ingest);
17064 data.forEach(function(d) {
17065 d.label = fmt(d.data);
17066 d.offset = offset;
17067 });
17068 def.scales = [ scaleSpec ];
17069 def.marks[0].from = function() { return tdata; };
17070 def.marks[1].from = function() { return data; };
17071 def.marks[2].from = def.marks[1].from;
17072
17073 return def;
17074 }
17075
17076 function o_legend_def(size, shape, fill, stroke) {
17077 // setup legend marks
17078 var titles = dl.extend(m.titles, vg_legendTitle(config)),
17079 symbols = dl.extend(m.symbols, vg_legendSymbols(config)),
17080 labels = dl.extend(m.labels, vg_vLegendLabels(config));
17081
17082 // extend legend marks
17083 vg_legendSymbolExtend(symbols, size, shape, fill, stroke);
17084
17085 // add / override custom style properties
17086 dl.extend(titles.properties.update, titleStyle);
17087 dl.extend(symbols.properties.update, symbolStyle);
17088 dl.extend(labels.properties.update, labelStyle);
17089
17090 // padding from legend border
17091 titles.properties.enter.x.value += padding;
17092 titles.properties.enter.y.value += padding;
17093 labels.properties.enter.x.offset += padding + 1;
17094 symbols.properties.enter.x.offset = padding + 1;
17095 labels.properties.update.x.offset += padding + 1;
17096 symbols.properties.update.x.offset = padding + 1;
17097
17098 dl.extend(legendDef, {
17099 type: 'group',
17100 interactive: false,
17101 properties: {
17102 enter: parseProperties(model, 'group', legendStyle),
17103 vg_legendPosition: {
17104 encode: vg_legendPosition,
17105 signals: [], scales:[], data: [], fields: []
17106 }
17107 }
17108 });
17109
17110 legendDef.marks = [titles, symbols, labels].map(function(m) { return parseMark(model, m); });
17111 return legendDef;
17112 }
17113
17114 function quantDef(scale) {
17115 var def = q_legend_def(scale),
17116 dom = scale.domain(),
17117 data = (values == null ?
17118 (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) :
17119 values).map(ingest),
17120 width = (gradientStyle.width && gradientStyle.width.value) || config.legend.gradientWidth,
17121 fmt = format==null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : String) : format;
17122
17123 // build scale for label layout
17124 var layoutSpec = {
17125 name: 'legend',
17126 type: scale.type,
17127 round: true,
17128 zero: false,
17129 domain: [dom[0], dom[dom.length-1]],
17130 range: [padding, width+padding]
17131 };
17132 if (scale.type==='pow') layoutSpec.exponent = scale.exponent();
17133
17134 // update legend def
17135 var tdata = (title ? [title] : []).map(ingest);
17136 data.forEach(function(d,i) {
17137 d.label = fmt(d.data);
17138 d.align = i==(data.length-1) ? 'right' : i===0 ? 'left' : 'center';
17139 });
17140 def.scales = [ layoutSpec ];
17141 def.marks[0].from = function() { return tdata; };
17142 def.marks[1].from = function() { return [1]; };
17143 def.marks[2].from = function() { return data; };
17144 return def;
17145 }
17146
17147 function q_legend_def(scale) {
17148 // setup legend marks
17149 var titles = dl.extend(m.titles, vg_legendTitle(config)),
17150 gradient = dl.extend(m.gradient, vg_legendGradient(config)),
17151 labels = dl.extend(m.labels, vg_hLegendLabels(config)),
17152 grad = new Gradient();
17153
17154 // setup color gradient
17155 var dom = scale.domain(),
17156 min = dom[0],
17157 max = dom[dom.length-1],
17158 f = scale.copy().domain([min, max]).range([0,1]);
17159
17160 var stops = (scale.type !== 'linear' && scale.ticks) ?
17161 scale.ticks.call(scale, 15) : dom;
17162 if (min !== stops[0]) stops.unshift(min);
17163 if (max !== stops[stops.length-1]) stops.push(max);
17164
17165 for (var i=0, n=stops.length; i<n; ++i) {
17166 grad.stop(f(stops[i]), scale(stops[i]));
17167 }
17168 gradient.properties.enter.fill = {value: grad};
17169
17170 // add / override custom style properties
17171 dl.extend(titles.properties.update, titleStyle);
17172 dl.extend(gradient.properties.update, gradientStyle);
17173 dl.extend(labels.properties.update, labelStyle);
17174
17175 // account for gradient size
17176 var gp = gradient.properties, gh = gradientStyle.height,
17177 hh = (gh && gh.value) || gp.enter.height.value;
17178 labels.properties.enter.y.value = hh;
17179 labels.properties.update.y.value = hh;
17180
17181 // account for title size as needed
17182 if (title) {
17183 var tp = titles.properties, fs = titleStyle.fontSize,
17184 sz = 4 + ((fs && fs.value) || tp.enter.fontSize.value);
17185 gradient.properties.enter.y.value += sz;
17186 labels.properties.enter.y.value += sz;
17187 gradient.properties.update.y.value += sz;
17188 labels.properties.update.y.value += sz;
17189 }
17190
17191 // padding from legend border
17192 titles.properties.enter.x.value += padding;
17193 titles.properties.enter.y.value += padding;
17194 gradient.properties.enter.x.value += padding;
17195 gradient.properties.enter.y.value += padding;
17196 labels.properties.enter.y.value += padding;
17197 gradient.properties.update.x.value += padding;
17198 gradient.properties.update.y.value += padding;
17199 labels.properties.update.y.value += padding;
17200
17201 dl.extend(legendDef, {
17202 type: 'group',
17203 interactive: false,
17204 properties: {
17205 enter: parseProperties(model, 'group', legendStyle),
17206 vg_legendPosition: {
17207 encode: vg_legendPosition,
17208 signals: [], scales: [], data: [], fields: []
17209 }
17210 }
17211 });
17212
17213 legendDef.marks = [titles, gradient, labels].map(function(m) { return parseMark(model, m); });
17214 return legendDef;
17215 }
17216
17217 legend.size = function(x) {
17218 if (!arguments.length) return size;
17219 if (size !== x) { size = x; reset(); }
17220 return legend;
17221 };
17222
17223 legend.shape = function(x) {
17224 if (!arguments.length) return shape;
17225 if (shape !== x) { shape = x; reset(); }
17226 return legend;
17227 };
17228
17229 legend.fill = function(x) {
17230 if (!arguments.length) return fill;
17231 if (fill !== x) { fill = x; reset(); }
17232 return legend;
17233 };
17234
17235 legend.stroke = function(x) {
17236 if (!arguments.length) return stroke;
17237 if (stroke !== x) { stroke = x; reset(); }
17238 return legend;
17239 };
17240
17241 legend.title = function(x) {
17242 if (!arguments.length) return title;
17243 if (title !== x) { title = x; reset(); }
17244 return legend;
17245 };
17246
17247 legend.format = function(x) {
17248 if (!arguments.length) return formatString;
17249 if (formatString !== x) {
17250 formatString = x;
17251 reset();
17252 }
17253 return legend;
17254 };
17255
17256 legend.spacing = function(x) {
17257 if (!arguments.length) return spacing;
17258 if (spacing !== +x) { spacing = +x; reset(); }
17259 return legend;
17260 };
17261
17262 legend.orient = function(x) {
17263 if (!arguments.length) return orient;
17264 orient = x in vg_legendOrients ? x + '' : config.legend.orient;
17265 return legend;
17266 };
17267
17268 legend.offset = function(x) {
17269 if (!arguments.length) return offset;
17270 offset = +x;
17271 return legend;
17272 };
17273
17274 legend.values = function(x) {
17275 if (!arguments.length) return values;
17276 values = x;
17277 return legend;
17278 };
17279
17280 legend.legendProperties = function(x) {
17281 if (!arguments.length) return legendStyle;
17282 legendStyle = x;
17283 return legend;
17284 };
17285
17286 legend.symbolProperties = function(x) {
17287 if (!arguments.length) return symbolStyle;
17288 symbolStyle = x;
17289 return legend;
17290 };
17291
17292 legend.gradientProperties = function(x) {
17293 if (!arguments.length) return gradientStyle;
17294 gradientStyle = x;
17295 return legend;
17296 };
17297
17298 legend.labelProperties = function(x) {
17299 if (!arguments.length) return labelStyle;
17300 labelStyle = x;
17301 return legend;
17302 };
17303
17304 legend.titleProperties = function(x) {
17305 if (!arguments.length) return titleStyle;
17306 titleStyle = x;
17307 return legend;
17308 };
17309
17310 legend.reset = function() {
17311 reset();
17312 return legend;
17313 };
17314
17315 return legend;
17316 }
17317
17318 var vg_legendOrients = {right: 1, left: 1};
17319
17320 function vg_legendPosition(item, group, trans, db, signals, predicates) {
17321 var o = trans ? {} : item, gx,
17322 offset = item.mark.def.offset,
17323 orient = item.mark.def.orient,
17324 pad = item.mark.def.padding * 2,
17325 lw = ~~item.bounds.width() + (item.width ? 0 : pad),
17326 lh = ~~item.bounds.height() + (item.height ? 0 : pad),
17327 pos = group._legendPositions ||
17328 (group._legendPositions = {right: 0.5, left: 0.5});
17329
17330 o.x = 0.5;
17331 o.width = lw;
17332 o.y = pos[orient];
17333 pos[orient] += (o.height = lh);
17334
17335 // HACK: use to estimate group bounds during animated transition
17336 if (!trans && group.bounds) {
17337 group.bounds.delta = group.bounds.x2 - group.width;
17338 }
17339
17340 switch (orient) {
17341 case 'left': {
17342 gx = group.bounds ? group.bounds.x1 : 0;
17343 o.x += gx - offset - lw;
17344 break;
17345 }
17346 case 'right': {
17347 gx = group.width + (group.bounds && trans ? group.bounds.delta : 0);
17348 o.x += gx + offset;
17349 break;
17350 }
17351 }
17352
17353 if (trans) trans.interpolate(item, o);
17354 var enc = item.mark.def.properties.enter.encode;
17355 enc.call(enc, item, group, trans, db, signals, predicates);
17356 return true;
17357 }
17358
17359 function vg_legendSymbolExtend(mark, size, shape, fill, stroke) {
17360 var e = mark.properties.enter,
17361 u = mark.properties.update;
17362 if (size) e.size = u.size = {scale: size.scaleName, field: 'data'};
17363 if (shape) e.shape = u.shape = {scale: shape.scaleName, field: 'data'};
17364 if (fill) e.fill = u.fill = {scale: fill.scaleName, field: 'data'};
17365 if (stroke) e.stroke = u.stroke = {scale: stroke.scaleName, field: 'data'};
17366 }
17367
17368 function vg_legendTitle(config) {
17369 var cfg = config.legend;
17370 return {
17371 type: 'text',
17372 interactive: false,
17373 key: 'data',
17374 properties: {
17375 enter: {
17376 x: {value: 0},
17377 y: {value: 0},
17378 fill: {value: cfg.titleColor},
17379 font: {value: cfg.titleFont},
17380 fontSize: {value: cfg.titleFontSize},
17381 fontWeight: {value: cfg.titleFontWeight},
17382 baseline: {value: 'top'},
17383 text: {field: 'data'},
17384 opacity: {value: 1e-6}
17385 },
17386 exit: { opacity: {value: 1e-6} },
17387 update: { opacity: {value: 1} }
17388 }
17389 };
17390 }
17391
17392 function vg_legendSymbols(config) {
17393 var cfg = config.legend;
17394 return {
17395 type: 'symbol',
17396 interactive: false,
17397 key: 'data',
17398 properties: {
17399 enter: {
17400 x: {field: 'offset', mult: 0.5},
17401 y: {scale: 'legend', field: 'index'},
17402 shape: {value: cfg.symbolShape},
17403 size: {value: cfg.symbolSize},
17404 stroke: {value: cfg.symbolColor},
17405 strokeWidth: {value: cfg.symbolStrokeWidth},
17406 opacity: {value: 1e-6}
17407 },
17408 exit: { opacity: {value: 1e-6} },
17409 update: {
17410 x: {field: 'offset', mult: 0.5},
17411 y: {scale: 'legend', field: 'index'},
17412 opacity: {value: 1}
17413 }
17414 }
17415 };
17416 }
17417
17418 function vg_vLegendLabels(config) {
17419 var cfg = config.legend;
17420 return {
17421 type: 'text',
17422 interactive: false,
17423 key: 'data',
17424 properties: {
17425 enter: {
17426 x: {field: 'offset', offset: 5},
17427 y: {scale: 'legend', field: 'index'},
17428 fill: {value: cfg.labelColor},
17429 font: {value: cfg.labelFont},
17430 fontSize: {value: cfg.labelFontSize},
17431 align: {value: cfg.labelAlign},
17432 baseline: {value: cfg.labelBaseline},
17433 text: {field: 'label'},
17434 opacity: {value: 1e-6}
17435 },
17436 exit: { opacity: {value: 1e-6} },
17437 update: {
17438 opacity: {value: 1},
17439 x: {field: 'offset', offset: 5},
17440 y: {scale: 'legend', field: 'index'},
17441 }
17442 }
17443 };
17444 }
17445
17446 function vg_legendGradient(config) {
17447 var cfg = config.legend;
17448 return {
17449 type: 'rect',
17450 interactive: false,
17451 properties: {
17452 enter: {
17453 x: {value: 0},
17454 y: {value: 0},
17455 width: {value: cfg.gradientWidth},
17456 height: {value: cfg.gradientHeight},
17457 stroke: {value: cfg.gradientStrokeColor},
17458 strokeWidth: {value: cfg.gradientStrokeWidth},
17459 opacity: {value: 1e-6}
17460 },
17461 exit: { opacity: {value: 1e-6} },
17462 update: {
17463 x: {value: 0},
17464 y: {value: 0},
17465 opacity: {value: 1}
17466 }
17467 }
17468 };
17469 }
17470
17471 function vg_hLegendLabels(config) {
17472 var cfg = config.legend;
17473 return {
17474 type: 'text',
17475 interactive: false,
17476 key: 'data',
17477 properties: {
17478 enter: {
17479 x: {scale: 'legend', field: 'data'},
17480 y: {value: 20},
17481 dy: {value: 2},
17482 fill: {value: cfg.labelColor},
17483 font: {value: cfg.labelFont},
17484 fontSize: {value: cfg.labelFontSize},
17485 align: {field: 'align'},
17486 baseline: {value: 'top'},
17487 text: {field: 'label'},
17488 opacity: {value: 1e-6}
17489 },
17490 exit: { opacity: {value: 1e-6} },
17491 update: {
17492 x: {scale: 'legend', field: 'data'},
17493 y: {value: 20},
17494 opacity: {value: 1}
17495 }
17496 }
17497 };
17498 }
17499
17500 module.exports = lgnd;
17501 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
17502
17503 },{"../parse/mark":97,"../parse/properties":102,"datalib":24,"vega-scenegraph":46}],115:[function(require,module,exports){
17504 module.exports = function visit(node, func) {
17505 var i, n, s, m, items;
17506 if (func(node)) return true;
17507
17508 var sets = ['items', 'axisItems', 'legendItems'];
17509 for (s=0, m=sets.length; s<m; ++s) {
17510 if ((items = node[sets[s]])) {
17511 for (i=0, n=items.length; i<n; ++i) {
17512 if (visit(items[i], func)) return true;
17513 }
17514 }
17515 }
17516 };
17517 },{}],116:[function(require,module,exports){
17518 var dl = require('datalib'),
17519 df = require('vega-dataflow'),
17520 log = require('vega-logging'),
17521 ChangeSet = df.ChangeSet,
17522 Tuple = df.Tuple,
17523 Deps = df.Dependencies,
17524 Transform = require('./Transform'),
17525 Facetor = require('./Facetor');
17526
17527 function Aggregate(graph) {
17528 Transform.prototype.init.call(this, graph);
17529
17530 Transform.addParameters(this, {
17531 groupby: {type: 'array<field>'},
17532 summarize: {
17533 type: 'custom',
17534 set: function(summarize) {
17535 var signalDeps = {},
17536 tx = this._transform,
17537 i, len, f, fields, name, ops;
17538
17539 if (!dl.isArray(fields = summarize)) { // Object syntax from dl
17540 fields = [];
17541 for (name in summarize) {
17542 ops = dl.array(summarize[name]);
17543 fields.push({field: name, ops: ops});
17544 }
17545 }
17546
17547 function sg(x) { if (x.signal) signalDeps[x.signal] = 1; }
17548
17549 for (i=0, len=fields.length; i<len; ++i) {
17550 f = fields[i];
17551 if (f.field.signal) { signalDeps[f.field.signal] = 1; }
17552 dl.array(f.ops).forEach(sg);
17553 dl.array(f.as).forEach(sg);
17554 }
17555
17556 tx._fields = fields;
17557 tx._aggr = null;
17558 tx.dependency(Deps.SIGNALS, dl.keys(signalDeps));
17559 return tx;
17560 }
17561 }
17562 });
17563
17564 this._aggr = null; // dl.Aggregator
17565 this._input = null; // Used by Facetor._on_keep.
17566 this._args = null; // To cull re-computation.
17567 this._fields = [];
17568 this._out = [];
17569
17570 this._type = TYPES.TUPLE;
17571 this._acc = {groupby: dl.true, value: dl.true};
17572
17573 return this.router(true).produces(true);
17574 }
17575
17576 var prototype = (Aggregate.prototype = Object.create(Transform.prototype));
17577 prototype.constructor = Aggregate;
17578
17579 var TYPES = Aggregate.TYPES = {
17580 VALUE: 1,
17581 TUPLE: 2,
17582 MULTI: 3
17583 };
17584
17585 Aggregate.VALID_OPS = [
17586 'values', 'count', 'valid', 'missing', 'distinct',
17587 'sum', 'mean', 'average', 'variance', 'variancep', 'stdev',
17588 'stdevp', 'median', 'q1', 'q3', 'modeskew', 'min', 'max',
17589 'argmin', 'argmax'
17590 ];
17591
17592 prototype.type = function(type) {
17593 return (this._type = type, this);
17594 };
17595
17596 prototype.accessors = function(groupby, value) {
17597 var acc = this._acc;
17598 acc.groupby = dl.$(groupby) || dl.true;
17599 acc.value = dl.$(value) || dl.true;
17600 };
17601
17602 prototype.aggr = function() {
17603 if (this._aggr) return this._aggr;
17604
17605 var g = this._graph,
17606 hasGetter = false,
17607 args = [],
17608 groupby = this.param('groupby').field,
17609 value = function(x) { return x.signal ? g.signalRef(x.signal) : x; };
17610
17611 // Prepare summarize fields.
17612 var fields = this._fields.map(function(f) {
17613 var field = {
17614 name: value(f.field),
17615 as: dl.array(f.as),
17616 ops: dl.array(value(f.ops)).map(value),
17617 get: f.get
17618 };
17619 hasGetter = hasGetter || field.get != null;
17620 args.push(field.name);
17621 return field;
17622 });
17623
17624 // If there is an arbitrary getter, all bets are off.
17625 // Otherwise, we can check argument fields to cull re-computation.
17626 groupby.forEach(function(g) {
17627 if (g.get) hasGetter = true;
17628 args.push(g.name || g);
17629 });
17630 this._args = hasGetter || !fields.length ? null : args;
17631
17632 if (!fields.length) fields = {'*': 'values'};
17633
17634 // Instatiate our aggregator instance.
17635 // Facetor is a special subclass that can facet into data pipelines.
17636 var aggr = this._aggr = new Facetor()
17637 .groupby(groupby)
17638 .stream(true)
17639 .summarize(fields);
17640
17641 // Collect output fields sets by this aggregate.
17642 this._out = getFields(aggr);
17643
17644 // If we are processing tuples, key them by '_id'.
17645 if (this._type !== TYPES.VALUE) { aggr.key('_id'); }
17646
17647 return aggr;
17648 };
17649
17650 function getFields(aggr) {
17651 // Collect the output fields set by this aggregate.
17652 var f = [], i, n, j, m, dims, vals, meas;
17653
17654 dims = aggr._dims;
17655 for (i=0, n=dims.length; i<n; ++i) {
17656 f.push(dims[i].name);
17657 }
17658
17659 vals = aggr._aggr;
17660 for (i=0, n=vals.length; i<n; ++i) {
17661 meas = vals[i].measures.fields;
17662 for (j=0, m=meas.length; j<m; ++j) {
17663 f.push(meas[j]);
17664 }
17665 }
17666
17667 return f;
17668 }
17669
17670 prototype.transform = function(input, reset) {
17671 log.debug(input, ['aggregate']);
17672 this._input = input; // Used by Facetor._on_keep.
17673
17674 var output = ChangeSet.create(input),
17675 aggr = this.aggr(),
17676 out = this._out,
17677 args = this._args,
17678 reeval = true,
17679 p = Tuple.prev,
17680 add, rem, mod, i;
17681
17682 // Upon reset, retract prior tuples and re-initialize.
17683 if (reset) {
17684 output.rem.push.apply(output.rem, aggr.result());
17685 aggr.clear();
17686 this._aggr = null;
17687 aggr = this.aggr();
17688 }
17689
17690 // Get update methods according to input type.
17691 if (this._type === TYPES.TUPLE) {
17692 add = function(x) { aggr._add(x); Tuple.prev_init(x); };
17693 rem = function(x) { aggr._rem(p(x)); };
17694 mod = function(x) { aggr._mod(x, p(x)); };
17695 } else {
17696 var gby = this._acc.groupby,
17697 val = this._acc.value,
17698 get = this._type === TYPES.VALUE ? val : function(x) {
17699 return { _id: x._id, groupby: gby(x), value: val(x) };
17700 };
17701 add = function(x) { aggr._add(get(x)); Tuple.prev_init(x); };
17702 rem = function(x) { aggr._rem(get(p(x))); };
17703 mod = function(x) { aggr._mod(get(x), get(p(x))); };
17704 }
17705
17706 input.add.forEach(add);
17707 if (reset) {
17708 // A signal change triggered reflow. Add everything.
17709 // No need for rem, we cleared the aggregator.
17710 input.mod.forEach(add);
17711 } else {
17712 input.rem.forEach(rem);
17713
17714 // If possible, check argument fields to see if we need to re-process mods.
17715 if (args) for (i=0, reeval=false; i<args.length; ++i) {
17716 if (input.fields[args[i]]) { reeval = true; break; }
17717 }
17718 if (reeval) input.mod.forEach(mod);
17719 }
17720
17721 // Indicate output fields and return aggregate tuples.
17722 for (i=0; i<out.length; ++i) {
17723 output.fields[out[i]] = 1;
17724 }
17725 return aggr.changes(output);
17726 };
17727
17728 module.exports = Aggregate;
17729 },{"./Facetor":122,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],117:[function(require,module,exports){
17730 var Base = require('./Transform').prototype;
17731
17732 function BatchTransform() {
17733 // Nearest appropriate collector.
17734 // Set by the dataflow Graph during connection.
17735 this._collector = null;
17736 }
17737
17738 var prototype = (BatchTransform.prototype = Object.create(Base));
17739 prototype.constructor = BatchTransform;
17740
17741 prototype.init = function(graph) {
17742 Base.init.call(this, graph);
17743 return this.batch(true);
17744 };
17745
17746 prototype.transform = function(input) {
17747 return this.batchTransform(input, this._collector.data());
17748 };
17749
17750 prototype.batchTransform = function(/* input, data */) {
17751 };
17752
17753 module.exports = BatchTransform;
17754 },{"./Transform":135}],118:[function(require,module,exports){
17755 var bins = require('datalib').bins,
17756 Tuple = require('vega-dataflow').Tuple,
17757 log = require('vega-logging'),
17758 Transform = require('./Transform');
17759
17760 function Bin(graph) {
17761 Transform.prototype.init.call(this, graph);
17762 Transform.addParameters(this, {
17763 field: {type: 'field'},
17764 min: {type: 'value'},
17765 max: {type: 'value'},
17766 base: {type: 'value', default: 10},
17767 maxbins: {type: 'value', default: 20},
17768 step: {type: 'value'},
17769 steps: {type: 'value'},
17770 minstep: {type: 'value'},
17771 div: {type: 'array<value>', default: [5, 2]}
17772 });
17773
17774 this._output = {bin: 'bin'};
17775 return this.mutates(true);
17776 }
17777
17778 var prototype = (Bin.prototype = Object.create(Transform.prototype));
17779 prototype.constructor = Bin;
17780
17781 prototype.transform = function(input) {
17782 log.debug(input, ['binning']);
17783
17784 var output = this._output.bin,
17785 step = this.param('step'),
17786 steps = this.param('steps'),
17787 minstep = this.param('minstep'),
17788 get = this.param('field').accessor,
17789 opt = {
17790 min: this.param('min'),
17791 max: this.param('max'),
17792 base: this.param('base'),
17793 maxbins: this.param('maxbins'),
17794 div: this.param('div')
17795 };
17796
17797 if (step) opt.step = step;
17798 if (steps) opt.steps = steps;
17799 if (minstep) opt.minstep = minstep;
17800 var b = bins(opt);
17801
17802 function update(d) {
17803 var v = get(d);
17804 v = v == null ? null
17805 : b.start + b.step * ~~((v - b.start) / b.step);
17806 Tuple.set(d, output, v);
17807 }
17808 input.add.forEach(update);
17809 input.mod.forEach(update);
17810 input.rem.forEach(update);
17811
17812 input.fields[output] = 1;
17813 return input;
17814 };
17815
17816 module.exports = Bin;
17817 },{"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],119:[function(require,module,exports){
17818 var df = require('vega-dataflow'),
17819 Tuple = df.Tuple,
17820 log = require('vega-logging'),
17821 Transform = require('./Transform');
17822
17823 function CountPattern(graph) {
17824 Transform.prototype.init.call(this, graph);
17825 Transform.addParameters(this, {
17826 field: {type: 'field', default: 'data'},
17827 pattern: {type: 'value', default: '[\\w\']+'},
17828 case: {type: 'value', default: 'lower'},
17829 stopwords: {type: 'value', default: ''}
17830 });
17831
17832 this._output = {text: 'text', count: 'count'};
17833
17834 return this.router(true).produces(true);
17835 }
17836
17837 var prototype = (CountPattern.prototype = Object.create(Transform.prototype));
17838 prototype.constructor = CountPattern;
17839
17840 prototype.transform = function(input, reset) {
17841 log.debug(input, ['countpattern']);
17842
17843 var get = this.param('field').accessor,
17844 pattern = this.param('pattern'),
17845 stop = this.param('stopwords'),
17846 rem = false;
17847
17848 // update parameters
17849 if (this._stop !== stop) {
17850 this._stop = stop;
17851 this._stop_re = new RegExp('^' + stop + '$', 'i');
17852 reset = true;
17853 }
17854
17855 if (this._pattern !== pattern) {
17856 this._pattern = pattern;
17857 this._match = new RegExp(this._pattern, 'g');
17858 reset = true;
17859 }
17860
17861 if (reset) this._counts = {};
17862
17863 function curr(t) { return (Tuple.prev_init(t), get(t)); }
17864 function prev(t) { return get(Tuple.prev(t)); }
17865
17866 this._add(input.add, curr);
17867 if (!reset) this._rem(input.rem, prev);
17868 if (reset || (rem = input.fields[get.field])) {
17869 if (rem) this._rem(input.mod, prev);
17870 this._add(input.mod, curr);
17871 }
17872
17873 // generate output tuples
17874 return this._changeset(input);
17875 };
17876
17877 prototype._changeset = function(input) {
17878 var counts = this._counts,
17879 tuples = this._tuples || (this._tuples = {}),
17880 change = df.ChangeSet.create(input),
17881 out = this._output, w, t, c;
17882
17883 for (w in counts) {
17884 t = tuples[w];
17885 c = counts[w] || 0;
17886 if (!t && c) {
17887 tuples[w] = (t = Tuple.ingest({}));
17888 t[out.text] = w;
17889 t[out.count] = c;
17890 change.add.push(t);
17891 } else if (c === 0) {
17892 if (t) change.rem.push(t);
17893 delete counts[w];
17894 delete tuples[w];
17895 } else if (t[out.count] !== c) {
17896 Tuple.set(t, out.count, c);
17897 change.mod.push(t);
17898 }
17899 }
17900 return change;
17901 };
17902
17903 prototype._tokenize = function(text) {
17904 switch (this.param('case')) {
17905 case 'upper': text = text.toUpperCase(); break;
17906 case 'lower': text = text.toLowerCase(); break;
17907 }
17908 return text.match(this._match);
17909 };
17910
17911 prototype._add = function(tuples, get) {
17912 var counts = this._counts,
17913 stop = this._stop_re,
17914 tok, i, j, t;
17915
17916 for (j=0; j<tuples.length; ++j) {
17917 tok = this._tokenize(get(tuples[j]));
17918 for (i=0; i<tok.length; ++i) {
17919 if (!stop.test(t=tok[i])) {
17920 counts[t] = 1 + (counts[t] || 0);
17921 }
17922 }
17923 }
17924 };
17925
17926 prototype._rem = function(tuples, get) {
17927 var counts = this._counts,
17928 stop = this._stop_re,
17929 tok, i, j, t;
17930
17931 for (j=0; j<tuples.length; ++j) {
17932 tok = this._tokenize(get(tuples[j]));
17933 for (i=0; i<tok.length; ++i) {
17934 if (!stop.test(t=tok[i])) {
17935 counts[t] -= 1;
17936 }
17937 }
17938 }
17939 };
17940
17941 module.exports = CountPattern;
17942 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],120:[function(require,module,exports){
17943 var df = require('vega-dataflow'),
17944 ChangeSet = df.ChangeSet,
17945 Tuple = df.Tuple,
17946 SIGNALS = df.Dependencies.SIGNALS,
17947 log = require('vega-logging'),
17948 Transform = require('./Transform'),
17949 BatchTransform = require('./BatchTransform');
17950
17951 function Cross(graph) {
17952 BatchTransform.prototype.init.call(this, graph);
17953 Transform.addParameters(this, {
17954 with: {type: 'data'},
17955 diagonal: {type: 'value', default: 'true'},
17956 filter: {type: 'expr'}
17957 });
17958
17959 this._output = {'left': 'a', 'right': 'b'};
17960 this._lastRem = null; // Most recent stamp that rem occured.
17961 this._lastWith = null; // Last time we crossed w/withds.
17962 this._ids = {};
17963 this._cache = {};
17964
17965 return this.router(true).produces(true);
17966 }
17967
17968 var prototype = (Cross.prototype = Object.create(BatchTransform.prototype));
17969 prototype.constructor = Cross;
17970
17971 // Each cached incoming tuple also has a stamp to track if we need to do
17972 // lazy filtering of removed tuples.
17973 function cache(x, t) {
17974 var c = this._cache[x._id] = this._cache[x._id] || {c: [], s: this._stamp};
17975 c.c.push(t);
17976 }
17977
17978 function add(output, left, data, diag, test, x) {
17979 var i = 0, len = data.length, t = {}, y, id;
17980
17981 for (; i<len; ++i) {
17982 y = data[i];
17983 id = left ? x._id+'_'+y._id : y._id+'_'+x._id;
17984 if (this._ids[id]) continue;
17985 if (x._id == y._id && !diag) continue;
17986
17987 t[this._output.left] = left ? x : y;
17988 t[this._output.right] = left ? y : x;
17989
17990 // Only ingest a tuple if we keep it around.
17991 if (!test || test(t)) {
17992 output.add.push(t=Tuple.ingest(t));
17993 cache.call(this, x, t);
17994 cache.call(this, y, t);
17995 this._ids[id] = 1;
17996 t = {};
17997 }
17998 }
17999 }
18000
18001 function mod(output, left, x) {
18002 var cross = this,
18003 c = this._cache[x._id];
18004
18005 if (this._lastRem > c.s) { // Removed tuples haven't been filtered yet
18006 c.c = c.c.filter(function(y) {
18007 var t = y[cross._output[left ? 'right' : 'left']];
18008 return cross._cache[t._id] !== null;
18009 });
18010 c.s = this._lastRem;
18011 }
18012
18013 output.mod.push.apply(output.mod, c.c);
18014 }
18015
18016 function rem(output, x) {
18017 output.rem.push.apply(output.rem, this._cache[x._id].c);
18018 this._cache[x._id] = null;
18019 this._lastRem = this._stamp;
18020 }
18021
18022 function upFields(input, output) {
18023 if (input.add.length || input.rem.length) {
18024 output.fields[this._output.left] = 1;
18025 output.fields[this._output.right] = 1;
18026 }
18027 }
18028
18029 prototype.batchTransform = function(input, data) {
18030 log.debug(input, ['crossing']);
18031
18032 var w = this.param('with'),
18033 f = this.param('filter'),
18034 diag = this.param('diagonal'),
18035 graph = this._graph,
18036 signals = graph.values(SIGNALS, this.dependency(SIGNALS)),
18037 test = f ? function(x) {return f(x, null, signals); } : null,
18038 selfCross = (!w.name),
18039 woutput = selfCross ? input : w.source.last(),
18040 wdata = selfCross ? data : w.source.values(),
18041 output = ChangeSet.create(input),
18042 r = rem.bind(this, output);
18043
18044 input.rem.forEach(r);
18045 input.add.forEach(add.bind(this, output, true, wdata, diag, test));
18046
18047 if (!selfCross && woutput.stamp > this._lastWith) {
18048 woutput.rem.forEach(r);
18049 woutput.add.forEach(add.bind(this, output, false, data, diag, test));
18050 woutput.mod.forEach(mod.bind(this, output, false));
18051 upFields.call(this, woutput, output);
18052 this._lastWith = woutput.stamp;
18053 }
18054
18055 // Mods need to come after all removals have been run.
18056 input.mod.forEach(mod.bind(this, output, true));
18057 upFields.call(this, input, output);
18058
18059 return output;
18060 };
18061
18062 module.exports = Cross;
18063 },{"./BatchTransform":117,"./Transform":135,"vega-dataflow":39,"vega-logging":45}],121:[function(require,module,exports){
18064 var Transform = require('./Transform'),
18065 Aggregate = require('./Aggregate');
18066
18067 function Facet(graph) {
18068 Transform.addParameters(this, {
18069 transform: {
18070 type: "custom",
18071 set: function(pipeline) {
18072 return (this._transform._pipeline = pipeline, this._transform);
18073 },
18074 get: function() {
18075 var parse = require('../parse/transforms'),
18076 facet = this._transform;
18077 return facet._pipeline.map(function(t) {
18078 return parse(facet._graph, t);
18079 });
18080 }
18081 }
18082 });
18083
18084 this._pipeline = [];
18085 return Aggregate.call(this, graph);
18086 }
18087
18088 var prototype = (Facet.prototype = Object.create(Aggregate.prototype));
18089 prototype.constructor = Facet;
18090
18091 prototype.aggr = function() {
18092 return Aggregate.prototype.aggr.call(this).facet(this);
18093 };
18094
18095 module.exports = Facet;
18096 },{"../parse/transforms":106,"./Aggregate":116,"./Transform":135}],122:[function(require,module,exports){
18097 var dl = require('datalib'),
18098 Aggregator = dl.Aggregator,
18099 Base = Aggregator.prototype,
18100 df = require('vega-dataflow'),
18101 Tuple = df.Tuple,
18102 log = require('vega-logging'),
18103 facetID = 0;
18104
18105 function Facetor() {
18106 Aggregator.call(this);
18107 this._facet = null;
18108 this._facetID = ++facetID;
18109 }
18110
18111 var prototype = (Facetor.prototype = Object.create(Base));
18112 prototype.constructor = Facetor;
18113
18114 prototype.facet = function(f) {
18115 return arguments.length ? (this._facet = f, this) : this._facet;
18116 };
18117
18118 prototype._ingest = function(t) {
18119 return Tuple.ingest(t, null);
18120 };
18121
18122 prototype._assign = Tuple.set;
18123
18124 function disconnect_cell(facet) {
18125 log.debug({}, ['disconnecting cell', this.tuple._id]);
18126 var pipeline = this.ds.pipeline();
18127 facet.removeListener(pipeline[0]);
18128 facet._graph.removeListener(pipeline[0]);
18129 facet._graph.disconnect(pipeline);
18130 }
18131
18132 prototype._newcell = function(x, key) {
18133 var cell = Base._newcell.call(this, x, key),
18134 facet = this._facet;
18135
18136 if (facet) {
18137 var graph = facet._graph,
18138 tuple = cell.tuple,
18139 pipeline = facet.param('transform');
18140 cell.ds = graph.data(tuple._facetID, pipeline, tuple);
18141 cell.disconnect = disconnect_cell;
18142 facet.addListener(pipeline[0]);
18143 }
18144
18145 return cell;
18146 };
18147
18148 prototype._newtuple = function(x, key) {
18149 var t = Base._newtuple.call(this, x);
18150 if (this._facet) {
18151 Tuple.set(t, 'key', key);
18152 Tuple.set(t, '_facetID', this._facetID + '_' + key);
18153 }
18154 return t;
18155 };
18156
18157 prototype.clear = function() {
18158 if (this._facet) {
18159 for (var k in this._cells) {
18160 this._cells[k].disconnect(this._facet);
18161 }
18162 }
18163 return Base.clear.call(this);
18164 };
18165
18166 prototype._on_add = function(x, cell) {
18167 if (this._facet) cell.ds._input.add.push(x);
18168 };
18169
18170 prototype._on_rem = function(x, cell) {
18171 if (this._facet) cell.ds._input.rem.push(x);
18172 };
18173
18174 prototype._on_mod = function(x, prev, cell0, cell1) {
18175 if (this._facet) { // Propagate tuples
18176 if (cell0 === cell1) {
18177 cell0.ds._input.mod.push(x);
18178 } else {
18179 cell0.ds._input.rem.push(x);
18180 cell1.ds._input.add.push(x);
18181 }
18182 }
18183 };
18184
18185 prototype._on_drop = function(cell) {
18186 if (this._facet) cell.disconnect(this._facet);
18187 };
18188
18189 prototype._on_keep = function(cell) {
18190 // propagate sort, signals, fields, etc.
18191 if (this._facet) df.ChangeSet.copy(this._input, cell.ds._input);
18192 };
18193
18194 module.exports = Facetor;
18195 },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],123:[function(require,module,exports){
18196 var df = require('vega-dataflow'),
18197 SIGNALS = df.Dependencies.SIGNALS,
18198 log = require('vega-logging'),
18199 Transform = require('./Transform');
18200
18201 function Filter(graph) {
18202 Transform.prototype.init.call(this, graph);
18203 Transform.addParameters(this, {test: {type: 'expr'}});
18204
18205 this._skip = {};
18206 return this.router(true);
18207 }
18208
18209 var prototype = (Filter.prototype = Object.create(Transform.prototype));
18210 prototype.constructor = Filter;
18211
18212 prototype.transform = function(input) {
18213 log.debug(input, ['filtering']);
18214
18215 var output = df.ChangeSet.create(input),
18216 graph = this._graph,
18217 skip = this._skip,
18218 test = this.param('test'),
18219 signals = graph.values(SIGNALS, this.dependency(SIGNALS));
18220
18221 input.rem.forEach(function(x) {
18222 if (skip[x._id] !== 1) output.rem.push(x);
18223 else skip[x._id] = 0;
18224 });
18225
18226 input.add.forEach(function(x) {
18227 if (test(x, null, signals)) output.add.push(x);
18228 else skip[x._id] = 1;
18229 });
18230
18231 input.mod.forEach(function(x) {
18232 var b = test(x, null, signals),
18233 s = (skip[x._id] === 1);
18234 if (b && s) {
18235 skip[x._id] = 0;
18236 output.add.push(x);
18237 } else if (b && !s) {
18238 output.mod.push(x);
18239 } else if (!b && s) {
18240 // do nothing, keep skip true
18241 } else { // !b && !s
18242 output.rem.push(x);
18243 skip[x._id] = 1;
18244 }
18245 });
18246
18247 return output;
18248 };
18249
18250 module.exports = Filter;
18251 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],124:[function(require,module,exports){
18252 var df = require('vega-dataflow'),
18253 Tuple = df.Tuple,
18254 log = require('vega-logging'),
18255 Transform = require('./Transform');
18256
18257 function Fold(graph) {
18258 Transform.prototype.init.call(this, graph);
18259 Transform.addParameters(this, {
18260 fields: {type: 'array<field>'}
18261 });
18262
18263 this._output = {key: 'key', value: 'value'};
18264 this._cache = {};
18265
18266 return this.router(true).produces(true);
18267 }
18268
18269 var prototype = (Fold.prototype = Object.create(Transform.prototype));
18270 prototype.constructor = Fold;
18271
18272 prototype._reset = function(input, output) {
18273 for (var id in this._cache) {
18274 output.rem.push.apply(output.rem, this._cache[id]);
18275 }
18276 this._cache = {};
18277 };
18278
18279 prototype._tuple = function(x, i, len) {
18280 var list = this._cache[x._id] || (this._cache[x._id] = Array(len));
18281 return list[i] ? Tuple.rederive(x, list[i]) : (list[i] = Tuple.derive(x));
18282 };
18283
18284 prototype._fn = function(data, on, out) {
18285 var i, j, n, m, d, t;
18286 for (i=0, n=data.length; i<n; ++i) {
18287 d = data[i];
18288 for (j=0, m=on.field.length; j<m; ++j) {
18289 t = this._tuple(d, j, m);
18290 Tuple.set(t, this._output.key, on.field[j]);
18291 Tuple.set(t, this._output.value, on.accessor[j](d));
18292 out.push(t);
18293 }
18294 }
18295 };
18296
18297 prototype.transform = function(input, reset) {
18298 log.debug(input, ['folding']);
18299
18300 var fold = this,
18301 on = this.param('fields'),
18302 output = df.ChangeSet.create(input);
18303
18304 if (reset) this._reset(input, output);
18305
18306 this._fn(input.add, on, output.add);
18307 this._fn(input.mod, on, reset ? output.add : output.mod);
18308 input.rem.forEach(function(x) {
18309 output.rem.push.apply(output.rem, fold._cache[x._id]);
18310 fold._cache[x._id] = null;
18311 });
18312
18313 // If we're only propagating values, don't mark key/value as updated.
18314 if (input.add.length || input.rem.length ||
18315 on.field.some(function(f) { return !!input.fields[f]; })) {
18316 output.fields[this._output.key] = 1;
18317 output.fields[this._output.value] = 1;
18318 }
18319 return output;
18320 };
18321
18322 module.exports = Fold;
18323 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],125:[function(require,module,exports){
18324 (function (global){
18325 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
18326 df = require('vega-dataflow'),
18327 Tuple = df.Tuple,
18328 ChangeSet = df.ChangeSet,
18329 log = require('vega-logging'),
18330 Transform = require('./Transform');
18331
18332 function Force(graph) {
18333 Transform.prototype.init.call(this, graph);
18334
18335 this._prev = null;
18336 this._interactive = false;
18337 this._setup = true;
18338 this._nodes = [];
18339 this._links = [];
18340 this._layout = d3.layout.force();
18341
18342 Transform.addParameters(this, {
18343 size: {type: 'array<value>', default: [500, 500]},
18344 bound: {type: 'value', default: true},
18345 links: {type: 'data'},
18346
18347 // TODO: for now force these to be value params only (pun-intended)
18348 // Can update to include fields after Parameter refactoring.
18349 linkStrength: {type: 'value', default: 1},
18350 linkDistance: {type: 'value', default: 20},
18351 charge: {type: 'value', default: -30},
18352
18353 chargeDistance: {type: 'value', default: Infinity},
18354 friction: {type: 'value', default: 0.9},
18355 theta: {type: 'value', default: 0.8},
18356 gravity: {type: 'value', default: 0.1},
18357 alpha: {type: 'value', default: 0.1},
18358 iterations: {type: 'value', default: 500},
18359
18360 interactive: {type: 'value', default: this._interactive},
18361 active: {type: 'value', default: this._prev},
18362 fixed: {type: 'data'}
18363 });
18364
18365 this._output = {
18366 'x': 'layout_x',
18367 'y': 'layout_y'
18368 };
18369
18370 return this.mutates(true);
18371 }
18372
18373 var prototype = (Force.prototype = Object.create(Transform.prototype));
18374 prototype.constructor = Force;
18375
18376 prototype.transform = function(nodeInput, reset) {
18377 log.debug(nodeInput, ['force']);
18378 reset = reset - (nodeInput.signals.active ? 1 : 0);
18379
18380 // get variables
18381 var interactive = this.param('interactive'),
18382 linkSource = this.param('links').source,
18383 linkInput = linkSource.last(),
18384 active = this.param('active'),
18385 output = this._output,
18386 layout = this._layout,
18387 nodes = this._nodes,
18388 links = this._links;
18389
18390 // configure nodes, links and layout
18391 if (linkInput.stamp < nodeInput.stamp) linkInput = null;
18392 this.configure(nodeInput, linkInput, interactive, reset);
18393
18394 // run batch layout
18395 if (!interactive) {
18396 var iterations = this.param('iterations');
18397 for (var i=0; i<iterations; ++i) layout.tick();
18398 layout.stop();
18399 }
18400
18401 // update node positions
18402 this.update(active);
18403
18404 // re-up alpha on parameter change
18405 if (reset || active !== this._prev && active && active.update) {
18406 layout.alpha(this.param('alpha')); // re-start layout
18407 }
18408
18409 // update active node status,
18410 if (active !== this._prev) {
18411 this._prev = active;
18412 }
18413
18414 // process removed nodes or edges
18415 if (nodeInput.rem.length) {
18416 layout.nodes(this._nodes = Tuple.idFilter(nodes, nodeInput.rem));
18417 }
18418 if (linkInput && linkInput.rem.length) {
18419 layout.links(this._links = Tuple.idFilter(links, linkInput.rem));
18420 }
18421
18422 // return changeset
18423 nodeInput.fields[output.x] = 1;
18424 nodeInput.fields[output.y] = 1;
18425 return nodeInput;
18426 };
18427
18428 prototype.configure = function(nodeInput, linkInput, interactive, reset) {
18429 // check if we need to run configuration
18430 var layout = this._layout,
18431 update = this._setup || nodeInput.add.length ||
18432 linkInput && linkInput.add.length ||
18433 interactive !== this._interactive ||
18434 this.param('charge') !== layout.charge() ||
18435 this.param('linkStrength') !== layout.linkStrength() ||
18436 this.param('linkDistance') !== layout.linkDistance();
18437
18438 if (update || reset) {
18439 // a parameter changed, so update tick-only parameters
18440 layout
18441 .size(this.param('size'))
18442 .chargeDistance(this.param('chargeDistance'))
18443 .theta(this.param('theta'))
18444 .gravity(this.param('gravity'))
18445 .friction(this.param('friction'));
18446 }
18447
18448 if (!update) return; // if no more updates needed, return now
18449
18450 this._setup = false;
18451 this._interactive = interactive;
18452
18453 var force = this,
18454 graph = this._graph,
18455 nodes = this._nodes,
18456 links = this._links, a, i;
18457
18458 // process added nodes
18459 for (a=nodeInput.add, i=0; i<a.length; ++i) {
18460 nodes.push({tuple: a[i]});
18461 }
18462
18463 // process added edges
18464 if (linkInput) for (a=linkInput.add, i=0; i<a.length; ++i) {
18465 // TODO add configurable source/target accessors
18466 // TODO support lookup by node id
18467 // TODO process 'mod' of edge source or target?
18468 links.push({
18469 tuple: a[i],
18470 source: nodes[a[i].source],
18471 target: nodes[a[i].target]
18472 });
18473 }
18474
18475 // setup handler for force layout tick events
18476 var tickHandler = !interactive ? null : function() {
18477 // re-schedule the transform, force reflow
18478 graph.propagate(ChangeSet.create(null, true), force);
18479 };
18480
18481 // configure the rest of the layout
18482 layout
18483 .linkStrength(this.param('linkStrength'))
18484 .linkDistance(this.param('linkDistance'))
18485 .charge(this.param('charge'))
18486 .nodes(nodes)
18487 .links(links)
18488 .on('tick', tickHandler)
18489 .start().alpha(this.param('alpha'));
18490 };
18491
18492 prototype.update = function(active) {
18493 var output = this._output,
18494 bound = this.param('bound'),
18495 fixed = this.param('fixed'),
18496 size = this.param('size'),
18497 nodes = this._nodes,
18498 lut = {}, id, i, n, t, x, y;
18499
18500 if (fixed && fixed.source) {
18501 // TODO: could cache and update as needed?
18502 fixed = fixed.source.values();
18503 for (i=0, n=fixed.length; i<n; ++i) {
18504 lut[fixed[i].id] = 1;
18505 }
18506 }
18507
18508 for (i=0; i<nodes.length; ++i) {
18509 n = nodes[i];
18510 t = n.tuple;
18511 id = t._id;
18512
18513 if (active && active.id === id) {
18514 n.fixed = 1;
18515 if (active.update) {
18516 n.x = n.px = active.x;
18517 n.y = n.py = active.y;
18518 }
18519 } else {
18520 n.fixed = lut[id] || 0;
18521 }
18522
18523 x = bound ? Math.max(0, Math.min(n.x, size[0])) : n.x;
18524 y = bound ? Math.max(0, Math.min(n.y, size[1])) : n.y;
18525 Tuple.set(t, output.x, x);
18526 Tuple.set(t, output.y, y);
18527 }
18528 };
18529
18530 module.exports = Force;
18531 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
18532
18533 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],126:[function(require,module,exports){
18534 var df = require('vega-dataflow'),
18535 Tuple = df.Tuple,
18536 SIGNALS = df.Dependencies.SIGNALS,
18537 log = require('vega-logging'),
18538 Transform = require('./Transform');
18539
18540 function Formula(graph) {
18541 Transform.prototype.init.call(this, graph);
18542 Transform.addParameters(this, {
18543 field: {type: 'value'},
18544 expr: {type: 'expr'}
18545 });
18546
18547 return this.mutates(true);
18548 }
18549
18550 var prototype = (Formula.prototype = Object.create(Transform.prototype));
18551 prototype.constructor = Formula;
18552
18553 prototype.transform = function(input) {
18554 log.debug(input, ['formulating']);
18555
18556 var g = this._graph,
18557 field = this.param('field'),
18558 expr = this.param('expr'),
18559 signals = g.values(SIGNALS, this.dependency(SIGNALS));
18560
18561 function set(x) {
18562 Tuple.set(x, field, expr(x, null, signals));
18563 }
18564
18565 input.add.forEach(set);
18566
18567 if (this.reevaluate(input)) {
18568 input.mod.forEach(set);
18569 }
18570
18571 input.fields[field] = 1;
18572 return input;
18573 };
18574
18575 module.exports = Formula;
18576 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],127:[function(require,module,exports){
18577 (function (global){
18578 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
18579 dl = require('datalib'),
18580 Tuple = require('vega-dataflow').Tuple,
18581 log = require('vega-logging'),
18582 Transform = require('./Transform');
18583
18584 function Geo(graph) {
18585 Transform.prototype.init.call(this, graph);
18586 Transform.addParameters(this, Geo.Parameters);
18587 Transform.addParameters(this, {
18588 lon: {type: 'field'},
18589 lat: {type: 'field'}
18590 });
18591
18592 this._output = {
18593 'x': 'layout_x',
18594 'y': 'layout_y'
18595 };
18596 return this.mutates(true);
18597 }
18598
18599 Geo.Parameters = {
18600 projection: {type: 'value', default: 'mercator'},
18601 center: {type: 'array<value>'},
18602 translate: {type: 'array<value>'},
18603 rotate: {type: 'array<value>'},
18604 scale: {type: 'value'},
18605 precision: {type: 'value'},
18606 clipAngle: {type: 'value'},
18607 clipExtent: {type: 'value'}
18608 };
18609
18610 Geo.d3Projection = function() {
18611 var p = this.param('projection'),
18612 param = Geo.Parameters,
18613 proj, name, value;
18614
18615 if (p !== this._mode) {
18616 this._mode = p;
18617 this._projection = d3.geo[p]();
18618 }
18619 proj = this._projection;
18620
18621 for (name in param) {
18622 if (name === 'projection' || !proj[name]) continue;
18623 value = this.param(name);
18624 if (value === undefined || (dl.isArray(value) && value.length === 0)) {
18625 continue;
18626 }
18627 if (value !== proj[name]()) {
18628 proj[name](value);
18629 }
18630 }
18631
18632 return proj;
18633 };
18634
18635 var prototype = (Geo.prototype = Object.create(Transform.prototype));
18636 prototype.constructor = Geo;
18637
18638 prototype.transform = function(input) {
18639 log.debug(input, ['geo']);
18640
18641 var output = this._output,
18642 lon = this.param('lon').accessor,
18643 lat = this.param('lat').accessor,
18644 proj = Geo.d3Projection.call(this);
18645
18646 function set(t) {
18647 var ll = [lon(t), lat(t)];
18648 var xy = proj(ll) || [null, null];
18649 Tuple.set(t, output.x, xy[0]);
18650 Tuple.set(t, output.y, xy[1]);
18651 }
18652
18653 input.add.forEach(set);
18654 if (this.reevaluate(input)) {
18655 input.mod.forEach(set);
18656 input.rem.forEach(set);
18657 }
18658
18659 input.fields[output.x] = 1;
18660 input.fields[output.y] = 1;
18661 return input;
18662 };
18663
18664 module.exports = Geo;
18665 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
18666
18667 },{"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],128:[function(require,module,exports){
18668 (function (global){
18669 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
18670 dl = require('datalib'),
18671 Tuple = require('vega-dataflow').Tuple,
18672 log = require('vega-logging'),
18673 Geo = require('./Geo'),
18674 Transform = require('./Transform');
18675
18676 function GeoPath(graph) {
18677 Transform.prototype.init.call(this, graph);
18678 Transform.addParameters(this, Geo.Parameters);
18679 Transform.addParameters(this, {
18680 field: {type: 'field', default: null},
18681 });
18682
18683 this._output = {
18684 'path': 'layout_path'
18685 };
18686 return this.mutates(true);
18687 }
18688
18689 var prototype = (GeoPath.prototype = Object.create(Transform.prototype));
18690 prototype.constructor = GeoPath;
18691
18692 prototype.transform = function(input) {
18693 log.debug(input, ['geopath']);
18694
18695 var output = this._output,
18696 geojson = this.param('field').accessor || dl.identity,
18697 proj = Geo.d3Projection.call(this),
18698 path = d3.geo.path().projection(proj);
18699
18700 function set(t) {
18701 Tuple.set(t, output.path, path(geojson(t)));
18702 }
18703
18704 input.add.forEach(set);
18705 if (this.reevaluate(input)) {
18706 input.mod.forEach(set);
18707 input.rem.forEach(set);
18708 }
18709
18710 input.fields[output.path] = 1;
18711 return input;
18712 };
18713
18714 module.exports = GeoPath;
18715 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
18716
18717 },{"./Geo":127,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],129:[function(require,module,exports){
18718 var Tuple = require('vega-dataflow').Tuple,
18719 log = require('vega-logging'),
18720 Transform = require('./Transform');
18721
18722 function LinkPath(graph) {
18723 Transform.prototype.init.call(this, graph);
18724 Transform.addParameters(this, {
18725 sourceX: {type: 'field', default: '_source.layout_x'},
18726 sourceY: {type: 'field', default: '_source.layout_y'},
18727 targetX: {type: 'field', default: '_target.layout_x'},
18728 targetY: {type: 'field', default: '_target.layout_y'},
18729 tension: {type: 'value', default: 0.2},
18730 shape: {type: 'value', default: 'line'}
18731 });
18732
18733 this._output = {'path': 'layout_path'};
18734 return this.mutates(true);
18735 }
18736
18737 var prototype = (LinkPath.prototype = Object.create(Transform.prototype));
18738 prototype.constructor = LinkPath;
18739
18740 function line(sx, sy, tx, ty) {
18741 return 'M' + sx + ',' + sy +
18742 'L' + tx + ',' + ty;
18743 }
18744
18745 function curve(sx, sy, tx, ty, tension) {
18746 var dx = tx - sx,
18747 dy = ty - sy,
18748 ix = tension * (dx + dy),
18749 iy = tension * (dy - dx);
18750 return 'M' + sx + ',' + sy +
18751 'C' + (sx+ix) + ',' + (sy+iy) +
18752 ' ' + (tx+iy) + ',' + (ty-ix) +
18753 ' ' + tx + ',' + ty;
18754 }
18755
18756 function diagonalX(sx, sy, tx, ty) {
18757 var m = (sx + tx) / 2;
18758 return 'M' + sx + ',' + sy +
18759 'C' + m + ',' + sy +
18760 ' ' + m + ',' + ty +
18761 ' ' + tx + ',' + ty;
18762 }
18763
18764 function diagonalY(sx, sy, tx, ty) {
18765 var m = (sy + ty) / 2;
18766 return 'M' + sx + ',' + sy +
18767 'C' + sx + ',' + m +
18768 ' ' + tx + ',' + m +
18769 ' ' + tx + ',' + ty;
18770 }
18771
18772 var shapes = {
18773 line: line,
18774 curve: curve,
18775 diagonal: diagonalX,
18776 diagonalX: diagonalX,
18777 diagonalY: diagonalY
18778 };
18779
18780 prototype.transform = function(input) {
18781 log.debug(input, ['linkpath']);
18782
18783 var output = this._output,
18784 shape = shapes[this.param('shape')] || shapes.line,
18785 sourceX = this.param('sourceX').accessor,
18786 sourceY = this.param('sourceY').accessor,
18787 targetX = this.param('targetX').accessor,
18788 targetY = this.param('targetY').accessor,
18789 tension = this.param('tension');
18790
18791 function set(t) {
18792 var path = shape(sourceX(t), sourceY(t), targetX(t), targetY(t), tension);
18793 Tuple.set(t, output.path, path);
18794 }
18795
18796 input.add.forEach(set);
18797 if (this.reevaluate(input)) {
18798 input.mod.forEach(set);
18799 input.rem.forEach(set);
18800 }
18801
18802 input.fields[output.path] = 1;
18803 return input;
18804 };
18805
18806 module.exports = LinkPath;
18807 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],130:[function(require,module,exports){
18808 var Tuple = require('vega-dataflow').Tuple,
18809 log = require('vega-logging'),
18810 Transform = require('./Transform');
18811
18812 function Lookup(graph) {
18813 Transform.prototype.init.call(this, graph);
18814 Transform.addParameters(this, {
18815 on: {type: 'data'},
18816 onKey: {type: 'field', default: null},
18817 as: {type: 'array<value>'},
18818 keys: {type: 'array<field>', default: ['data']},
18819 default: {type: 'value'}
18820 });
18821
18822 return this.mutates(true);
18823 }
18824
18825 var prototype = (Lookup.prototype = Object.create(Transform.prototype));
18826 prototype.constructor = Lookup;
18827
18828 prototype.transform = function(input, reset) {
18829 log.debug(input, ['lookup']);
18830
18831 var on = this.param('on'),
18832 onLast = on.source.last(),
18833 onData = on.source.values(),
18834 onKey = this.param('onKey'),
18835 onF = onKey.field,
18836 keys = this.param('keys'),
18837 get = keys.accessor,
18838 as = this.param('as'),
18839 defaultValue = this.param('default'),
18840 lut = this._lut,
18841 i, v;
18842
18843 // build lookup table on init, withKey modified, or tuple add/rem
18844 if (lut == null || this._on !== onF || onF && onLast.fields[onF] ||
18845 onLast.add.length || onLast.rem.length)
18846 {
18847 if (onF) { // build hash from withKey field
18848 onKey = onKey.accessor;
18849 for (lut={}, i=0; i<onData.length; ++i) {
18850 lut[onKey(v = onData[i])] = v;
18851 }
18852 } else { // otherwise, use index-based lookup
18853 lut = onData;
18854 }
18855 this._lut = lut;
18856 this._on = onF;
18857 reset = true;
18858 }
18859
18860 function set(t) {
18861 for (var i=0; i<get.length; ++i) {
18862 var v = lut[get[i](t)] || defaultValue;
18863 Tuple.set(t, as[i], v);
18864 }
18865 }
18866
18867 input.add.forEach(set);
18868 var run = keys.field.some(function(f) { return input.fields[f]; });
18869 if (run || reset) {
18870 input.mod.forEach(set);
18871 input.rem.forEach(set);
18872 }
18873
18874 as.forEach(function(k) { input.fields[k] = 1; });
18875 return input;
18876 };
18877
18878 module.exports = Lookup;
18879 },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],131:[function(require,module,exports){
18880 var dl = require('datalib'),
18881 Deps = require('vega-dataflow').Dependencies,
18882 expr = require('../parse/expr');
18883
18884 var arrayType = /array/i,
18885 dataType = /data/i,
18886 fieldType = /field/i,
18887 exprType = /expr/i,
18888 valType = /value/i;
18889
18890 function Parameter(name, type, transform) {
18891 this._name = name;
18892 this._type = type;
18893 this._transform = transform;
18894
18895 // If parameter is defined w/signals, it must be resolved
18896 // on every pulse.
18897 this._value = [];
18898 this._accessors = [];
18899 this._resolution = false;
18900 this._signals = {};
18901 }
18902
18903 var prototype = Parameter.prototype;
18904
18905 function get() {
18906 var isArray = arrayType.test(this._type),
18907 isData = dataType.test(this._type),
18908 isField = fieldType.test(this._type);
18909
18910 var val = isArray ? this._value : this._value[0],
18911 acc = isArray ? this._accessors : this._accessors[0];
18912
18913 if (!dl.isValid(acc) && valType.test(this._type)) {
18914 return val;
18915 } else {
18916 return isData ? { name: val, source: acc } :
18917 isField ? { field: val, accessor: acc } : val;
18918 }
18919 }
18920
18921 prototype.get = function() {
18922 var graph = this._transform._graph,
18923 isData = dataType.test(this._type),
18924 isField = fieldType.test(this._type),
18925 s, idx, val;
18926
18927 // If we don't require resolution, return the value immediately.
18928 if (!this._resolution) return get.call(this);
18929
18930 if (isData) {
18931 this._accessors = this._value.map(function(v) { return graph.data(v); });
18932 return get.call(this); // TODO: support signal as dataTypes
18933 }
18934
18935 for (s in this._signals) {
18936 idx = this._signals[s];
18937 val = graph.signalRef(s);
18938
18939 if (isField) {
18940 this._accessors[idx] = this._value[idx] != val ?
18941 dl.accessor(val) : this._accessors[idx];
18942 }
18943
18944 this._value[idx] = val;
18945 }
18946
18947 return get.call(this);
18948 };
18949
18950 prototype.set = function(value) {
18951 var p = this,
18952 isExpr = exprType.test(this._type),
18953 isData = dataType.test(this._type),
18954 isField = fieldType.test(this._type);
18955
18956 this._value = dl.array(value).map(function(v, i) {
18957 if (dl.isString(v)) {
18958 if (isExpr) {
18959 var e = expr(v);
18960 p._transform.dependency(Deps.FIELDS, e.fields);
18961 p._transform.dependency(Deps.SIGNALS, e.globals);
18962 return e.fn;
18963 } else if (isField) { // Backwards compatibility
18964 p._accessors[i] = dl.accessor(v);
18965 p._transform.dependency(Deps.FIELDS, dl.field(v));
18966 } else if (isData) {
18967 p._resolution = true;
18968 p._transform.dependency(Deps.DATA, v);
18969 }
18970 return v;
18971 } else if (v.value !== undefined) {
18972 return v.value;
18973 } else if (v.field !== undefined) {
18974 p._accessors[i] = dl.accessor(v.field);
18975 p._transform.dependency(Deps.FIELDS, dl.field(v.field));
18976 return v.field;
18977 } else if (v.signal !== undefined) {
18978 p._resolution = true;
18979 p._signals[v.signal] = i;
18980 p._transform.dependency(Deps.SIGNALS, v.signal);
18981 return v.signal;
18982 }
18983
18984 return v;
18985 });
18986
18987 return p._transform;
18988 };
18989
18990 module.exports = Parameter;
18991 },{"../parse/expr":94,"datalib":24,"vega-dataflow":39}],132:[function(require,module,exports){
18992 var dl = require('datalib'),
18993 Tuple = require('vega-dataflow').Tuple,
18994 log = require('vega-logging'),
18995 Transform = require('./Transform'),
18996 BatchTransform = require('./BatchTransform');
18997
18998 function Pie(graph) {
18999 BatchTransform.prototype.init.call(this, graph);
19000 Transform.addParameters(this, {
19001 field: {type: 'field', default: null},
19002 startAngle: {type: 'value', default: 0},
19003 endAngle: {type: 'value', default: 2 * Math.PI},
19004 sort: {type: 'value', default: false}
19005 });
19006
19007 this._output = {
19008 'start': 'layout_start',
19009 'end': 'layout_end',
19010 'mid': 'layout_mid'
19011 };
19012
19013 return this.mutates(true);
19014 }
19015
19016 var prototype = (Pie.prototype = Object.create(BatchTransform.prototype));
19017 prototype.constructor = Pie;
19018
19019 function ones() { return 1; }
19020
19021 prototype.batchTransform = function(input, data) {
19022 log.debug(input, ['pie']);
19023
19024 var output = this._output,
19025 field = this.param('field').accessor || ones,
19026 start = this.param('startAngle'),
19027 stop = this.param('endAngle'),
19028 sort = this.param('sort');
19029
19030 var values = data.map(field),
19031 a = start,
19032 k = (stop - start) / dl.sum(values),
19033 index = dl.range(data.length),
19034 i, t, v;
19035
19036 if (sort) {
19037 index.sort(function(a, b) {
19038 return values[a] - values[b];
19039 });
19040 }
19041
19042 for (i=0; i<index.length; ++i) {
19043 t = data[index[i]];
19044 v = values[index[i]];
19045 Tuple.set(t, output.start, a);
19046 Tuple.set(t, output.mid, (a + 0.5 * v * k));
19047 Tuple.set(t, output.end, (a += v * k));
19048 }
19049
19050 input.fields[output.start] = 1;
19051 input.fields[output.end] = 1;
19052 input.fields[output.mid] = 1;
19053 return input;
19054 };
19055
19056 module.exports = Pie;
19057 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],133:[function(require,module,exports){
19058 var dl = require('datalib'),
19059 log = require('vega-logging'),
19060 Transform = require('./Transform');
19061
19062 function Sort(graph) {
19063 Transform.prototype.init.call(this, graph);
19064 Transform.addParameters(this, {by: {type: 'array<field>'} });
19065 this.router(true);
19066 }
19067
19068 var prototype = (Sort.prototype = Object.create(Transform.prototype));
19069 prototype.constructor = Sort;
19070
19071 prototype.transform = function(input) {
19072 log.debug(input, ['sorting']);
19073
19074 if (input.add.length || input.mod.length || input.rem.length) {
19075 input.sort = dl.comparator(this.param('by').field);
19076 }
19077 return input;
19078 };
19079
19080 module.exports = Sort;
19081 },{"./Transform":135,"datalib":24,"vega-logging":45}],134:[function(require,module,exports){
19082 var dl = require('datalib'),
19083 Tuple = require('vega-dataflow').Tuple,
19084 log = require('vega-logging'),
19085 Transform = require('./Transform'),
19086 BatchTransform = require('./BatchTransform');
19087
19088 function Stack(graph) {
19089 BatchTransform.prototype.init.call(this, graph);
19090 Transform.addParameters(this, {
19091 groupby: {type: 'array<field>'},
19092 sortby: {type: 'array<field>'},
19093 field: {type: 'field'},
19094 offset: {type: 'value', default: 'zero'}
19095 });
19096
19097 this._output = {
19098 'start': 'layout_start',
19099 'end': 'layout_end',
19100 'mid': 'layout_mid'
19101 };
19102 return this.mutates(true);
19103 }
19104
19105 var prototype = (Stack.prototype = Object.create(BatchTransform.prototype));
19106 prototype.constructor = Stack;
19107
19108 prototype.batchTransform = function(input, data) {
19109 log.debug(input, ['stacking']);
19110
19111 var groupby = this.param('groupby').accessor,
19112 sortby = dl.comparator(this.param('sortby').field),
19113 field = this.param('field').accessor,
19114 offset = this.param('offset'),
19115 output = this._output;
19116
19117 // partition, sum, and sort the stack groups
19118 var groups = partition(data, groupby, sortby, field);
19119
19120 // compute stack layouts per group
19121 for (var i=0, max=groups.max; i<groups.length; ++i) {
19122 var group = groups[i],
19123 sum = group.sum,
19124 off = offset==='center' ? (max - sum)/2 : 0,
19125 scale = offset==='normalize' ? (1/sum) : 1,
19126 j, x, a, b = off, v = 0;
19127
19128 // set stack coordinates for each datum in group
19129 for (j=0; j<group.length; ++j) {
19130 x = group[j];
19131 a = b; // use previous value for start point
19132 v += field(x);
19133 b = scale * v + off; // compute end point
19134 Tuple.set(x, output.start, a);
19135 Tuple.set(x, output.end, b);
19136 Tuple.set(x, output.mid, 0.5 * (a + b));
19137 }
19138 }
19139
19140 input.fields[output.start] = 1;
19141 input.fields[output.end] = 1;
19142 input.fields[output.mid] = 1;
19143 return input;
19144 };
19145
19146 function partition(data, groupby, sortby, field) {
19147 var groups = [],
19148 get = function(f) { return f(x); },
19149 map, i, x, k, g, s, max;
19150
19151 // partition data points into stack groups
19152 if (groupby == null) {
19153 groups.push(data.slice());
19154 } else {
19155 for (map={}, i=0; i<data.length; ++i) {
19156 x = data[i];
19157 k = groupby.map(get);
19158 g = map[k] || (groups.push(map[k] = []), map[k]);
19159 g.push(x);
19160 }
19161 }
19162
19163 // compute sums of groups, sort groups as needed
19164 for (k=0, max=0; k<groups.length; ++k) {
19165 g = groups[k];
19166 for (i=0, s=0; i<g.length; ++i) {
19167 s += field(g[i]);
19168 }
19169 g.sum = s;
19170 if (s > max) max = s;
19171 if (sortby != null) g.sort(sortby);
19172 }
19173 groups.max = max;
19174
19175 return groups;
19176 }
19177
19178 module.exports = Stack;
19179 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],135:[function(require,module,exports){
19180 var df = require('vega-dataflow'),
19181 Base = df.Node.prototype, // jshint ignore:line
19182 Deps = df.Dependencies,
19183 Parameter = require('./Parameter');
19184
19185 function Transform(graph) {
19186 if (graph) Base.init.call(this, graph);
19187 }
19188
19189 Transform.addParameters = function(proto, params) {
19190 proto._parameters = proto._parameters || {};
19191 for (var name in params) {
19192 var p = params[name],
19193 param = new Parameter(name, p.type, proto);
19194
19195 proto._parameters[name] = param;
19196
19197 if (p.type === 'custom') {
19198 if (p.set) param.set = p.set.bind(param);
19199 if (p.get) param.get = p.get.bind(param);
19200 }
19201
19202 if (p.hasOwnProperty('default')) param.set(p.default);
19203 }
19204 };
19205
19206 var prototype = (Transform.prototype = Object.create(Base));
19207 prototype.constructor = Transform;
19208
19209 prototype.param = function(name, value) {
19210 var param = this._parameters[name];
19211 return (param === undefined) ? this :
19212 (arguments.length === 1) ? param.get() : param.set(value);
19213 };
19214
19215 // Perform transformation. Subclasses should override.
19216 prototype.transform = function(input/*, reset */) {
19217 return input;
19218 };
19219
19220 prototype.evaluate = function(input) {
19221 // Many transforms store caches that must be invalidated if
19222 // a signal value has changed.
19223 var reset = this._stamp < input.stamp &&
19224 this.dependency(Deps.SIGNALS).reduce(function(c, s) {
19225 return c += input.signals[s] ? 1 : 0;
19226 }, 0);
19227 return this.transform(input, reset);
19228 };
19229
19230 prototype.output = function(map) {
19231 for (var key in this._output) {
19232 if (map[key] !== undefined) {
19233 this._output[key] = map[key];
19234 }
19235 }
19236 return this;
19237 };
19238
19239 module.exports = Transform;
19240 },{"./Parameter":131,"vega-dataflow":39}],136:[function(require,module,exports){
19241 (function (global){
19242 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
19243 dl = require('datalib'),
19244 Tuple = require('vega-dataflow').Tuple,
19245 log = require('vega-logging'),
19246 Transform = require('./Transform'),
19247 BatchTransform = require('./BatchTransform');
19248
19249 var defaultRatio = 0.5 * (1 + Math.sqrt(5));
19250
19251 function Treemap(graph) {
19252 BatchTransform.prototype.init.call(this, graph);
19253 Transform.addParameters(this, {
19254 // hierarchy parameters
19255 sort: {type: 'array<field>', default: ['-value']},
19256 children: {type: 'field', default: 'children'},
19257 field: {type: 'field', default: 'value'},
19258 // treemap parameters
19259 size: {type: 'array<value>', default: [500, 500]},
19260 round: {type: 'value', default: true},
19261 sticky: {type: 'value', default: false},
19262 ratio: {type: 'value', default: defaultRatio},
19263 padding: {type: 'value', default: null},
19264 mode: {type: 'value', default: 'squarify'}
19265 });
19266
19267 this._layout = d3.layout.treemap();
19268
19269 this._output = {
19270 'x': 'layout_x',
19271 'y': 'layout_y',
19272 'width': 'layout_width',
19273 'height': 'layout_height',
19274 'depth': 'layout_depth',
19275 };
19276 return this.mutates(true);
19277 }
19278
19279 var prototype = (Treemap.prototype = Object.create(BatchTransform.prototype));
19280 prototype.constructor = Treemap;
19281
19282 prototype.batchTransform = function(input, data) {
19283 log.debug(input, ['treemap']);
19284
19285 // get variables
19286 var layout = this._layout,
19287 output = this._output;
19288
19289 // configure layout
19290 layout
19291 .sort(dl.comparator(this.param('sort').field))
19292 .children(this.param('children').accessor)
19293 .value(this.param('field').accessor)
19294 .size(this.param('size'))
19295 .round(this.param('round'))
19296 .sticky(this.param('sticky'))
19297 .ratio(this.param('ratio'))
19298 .padding(this.param('padding'))
19299 .mode(this.param('mode'))
19300 .nodes(data[0]);
19301
19302 // copy layout values to nodes
19303 data.forEach(function(n) {
19304 Tuple.set(n, output.x, n.x);
19305 Tuple.set(n, output.y, n.y);
19306 Tuple.set(n, output.width, n.dx);
19307 Tuple.set(n, output.height, n.dy);
19308 Tuple.set(n, output.depth, n.depth);
19309 });
19310
19311 // return changeset
19312 input.fields[output.x] = 1;
19313 input.fields[output.y] = 1;
19314 input.fields[output.width] = 1;
19315 input.fields[output.height] = 1;
19316 return input;
19317 };
19318
19319 module.exports = Treemap;
19320 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
19321
19322 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],137:[function(require,module,exports){
19323 (function (global){
19324 var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
19325 Tuple = require('vega-dataflow/src/Tuple'),
19326 log = require('vega-logging'),
19327 Transform = require('./Transform'),
19328 BatchTransform = require('./BatchTransform');
19329
19330 function Voronoi(graph) {
19331 BatchTransform.prototype.init.call(this, graph);
19332 Transform.addParameters(this, {
19333 clipExtent: {type: 'array<value>', default: [[-1e5,-1e5],[1e5,1e5]]},
19334 x: {type: 'field', default: 'layout_x'},
19335 y: {type: 'field', default: 'layout_y'}
19336 });
19337
19338 this._layout = d3.geom.voronoi();
19339 this._output = {'path': 'layout_path'};
19340
19341 return this.mutates(true);
19342 }
19343
19344 var prototype = (Voronoi.prototype = Object.create(BatchTransform.prototype));
19345 prototype.constructor = Voronoi;
19346
19347 prototype.batchTransform = function(input, data) {
19348 log.debug(input, ['voronoi']);
19349
19350 // get variables
19351 var pathname = this._output.path;
19352
19353 // configure layout
19354 var polygons = this._layout
19355 .clipExtent(this.param('clipExtent'))
19356 .x(this.param('x').accessor)
19357 .y(this.param('y').accessor)
19358 (data);
19359
19360 // build and assign path strings
19361 for (var i=0; i<data.length; ++i) {
19362 Tuple.set(data[i], pathname, 'M' + polygons[i].join('L') + 'Z');
19363 }
19364
19365 // return changeset
19366 input.fields[pathname] = 1;
19367 return input;
19368 };
19369
19370 module.exports = Voronoi;
19371 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
19372
19373 },{"./BatchTransform":117,"./Transform":135,"vega-dataflow/src/Tuple":38,"vega-logging":45}],138:[function(require,module,exports){
19374 (function (global){
19375 var dl = require('datalib'),
19376 d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null),
19377 d3_cloud = (typeof window !== "undefined" ? window['d3']['layout']['cloud'] : typeof global !== "undefined" ? global['d3']['layout']['cloud'] : null),
19378 Tuple = require('vega-dataflow/src/Tuple'),
19379 log = require('vega-logging'),
19380 Transform = require('./Transform'),
19381 BatchTransform = require('./BatchTransform');
19382
19383 function Wordcloud(graph) {
19384 BatchTransform.prototype.init.call(this, graph);
19385 Transform.addParameters(this, {
19386 size: {type: 'array<value>', default: [900, 500]},
19387 text: {type: 'field', default: 'data'},
19388 rotate: {type: 'field|value', default: 0},
19389 font: {type: 'field|value', default: {value: 'sans-serif'}},
19390 fontSize: {type: 'field|value', default: 14},
19391 fontStyle: {type: 'field|value', default: {value: 'normal'}},
19392 fontWeight: {type: 'field|value', default: {value: 'normal'}},
19393 fontScale: {type: 'array<value>', default: [10, 50]},
19394 padding: {type: 'value', default: 1},
19395 spiral: {type: 'value', default: 'archimedean'}
19396 });
19397
19398 this._layout = d3_cloud();
19399
19400 this._output = {
19401 'x': 'layout_x',
19402 'y': 'layout_y',
19403 'font': 'layout_font',
19404 'fontSize': 'layout_fontSize',
19405 'fontStyle': 'layout_fontStyle',
19406 'fontWeight': 'layout_fontWeight',
19407 'rotate': 'layout_rotate',
19408 };
19409
19410 return this.mutates(true);
19411 }
19412
19413 var prototype = (Wordcloud.prototype = Object.create(BatchTransform.prototype));
19414 prototype.constructor = Wordcloud;
19415
19416 function get(p) {
19417 return (p && p.accessor) || p;
19418 }
19419
19420 function wrap(tuple) {
19421 var x = Object.create(tuple);
19422 x._tuple = tuple;
19423 return x;
19424 }
19425
19426 prototype.batchTransform = function(input, data) {
19427 log.debug(input, ['wordcloud']);
19428
19429 // get variables
19430 var layout = this._layout,
19431 output = this._output,
19432 fontSize = this.param('fontSize'),
19433 range = fontSize.accessor && this.param('fontScale'),
19434 size, scale;
19435 fontSize = fontSize.accessor || d3.functor(fontSize);
19436
19437 // create font size scaling function as needed
19438 if (range.length) {
19439 scale = d3.scale.sqrt()
19440 .domain(dl.extent(data, size=fontSize))
19441 .range(range);
19442 fontSize = function(x) { return scale(size(x)); };
19443 }
19444
19445 // configure layout
19446 layout
19447 .size(this.param('size'))
19448 .text(get(this.param('text')))
19449 .padding(this.param('padding'))
19450 .spiral(this.param('spiral'))
19451 .rotate(get(this.param('rotate')))
19452 .font(get(this.param('font')))
19453 .fontStyle(get(this.param('fontStyle')))
19454 .fontWeight(get(this.param('fontWeight')))
19455 .fontSize(fontSize)
19456 .words(data.map(wrap)) // wrap to avoid tuple writes
19457 .on('end', function(words) {
19458 var size = layout.size(),
19459 dx = size[0] >> 1,
19460 dy = size[1] >> 1,
19461 w, t, i, len;
19462
19463 for (i=0, len=words.length; i<len; ++i) {
19464 w = words[i];
19465 t = w._tuple;
19466 Tuple.set(t, output.x, w.x + dx);
19467 Tuple.set(t, output.y, w.y + dy);
19468 Tuple.set(t, output.font, w.font);
19469 Tuple.set(t, output.fontSize, w.size);
19470 Tuple.set(t, output.fontStyle, w.style);
19471 Tuple.set(t, output.fontWeight, w.weight);
19472 Tuple.set(t, output.rotate, w.rotate);
19473 }
19474 })
19475 .start();
19476
19477 // return changeset
19478 for (var key in output) input.fields[output[key]] = 1;
19479 return input;
19480 };
19481
19482 module.exports = Wordcloud;
19483 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
19484
19485 },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow/src/Tuple":38,"vega-logging":45}],139:[function(require,module,exports){
19486 module.exports = {
19487 aggregate: require('./Aggregate'),
19488 bin: require('./Bin'),
19489 cross: require('./Cross'),
19490 countpattern: require('./CountPattern'),
19491 linkpath: require('./LinkPath'),
19492 facet: require('./Facet'),
19493 filter: require('./Filter'),
19494 fold: require('./Fold'),
19495 force: require('./Force'),
19496 formula: require('./Formula'),
19497 geo: require('./Geo'),
19498 geopath: require('./GeoPath'),
19499 lookup: require('./Lookup'),
19500 pie: require('./Pie'),
19501 sort: require('./Sort'),
19502 stack: require('./Stack'),
19503 treemap: require('./Treemap'),
19504 voronoi: require('./Voronoi'),
19505 wordcloud: require('./Wordcloud')
19506 };
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)
19508 });
19509 //# sourceMappingURL=vega.js.map