Daniel@0: (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= N) return EOF; // special case: end of file Daniel@0: if (eol) return eol = false, EOL; // special case: end of line Daniel@0: Daniel@0: // special case: quotes Daniel@0: var j = I; Daniel@0: if (text.charCodeAt(j) === 34) { Daniel@0: var i = j; Daniel@0: while (i++ < N) { Daniel@0: if (text.charCodeAt(i) === 34) { Daniel@0: if (text.charCodeAt(i + 1) !== 34) break; Daniel@0: ++i; Daniel@0: } Daniel@0: } Daniel@0: I = i + 2; Daniel@0: var c = text.charCodeAt(i + 1); Daniel@0: if (c === 13) { Daniel@0: eol = true; Daniel@0: if (text.charCodeAt(i + 2) === 10) ++I; Daniel@0: } else if (c === 10) { Daniel@0: eol = true; Daniel@0: } Daniel@0: return text.slice(j + 1, i).replace(/""/g, "\""); Daniel@0: } Daniel@0: Daniel@0: // common case: find next delimiter or newline Daniel@0: while (I < N) { Daniel@0: var c = text.charCodeAt(I++), k = 1; Daniel@0: if (c === 10) eol = true; // \n Daniel@0: else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n Daniel@0: else if (c !== delimiterCode) continue; Daniel@0: return text.slice(j, I - k); Daniel@0: } Daniel@0: Daniel@0: // special case: last token before EOF Daniel@0: return text.slice(j); Daniel@0: } Daniel@0: Daniel@0: while ((t = token()) !== EOF) { Daniel@0: var a = []; Daniel@0: while (t !== EOL && t !== EOF) { Daniel@0: a.push(t); Daniel@0: t = token(); Daniel@0: } Daniel@0: if (f && (a = f(a, n++)) == null) continue; Daniel@0: rows.push(a); Daniel@0: } Daniel@0: Daniel@0: return rows; Daniel@0: } Daniel@0: Daniel@0: function format(rows) { Daniel@0: if (Array.isArray(rows[0])) return formatRows(rows); // deprecated; use formatRows Daniel@0: var fieldSet = Object.create(null), fields = []; Daniel@0: Daniel@0: // Compute unique fields in order of discovery. Daniel@0: rows.forEach(function(row) { Daniel@0: for (var field in row) { Daniel@0: if (!((field += "") in fieldSet)) { Daniel@0: fields.push(fieldSet[field] = field); Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: return [fields.map(formatValue).join(delimiter)].concat(rows.map(function(row) { Daniel@0: return fields.map(function(field) { Daniel@0: return formatValue(row[field]); Daniel@0: }).join(delimiter); Daniel@0: })).join("\n"); Daniel@0: } Daniel@0: Daniel@0: function formatRows(rows) { Daniel@0: return rows.map(formatRow).join("\n"); Daniel@0: } Daniel@0: Daniel@0: function formatRow(row) { Daniel@0: return row.map(formatValue).join(delimiter); Daniel@0: } Daniel@0: Daniel@0: function formatValue(text) { Daniel@0: return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: parse: parse, Daniel@0: parseRows: parseRows, Daniel@0: format: format, Daniel@0: formatRows: formatRows Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: exports.csv = dsv(","); Daniel@0: exports.tsv = dsv("\t"); Daniel@0: Daniel@0: exports.dsv = dsv; Daniel@0: Daniel@0: })); Daniel@0: },{}],4:[function(require,module,exports){ Daniel@0: if (typeof Map === "undefined") { Daniel@0: Map = function() { this.clear(); }; Daniel@0: Map.prototype = { Daniel@0: set: function(k, v) { this._[k] = v; return this; }, Daniel@0: get: function(k) { return this._[k]; }, Daniel@0: has: function(k) { return k in this._; }, Daniel@0: delete: function(k) { return k in this._ && delete this._[k]; }, Daniel@0: clear: function() { this._ = Object.create(null); }, Daniel@0: get size() { var n = 0; for (var k in this._) ++n; return n; }, Daniel@0: forEach: function(c) { for (var k in this._) c(this._[k], k, this); } Daniel@0: }; Daniel@0: } else (function() { Daniel@0: var m = new Map; Daniel@0: if (m.set(0, 0) !== m) { Daniel@0: m = m.set; Daniel@0: Map.prototype.set = function() { m.apply(this, arguments); return this; }; Daniel@0: } Daniel@0: })(); Daniel@0: Daniel@0: (function (global, factory) { Daniel@0: typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : Daniel@0: typeof define === 'function' && define.amd ? define(['exports'], factory) : Daniel@0: factory((global.format = {})); Daniel@0: }(this, function (exports) { 'use strict'; Daniel@0: Daniel@0: var zhCn = { Daniel@0: decimal: ".", Daniel@0: thousands: ",", Daniel@0: grouping: [3], Daniel@0: currency: ["¥", ""] Daniel@0: }; Daniel@0: Daniel@0: var ruRu = { Daniel@0: decimal: ",", Daniel@0: thousands: "\xa0", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0руб."] Daniel@0: }; Daniel@0: Daniel@0: var ptBr = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["R$", ""] Daniel@0: }; Daniel@0: Daniel@0: var plPl = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["", "zł"] Daniel@0: }; Daniel@0: Daniel@0: var nlNl = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["€\xa0", ""] Daniel@0: }; Daniel@0: Daniel@0: var mkMk = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0ден."] Daniel@0: }; Daniel@0: Daniel@0: var jaJp = { Daniel@0: decimal: ".", Daniel@0: thousands: ",", Daniel@0: grouping: [3], Daniel@0: currency: ["", "円"] Daniel@0: }; Daniel@0: Daniel@0: var itIt = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["€", ""] Daniel@0: }; Daniel@0: Daniel@0: var heIl = { Daniel@0: decimal: ".", Daniel@0: thousands: ",", Daniel@0: grouping: [3], Daniel@0: currency: ["₪", ""] Daniel@0: }; Daniel@0: Daniel@0: var frFr = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0€"] Daniel@0: }; Daniel@0: Daniel@0: var frCa = { Daniel@0: decimal: ",", Daniel@0: thousands: "\xa0", Daniel@0: grouping: [3], Daniel@0: currency: ["", "$"] Daniel@0: }; Daniel@0: Daniel@0: var fiFi = { Daniel@0: decimal: ",", Daniel@0: thousands: "\xa0", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0€"] Daniel@0: }; Daniel@0: Daniel@0: var esEs = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0€"] Daniel@0: }; Daniel@0: Daniel@0: var enUs = { Daniel@0: decimal: ".", Daniel@0: thousands: ",", Daniel@0: grouping: [3], Daniel@0: currency: ["$", ""] Daniel@0: }; Daniel@0: Daniel@0: var enGb = { Daniel@0: decimal: ".", Daniel@0: thousands: ",", Daniel@0: grouping: [3], Daniel@0: currency: ["£", ""] Daniel@0: }; Daniel@0: Daniel@0: var enCa = { Daniel@0: decimal: ".", Daniel@0: thousands: ",", Daniel@0: grouping: [3], Daniel@0: currency: ["$", ""] Daniel@0: }; Daniel@0: Daniel@0: var deDe = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0€"] Daniel@0: }; Daniel@0: Daniel@0: var caEs = { Daniel@0: decimal: ",", Daniel@0: thousands: ".", Daniel@0: grouping: [3], Daniel@0: currency: ["", "\xa0€"] Daniel@0: }; Daniel@0: Daniel@0: Daniel@0: // Computes the decimal coefficient and exponent of the specified number x with Daniel@0: // significant digits p, where x is positive and p is in [1, 21] or undefined. Daniel@0: // For example, formatDecimal(1.23) returns ["123", 0]. Daniel@0: function formatDecimal(x, p) { Daniel@0: if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity Daniel@0: var i, coefficient = x.slice(0, i); Daniel@0: Daniel@0: // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ Daniel@0: // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). Daniel@0: return [ Daniel@0: coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, Daniel@0: +x.slice(i + 1) Daniel@0: ]; Daniel@0: } Daniel@0: Daniel@0: function exponent(x) { Daniel@0: return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; Daniel@0: } Daniel@0: Daniel@0: var prefixExponent; Daniel@0: Daniel@0: function formatPrefixAuto(x, p) { Daniel@0: var d = formatDecimal(x, p); Daniel@0: if (!d) return x + ""; Daniel@0: var coefficient = d[0], Daniel@0: exponent = d[1], Daniel@0: i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, Daniel@0: n = coefficient.length; Daniel@0: return i === n ? coefficient Daniel@0: : i > n ? coefficient + new Array(i - n + 1).join("0") Daniel@0: : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) Daniel@0: : "0." + new Array(1 - i).join("0") + formatDecimal(x, p + i - 1)[0]; // less than 1y! Daniel@0: } Daniel@0: Daniel@0: function formatRounded(x, p) { Daniel@0: var d = formatDecimal(x, p); Daniel@0: if (!d) return x + ""; Daniel@0: var coefficient = d[0], Daniel@0: exponent = d[1]; Daniel@0: return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient Daniel@0: : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) Daniel@0: : coefficient + new Array(exponent - coefficient.length + 2).join("0"); Daniel@0: } Daniel@0: Daniel@0: function formatDefault(x, p) { Daniel@0: x = x.toPrecision(p); Daniel@0: Daniel@0: out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { Daniel@0: switch (x[i]) { Daniel@0: case ".": i0 = i1 = i; break; Daniel@0: case "0": if (i0 === 0) i0 = i; i1 = i; break; Daniel@0: case "e": break out; Daniel@0: default: if (i0 > 0) i0 = 0; break; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; Daniel@0: } Daniel@0: Daniel@0: var formatTypes = { Daniel@0: "": formatDefault, Daniel@0: "%": function(x, p) { return (x * 100).toFixed(p); }, Daniel@0: "b": function(x) { return Math.round(x).toString(2); }, Daniel@0: "c": function(x) { return x + ""; }, Daniel@0: "d": function(x) { return Math.round(x).toString(10); }, Daniel@0: "e": function(x, p) { return x.toExponential(p); }, Daniel@0: "f": function(x, p) { return x.toFixed(p); }, Daniel@0: "g": function(x, p) { return x.toPrecision(p); }, Daniel@0: "o": function(x) { return Math.round(x).toString(8); }, Daniel@0: "p": function(x, p) { return formatRounded(x * 100, p); }, Daniel@0: "r": formatRounded, Daniel@0: "s": formatPrefixAuto, Daniel@0: "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, Daniel@0: "x": function(x) { return Math.round(x).toString(16); } Daniel@0: }; Daniel@0: Daniel@0: Daniel@0: // [[fill]align][sign][symbol][0][width][,][.precision][type] Daniel@0: var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; Daniel@0: Daniel@0: function formatSpecifier(specifier) { Daniel@0: return new FormatSpecifier(specifier); Daniel@0: } Daniel@0: Daniel@0: function FormatSpecifier(specifier) { Daniel@0: if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); Daniel@0: Daniel@0: var match, Daniel@0: fill = match[1] || " ", Daniel@0: align = match[2] || ">", Daniel@0: sign = match[3] || "-", Daniel@0: symbol = match[4] || "", Daniel@0: zero = !!match[5], Daniel@0: width = match[6] && +match[6], Daniel@0: comma = !!match[7], Daniel@0: precision = match[8] && +match[8].slice(1), Daniel@0: type = match[9] || ""; Daniel@0: Daniel@0: // The "n" type is an alias for ",g". Daniel@0: if (type === "n") comma = true, type = "g"; Daniel@0: Daniel@0: // Map invalid types to the default format. Daniel@0: else if (!formatTypes[type]) type = ""; Daniel@0: Daniel@0: // If zero fill is specified, padding goes after sign and before digits. Daniel@0: if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; Daniel@0: Daniel@0: this.fill = fill; Daniel@0: this.align = align; Daniel@0: this.sign = sign; Daniel@0: this.symbol = symbol; Daniel@0: this.zero = zero; Daniel@0: this.width = width; Daniel@0: this.comma = comma; Daniel@0: this.precision = precision; Daniel@0: this.type = type; Daniel@0: } Daniel@0: Daniel@0: FormatSpecifier.prototype.toString = function() { Daniel@0: return this.fill Daniel@0: + this.align Daniel@0: + this.sign Daniel@0: + this.symbol Daniel@0: + (this.zero ? "0" : "") Daniel@0: + (this.width == null ? "" : Math.max(1, this.width | 0)) Daniel@0: + (this.comma ? "," : "") Daniel@0: + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) Daniel@0: + this.type; Daniel@0: }; Daniel@0: Daniel@0: function formatGroup(grouping, thousands) { Daniel@0: return function(value, width) { Daniel@0: var i = value.length, Daniel@0: t = [], Daniel@0: j = 0, Daniel@0: g = grouping[0], Daniel@0: length = 0; Daniel@0: Daniel@0: while (i > 0 && g > 0) { Daniel@0: if (length + g + 1 > width) g = Math.max(1, width - length); Daniel@0: t.push(value.substring(i -= g, i + g)); Daniel@0: if ((length += g + 1) > width) break; Daniel@0: g = grouping[j = (j + 1) % grouping.length]; Daniel@0: } Daniel@0: Daniel@0: return t.reverse().join(thousands); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; Daniel@0: Daniel@0: function identity(x) { Daniel@0: return x; Daniel@0: } Daniel@0: Daniel@0: function locale(locale) { Daniel@0: var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity, Daniel@0: currency = locale.currency, Daniel@0: decimal = locale.decimal; Daniel@0: Daniel@0: function format(specifier) { Daniel@0: specifier = formatSpecifier(specifier); Daniel@0: Daniel@0: var fill = specifier.fill, Daniel@0: align = specifier.align, Daniel@0: sign = specifier.sign, Daniel@0: symbol = specifier.symbol, Daniel@0: zero = specifier.zero, Daniel@0: width = specifier.width, Daniel@0: comma = specifier.comma, Daniel@0: precision = specifier.precision, Daniel@0: type = specifier.type; Daniel@0: Daniel@0: // Compute the prefix and suffix. Daniel@0: // For SI-prefix, the suffix is lazily computed. Daniel@0: var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", Daniel@0: suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : ""; Daniel@0: Daniel@0: // What format function should we use? Daniel@0: // Is this an integer type? Daniel@0: // Can this type generate exponential notation? Daniel@0: var formatType = formatTypes[type], Daniel@0: maybeSuffix = !type || /[defgprs%]/.test(type); Daniel@0: Daniel@0: // Set the default precision if not specified, Daniel@0: // or clamp the specified precision to the supported range. Daniel@0: // For significant precision, it must be in [1, 21]. Daniel@0: // For fixed precision, it must be in [0, 20]. Daniel@0: precision = precision == null ? (type ? 6 : 12) Daniel@0: : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) Daniel@0: : Math.max(0, Math.min(20, precision)); Daniel@0: Daniel@0: return function(value) { Daniel@0: var valuePrefix = prefix, Daniel@0: valueSuffix = suffix; Daniel@0: Daniel@0: if (type === "c") { Daniel@0: valueSuffix = formatType(value) + valueSuffix; Daniel@0: value = ""; Daniel@0: } else { Daniel@0: value = +value; Daniel@0: Daniel@0: // Convert negative to positive, and compute the prefix. Daniel@0: // Note that -0 is not less than 0, but 1 / -0 is! Daniel@0: var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true); Daniel@0: Daniel@0: // Perform the initial formatting. Daniel@0: value = formatType(value, precision); Daniel@0: Daniel@0: // Compute the prefix and suffix. Daniel@0: valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; Daniel@0: valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); Daniel@0: Daniel@0: // Break the formatted value into the integer “value” part that can be Daniel@0: // grouped, and fractional or exponential “suffix” part that is not. Daniel@0: if (maybeSuffix) { Daniel@0: var i = -1, n = value.length, c; Daniel@0: while (++i < n) { Daniel@0: if (c = value.charCodeAt(i), 48 > c || c > 57) { Daniel@0: valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; Daniel@0: value = value.slice(0, i); Daniel@0: break; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // If the fill character is not "0", grouping is applied before padding. Daniel@0: if (comma && !zero) value = group(value, Infinity); Daniel@0: Daniel@0: // Compute the padding. Daniel@0: var length = valuePrefix.length + value.length + valueSuffix.length, Daniel@0: padding = length < width ? new Array(width - length + 1).join(fill) : ""; Daniel@0: Daniel@0: // If the fill character is "0", grouping is applied after padding. Daniel@0: if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; Daniel@0: Daniel@0: // Reconstruct the final output based on the desired alignment. Daniel@0: switch (align) { Daniel@0: case "<": return valuePrefix + value + valueSuffix + padding; Daniel@0: case "=": return valuePrefix + padding + value + valueSuffix; Daniel@0: case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); Daniel@0: } Daniel@0: return padding + valuePrefix + value + valueSuffix; Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function formatPrefix(specifier, value) { Daniel@0: var f = format((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), Daniel@0: e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, Daniel@0: k = Math.pow(10, -e), Daniel@0: prefix = prefixes[8 + e / 3]; Daniel@0: return function(value) { Daniel@0: return f(k * value) + prefix; Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: format: format, Daniel@0: formatPrefix: formatPrefix Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function precisionRound(step, max) { Daniel@0: return Math.max(0, exponent(Math.abs(max)) - exponent(Math.abs(step))) + 1; Daniel@0: } Daniel@0: Daniel@0: function precisionPrefix(step, value) { Daniel@0: return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step))); Daniel@0: } Daniel@0: Daniel@0: function precisionFixed(step) { Daniel@0: return Math.max(0, -exponent(Math.abs(step))); Daniel@0: } Daniel@0: Daniel@0: var localeDefinitions = (new Map) Daniel@0: .set("ca-ES", caEs) Daniel@0: .set("de-DE", deDe) Daniel@0: .set("en-CA", enCa) Daniel@0: .set("en-GB", enGb) Daniel@0: .set("en-US", enUs) Daniel@0: .set("es-ES", esEs) Daniel@0: .set("fi-FI", fiFi) Daniel@0: .set("fr-CA", frCa) Daniel@0: .set("fr-FR", frFr) Daniel@0: .set("he-IL", heIl) Daniel@0: .set("it-IT", itIt) Daniel@0: .set("ja-JP", jaJp) Daniel@0: .set("mk-MK", mkMk) Daniel@0: .set("nl-NL", nlNl) Daniel@0: .set("pl-PL", plPl) Daniel@0: .set("pt-BR", ptBr) Daniel@0: .set("ru-RU", ruRu) Daniel@0: .set("zh-CN", zhCn); Daniel@0: Daniel@0: var defaultLocale = locale(enUs); Daniel@0: exports.format = defaultLocale.format; Daniel@0: exports.formatPrefix = defaultLocale.formatPrefix; Daniel@0: Daniel@0: function localeFormat(definition) { Daniel@0: if (typeof definition === "string") { Daniel@0: definition = localeDefinitions.get(definition); Daniel@0: if (!definition) return null; Daniel@0: } Daniel@0: return locale(definition); Daniel@0: } Daniel@0: ; Daniel@0: Daniel@0: exports.localeFormat = localeFormat; Daniel@0: exports.formatSpecifier = formatSpecifier; Daniel@0: exports.precisionFixed = precisionFixed; Daniel@0: exports.precisionPrefix = precisionPrefix; Daniel@0: exports.precisionRound = precisionRound; Daniel@0: Daniel@0: })); Daniel@0: },{}],5:[function(require,module,exports){ Daniel@0: if (typeof Map === "undefined") { Daniel@0: Map = function() { this.clear(); }; Daniel@0: Map.prototype = { Daniel@0: set: function(k, v) { this._[k] = v; return this; }, Daniel@0: get: function(k) { return this._[k]; }, Daniel@0: has: function(k) { return k in this._; }, Daniel@0: delete: function(k) { return k in this._ && delete this._[k]; }, Daniel@0: clear: function() { this._ = Object.create(null); }, Daniel@0: get size() { var n = 0; for (var k in this._) ++n; return n; }, Daniel@0: forEach: function(c) { for (var k in this._) c(this._[k], k, this); } Daniel@0: }; Daniel@0: } else (function() { Daniel@0: var m = new Map; Daniel@0: if (m.set(0, 0) !== m) { Daniel@0: m = m.set; Daniel@0: Map.prototype.set = function() { m.apply(this, arguments); return this; }; Daniel@0: } Daniel@0: })(); Daniel@0: Daniel@0: (function (global, factory) { Daniel@0: typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : Daniel@0: typeof define === 'function' && define.amd ? define(['exports'], factory) : Daniel@0: factory((global.timeFormat = {})); Daniel@0: }(this, function (exports) { 'use strict'; Daniel@0: Daniel@0: var zhCn = { Daniel@0: dateTime: "%a %b %e %X %Y", Daniel@0: date: "%Y/%-m/%-d", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["上午", "下午"], Daniel@0: days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], Daniel@0: shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], Daniel@0: months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], Daniel@0: shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"] Daniel@0: }; Daniel@0: Daniel@0: var ruRu = { Daniel@0: dateTime: "%A, %e %B %Y г. %X", Daniel@0: date: "%d.%m.%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"], Daniel@0: shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"], Daniel@0: months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"], Daniel@0: shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"] Daniel@0: }; Daniel@0: Daniel@0: var ptBr = { Daniel@0: dateTime: "%A, %e de %B de %Y. %X", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"], Daniel@0: shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"], Daniel@0: months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], Daniel@0: shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"] Daniel@0: }; Daniel@0: Daniel@0: var plPl = { Daniel@0: dateTime: "%A, %e %B %Y, %X", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], // unused Daniel@0: days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"], Daniel@0: shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."], Daniel@0: months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], Daniel@0: shortMonths: ["Stycz.", "Luty", "Marz.", "Kwie.", "Maj", "Czerw.", "Lipc.", "Sierp.", "Wrz.", "Paźdz.", "Listop.", "Grudz."]/* In Polish language abbraviated months are not commonly used so there is a dispute about the proper abbraviations. */ Daniel@0: }; Daniel@0: Daniel@0: var nlNl = { Daniel@0: dateTime: "%a %e %B %Y %T", Daniel@0: date: "%d-%m-%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], // unused Daniel@0: days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"], Daniel@0: shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"], Daniel@0: months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"], Daniel@0: shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"] Daniel@0: }; Daniel@0: Daniel@0: var mkMk = { Daniel@0: dateTime: "%A, %e %B %Y г. %X", Daniel@0: date: "%d.%m.%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"], Daniel@0: shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"], Daniel@0: months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"], Daniel@0: shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"] Daniel@0: }; Daniel@0: Daniel@0: var jaJp = { Daniel@0: dateTime: "%Y %b %e %a %X", Daniel@0: date: "%Y/%m/%d", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"], Daniel@0: shortDays: ["日", "月", "火", "水", "木", "金", "土"], Daniel@0: months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"], Daniel@0: shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"] Daniel@0: }; Daniel@0: Daniel@0: var itIt = { Daniel@0: dateTime: "%A %e %B %Y, %X", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], // unused Daniel@0: days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"], Daniel@0: shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], Daniel@0: months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], Daniel@0: shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"] Daniel@0: }; Daniel@0: Daniel@0: var heIl = { Daniel@0: dateTime: "%A, %e ב%B %Y %X", Daniel@0: date: "%d.%m.%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"], Daniel@0: shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"], Daniel@0: months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], Daniel@0: shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"] Daniel@0: }; Daniel@0: Daniel@0: var frFr = { Daniel@0: dateTime: "%A, le %e %B %Y, %X", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], // unused Daniel@0: days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"], Daniel@0: shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."], Daniel@0: months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], Daniel@0: shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."] Daniel@0: }; Daniel@0: Daniel@0: var frCa = { Daniel@0: dateTime: "%a %e %b %Y %X", Daniel@0: date: "%Y-%m-%d", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["", ""], Daniel@0: days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"], Daniel@0: shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"], Daniel@0: months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], Daniel@0: shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"] Daniel@0: }; Daniel@0: Daniel@0: var fiFi = { Daniel@0: dateTime: "%A, %-d. %Bta %Y klo %X", Daniel@0: date: "%-d.%-m.%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["a.m.", "p.m."], Daniel@0: days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"], Daniel@0: shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"], Daniel@0: months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], Daniel@0: shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"] Daniel@0: }; Daniel@0: Daniel@0: var esEs = { Daniel@0: dateTime: "%A, %e de %B de %Y, %X", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"], Daniel@0: shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"], Daniel@0: months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"], Daniel@0: shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"] Daniel@0: }; Daniel@0: Daniel@0: var enUs = { Daniel@0: dateTime: "%a %b %e %X %Y", Daniel@0: date: "%m/%d/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], Daniel@0: shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], Daniel@0: months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], Daniel@0: shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] Daniel@0: }; Daniel@0: Daniel@0: var enGb = { Daniel@0: dateTime: "%a %e %b %X %Y", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], Daniel@0: shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], Daniel@0: months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], Daniel@0: shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] Daniel@0: }; Daniel@0: Daniel@0: var enCa = { Daniel@0: dateTime: "%a %b %e %X %Y", Daniel@0: date: "%Y-%m-%d", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], Daniel@0: shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], Daniel@0: months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], Daniel@0: shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] Daniel@0: }; Daniel@0: Daniel@0: var deDe = { Daniel@0: dateTime: "%A, der %e. %B %Y, %X", Daniel@0: date: "%d.%m.%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], // unused Daniel@0: days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], Daniel@0: shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], Daniel@0: months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], Daniel@0: shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"] Daniel@0: }; Daniel@0: Daniel@0: var caEs = { Daniel@0: dateTime: "%A, %e de %B de %Y, %X", Daniel@0: date: "%d/%m/%Y", Daniel@0: time: "%H:%M:%S", Daniel@0: periods: ["AM", "PM"], Daniel@0: days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"], Daniel@0: shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."], Daniel@0: months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"], Daniel@0: shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."] Daniel@0: }; Daniel@0: Daniel@0: var t0 = new Date; Daniel@0: var t1 = new Date; Daniel@0: Daniel@0: function newInterval(floori, offseti, count) { Daniel@0: Daniel@0: function interval(date) { Daniel@0: return floori(date = new Date(+date)), date; Daniel@0: } Daniel@0: Daniel@0: interval.floor = interval; Daniel@0: Daniel@0: interval.round = function(date) { Daniel@0: var d0 = new Date(+date), Daniel@0: d1 = new Date(date - 1); Daniel@0: floori(d0), floori(d1), offseti(d1, 1); Daniel@0: return date - d0 < d1 - date ? d0 : d1; Daniel@0: }; Daniel@0: Daniel@0: interval.ceil = function(date) { Daniel@0: return floori(date = new Date(date - 1)), offseti(date, 1), date; Daniel@0: }; Daniel@0: Daniel@0: interval.offset = function(date, step) { Daniel@0: return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; Daniel@0: }; Daniel@0: Daniel@0: interval.range = function(start, stop, step) { Daniel@0: var range = []; Daniel@0: start = new Date(start - 1); Daniel@0: stop = new Date(+stop); Daniel@0: step = step == null ? 1 : Math.floor(step); Daniel@0: if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date Daniel@0: offseti(start, 1), floori(start); Daniel@0: if (start < stop) range.push(new Date(+start)); Daniel@0: while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start)); Daniel@0: return range; Daniel@0: }; Daniel@0: Daniel@0: interval.filter = function(test) { Daniel@0: return newInterval(function(date) { Daniel@0: while (floori(date), !test(date)) date.setTime(date - 1); Daniel@0: }, function(date, step) { Daniel@0: while (--step >= 0) while (offseti(date, 1), !test(date)); Daniel@0: }); Daniel@0: }; Daniel@0: Daniel@0: if (count) interval.count = function(start, end) { Daniel@0: t0.setTime(+start), t1.setTime(+end); Daniel@0: floori(t0), floori(t1); Daniel@0: return Math.floor(count(t0, t1)); Daniel@0: }; Daniel@0: Daniel@0: return interval; Daniel@0: } Daniel@0: Daniel@0: var day = newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setDate(date.getDate() + step); Daniel@0: }, function(start, end) { Daniel@0: return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5; Daniel@0: }); Daniel@0: Daniel@0: function weekday(i) { Daniel@0: return newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); Daniel@0: }, function(date, step) { Daniel@0: date.setDate(date.getDate() + step * 7); Daniel@0: }, function(start, end) { Daniel@0: return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5; Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: var sunday = weekday(0); Daniel@0: var monday = weekday(1); Daniel@0: Daniel@0: var year = newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: date.setMonth(0, 1); Daniel@0: }, function(date, step) { Daniel@0: date.setFullYear(date.getFullYear() + step); Daniel@0: }, function(start, end) { Daniel@0: return end.getFullYear() - start.getFullYear(); Daniel@0: }); Daniel@0: Daniel@0: var utcDay = newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCDate(date.getUTCDate() + step); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 864e5; Daniel@0: }); Daniel@0: Daniel@0: function utcWeekday(i) { Daniel@0: return newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCDate(date.getUTCDate() + step * 7); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 6048e5; Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: var utcSunday = utcWeekday(0); Daniel@0: var utcMonday = utcWeekday(1); Daniel@0: Daniel@0: var utcYear = newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: date.setUTCMonth(0, 1); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCFullYear(date.getUTCFullYear() + step); Daniel@0: }, function(start, end) { Daniel@0: return end.getUTCFullYear() - start.getUTCFullYear(); Daniel@0: }); Daniel@0: Daniel@0: function localDate(d) { Daniel@0: if (0 <= d.y && d.y < 100) { Daniel@0: var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); Daniel@0: date.setFullYear(d.y); Daniel@0: return date; Daniel@0: } Daniel@0: return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); Daniel@0: } Daniel@0: Daniel@0: function utcDate(d) { Daniel@0: if (0 <= d.y && d.y < 100) { Daniel@0: var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); Daniel@0: date.setUTCFullYear(d.y); Daniel@0: return date; Daniel@0: } Daniel@0: return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); Daniel@0: } Daniel@0: Daniel@0: function newYear(y) { Daniel@0: return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; Daniel@0: } Daniel@0: Daniel@0: function locale(locale) { Daniel@0: var locale_dateTime = locale.dateTime, Daniel@0: locale_date = locale.date, Daniel@0: locale_time = locale.time, Daniel@0: locale_periods = locale.periods, Daniel@0: locale_weekdays = locale.days, Daniel@0: locale_shortWeekdays = locale.shortDays, Daniel@0: locale_months = locale.months, Daniel@0: locale_shortMonths = locale.shortMonths; Daniel@0: Daniel@0: var periodLookup = formatLookup(locale_periods), Daniel@0: weekdayRe = formatRe(locale_weekdays), Daniel@0: weekdayLookup = formatLookup(locale_weekdays), Daniel@0: shortWeekdayRe = formatRe(locale_shortWeekdays), Daniel@0: shortWeekdayLookup = formatLookup(locale_shortWeekdays), Daniel@0: monthRe = formatRe(locale_months), Daniel@0: monthLookup = formatLookup(locale_months), Daniel@0: shortMonthRe = formatRe(locale_shortMonths), Daniel@0: shortMonthLookup = formatLookup(locale_shortMonths); Daniel@0: Daniel@0: var formats = { Daniel@0: "a": formatShortWeekday, Daniel@0: "A": formatWeekday, Daniel@0: "b": formatShortMonth, Daniel@0: "B": formatMonth, Daniel@0: "c": null, Daniel@0: "d": formatDayOfMonth, Daniel@0: "e": formatDayOfMonth, Daniel@0: "H": formatHour24, Daniel@0: "I": formatHour12, Daniel@0: "j": formatDayOfYear, Daniel@0: "L": formatMilliseconds, Daniel@0: "m": formatMonthNumber, Daniel@0: "M": formatMinutes, Daniel@0: "p": formatPeriod, Daniel@0: "S": formatSeconds, Daniel@0: "U": formatWeekNumberSunday, Daniel@0: "w": formatWeekdayNumber, Daniel@0: "W": formatWeekNumberMonday, Daniel@0: "x": null, Daniel@0: "X": null, Daniel@0: "y": formatYear, Daniel@0: "Y": formatFullYear, Daniel@0: "Z": formatZone, Daniel@0: "%": formatLiteralPercent Daniel@0: }; Daniel@0: Daniel@0: var utcFormats = { Daniel@0: "a": formatUTCShortWeekday, Daniel@0: "A": formatUTCWeekday, Daniel@0: "b": formatUTCShortMonth, Daniel@0: "B": formatUTCMonth, Daniel@0: "c": null, Daniel@0: "d": formatUTCDayOfMonth, Daniel@0: "e": formatUTCDayOfMonth, Daniel@0: "H": formatUTCHour24, Daniel@0: "I": formatUTCHour12, Daniel@0: "j": formatUTCDayOfYear, Daniel@0: "L": formatUTCMilliseconds, Daniel@0: "m": formatUTCMonthNumber, Daniel@0: "M": formatUTCMinutes, Daniel@0: "p": formatUTCPeriod, Daniel@0: "S": formatUTCSeconds, Daniel@0: "U": formatUTCWeekNumberSunday, Daniel@0: "w": formatUTCWeekdayNumber, Daniel@0: "W": formatUTCWeekNumberMonday, Daniel@0: "x": null, Daniel@0: "X": null, Daniel@0: "y": formatUTCYear, Daniel@0: "Y": formatUTCFullYear, Daniel@0: "Z": formatUTCZone, Daniel@0: "%": formatLiteralPercent Daniel@0: }; Daniel@0: Daniel@0: var parses = { Daniel@0: "a": parseShortWeekday, Daniel@0: "A": parseWeekday, Daniel@0: "b": parseShortMonth, Daniel@0: "B": parseMonth, Daniel@0: "c": parseLocaleDateTime, Daniel@0: "d": parseDayOfMonth, Daniel@0: "e": parseDayOfMonth, Daniel@0: "H": parseHour24, Daniel@0: "I": parseHour24, Daniel@0: "j": parseDayOfYear, Daniel@0: "L": parseMilliseconds, Daniel@0: "m": parseMonthNumber, Daniel@0: "M": parseMinutes, Daniel@0: "p": parsePeriod, Daniel@0: "S": parseSeconds, Daniel@0: "U": parseWeekNumberSunday, Daniel@0: "w": parseWeekdayNumber, Daniel@0: "W": parseWeekNumberMonday, Daniel@0: "x": parseLocaleDate, Daniel@0: "X": parseLocaleTime, Daniel@0: "y": parseYear, Daniel@0: "Y": parseFullYear, Daniel@0: "Z": parseZone, Daniel@0: "%": parseLiteralPercent Daniel@0: }; Daniel@0: Daniel@0: // These recursive directive definitions must be deferred. Daniel@0: formats.x = newFormat(locale_date, formats); Daniel@0: formats.X = newFormat(locale_time, formats); Daniel@0: formats.c = newFormat(locale_dateTime, formats); Daniel@0: utcFormats.x = newFormat(locale_date, utcFormats); Daniel@0: utcFormats.X = newFormat(locale_time, utcFormats); Daniel@0: utcFormats.c = newFormat(locale_dateTime, utcFormats); Daniel@0: Daniel@0: function newFormat(specifier, formats) { Daniel@0: return function(date) { Daniel@0: var string = [], Daniel@0: i = -1, Daniel@0: j = 0, Daniel@0: n = specifier.length, Daniel@0: c, Daniel@0: pad, Daniel@0: format; Daniel@0: Daniel@0: while (++i < n) { Daniel@0: if (specifier.charCodeAt(i) === 37) { Daniel@0: string.push(specifier.slice(j, i)); Daniel@0: if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); Daniel@0: if (format = formats[c]) c = format(date, pad == null ? (c === "e" ? " " : "0") : pad); Daniel@0: string.push(c); Daniel@0: j = i + 1; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: string.push(specifier.slice(j, i)); Daniel@0: return string.join(""); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function newParse(specifier, newDate) { Daniel@0: return function(string) { Daniel@0: var d = newYear(1900), Daniel@0: i = parseSpecifier(d, specifier, string, 0); Daniel@0: if (i != string.length) return null; Daniel@0: Daniel@0: // The am-pm flag is 0 for AM, and 1 for PM. Daniel@0: if ("p" in d) d.H = d.H % 12 + d.p * 12; Daniel@0: Daniel@0: // If a time zone is specified, all fields are interpreted as UTC and then Daniel@0: // offset according to the specified time zone. Daniel@0: if ("Z" in d) { Daniel@0: if ("w" in d && ("W" in d || "U" in d)) { Daniel@0: var day = utcDate(newYear(d.y)).getUTCDay(); Daniel@0: if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day; Daniel@0: d.m = 0; Daniel@0: d.d = d.w + d.U * 7 - (day + 6) % 7; Daniel@0: } Daniel@0: d.H += d.Z / 100 | 0; Daniel@0: d.M += d.Z % 100; Daniel@0: return utcDate(d); Daniel@0: } Daniel@0: Daniel@0: // Otherwise, all fields are in local time. Daniel@0: if ("w" in d && ("W" in d || "U" in d)) { Daniel@0: var day = newDate(newYear(d.y)).getDay(); Daniel@0: if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day; Daniel@0: d.m = 0; Daniel@0: d.d = d.w + d.U * 7 - (day + 6) % 7; Daniel@0: } Daniel@0: return newDate(d); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function parseSpecifier(d, specifier, string, j) { Daniel@0: var i = 0, Daniel@0: n = specifier.length, Daniel@0: m = string.length, Daniel@0: c, Daniel@0: parse; Daniel@0: Daniel@0: while (i < n) { Daniel@0: if (j >= m) return -1; Daniel@0: c = specifier.charCodeAt(i++); Daniel@0: if (c === 37) { Daniel@0: c = specifier.charAt(i++); Daniel@0: parse = parses[c in pads ? specifier.charAt(i++) : c]; Daniel@0: if (!parse || ((j = parse(d, string, j)) < 0)) return -1; Daniel@0: } else if (c != string.charCodeAt(j++)) { Daniel@0: return -1; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return j; Daniel@0: } Daniel@0: Daniel@0: function parseShortWeekday(d, string, i) { Daniel@0: var n = shortWeekdayRe.exec(string.slice(i)); Daniel@0: return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseWeekday(d, string, i) { Daniel@0: var n = weekdayRe.exec(string.slice(i)); Daniel@0: return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseShortMonth(d, string, i) { Daniel@0: var n = shortMonthRe.exec(string.slice(i)); Daniel@0: return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseMonth(d, string, i) { Daniel@0: var n = monthRe.exec(string.slice(i)); Daniel@0: return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseLocaleDateTime(d, string, i) { Daniel@0: return parseSpecifier(d, locale_dateTime, string, i); Daniel@0: } Daniel@0: Daniel@0: function parseLocaleDate(d, string, i) { Daniel@0: return parseSpecifier(d, locale_date, string, i); Daniel@0: } Daniel@0: Daniel@0: function parseLocaleTime(d, string, i) { Daniel@0: return parseSpecifier(d, locale_time, string, i); Daniel@0: } Daniel@0: Daniel@0: function parsePeriod(d, string, i) { Daniel@0: var n = periodLookup.get(string.slice(i, i += 2).toLowerCase()); Daniel@0: return n == null ? -1 : (d.p = n, i); Daniel@0: } Daniel@0: Daniel@0: function formatShortWeekday(d) { Daniel@0: return locale_shortWeekdays[d.getDay()]; Daniel@0: } Daniel@0: Daniel@0: function formatWeekday(d) { Daniel@0: return locale_weekdays[d.getDay()]; Daniel@0: } Daniel@0: Daniel@0: function formatShortMonth(d) { Daniel@0: return locale_shortMonths[d.getMonth()]; Daniel@0: } Daniel@0: Daniel@0: function formatMonth(d) { Daniel@0: return locale_months[d.getMonth()]; Daniel@0: } Daniel@0: Daniel@0: function formatPeriod(d) { Daniel@0: return locale_periods[+(d.getHours() >= 12)]; Daniel@0: } Daniel@0: Daniel@0: function formatUTCShortWeekday(d) { Daniel@0: return locale_shortWeekdays[d.getUTCDay()]; Daniel@0: } Daniel@0: Daniel@0: function formatUTCWeekday(d) { Daniel@0: return locale_weekdays[d.getUTCDay()]; Daniel@0: } Daniel@0: Daniel@0: function formatUTCShortMonth(d) { Daniel@0: return locale_shortMonths[d.getUTCMonth()]; Daniel@0: } Daniel@0: Daniel@0: function formatUTCMonth(d) { Daniel@0: return locale_months[d.getUTCMonth()]; Daniel@0: } Daniel@0: Daniel@0: function formatUTCPeriod(d) { Daniel@0: return locale_periods[+(d.getUTCHours() >= 12)]; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: format: function(specifier) { Daniel@0: var f = newFormat(specifier += "", formats); Daniel@0: f.parse = newParse(specifier, localDate); Daniel@0: f.toString = function() { return specifier; }; Daniel@0: return f; Daniel@0: }, Daniel@0: utcFormat: function(specifier) { Daniel@0: var f = newFormat(specifier += "", utcFormats); Daniel@0: f.parse = newParse(specifier, utcDate); Daniel@0: f.toString = function() { return specifier; }; Daniel@0: return f; Daniel@0: } Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: var pads = {"-": "", "_": " ", "0": "0"}; Daniel@0: var numberRe = /^\s*\d+/; Daniel@0: var percentRe = /^%/; Daniel@0: var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; Daniel@0: Daniel@0: function pad(value, fill, width) { Daniel@0: var sign = value < 0 ? "-" : "", Daniel@0: string = (sign ? -value : value) + "", Daniel@0: length = string.length; Daniel@0: return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); Daniel@0: } Daniel@0: Daniel@0: function requote(s) { Daniel@0: return s.replace(requoteRe, "\\$&"); Daniel@0: } Daniel@0: Daniel@0: function formatRe(names) { Daniel@0: return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); Daniel@0: } Daniel@0: Daniel@0: function formatLookup(names) { Daniel@0: var map = new Map, i = -1, n = names.length; Daniel@0: while (++i < n) map.set(names[i].toLowerCase(), i); Daniel@0: return map; Daniel@0: } Daniel@0: Daniel@0: function parseWeekdayNumber(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 1)); Daniel@0: return n ? (d.w = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseWeekNumberSunday(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i)); Daniel@0: return n ? (d.U = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseWeekNumberMonday(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i)); Daniel@0: return n ? (d.W = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseFullYear(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 4)); Daniel@0: return n ? (d.y = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseYear(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 2)); Daniel@0: return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseZone(d, string, i) { Daniel@0: return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) Daniel@0: ? (d.Z = -string, i + 5) // sign differs from getTimezoneOffset! Daniel@0: : -1; Daniel@0: } Daniel@0: Daniel@0: function parseMonthNumber(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 2)); Daniel@0: return n ? (d.m = n[0] - 1, i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseDayOfMonth(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 2)); Daniel@0: return n ? (d.d = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseDayOfYear(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 3)); Daniel@0: return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseHour24(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 2)); Daniel@0: return n ? (d.H = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseMinutes(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 2)); Daniel@0: return n ? (d.M = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseSeconds(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 2)); Daniel@0: return n ? (d.S = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseMilliseconds(d, string, i) { Daniel@0: var n = numberRe.exec(string.slice(i, i + 3)); Daniel@0: return n ? (d.L = +n[0], i + n[0].length) : -1; Daniel@0: } Daniel@0: Daniel@0: function parseLiteralPercent(d, string, i) { Daniel@0: var n = percentRe.exec(string.slice(i, i + 1)); Daniel@0: return n ? i + n[0].length : -1; Daniel@0: } Daniel@0: Daniel@0: function formatDayOfMonth(d, p) { Daniel@0: return pad(d.getDate(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatHour24(d, p) { Daniel@0: return pad(d.getHours(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatHour12(d, p) { Daniel@0: return pad(d.getHours() % 12 || 12, p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatDayOfYear(d, p) { Daniel@0: return pad(1 + day.count(year(d), d), p, 3); Daniel@0: } Daniel@0: Daniel@0: function formatMilliseconds(d, p) { Daniel@0: return pad(d.getMilliseconds(), p, 3); Daniel@0: } Daniel@0: Daniel@0: function formatMonthNumber(d, p) { Daniel@0: return pad(d.getMonth() + 1, p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatMinutes(d, p) { Daniel@0: return pad(d.getMinutes(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatSeconds(d, p) { Daniel@0: return pad(d.getSeconds(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatWeekNumberSunday(d, p) { Daniel@0: return pad(sunday.count(year(d), d), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatWeekdayNumber(d) { Daniel@0: return d.getDay(); Daniel@0: } Daniel@0: Daniel@0: function formatWeekNumberMonday(d, p) { Daniel@0: return pad(monday.count(year(d), d), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatYear(d, p) { Daniel@0: return pad(d.getFullYear() % 100, p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatFullYear(d, p) { Daniel@0: return pad(d.getFullYear() % 10000, p, 4); Daniel@0: } Daniel@0: Daniel@0: function formatZone(d) { Daniel@0: var z = d.getTimezoneOffset(); Daniel@0: return (z > 0 ? "-" : (z *= -1, "+")) Daniel@0: + pad(z / 60 | 0, "0", 2) Daniel@0: + pad(z % 60, "0", 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCDayOfMonth(d, p) { Daniel@0: return pad(d.getUTCDate(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCHour24(d, p) { Daniel@0: return pad(d.getUTCHours(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCHour12(d, p) { Daniel@0: return pad(d.getUTCHours() % 12 || 12, p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCDayOfYear(d, p) { Daniel@0: return pad(1 + utcDay.count(utcYear(d), d), p, 3); Daniel@0: } Daniel@0: Daniel@0: function formatUTCMilliseconds(d, p) { Daniel@0: return pad(d.getUTCMilliseconds(), p, 3); Daniel@0: } Daniel@0: Daniel@0: function formatUTCMonthNumber(d, p) { Daniel@0: return pad(d.getUTCMonth() + 1, p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCMinutes(d, p) { Daniel@0: return pad(d.getUTCMinutes(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCSeconds(d, p) { Daniel@0: return pad(d.getUTCSeconds(), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCWeekNumberSunday(d, p) { Daniel@0: return pad(utcSunday.count(utcYear(d), d), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCWeekdayNumber(d) { Daniel@0: return d.getUTCDay(); Daniel@0: } Daniel@0: Daniel@0: function formatUTCWeekNumberMonday(d, p) { Daniel@0: return pad(utcMonday.count(utcYear(d), d), p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCYear(d, p) { Daniel@0: return pad(d.getUTCFullYear() % 100, p, 2); Daniel@0: } Daniel@0: Daniel@0: function formatUTCFullYear(d, p) { Daniel@0: return pad(d.getUTCFullYear() % 10000, p, 4); Daniel@0: } Daniel@0: Daniel@0: function formatUTCZone() { Daniel@0: return "+0000"; Daniel@0: } Daniel@0: Daniel@0: function formatLiteralPercent() { Daniel@0: return "%"; Daniel@0: } Daniel@0: Daniel@0: var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; Daniel@0: Daniel@0: function formatIsoNative(date) { Daniel@0: return date.toISOString(); Daniel@0: } Daniel@0: Daniel@0: formatIsoNative.parse = function(string) { Daniel@0: var date = new Date(string); Daniel@0: return isNaN(date) ? null : date; Daniel@0: }; Daniel@0: Daniel@0: formatIsoNative.toString = function() { Daniel@0: return isoSpecifier; Daniel@0: }; Daniel@0: Daniel@0: var formatIso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") Daniel@0: ? formatIsoNative Daniel@0: : enUs.utcFormat(isoSpecifier); Daniel@0: Daniel@0: var isoFormat = formatIso; Daniel@0: Daniel@0: var localeDefinitions = (new Map) Daniel@0: .set("ca-ES", caEs) Daniel@0: .set("de-DE", deDe) Daniel@0: .set("en-CA", enCa) Daniel@0: .set("en-GB", enGb) Daniel@0: .set("en-US", enUs) Daniel@0: .set("es-ES", esEs) Daniel@0: .set("fi-FI", fiFi) Daniel@0: .set("fr-CA", frCa) Daniel@0: .set("fr-FR", frFr) Daniel@0: .set("he-IL", heIl) Daniel@0: .set("it-IT", itIt) Daniel@0: .set("ja-JP", jaJp) Daniel@0: .set("mk-MK", mkMk) Daniel@0: .set("nl-NL", nlNl) Daniel@0: .set("pl-PL", plPl) Daniel@0: .set("pt-BR", ptBr) Daniel@0: .set("ru-RU", ruRu) Daniel@0: .set("zh-CN", zhCn); Daniel@0: Daniel@0: var defaultLocale = locale(enUs); Daniel@0: exports.format = defaultLocale.format; Daniel@0: exports.utcFormat = defaultLocale.utcFormat; Daniel@0: Daniel@0: function localeFormat(definition) { Daniel@0: if (typeof definition === "string") { Daniel@0: definition = localeDefinitions.get(definition); Daniel@0: if (!definition) return null; Daniel@0: } Daniel@0: return locale(definition); Daniel@0: } Daniel@0: ; Daniel@0: Daniel@0: exports.localeFormat = localeFormat; Daniel@0: exports.isoFormat = isoFormat; Daniel@0: Daniel@0: })); Daniel@0: },{}],6:[function(require,module,exports){ Daniel@0: (function (global, factory) { Daniel@0: typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : Daniel@0: typeof define === 'function' && define.amd ? define(['exports'], factory) : Daniel@0: factory((global.time = {})); Daniel@0: }(this, function (exports) { 'use strict'; Daniel@0: Daniel@0: var t1 = new Date; Daniel@0: Daniel@0: var t0 = new Date; Daniel@0: Daniel@0: function newInterval(floori, offseti, count) { Daniel@0: Daniel@0: function interval(date) { Daniel@0: return floori(date = new Date(+date)), date; Daniel@0: } Daniel@0: Daniel@0: interval.floor = interval; Daniel@0: Daniel@0: interval.round = function(date) { Daniel@0: var d0 = new Date(+date), Daniel@0: d1 = new Date(date - 1); Daniel@0: floori(d0), floori(d1), offseti(d1, 1); Daniel@0: return date - d0 < d1 - date ? d0 : d1; Daniel@0: }; Daniel@0: Daniel@0: interval.ceil = function(date) { Daniel@0: return floori(date = new Date(date - 1)), offseti(date, 1), date; Daniel@0: }; Daniel@0: Daniel@0: interval.offset = function(date, step) { Daniel@0: return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; Daniel@0: }; Daniel@0: Daniel@0: interval.range = function(start, stop, step) { Daniel@0: var range = []; Daniel@0: start = new Date(start - 1); Daniel@0: stop = new Date(+stop); Daniel@0: step = step == null ? 1 : Math.floor(step); Daniel@0: if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date Daniel@0: offseti(start, 1), floori(start); Daniel@0: if (start < stop) range.push(new Date(+start)); Daniel@0: while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start)); Daniel@0: return range; Daniel@0: }; Daniel@0: Daniel@0: interval.filter = function(test) { Daniel@0: return newInterval(function(date) { Daniel@0: while (floori(date), !test(date)) date.setTime(date - 1); Daniel@0: }, function(date, step) { Daniel@0: while (--step >= 0) while (offseti(date, 1), !test(date)); Daniel@0: }); Daniel@0: }; Daniel@0: Daniel@0: if (count) interval.count = function(start, end) { Daniel@0: t0.setTime(+start), t1.setTime(+end); Daniel@0: floori(t0), floori(t1); Daniel@0: return Math.floor(count(t0, t1)); Daniel@0: }; Daniel@0: Daniel@0: return interval; Daniel@0: } Daniel@0: Daniel@0: var second = newInterval(function(date) { Daniel@0: date.setMilliseconds(0); Daniel@0: }, function(date, step) { Daniel@0: date.setTime(+date + step * 1e3); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 1e3; Daniel@0: }); Daniel@0: Daniel@0: exports.seconds = second.range; Daniel@0: Daniel@0: var minute = newInterval(function(date) { Daniel@0: date.setSeconds(0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setTime(+date + step * 6e4); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 6e4; Daniel@0: }); Daniel@0: Daniel@0: exports.minutes = minute.range; Daniel@0: Daniel@0: var hour = newInterval(function(date) { Daniel@0: date.setMinutes(0, 0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setTime(+date + step * 36e5); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 36e5; Daniel@0: }); Daniel@0: Daniel@0: exports.hours = hour.range; Daniel@0: Daniel@0: var day = newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setDate(date.getDate() + step); Daniel@0: }, function(start, end) { Daniel@0: return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5; Daniel@0: }); Daniel@0: Daniel@0: exports.days = day.range; Daniel@0: Daniel@0: function weekday(i) { Daniel@0: return newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); Daniel@0: }, function(date, step) { Daniel@0: date.setDate(date.getDate() + step * 7); Daniel@0: }, function(start, end) { Daniel@0: return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5; Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: exports.sunday = weekday(0); Daniel@0: Daniel@0: exports.sundays = exports.sunday.range; Daniel@0: Daniel@0: exports.monday = weekday(1); Daniel@0: Daniel@0: exports.mondays = exports.monday.range; Daniel@0: Daniel@0: exports.tuesday = weekday(2); Daniel@0: Daniel@0: exports.tuesdays = exports.tuesday.range; Daniel@0: Daniel@0: exports.wednesday = weekday(3); Daniel@0: Daniel@0: exports.wednesdays = exports.wednesday.range; Daniel@0: Daniel@0: exports.thursday = weekday(4); Daniel@0: Daniel@0: exports.thursdays = exports.thursday.range; Daniel@0: Daniel@0: exports.friday = weekday(5); Daniel@0: Daniel@0: exports.fridays = exports.friday.range; Daniel@0: Daniel@0: exports.saturday = weekday(6); Daniel@0: Daniel@0: exports.saturdays = exports.saturday.range; Daniel@0: Daniel@0: var week = exports.sunday; Daniel@0: Daniel@0: exports.weeks = week.range; Daniel@0: Daniel@0: var month = newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: date.setDate(1); Daniel@0: }, function(date, step) { Daniel@0: date.setMonth(date.getMonth() + step); Daniel@0: }, function(start, end) { Daniel@0: return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; Daniel@0: }); Daniel@0: Daniel@0: exports.months = month.range; Daniel@0: Daniel@0: var year = newInterval(function(date) { Daniel@0: date.setHours(0, 0, 0, 0); Daniel@0: date.setMonth(0, 1); Daniel@0: }, function(date, step) { Daniel@0: date.setFullYear(date.getFullYear() + step); Daniel@0: }, function(start, end) { Daniel@0: return end.getFullYear() - start.getFullYear(); Daniel@0: }); Daniel@0: Daniel@0: exports.years = year.range; Daniel@0: Daniel@0: var utcSecond = newInterval(function(date) { Daniel@0: date.setUTCMilliseconds(0); Daniel@0: }, function(date, step) { Daniel@0: date.setTime(+date + step * 1e3); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 1e3; Daniel@0: }); Daniel@0: Daniel@0: exports.utcSeconds = utcSecond.range; Daniel@0: Daniel@0: var utcMinute = newInterval(function(date) { Daniel@0: date.setUTCSeconds(0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setTime(+date + step * 6e4); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 6e4; Daniel@0: }); Daniel@0: Daniel@0: exports.utcMinutes = utcMinute.range; Daniel@0: Daniel@0: var utcHour = newInterval(function(date) { Daniel@0: date.setUTCMinutes(0, 0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setTime(+date + step * 36e5); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 36e5; Daniel@0: }); Daniel@0: Daniel@0: exports.utcHours = utcHour.range; Daniel@0: Daniel@0: var utcDay = newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCDate(date.getUTCDate() + step); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 864e5; Daniel@0: }); Daniel@0: Daniel@0: exports.utcDays = utcDay.range; Daniel@0: Daniel@0: function utcWeekday(i) { Daniel@0: return newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCDate(date.getUTCDate() + step * 7); Daniel@0: }, function(start, end) { Daniel@0: return (end - start) / 6048e5; Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: exports.utcSunday = utcWeekday(0); Daniel@0: Daniel@0: exports.utcSundays = exports.utcSunday.range; Daniel@0: Daniel@0: exports.utcMonday = utcWeekday(1); Daniel@0: Daniel@0: exports.utcMondays = exports.utcMonday.range; Daniel@0: Daniel@0: exports.utcTuesday = utcWeekday(2); Daniel@0: Daniel@0: exports.utcTuesdays = exports.utcTuesday.range; Daniel@0: Daniel@0: exports.utcWednesday = utcWeekday(3); Daniel@0: Daniel@0: exports.utcWednesdays = exports.utcWednesday.range; Daniel@0: Daniel@0: exports.utcThursday = utcWeekday(4); Daniel@0: Daniel@0: exports.utcThursdays = exports.utcThursday.range; Daniel@0: Daniel@0: exports.utcFriday = utcWeekday(5); Daniel@0: Daniel@0: exports.utcFridays = exports.utcFriday.range; Daniel@0: Daniel@0: exports.utcSaturday = utcWeekday(6); Daniel@0: Daniel@0: exports.utcSaturdays = exports.utcSaturday.range; Daniel@0: Daniel@0: var utcWeek = exports.utcSunday; Daniel@0: Daniel@0: exports.utcWeeks = utcWeek.range; Daniel@0: Daniel@0: var utcMonth = newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: date.setUTCDate(1); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCMonth(date.getUTCMonth() + step); Daniel@0: }, function(start, end) { Daniel@0: return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; Daniel@0: }); Daniel@0: Daniel@0: exports.utcMonths = utcMonth.range; Daniel@0: Daniel@0: var utcYear = newInterval(function(date) { Daniel@0: date.setUTCHours(0, 0, 0, 0); Daniel@0: date.setUTCMonth(0, 1); Daniel@0: }, function(date, step) { Daniel@0: date.setUTCFullYear(date.getUTCFullYear() + step); Daniel@0: }, function(start, end) { Daniel@0: return end.getUTCFullYear() - start.getUTCFullYear(); Daniel@0: }); Daniel@0: Daniel@0: exports.utcYears = utcYear.range; Daniel@0: Daniel@0: exports.interval = newInterval; Daniel@0: exports.second = second; Daniel@0: exports.minute = minute; Daniel@0: exports.hour = hour; Daniel@0: exports.day = day; Daniel@0: exports.week = week; Daniel@0: exports.month = month; Daniel@0: exports.year = year; Daniel@0: exports.utcSecond = utcSecond; Daniel@0: exports.utcMinute = utcMinute; Daniel@0: exports.utcHour = utcHour; Daniel@0: exports.utcDay = utcDay; Daniel@0: exports.utcWeek = utcWeek; Daniel@0: exports.utcMonth = utcMonth; Daniel@0: exports.utcYear = utcYear; Daniel@0: Daniel@0: })); Daniel@0: },{}],7:[function(require,module,exports){ Daniel@0: var util = require('../util'), Daniel@0: Measures = require('./measures'), Daniel@0: Collector = require('./collector'); Daniel@0: Daniel@0: function Aggregator() { Daniel@0: this._cells = {}; Daniel@0: this._aggr = []; Daniel@0: this._stream = false; Daniel@0: } Daniel@0: Daniel@0: var Flags = Aggregator.Flags = { Daniel@0: ADD_CELL: 1, Daniel@0: MOD_CELL: 2 Daniel@0: }; Daniel@0: Daniel@0: var proto = Aggregator.prototype; Daniel@0: Daniel@0: // Parameters Daniel@0: Daniel@0: proto.stream = function(v) { Daniel@0: if (v == null) return this._stream; Daniel@0: this._stream = !!v; Daniel@0: this._aggr = []; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: // key accessor to use for streaming removes Daniel@0: proto.key = function(key) { Daniel@0: if (key == null) return this._key; Daniel@0: this._key = util.$(key); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: // Input: array of objects of the form Daniel@0: // {name: string, get: function} Daniel@0: proto.groupby = function(dims) { Daniel@0: this._dims = util.array(dims).map(function(d, i) { Daniel@0: d = util.isString(d) ? {name: d, get: util.$(d)} Daniel@0: : util.isFunction(d) ? {name: util.name(d) || d.name || ('_' + i), get: d} Daniel@0: : (d.name && util.isFunction(d.get)) ? d : null; Daniel@0: if (d == null) throw 'Invalid groupby argument: ' + d; Daniel@0: return d; Daniel@0: }); Daniel@0: return this.clear(); Daniel@0: }; Daniel@0: Daniel@0: // Input: array of objects of the form Daniel@0: // {name: string, ops: [string, ...]} Daniel@0: proto.summarize = function(fields) { Daniel@0: fields = summarize_args(fields); Daniel@0: this._count = true; Daniel@0: var aggr = (this._aggr = []), Daniel@0: m, f, i, j, op, as, get; Daniel@0: Daniel@0: for (i=0; i 0) { Daniel@0: // consolidate collector values Daniel@0: if (cell.collect) { Daniel@0: cell.data.values(); Daniel@0: } Daniel@0: // update tuple properties Daniel@0: for (i=0; i 0) { Daniel@0: m[a[i]] -= 1; Daniel@0: } else { Daniel@0: x[j++] = a[i]; Daniel@0: } Daniel@0: } Daniel@0: } else if (k) { Daniel@0: // has unique key field, so use that Daniel@0: m = util.toMap(r, k); Daniel@0: for (i=0, j=0, n=a.length; i 1 ? this.dev / (this.valid-1) : 0', Daniel@0: req: ['mean'], idx: 1 Daniel@0: }), Daniel@0: 'variancep': measure({ Daniel@0: name: 'variancep', Daniel@0: set: 'this.valid > 1 ? this.dev / this.valid : 0', Daniel@0: req: ['variance'], idx: 2 Daniel@0: }), Daniel@0: 'stdev': measure({ Daniel@0: name: 'stdev', Daniel@0: set: 'this.valid > 1 ? Math.sqrt(this.dev / (this.valid-1)) : 0', Daniel@0: req: ['variance'], idx: 2 Daniel@0: }), Daniel@0: 'stdevp': measure({ Daniel@0: name: 'stdevp', Daniel@0: set: 'this.valid > 1 ? Math.sqrt(this.dev / this.valid) : 0', Daniel@0: req: ['variance'], idx: 2 Daniel@0: }), Daniel@0: 'median': measure({ Daniel@0: name: 'median', Daniel@0: set: 'cell.data.q2(this.get)', Daniel@0: req: ['values'], idx: 3 Daniel@0: }), Daniel@0: 'q1': measure({ Daniel@0: name: 'q1', Daniel@0: set: 'cell.data.q1(this.get)', Daniel@0: req: ['values'], idx: 3 Daniel@0: }), Daniel@0: 'q3': measure({ Daniel@0: name: 'q3', Daniel@0: set: 'cell.data.q3(this.get)', Daniel@0: req: ['values'], idx: 3 Daniel@0: }), Daniel@0: 'distinct': measure({ Daniel@0: name: 'distinct', Daniel@0: set: 'this.distinct(cell.data.values(), this.get)', Daniel@0: req: ['values'], idx: 3 Daniel@0: }), Daniel@0: 'argmin': measure({ Daniel@0: name: 'argmin', Daniel@0: add: 'if (v < this.min) this.argmin = t;', Daniel@0: rem: 'if (v <= this.min) this.argmin = null;', Daniel@0: set: 'this.argmin = this.argmin || cell.data.argmin(this.get)', Daniel@0: req: ['min'], str: ['values'], idx: 3 Daniel@0: }), Daniel@0: 'argmax': measure({ Daniel@0: name: 'argmax', Daniel@0: add: 'if (v > this.max) this.argmax = t;', Daniel@0: rem: 'if (v >= this.max) this.argmax = null;', Daniel@0: set: 'this.argmax = this.argmax || cell.data.argmax(this.get)', Daniel@0: req: ['max'], str: ['values'], idx: 3 Daniel@0: }), Daniel@0: 'min': measure({ Daniel@0: name: 'min', Daniel@0: init: 'this.min = +Infinity;', Daniel@0: add: 'if (v < this.min) this.min = v;', Daniel@0: rem: 'if (v <= this.min) this.min = NaN;', Daniel@0: set: 'this.min = (isNaN(this.min) ? cell.data.min(this.get) : this.min)', Daniel@0: str: ['values'], idx: 4 Daniel@0: }), Daniel@0: 'max': measure({ Daniel@0: name: 'max', Daniel@0: init: 'this.max = -Infinity;', Daniel@0: add: 'if (v > this.max) this.max = v;', Daniel@0: rem: 'if (v >= this.max) this.max = NaN;', Daniel@0: set: 'this.max = (isNaN(this.max) ? cell.data.max(this.get) : this.max)', Daniel@0: str: ['values'], idx: 4 Daniel@0: }), Daniel@0: 'modeskew': measure({ Daniel@0: name: 'modeskew', Daniel@0: set: 'this.dev===0 ? 0 : (this.mean - cell.data.q2(this.get)) / Math.sqrt(this.dev/(this.valid-1))', Daniel@0: req: ['mean', 'stdev', 'median'], idx: 5 Daniel@0: }) Daniel@0: }; Daniel@0: Daniel@0: function measure(base) { Daniel@0: return function(out) { Daniel@0: var m = util.extend({init:'', add:'', rem:'', idx:0}, base); Daniel@0: m.out = out || base.name; Daniel@0: return m; Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function resolve(agg, stream) { Daniel@0: function collect(m, a) { Daniel@0: function helper(r) { if (!m[r]) collect(m, m[r] = types[r]()); } Daniel@0: if (a.req) a.req.forEach(helper); Daniel@0: if (stream && a.str) a.str.forEach(helper); Daniel@0: return m; Daniel@0: } Daniel@0: var map = agg.reduce( Daniel@0: collect, Daniel@0: agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {}) Daniel@0: ); Daniel@0: return util.vals(map).sort(function(a, b) { return a.idx - b.idx; }); Daniel@0: } Daniel@0: Daniel@0: function create(agg, stream, accessor, mutator) { Daniel@0: var all = resolve(agg, stream), Daniel@0: ctr = 'this.cell = cell; this.tuple = t; this.valid = 0; this.missing = 0;', Daniel@0: add = 'if (v==null) this.missing++; if (!this.isValid(v)) return; ++this.valid;', Daniel@0: rem = 'if (v==null) this.missing--; if (!this.isValid(v)) return; --this.valid;', Daniel@0: set = 'var t = this.tuple; var cell = this.cell;'; Daniel@0: Daniel@0: all.forEach(function(a) { Daniel@0: if (a.idx < 0) { Daniel@0: ctr = a.init + ctr; Daniel@0: add = a.add + add; Daniel@0: rem = a.rem + rem; Daniel@0: } else { Daniel@0: ctr += a.init; Daniel@0: add += a.add; Daniel@0: rem += a.rem; Daniel@0: } Daniel@0: }); Daniel@0: agg.slice() Daniel@0: .sort(function(a, b) { return a.idx - b.idx; }) Daniel@0: .forEach(function(a) { Daniel@0: set += 'this.assign(t,\''+a.out+'\','+a.set+');'; Daniel@0: }); Daniel@0: set += 'return t;'; Daniel@0: Daniel@0: /* jshint evil: true */ Daniel@0: ctr = Function('cell', 't', ctr); Daniel@0: ctr.prototype.assign = mutator; Daniel@0: ctr.prototype.add = Function('t', 'var v = this.get(t);' + add); Daniel@0: ctr.prototype.rem = Function('t', 'var v = this.get(t);' + rem); Daniel@0: ctr.prototype.set = Function(set); Daniel@0: ctr.prototype.get = accessor; Daniel@0: ctr.prototype.distinct = require('../stats').count.distinct; Daniel@0: ctr.prototype.isValid = util.isValid; Daniel@0: ctr.fields = agg.map(util.$('out')); Daniel@0: return ctr; Daniel@0: } Daniel@0: Daniel@0: types.create = create; Daniel@0: module.exports = types; Daniel@0: },{"../stats":26,"../util":29}],11:[function(require,module,exports){ Daniel@0: var util = require('../util'), Daniel@0: time = require('../time'), Daniel@0: EPSILON = 1e-15; Daniel@0: Daniel@0: function bins(opt) { Daniel@0: if (!opt) { throw Error("Missing binning options."); } Daniel@0: Daniel@0: // determine range Daniel@0: var maxb = opt.maxbins || 15, Daniel@0: base = opt.base || 10, Daniel@0: logb = Math.log(base), Daniel@0: div = opt.div || [5, 2], Daniel@0: min = opt.min, Daniel@0: max = opt.max, Daniel@0: span = max - min, Daniel@0: step, level, minstep, precision, v, i, eps; Daniel@0: Daniel@0: if (opt.step) { Daniel@0: // if step size is explicitly given, use that Daniel@0: step = opt.step; Daniel@0: } else if (opt.steps) { Daniel@0: // if provided, limit choice to acceptable step sizes Daniel@0: step = opt.steps[Math.min( Daniel@0: opt.steps.length - 1, Daniel@0: bisect(opt.steps, span/maxb, 0, opt.steps.length) Daniel@0: )]; Daniel@0: } else { Daniel@0: // else use span to determine step size Daniel@0: level = Math.ceil(Math.log(maxb) / logb); Daniel@0: minstep = opt.minstep || 0; Daniel@0: step = Math.max( Daniel@0: minstep, Daniel@0: Math.pow(base, Math.round(Math.log(span) / logb) - level) Daniel@0: ); Daniel@0: Daniel@0: // increase step size if too many bins Daniel@0: do { step *= base; } while (Math.ceil(span/step) > maxb); Daniel@0: Daniel@0: // decrease step size if allowed Daniel@0: for (i=0; i= minstep && span / v <= maxb) step = v; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // update precision, min and max Daniel@0: v = Math.log(step); Daniel@0: precision = v >= 0 ? 0 : ~~(-v / logb) + 1; Daniel@0: eps = Math.pow(base, -precision - 1); Daniel@0: min = Math.min(min, Math.floor(min / step + eps) * step); Daniel@0: max = Math.ceil(max / step) * step; Daniel@0: Daniel@0: return { Daniel@0: start: min, Daniel@0: stop: max, Daniel@0: step: step, Daniel@0: unit: {precision: precision}, Daniel@0: value: value, Daniel@0: index: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function bisect(a, x, lo, hi) { Daniel@0: while (lo < hi) { Daniel@0: var mid = lo + hi >>> 1; Daniel@0: if (util.cmp(a[mid], x) < 0) { lo = mid + 1; } Daniel@0: else { hi = mid; } Daniel@0: } Daniel@0: return lo; Daniel@0: } Daniel@0: Daniel@0: function value(v) { Daniel@0: return this.step * Math.floor(v / this.step + EPSILON); Daniel@0: } Daniel@0: Daniel@0: function index(v) { Daniel@0: return Math.floor((v - this.start) / this.step + EPSILON); Daniel@0: } Daniel@0: Daniel@0: function date_value(v) { Daniel@0: return this.unit.date(value.call(this, v)); Daniel@0: } Daniel@0: Daniel@0: function date_index(v) { Daniel@0: return index.call(this, this.unit.unit(v)); Daniel@0: } Daniel@0: Daniel@0: bins.date = function(opt) { Daniel@0: if (!opt) { throw Error("Missing date binning options."); } Daniel@0: Daniel@0: // find time step, then bin Daniel@0: var units = opt.utc ? time.utc : time, Daniel@0: dmin = opt.min, Daniel@0: dmax = opt.max, Daniel@0: maxb = opt.maxbins || 20, Daniel@0: minb = opt.minbins || 4, Daniel@0: span = (+dmax) - (+dmin), Daniel@0: unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb), Daniel@0: spec = bins({ Daniel@0: min: unit.min != null ? unit.min : unit.unit(dmin), Daniel@0: max: unit.max != null ? unit.max : unit.unit(dmax), Daniel@0: maxbins: maxb, Daniel@0: minstep: unit.minstep, Daniel@0: steps: unit.step Daniel@0: }); Daniel@0: Daniel@0: spec.unit = unit; Daniel@0: spec.index = date_index; Daniel@0: if (!opt.raw) spec.value = date_value; Daniel@0: return spec; Daniel@0: }; Daniel@0: Daniel@0: module.exports = bins; Daniel@0: Daniel@0: },{"../time":28,"../util":29}],12:[function(require,module,exports){ Daniel@0: var bins = require('./bins'), Daniel@0: gen = require('../generate'), Daniel@0: type = require('../import/type'), Daniel@0: util = require('../util'), Daniel@0: stats = require('../stats'); Daniel@0: Daniel@0: var qtype = { Daniel@0: 'integer': 1, Daniel@0: 'number': 1, Daniel@0: 'date': 1 Daniel@0: }; Daniel@0: Daniel@0: function $bin(values, f, opt) { Daniel@0: opt = options(values, f, opt); Daniel@0: var b = spec(opt); Daniel@0: return !b ? (opt.accessor || util.identity) : Daniel@0: util.$func('bin', b.unit.unit ? Daniel@0: function(x) { return b.value(b.unit.unit(x)); } : Daniel@0: function(x) { return b.value(x); } Daniel@0: )(opt.accessor); Daniel@0: } Daniel@0: Daniel@0: function histogram(values, f, opt) { Daniel@0: opt = options(values, f, opt); Daniel@0: var b = spec(opt); Daniel@0: return b ? Daniel@0: numerical(values, opt.accessor, b) : Daniel@0: categorical(values, opt.accessor, opt && opt.sort); Daniel@0: } Daniel@0: Daniel@0: function spec(opt) { Daniel@0: var t = opt.type, b = null; Daniel@0: if (t == null || qtype[t]) { Daniel@0: if (t === 'integer' && opt.minstep == null) opt.minstep = 1; Daniel@0: b = (t === 'date') ? bins.date(opt) : bins(opt); Daniel@0: } Daniel@0: return b; Daniel@0: } Daniel@0: Daniel@0: function options() { Daniel@0: var a = arguments, Daniel@0: i = 0, Daniel@0: values = util.isArray(a[i]) ? a[i++] : null, Daniel@0: f = util.isFunction(a[i]) || util.isString(a[i]) ? util.$(a[i++]) : null, Daniel@0: opt = util.extend({}, a[i]); Daniel@0: Daniel@0: if (values) { Daniel@0: opt.type = opt.type || type(values, f); Daniel@0: if (qtype[opt.type]) { Daniel@0: var ext = stats.extent(values, f); Daniel@0: opt = util.extend({min: ext[0], max: ext[1]}, opt); Daniel@0: } Daniel@0: } Daniel@0: if (f) { opt.accessor = f; } Daniel@0: return opt; Daniel@0: } Daniel@0: Daniel@0: function numerical(values, f, b) { Daniel@0: var h = gen.range(b.start, b.stop + b.step/2, b.step) Daniel@0: .map(function(v) { return {value: b.value(v), count: 0}; }); Daniel@0: Daniel@0: for (var i=0, v, j; i= h.length || !isFinite(j)) continue; Daniel@0: h[j].count += 1; Daniel@0: } Daniel@0: } Daniel@0: h.bins = b; Daniel@0: return h; Daniel@0: } Daniel@0: Daniel@0: function categorical(values, f, sort) { Daniel@0: var u = stats.unique(values, f), Daniel@0: c = stats.count.map(values, f); Daniel@0: return u.map(function(k) { return {value: k, count: c[k]}; }) Daniel@0: .sort(util.comparator(sort ? '-count' : '+value')); Daniel@0: } Daniel@0: Daniel@0: module.exports = { Daniel@0: $bin: $bin, Daniel@0: histogram: histogram Daniel@0: }; Daniel@0: },{"../generate":14,"../import/type":23,"../stats":26,"../util":29,"./bins":11}],13:[function(require,module,exports){ Daniel@0: var d3_time = require('d3-time'), Daniel@0: d3_timeF = require('d3-time-format'), Daniel@0: d3_numberF = require('d3-format'), Daniel@0: numberF = d3_numberF, // defaults to EN-US Daniel@0: timeF = d3_timeF; // defaults to EN-US Daniel@0: Daniel@0: function numberLocale(l) { Daniel@0: var f = d3_numberF.localeFormat(l); Daniel@0: if (f == null) throw Error('Unrecognized locale: ' + l); Daniel@0: numberF = f; Daniel@0: } Daniel@0: Daniel@0: function timeLocale(l) { Daniel@0: var f = d3_timeF.localeFormat(l); Daniel@0: if (f == null) throw Error('Unrecognized locale: ' + l); Daniel@0: timeF = f; Daniel@0: } Daniel@0: Daniel@0: module.exports = { Daniel@0: // Update number formatter to use provided locale configuration. Daniel@0: // For more see https://github.com/d3/d3-format Daniel@0: numberLocale: numberLocale, Daniel@0: number: function(f) { return numberF.format(f); }, Daniel@0: numberPrefix: function(f, v) { return numberF.formatPrefix(f, v); }, Daniel@0: Daniel@0: // Update time formatter to use provided locale configuration. Daniel@0: // For more see https://github.com/d3/d3-time-format Daniel@0: timeLocale: timeLocale, Daniel@0: time: function(f) { return timeF.format(f); }, Daniel@0: utc: function(f) { return timeF.utcFormat(f); }, Daniel@0: Daniel@0: // Set number and time locale simultaneously. Daniel@0: locale: function(l) { numberLocale(l); timeLocale(l); }, Daniel@0: Daniel@0: // automatic formatting functions Daniel@0: auto: { Daniel@0: number: numberAutoFormat, Daniel@0: time: function() { return timeAutoFormat(); }, Daniel@0: utc: function() { return utcAutoFormat(); } Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: var e10 = Math.sqrt(50), Daniel@0: e5 = Math.sqrt(10), Daniel@0: e2 = Math.sqrt(2); Daniel@0: Daniel@0: function intervals(domain, count) { Daniel@0: if (!domain.length) domain = [0]; Daniel@0: if (count == null) count = 10; Daniel@0: Daniel@0: var start = domain[0], Daniel@0: stop = domain[domain.length - 1]; Daniel@0: Daniel@0: if (stop < start) { error = stop; stop = start; start = error; } Daniel@0: Daniel@0: var span = (stop - start) || (count = 1, start || stop || 1), Daniel@0: step = Math.pow(10, Math.floor(Math.log(span / count) / Math.LN10)), Daniel@0: error = span / count / step; Daniel@0: Daniel@0: // Filter ticks to get closer to the desired count. Daniel@0: if (error >= e10) step *= 10; Daniel@0: else if (error >= e5) step *= 5; Daniel@0: else if (error >= e2) step *= 2; Daniel@0: Daniel@0: // Round start and stop values to step interval. Daniel@0: return [ Daniel@0: Math.ceil(start / step) * step, Daniel@0: Math.floor(stop / step) * step + step / 2, // inclusive Daniel@0: step Daniel@0: ]; Daniel@0: } Daniel@0: Daniel@0: function numberAutoFormat(domain, count, f) { Daniel@0: var range = intervals(domain, count); Daniel@0: if (f == null) { Daniel@0: f = ',.' + d3_numberF.precisionFixed(range[2]) + 'f'; Daniel@0: } else { Daniel@0: switch (f = d3_numberF.formatSpecifier(f), f.type) { Daniel@0: case 's': { Daniel@0: var value = Math.max(Math.abs(range[0]), Math.abs(range[1])); Daniel@0: if (f.precision == null) f.precision = d3_numberF.precisionPrefix(range[2], value); Daniel@0: return numberF.formatPrefix(f, value); Daniel@0: } Daniel@0: case '': Daniel@0: case 'e': Daniel@0: case 'g': Daniel@0: case 'p': Daniel@0: case 'r': { Daniel@0: if (f.precision == null) f.precision = d3_numberF.precisionRound(range[2], Math.max(Math.abs(range[0]), Math.abs(range[1]))) - (f.type === 'e'); Daniel@0: break; Daniel@0: } Daniel@0: case 'f': Daniel@0: case '%': { Daniel@0: if (f.precision == null) f.precision = d3_numberF.precisionFixed(range[2]) - (f.type === '%') * 2; Daniel@0: break; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: return numberF.format(f); Daniel@0: } Daniel@0: Daniel@0: function timeAutoFormat() { Daniel@0: var f = timeF.format, Daniel@0: formatMillisecond = f('.%L'), Daniel@0: formatSecond = f(':%S'), Daniel@0: formatMinute = f('%I:%M'), Daniel@0: formatHour = f('%I %p'), Daniel@0: formatDay = f('%a %d'), Daniel@0: formatWeek = f('%b %d'), Daniel@0: formatMonth = f('%B'), Daniel@0: formatYear = f('%Y'); Daniel@0: Daniel@0: return function(date) { Daniel@0: var d = +date; Daniel@0: return (d3_time.second(date) < d ? formatMillisecond Daniel@0: : d3_time.minute(date) < d ? formatSecond Daniel@0: : d3_time.hour(date) < d ? formatMinute Daniel@0: : d3_time.day(date) < d ? formatHour Daniel@0: : d3_time.month(date) < d ? Daniel@0: (d3_time.week(date) < d ? formatDay : formatWeek) Daniel@0: : d3_time.year(date) < d ? formatMonth Daniel@0: : formatYear)(date); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function utcAutoFormat() { Daniel@0: var f = timeF.utcFormat, Daniel@0: formatMillisecond = f('.%L'), Daniel@0: formatSecond = f(':%S'), Daniel@0: formatMinute = f('%I:%M'), Daniel@0: formatHour = f('%I %p'), Daniel@0: formatDay = f('%a %d'), Daniel@0: formatWeek = f('%b %d'), Daniel@0: formatMonth = f('%B'), Daniel@0: formatYear = f('%Y'); Daniel@0: Daniel@0: return function(date) { Daniel@0: var d = +date; Daniel@0: return (d3_time.utcSecond(date) < d ? formatMillisecond Daniel@0: : d3_time.utcMinute(date) < d ? formatSecond Daniel@0: : d3_time.utcHour(date) < d ? formatMinute Daniel@0: : d3_time.utcDay(date) < d ? formatHour Daniel@0: : d3_time.utcMonth(date) < d ? Daniel@0: (d3_time.utcWeek(date) < d ? formatDay : formatWeek) Daniel@0: : d3_time.utcYear(date) < d ? formatMonth Daniel@0: : formatYear)(date); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: },{"d3-format":4,"d3-time":6,"d3-time-format":5}],14:[function(require,module,exports){ Daniel@0: var gen = module.exports = {}; Daniel@0: Daniel@0: gen.repeat = function(val, n) { Daniel@0: var a = Array(n), i; Daniel@0: for (i=0; i stop) range.push(j); Daniel@0: else while ((j = start + step * ++i) < stop) range.push(j); Daniel@0: return range; Daniel@0: }; Daniel@0: Daniel@0: gen.random = {}; Daniel@0: Daniel@0: gen.random.uniform = function(min, max) { Daniel@0: if (max === undefined) { Daniel@0: max = min === undefined ? 1 : min; Daniel@0: min = 0; Daniel@0: } Daniel@0: var d = max - min; Daniel@0: var f = function() { Daniel@0: return min + d * Math.random(); Daniel@0: }; Daniel@0: f.samples = function(n) { return gen.zeros(n).map(f); }; Daniel@0: return f; Daniel@0: }; Daniel@0: Daniel@0: gen.random.integer = function(a, b) { Daniel@0: if (b === undefined) { Daniel@0: b = a; Daniel@0: a = 0; Daniel@0: } Daniel@0: var d = b - a; Daniel@0: var f = function() { Daniel@0: return a + Math.floor(d * Math.random()); Daniel@0: }; Daniel@0: f.samples = function(n) { return gen.zeros(n).map(f); }; Daniel@0: return f; Daniel@0: }; Daniel@0: Daniel@0: gen.random.normal = function(mean, stdev) { Daniel@0: mean = mean || 0; Daniel@0: stdev = stdev || 1; Daniel@0: var next; Daniel@0: var f = function() { Daniel@0: var x = 0, y = 0, rds, c; Daniel@0: if (next !== undefined) { Daniel@0: x = next; Daniel@0: next = undefined; Daniel@0: return x; Daniel@0: } Daniel@0: do { Daniel@0: x = Math.random()*2-1; Daniel@0: y = Math.random()*2-1; Daniel@0: rds = x*x + y*y; Daniel@0: } while (rds === 0 || rds > 1); Daniel@0: c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform Daniel@0: next = mean + y*c*stdev; Daniel@0: return mean + x*c*stdev; Daniel@0: }; Daniel@0: f.samples = function(n) { return gen.zeros(n).map(f); }; Daniel@0: return f; Daniel@0: }; Daniel@0: },{}],15:[function(require,module,exports){ Daniel@0: var util = require('../../util'); Daniel@0: var d3_dsv = require('d3-dsv'); Daniel@0: Daniel@0: function dsv(data, format) { Daniel@0: if (data) { Daniel@0: var h = format.header; Daniel@0: data = (h ? h.join(format.delimiter) + '\n' : '') + data; Daniel@0: } Daniel@0: return d3_dsv.dsv(format.delimiter).parse(data); Daniel@0: } Daniel@0: Daniel@0: dsv.delimiter = function(delim) { Daniel@0: var fmt = {delimiter: delim}; Daniel@0: return function(data, format) { Daniel@0: return dsv(data, format ? util.extend(format, fmt) : fmt); Daniel@0: }; Daniel@0: }; Daniel@0: Daniel@0: module.exports = dsv; Daniel@0: },{"../../util":29,"d3-dsv":3}],16:[function(require,module,exports){ Daniel@0: var dsv = require('./dsv'); Daniel@0: Daniel@0: module.exports = { Daniel@0: json: require('./json'), Daniel@0: topojson: require('./topojson'), Daniel@0: treejson: require('./treejson'), Daniel@0: dsv: dsv, Daniel@0: csv: dsv.delimiter(','), Daniel@0: tsv: dsv.delimiter('\t') Daniel@0: }; Daniel@0: },{"./dsv":15,"./json":17,"./topojson":18,"./treejson":19}],17:[function(require,module,exports){ Daniel@0: var util = require('../../util'); Daniel@0: Daniel@0: module.exports = function(data, format) { Daniel@0: var d = util.isObject(data) && !util.isBuffer(data) ? Daniel@0: data : JSON.parse(data); Daniel@0: if (format && format.property) { Daniel@0: d = util.accessor(format.property)(d); Daniel@0: } Daniel@0: return d; Daniel@0: }; Daniel@0: Daniel@0: },{"../../util":29}],18:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var json = require('./json'); Daniel@0: Daniel@0: var reader = function(data, format) { Daniel@0: var topojson = reader.topojson; Daniel@0: if (topojson == null) { throw Error('TopoJSON library not loaded.'); } Daniel@0: Daniel@0: var t = json(data, format), obj; Daniel@0: Daniel@0: if (format && format.feature) { Daniel@0: if ((obj = t.objects[format.feature])) { Daniel@0: return topojson.feature(t, obj).features; Daniel@0: } else { Daniel@0: throw Error('Invalid TopoJSON object: ' + format.feature); Daniel@0: } Daniel@0: } else if (format && format.mesh) { Daniel@0: if ((obj = t.objects[format.mesh])) { Daniel@0: return [topojson.mesh(t, t.objects[format.mesh])]; Daniel@0: } else { Daniel@0: throw Error('Invalid TopoJSON object: ' + format.mesh); Daniel@0: } Daniel@0: } else { Daniel@0: throw Error('Missing TopoJSON feature or mesh parameter.'); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: reader.topojson = (typeof window !== "undefined" ? window['topojson'] : typeof global !== "undefined" ? global['topojson'] : null); Daniel@0: module.exports = reader; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"./json":17}],19:[function(require,module,exports){ Daniel@0: var json = require('./json'); Daniel@0: Daniel@0: module.exports = function(data, format) { Daniel@0: data = json(data, format); Daniel@0: return toTable(data, (format && format.children)); Daniel@0: }; Daniel@0: Daniel@0: function toTable(root, childrenField) { Daniel@0: childrenField = childrenField || 'children'; Daniel@0: var table = []; Daniel@0: Daniel@0: function visit(node) { Daniel@0: table.push(node); Daniel@0: var children = node[childrenField]; Daniel@0: if (children) { Daniel@0: for (var i=0; i 1 && domain[idx-1] === '.' && domain.lastIndexOf(d) === idx); Daniel@0: }); Daniel@0: if (!whiteListed) { Daniel@0: throw 'URL is not whitelisted: ' + url; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: return url; Daniel@0: } Daniel@0: Daniel@0: function load(opt, callback) { Daniel@0: var error = callback || function(e) { throw e; }, url; Daniel@0: Daniel@0: try { Daniel@0: url = load.sanitizeUrl(opt); // enable override Daniel@0: } catch (err) { Daniel@0: error(err); Daniel@0: return; Daniel@0: } Daniel@0: Daniel@0: if (!url) { Daniel@0: error('Invalid URL: ' + opt.url); Daniel@0: } else if (load.useXHR) { Daniel@0: // on client, use xhr Daniel@0: return xhr(url, callback); Daniel@0: } else if (startsWith(url, fileProtocol)) { Daniel@0: // on server, if url starts with 'file://', strip it and load from file Daniel@0: return file(url.slice(fileProtocol.length), callback); Daniel@0: } else if (url.indexOf('://') < 0) { // TODO better protocol check? Daniel@0: // on server, if no protocol assume file Daniel@0: return file(url, callback); Daniel@0: } else { Daniel@0: // for regular URLs on server Daniel@0: return http(url, callback); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function xhrHasResponse(request) { Daniel@0: var type = request.responseType; Daniel@0: return type && type !== 'text' ? Daniel@0: request.response : // null on error Daniel@0: request.responseText; // '' on error Daniel@0: } Daniel@0: Daniel@0: function xhr(url, callback) { Daniel@0: var async = !!callback; Daniel@0: var request = new XMLHttpRequest(); Daniel@0: // If IE does not support CORS, use XDomainRequest (copied from d3.xhr) Daniel@0: if (this.XDomainRequest && Daniel@0: !('withCredentials' in request) && Daniel@0: /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); Daniel@0: Daniel@0: function respond() { Daniel@0: var status = request.status; Daniel@0: if (!status && xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { Daniel@0: callback(null, request.responseText); Daniel@0: } else { Daniel@0: callback(request, null); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (async) { Daniel@0: if ('onload' in request) { Daniel@0: request.onload = request.onerror = respond; Daniel@0: } else { Daniel@0: request.onreadystatechange = function() { Daniel@0: if (request.readyState > 3) respond(); Daniel@0: }; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: request.open('GET', url, async); Daniel@0: request.send(); Daniel@0: Daniel@0: if (!async && xhrHasResponse(request)) { Daniel@0: return request.responseText; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function file(filename, callback) { Daniel@0: var fs = require('fs'); Daniel@0: if (!callback) { Daniel@0: return fs.readFileSync(filename, 'utf8'); Daniel@0: } Daniel@0: fs.readFile(filename, callback); Daniel@0: } Daniel@0: Daniel@0: function http(url, callback) { Daniel@0: if (!callback) { Daniel@0: return require('sync-request')('GET', url).getBody(); Daniel@0: } Daniel@0: Daniel@0: var options = {url: url, encoding: null, gzip: true}; Daniel@0: require('request')(options, function(error, response, body) { Daniel@0: if (!error && response.statusCode === 200) { Daniel@0: callback(null, body); Daniel@0: } else { Daniel@0: error = error || Daniel@0: 'Load failed with response code ' + response.statusCode + '.'; Daniel@0: callback(error, null); Daniel@0: } Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: function startsWith(string, searchString) { Daniel@0: return string == null ? false : string.lastIndexOf(searchString, 0) === 0; Daniel@0: } Daniel@0: Daniel@0: load.sanitizeUrl = sanitizeUrl; Daniel@0: Daniel@0: load.useXHR = (typeof XMLHttpRequest !== 'undefined'); Daniel@0: Daniel@0: module.exports = load; Daniel@0: Daniel@0: },{"fs":2,"request":2,"sync-request":2,"url":2}],21:[function(require,module,exports){ Daniel@0: var util = require('../util'); Daniel@0: var type = require('./type'); Daniel@0: var formats = require('./formats'); Daniel@0: Daniel@0: function read(data, format) { Daniel@0: var type = (format && format.type) || 'json'; Daniel@0: data = formats[type](data, format); Daniel@0: if (format && format.parse) parse(data, format.parse); Daniel@0: return data; Daniel@0: } Daniel@0: Daniel@0: function parse(data, types) { Daniel@0: var cols, parsers, d, i, j, clen, len = data.length; Daniel@0: Daniel@0: types = (types==='auto') ? type.inferAll(data) : util.duplicate(types); Daniel@0: cols = util.keys(types); Daniel@0: parsers = cols.map(function(c) { return type.parsers[types[c]]; }); Daniel@0: Daniel@0: for (i=0, clen=cols.length; i 0 ? Math.min(l, opt.maxwidth) : l; Daniel@0: }); Daniel@0: Daniel@0: // print header row Daniel@0: var head = fields.map(function(name, i) { Daniel@0: return util.truncate(util.pad(name, lens[i], 'center'), lens[i]); Daniel@0: }).join(opt.separator); Daniel@0: Daniel@0: // build template function for each row Daniel@0: var tmpl = template(fields.map(function(name, i) { Daniel@0: return '{{' + Daniel@0: name + Daniel@0: (FMT[types[name]] || '') + Daniel@0: ('|pad:' + lens[i] + ',' + (POS[types[name]] || 'right')) + Daniel@0: ('|truncate:' + lens[i]) + Daniel@0: '}}'; Daniel@0: }).join(opt.separator)); Daniel@0: Daniel@0: // print table Daniel@0: return head + "\n" + data.map(tmpl).join('\n'); Daniel@0: }; Daniel@0: Daniel@0: module.exports.summary = function(s) { Daniel@0: s = s ? s.__summary__ ? s : stats.summary(s) : this; Daniel@0: var str = [], i, n; Daniel@0: for (i=0, n=s.length; i b) b = v; Daniel@0: } Daniel@0: } Daniel@0: return [a, b]; Daniel@0: }; Daniel@0: Daniel@0: // Find the integer indices of the minimum and maximum values. Daniel@0: stats.extent.index = function(values, f) { Daniel@0: f = util.$(f); Daniel@0: var x = -1, y = -1, a, b, v, i, n = values.length; Daniel@0: for (i=0; i b) { b = v; y = i; } Daniel@0: } Daniel@0: } Daniel@0: return [x, y]; Daniel@0: }; Daniel@0: Daniel@0: // Compute the dot product of two arrays of numbers. Daniel@0: stats.dot = function(values, a, b) { Daniel@0: var sum = 0, i, v; Daniel@0: if (!b) { Daniel@0: if (values.length !== a.length) { Daniel@0: throw Error('Array lengths must match.'); Daniel@0: } Daniel@0: for (i=0; i -1 && p !== v) { Daniel@0: mu = 1 + (i-1 + tie) / 2; Daniel@0: for (; tie -1) { Daniel@0: mu = 1 + (n-1 + tie) / 2; Daniel@0: for (; tie max) max = x; Daniel@0: delta = x - mean; Daniel@0: mean = mean + delta / (++valid); Daniel@0: M2 = M2 + delta * (x - mean); Daniel@0: vals.push(x); Daniel@0: } Daniel@0: } Daniel@0: M2 = M2 / (valid - 1); Daniel@0: sd = Math.sqrt(M2); Daniel@0: Daniel@0: // sort values for median and iqr Daniel@0: vals.sort(util.cmp); Daniel@0: Daniel@0: return { Daniel@0: type: type(values, f), Daniel@0: unique: u, Daniel@0: count: values.length, Daniel@0: valid: valid, Daniel@0: missing: missing, Daniel@0: distinct: distinct, Daniel@0: min: min, Daniel@0: max: max, Daniel@0: mean: mean, Daniel@0: stdev: sd, Daniel@0: median: (v = stats.quantile(vals, 0.5)), Daniel@0: q1: stats.quantile(vals, 0.25), Daniel@0: q3: stats.quantile(vals, 0.75), Daniel@0: modeskew: sd === 0 ? 0 : (mean - v) / sd Daniel@0: }; Daniel@0: }; Daniel@0: Daniel@0: // Compute profiles for all variables in a data set. Daniel@0: stats.summary = function(data, fields) { Daniel@0: fields = fields || util.keys(data[0]); Daniel@0: var s = fields.map(function(f) { Daniel@0: var p = stats.profile(data, util.$(f)); Daniel@0: return (p.field = f, p); Daniel@0: }); Daniel@0: return (s.__summary__ = true, s); Daniel@0: }; Daniel@0: Daniel@0: module.exports = stats; Daniel@0: },{"./generate":14,"./import/type":23,"./util":29}],27:[function(require,module,exports){ Daniel@0: var util = require('./util'), Daniel@0: format = require('./format'); Daniel@0: Daniel@0: var context = { Daniel@0: formats: [], Daniel@0: format_map: {}, Daniel@0: truncate: util.truncate, Daniel@0: pad: util.pad Daniel@0: }; Daniel@0: Daniel@0: function template(text) { Daniel@0: var src = source(text, 'd'); Daniel@0: src = 'var __t; return ' + src + ';'; Daniel@0: Daniel@0: /* jshint evil: true */ Daniel@0: return (new Function('d', src)).bind(context); Daniel@0: } Daniel@0: Daniel@0: template.source = source; Daniel@0: template.context = context; Daniel@0: module.exports = template; Daniel@0: Daniel@0: // Clear cache of format objects. Daniel@0: // This can *break* prior template functions, so invoke with care! Daniel@0: template.clearFormatCache = function() { Daniel@0: context.formats = []; Daniel@0: context.format_map = {}; Daniel@0: }; Daniel@0: Daniel@0: // Generate property access code for use within template source. Daniel@0: // object: the name of the object (variable) containing template data Daniel@0: // property: the property access string, verbatim from template tag Daniel@0: template.property = function(object, property) { Daniel@0: var src = util.field(property).map(util.str).join(']['); Daniel@0: return object + '[' + src + ']'; Daniel@0: }; Daniel@0: Daniel@0: // Generate source code for a template function. Daniel@0: // text: the template text Daniel@0: // variable: the name of the data object variable ('obj' by default) Daniel@0: // properties: optional hash for collecting all accessed properties Daniel@0: function source(text, variable, properties) { Daniel@0: variable = variable || 'obj'; Daniel@0: var index = 0; Daniel@0: var src = '\''; Daniel@0: var regex = template_re; Daniel@0: Daniel@0: // Compile the template source, escaping string literals appropriately. Daniel@0: text.replace(regex, function(match, interpolate, offset) { Daniel@0: src += text Daniel@0: .slice(index, offset) Daniel@0: .replace(template_escaper, template_escapeChar); Daniel@0: index = offset + match.length; Daniel@0: Daniel@0: if (interpolate) { Daniel@0: src += '\'\n+((__t=(' + Daniel@0: template_var(interpolate, variable, properties) + Daniel@0: '))==null?\'\':__t)+\n\''; Daniel@0: } Daniel@0: Daniel@0: // Adobe VMs need the match returned to produce the correct offest. Daniel@0: return match; Daniel@0: }); Daniel@0: return src + '\''; Daniel@0: } Daniel@0: Daniel@0: function template_var(text, variable, properties) { Daniel@0: var filters = text.match(filter_re); Daniel@0: var prop = filters.shift().trim(); Daniel@0: var stringCast = true; Daniel@0: Daniel@0: function strcall(fn) { Daniel@0: fn = fn || ''; Daniel@0: if (stringCast) { Daniel@0: stringCast = false; Daniel@0: src = 'String(' + src + ')' + fn; Daniel@0: } else { Daniel@0: src += fn; Daniel@0: } Daniel@0: return src; Daniel@0: } Daniel@0: Daniel@0: function date() { Daniel@0: return '(typeof ' + src + '==="number"?new Date('+src+'):'+src+')'; Daniel@0: } Daniel@0: Daniel@0: function number_format(fmt, key) { Daniel@0: a = template_format(args[0], key, fmt); Daniel@0: stringCast = false; Daniel@0: src = 'this.formats['+a+']('+src+')'; Daniel@0: } Daniel@0: Daniel@0: function time_format(fmt, key) { Daniel@0: a = template_format(args[0], key, fmt); Daniel@0: stringCast = false; Daniel@0: src = 'this.formats['+a+']('+date()+')'; Daniel@0: } Daniel@0: Daniel@0: if (properties) properties[prop] = 1; Daniel@0: var src = template.property(variable, prop); Daniel@0: Daniel@0: for (var i=0; i 0) { Daniel@0: f = f.slice(0, pidx); Daniel@0: args = filters[i].slice(pidx+1) Daniel@0: .match(args_re) Daniel@0: .map(function(s) { return s.trim(); }); Daniel@0: } Daniel@0: f = f.trim(); Daniel@0: Daniel@0: switch (f) { Daniel@0: case 'length': Daniel@0: strcall('.length'); Daniel@0: break; Daniel@0: case 'lower': Daniel@0: strcall('.toLowerCase()'); Daniel@0: break; Daniel@0: case 'upper': Daniel@0: strcall('.toUpperCase()'); Daniel@0: break; Daniel@0: case 'lower-locale': Daniel@0: strcall('.toLocaleLowerCase()'); Daniel@0: break; Daniel@0: case 'upper-locale': Daniel@0: strcall('.toLocaleUpperCase()'); Daniel@0: break; Daniel@0: case 'trim': Daniel@0: strcall('.trim()'); Daniel@0: break; Daniel@0: case 'left': Daniel@0: a = util.number(args[0]); Daniel@0: strcall('.slice(0,' + a + ')'); Daniel@0: break; Daniel@0: case 'right': Daniel@0: a = util.number(args[0]); Daniel@0: strcall('.slice(-' + a +')'); Daniel@0: break; Daniel@0: case 'mid': Daniel@0: a = util.number(args[0]); Daniel@0: b = a + util.number(args[1]); Daniel@0: strcall('.slice(+'+a+','+b+')'); Daniel@0: break; Daniel@0: case 'slice': Daniel@0: a = util.number(args[0]); Daniel@0: strcall('.slice('+ a + Daniel@0: (args.length > 1 ? ',' + util.number(args[1]) : '') + Daniel@0: ')'); Daniel@0: break; Daniel@0: case 'truncate': Daniel@0: a = util.number(args[0]); Daniel@0: b = args[1]; Daniel@0: b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b; Daniel@0: src = 'this.truncate(' + strcall() + ',' + a + ',\'' + b + '\')'; Daniel@0: break; Daniel@0: case 'pad': Daniel@0: a = util.number(args[0]); Daniel@0: b = args[1]; Daniel@0: b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b; Daniel@0: src = 'this.pad(' + strcall() + ',' + a + ',\'' + b + '\')'; Daniel@0: break; Daniel@0: case 'number': Daniel@0: number_format(format.number, 'number'); Daniel@0: break; Daniel@0: case 'time': Daniel@0: time_format(format.time, 'time'); Daniel@0: break; Daniel@0: case 'time-utc': Daniel@0: time_format(format.utc, 'time-utc'); Daniel@0: break; Daniel@0: default: Daniel@0: throw Error('Unrecognized template filter: ' + f); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return src; Daniel@0: } Daniel@0: Daniel@0: var template_re = /\{\{(.+?)\}\}|$/g, Daniel@0: filter_re = /(?:"[^"]*"|\'[^\']*\'|[^\|"]+|[^\|\']+)+/g, Daniel@0: args_re = /(?:"[^"]*"|\'[^\']*\'|[^,"]+|[^,\']+)+/g; Daniel@0: Daniel@0: // Certain characters need to be escaped so that they can be put into a Daniel@0: // string literal. Daniel@0: var template_escapes = { Daniel@0: '\'': '\'', Daniel@0: '\\': '\\', Daniel@0: '\r': 'r', Daniel@0: '\n': 'n', Daniel@0: '\u2028': 'u2028', Daniel@0: '\u2029': 'u2029' Daniel@0: }; Daniel@0: Daniel@0: var template_escaper = /\\|'|\r|\n|\u2028|\u2029/g; Daniel@0: Daniel@0: function template_escapeChar(match) { Daniel@0: return '\\' + template_escapes[match]; Daniel@0: } Daniel@0: Daniel@0: function template_format(pattern, key, fmt) { Daniel@0: if ((pattern[0] === '\'' && pattern[pattern.length-1] === '\'') || Daniel@0: (pattern[0] === '"' && pattern[pattern.length-1] === '"')) { Daniel@0: pattern = pattern.slice(1, -1); Daniel@0: } else { Daniel@0: throw Error('Format pattern must be quoted: ' + pattern); Daniel@0: } Daniel@0: key = key + ':' + pattern; Daniel@0: if (!context.format_map[key]) { Daniel@0: var f = fmt(pattern); Daniel@0: var i = context.formats.length; Daniel@0: context.formats.push(f); Daniel@0: context.format_map[key] = i; Daniel@0: } Daniel@0: return context.format_map[key]; Daniel@0: } Daniel@0: Daniel@0: },{"./format":13,"./util":29}],28:[function(require,module,exports){ Daniel@0: var d3_time = require('d3-time'); Daniel@0: Daniel@0: var tempDate = new Date(), Daniel@0: baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD Daniel@0: utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0); Daniel@0: Daniel@0: function date(d) { Daniel@0: return (tempDate.setTime(+d), tempDate); Daniel@0: } Daniel@0: Daniel@0: // create a time unit entry Daniel@0: function entry(type, date, unit, step, min, max) { Daniel@0: var e = { Daniel@0: type: type, Daniel@0: date: date, Daniel@0: unit: unit Daniel@0: }; Daniel@0: if (step) { Daniel@0: e.step = step; Daniel@0: } else { Daniel@0: e.minstep = 1; Daniel@0: } Daniel@0: if (min != null) e.min = min; Daniel@0: if (max != null) e.max = max; Daniel@0: return e; Daniel@0: } Daniel@0: Daniel@0: function create(type, unit, base, step, min, max) { Daniel@0: return entry(type, Daniel@0: function(d) { return unit.offset(base, d); }, Daniel@0: function(d) { return unit.count(base, d); }, Daniel@0: step, min, max); Daniel@0: } Daniel@0: Daniel@0: var locale = [ Daniel@0: create('second', d3_time.second, baseDate), Daniel@0: create('minute', d3_time.minute, baseDate), Daniel@0: create('hour', d3_time.hour, baseDate), Daniel@0: create('day', d3_time.day, baseDate, [1, 7]), Daniel@0: create('month', d3_time.month, baseDate, [1, 3, 6]), Daniel@0: create('year', d3_time.year, baseDate), Daniel@0: Daniel@0: // periodic units Daniel@0: entry('seconds', Daniel@0: function(d) { return new Date(1970, 0, 1, 0, 0, d); }, Daniel@0: function(d) { return date(d).getSeconds(); }, Daniel@0: null, 0, 59 Daniel@0: ), Daniel@0: entry('minutes', Daniel@0: function(d) { return new Date(1970, 0, 1, 0, d); }, Daniel@0: function(d) { return date(d).getMinutes(); }, Daniel@0: null, 0, 59 Daniel@0: ), Daniel@0: entry('hours', Daniel@0: function(d) { return new Date(1970, 0, 1, d); }, Daniel@0: function(d) { return date(d).getHours(); }, Daniel@0: null, 0, 23 Daniel@0: ), Daniel@0: entry('weekdays', Daniel@0: function(d) { return new Date(1970, 0, 4+d); }, Daniel@0: function(d) { return date(d).getDay(); }, Daniel@0: [1], 0, 6 Daniel@0: ), Daniel@0: entry('dates', Daniel@0: function(d) { return new Date(1970, 0, d); }, Daniel@0: function(d) { return date(d).getDate(); }, Daniel@0: [1], 1, 31 Daniel@0: ), Daniel@0: entry('months', Daniel@0: function(d) { return new Date(1970, d % 12, 1); }, Daniel@0: function(d) { return date(d).getMonth(); }, Daniel@0: [1], 0, 11 Daniel@0: ) Daniel@0: ]; Daniel@0: Daniel@0: var utc = [ Daniel@0: create('second', d3_time.utcSecond, utcBaseDate), Daniel@0: create('minute', d3_time.utcMinute, utcBaseDate), Daniel@0: create('hour', d3_time.utcHour, utcBaseDate), Daniel@0: create('day', d3_time.utcDay, utcBaseDate, [1, 7]), Daniel@0: create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]), Daniel@0: create('year', d3_time.utcYear, utcBaseDate), Daniel@0: Daniel@0: // periodic units Daniel@0: entry('seconds', Daniel@0: function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); }, Daniel@0: function(d) { return date(d).getUTCSeconds(); }, Daniel@0: null, 0, 59 Daniel@0: ), Daniel@0: entry('minutes', Daniel@0: function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); }, Daniel@0: function(d) { return date(d).getUTCMinutes(); }, Daniel@0: null, 0, 59 Daniel@0: ), Daniel@0: entry('hours', Daniel@0: function(d) { return new Date(Date.UTC(1970, 0, 1, d)); }, Daniel@0: function(d) { return date(d).getUTCHours(); }, Daniel@0: null, 0, 23 Daniel@0: ), Daniel@0: entry('weekdays', Daniel@0: function(d) { return new Date(Date.UTC(1970, 0, 4+d)); }, Daniel@0: function(d) { return date(d).getUTCDay(); }, Daniel@0: [1], 0, 6 Daniel@0: ), Daniel@0: entry('dates', Daniel@0: function(d) { return new Date(Date.UTC(1970, 0, d)); }, Daniel@0: function(d) { return date(d).getUTCDate(); }, Daniel@0: [1], 1, 31 Daniel@0: ), Daniel@0: entry('months', Daniel@0: function(d) { return new Date(Date.UTC(1970, d % 12, 1)); }, Daniel@0: function(d) { return date(d).getUTCMonth(); }, Daniel@0: [1], 0, 11 Daniel@0: ) Daniel@0: ]; Daniel@0: Daniel@0: var STEPS = [ Daniel@0: [31536e6, 5], // 1-year Daniel@0: [7776e6, 4], // 3-month Daniel@0: [2592e6, 4], // 1-month Daniel@0: [12096e5, 3], // 2-week Daniel@0: [6048e5, 3], // 1-week Daniel@0: [1728e5, 3], // 2-day Daniel@0: [864e5, 3], // 1-day Daniel@0: [432e5, 2], // 12-hour Daniel@0: [216e5, 2], // 6-hour Daniel@0: [108e5, 2], // 3-hour Daniel@0: [36e5, 2], // 1-hour Daniel@0: [18e5, 1], // 30-minute Daniel@0: [9e5, 1], // 15-minute Daniel@0: [3e5, 1], // 5-minute Daniel@0: [6e4, 1], // 1-minute Daniel@0: [3e4, 0], // 30-second Daniel@0: [15e3, 0], // 15-second Daniel@0: [5e3, 0], // 5-second Daniel@0: [1e3, 0] // 1-second Daniel@0: ]; Daniel@0: Daniel@0: function find(units, span, minb, maxb) { Daniel@0: var step = STEPS[0], i, n, bins; Daniel@0: Daniel@0: for (i=1, n=STEPS.length; i step[0]) { Daniel@0: bins = span / step[0]; Daniel@0: if (bins > maxb) { Daniel@0: return units[STEPS[i-1][1]]; Daniel@0: } Daniel@0: if (bins >= minb) { Daniel@0: return units[step[1]]; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: return units[STEPS[n-1][1]]; Daniel@0: } Daniel@0: Daniel@0: function toUnitMap(units) { Daniel@0: var map = {}, i, n; Daniel@0: for (i=0, n=units.length; i 1 ? Daniel@0: function(x) { return s.reduce(function(x,f) { return x[f]; }, x); } : Daniel@0: function(x) { return x[f]; } Daniel@0: ); Daniel@0: }; Daniel@0: Daniel@0: // short-cut for accessor Daniel@0: u.$ = u.accessor; Daniel@0: Daniel@0: u.mutator = function(f) { Daniel@0: var s; Daniel@0: return u.isString(f) && (s=u.field(f)).length > 1 ? Daniel@0: function(x, v) { Daniel@0: for (var i=0; i y) return sign[i]; Daniel@0: } Daniel@0: return 0; Daniel@0: }; Daniel@0: }; Daniel@0: Daniel@0: u.cmp = function(a, b) { Daniel@0: if (a < b) { Daniel@0: return -1; Daniel@0: } else if (a > b) { Daniel@0: return 1; Daniel@0: } else if (a >= b) { Daniel@0: return 0; Daniel@0: } else if (a === null) { Daniel@0: return -1; Daniel@0: } else if (b === null) { Daniel@0: return 1; Daniel@0: } Daniel@0: return NaN; Daniel@0: }; Daniel@0: Daniel@0: u.numcmp = function(a, b) { return a - b; }; Daniel@0: Daniel@0: u.stablesort = function(array, sortBy, keyFn) { Daniel@0: var indices = array.reduce(function(idx, v, i) { Daniel@0: return (idx[keyFn(v)] = i, idx); Daniel@0: }, {}); Daniel@0: Daniel@0: array.sort(function(a, b) { Daniel@0: var sa = sortBy(a), Daniel@0: sb = sortBy(b); Daniel@0: return sa < sb ? -1 : sa > sb ? 1 Daniel@0: : (indices[keyFn(a)] - indices[keyFn(b)]); Daniel@0: }); Daniel@0: Daniel@0: return array; Daniel@0: }; Daniel@0: Daniel@0: Daniel@0: // string functions Daniel@0: Daniel@0: u.pad = function(s, length, pos, padchar) { Daniel@0: padchar = padchar || " "; Daniel@0: var d = length - s.length; Daniel@0: if (d <= 0) return s; Daniel@0: switch (pos) { Daniel@0: case 'left': Daniel@0: return strrep(d, padchar) + s; Daniel@0: case 'middle': Daniel@0: case 'center': Daniel@0: return strrep(Math.floor(d/2), padchar) + Daniel@0: s + strrep(Math.ceil(d/2), padchar); Daniel@0: default: Daniel@0: return s + strrep(d, padchar); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: function strrep(n, str) { Daniel@0: var s = "", i; Daniel@0: for (i=0; i 1) { Daniel@0: for (var i=1, n=ref.length; i 0) { Daniel@0: node = pq.peek(); Daniel@0: pulse = pulses[node._id]; Daniel@0: Daniel@0: if (node.rank() !== node.qrank()) { Daniel@0: // A node's rank might change during a propagation. Re-queue if so. Daniel@0: pq.replace(node.qrank(true)); Daniel@0: } else { Daniel@0: // Evaluate node and propagate pulse. Daniel@0: pq.pop(); Daniel@0: pulses[node._id] = null; Daniel@0: listeners = node._listeners; Daniel@0: pulse = this.evaluate(pulse, node); Daniel@0: Daniel@0: // Propagate the pulse. Daniel@0: if (pulse !== this.doNotPropagate) { Daniel@0: // Ensure reflow pulses always send reflow pulses even if skipped. Daniel@0: if (!pulse.reflow && node.reflows()) { Daniel@0: pulse = ChangeSet.create(pulse, true); Daniel@0: } Daniel@0: Daniel@0: for (i=0, len=listeners.length; i 0) branch[i-1].addListener(node); Daniel@0: } Daniel@0: Daniel@0: return branch; Daniel@0: }; Daniel@0: Daniel@0: prototype.disconnect = function(branch) { Daniel@0: var collector, node, data, signals, i, n, j, m; Daniel@0: Daniel@0: for (i=0, n=branch.length; i= pulse.stamp, Daniel@0: run = node.router() || pulse.add.length || pulse.rem.length; Daniel@0: Daniel@0: return run || !reflowed || node.reevaluate(pulse); Daniel@0: }; Daniel@0: Daniel@0: prototype.evaluate = function(pulse, node) { Daniel@0: if (!this.reevaluate(pulse, node)) return pulse; Daniel@0: pulse = node.evaluate(pulse); Daniel@0: node.last(pulse.stamp); Daniel@0: return pulse; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Graph; Daniel@0: Daniel@0: },{"./ChangeSet":30,"./Collector":31,"./DataSource":32,"./Dependencies":33,"./Heap":35,"./Signal":37,"./Tuple":38,"datalib":24}],35:[function(require,module,exports){ Daniel@0: function Heap(comparator) { Daniel@0: this.cmp = comparator; Daniel@0: this.nodes = []; Daniel@0: } Daniel@0: Daniel@0: var prototype = Heap.prototype; Daniel@0: Daniel@0: prototype.size = function() { Daniel@0: return this.nodes.length; Daniel@0: }; Daniel@0: Daniel@0: prototype.clear = function() { Daniel@0: return (this.nodes = [], this); Daniel@0: }; Daniel@0: Daniel@0: prototype.peek = function() { Daniel@0: return this.nodes[0]; Daniel@0: }; Daniel@0: Daniel@0: prototype.push = function(x) { Daniel@0: var array = this.nodes; Daniel@0: array.push(x); Daniel@0: return _siftdown(array, 0, array.length-1, this.cmp); Daniel@0: }; Daniel@0: Daniel@0: prototype.pop = function() { Daniel@0: var array = this.nodes, Daniel@0: last = array.pop(), Daniel@0: item; Daniel@0: Daniel@0: if (array.length) { Daniel@0: item = array[0]; Daniel@0: array[0] = last; Daniel@0: _siftup(array, 0, this.cmp); Daniel@0: } else { Daniel@0: item = last; Daniel@0: } Daniel@0: return item; Daniel@0: }; Daniel@0: Daniel@0: prototype.replace = function(item) { Daniel@0: var array = this.nodes, Daniel@0: retval = array[0]; Daniel@0: array[0] = item; Daniel@0: _siftup(array, 0, this.cmp); Daniel@0: return retval; Daniel@0: }; Daniel@0: Daniel@0: prototype.pushpop = function(item) { Daniel@0: var array = this.nodes, ref = array[0]; Daniel@0: if (array.length && this.cmp(ref, item) < 0) { Daniel@0: array[0] = item; Daniel@0: item = ref; Daniel@0: _siftup(array, 0, this.cmp); Daniel@0: } Daniel@0: return item; Daniel@0: }; Daniel@0: Daniel@0: function _siftdown(array, start, idx, cmp) { Daniel@0: var item, parent, pidx; Daniel@0: Daniel@0: item = array[idx]; Daniel@0: while (idx > start) { Daniel@0: pidx = (idx - 1) >> 1; Daniel@0: parent = array[pidx]; Daniel@0: if (cmp(item, parent) < 0) { Daniel@0: array[idx] = parent; Daniel@0: idx = pidx; Daniel@0: continue; Daniel@0: } Daniel@0: break; Daniel@0: } Daniel@0: return (array[idx] = item); Daniel@0: } Daniel@0: Daniel@0: function _siftup(array, idx, cmp) { Daniel@0: var start = idx, Daniel@0: end = array.length, Daniel@0: item = array[idx], Daniel@0: cidx = 2 * idx + 1, ridx; Daniel@0: Daniel@0: while (cidx < end) { Daniel@0: ridx = cidx + 1; Daniel@0: if (ridx < end && cmp(array[cidx], array[ridx]) >= 0) { Daniel@0: cidx = ridx; Daniel@0: } Daniel@0: array[idx] = array[cidx]; Daniel@0: idx = cidx; Daniel@0: cidx = 2 * idx + 1; Daniel@0: } Daniel@0: array[idx] = item; Daniel@0: return _siftdown(array, start, idx, cmp); Daniel@0: } Daniel@0: Daniel@0: module.exports = Heap; Daniel@0: Daniel@0: },{}],36:[function(require,module,exports){ Daniel@0: var DEPS = require('./Dependencies').ALL, Daniel@0: nodeID = 0; Daniel@0: Daniel@0: function Node(graph) { Daniel@0: if (graph) this.init(graph); Daniel@0: } Daniel@0: Daniel@0: var Flags = Node.Flags = { Daniel@0: Router: 0x01, // Responsible for propagating tuples, cannot be skipped. Daniel@0: Collector: 0x02, // Holds a materialized dataset, pulse node to reflow. Daniel@0: Produces: 0x04, // Produces new tuples. Daniel@0: Mutates: 0x08, // Sets properties of incoming tuples. Daniel@0: Reflows: 0x10, // Forwards a reflow pulse. Daniel@0: Batch: 0x20 // Performs batch data processing, needs collector. Daniel@0: }; Daniel@0: Daniel@0: var prototype = Node.prototype; Daniel@0: Daniel@0: prototype.init = function(graph) { Daniel@0: this._id = ++nodeID; Daniel@0: this._graph = graph; Daniel@0: this._rank = graph.rank(); // Topological sort by rank Daniel@0: this._qrank = null; // Rank when enqueued for propagation Daniel@0: this._stamp = 0; // Last stamp seen Daniel@0: Daniel@0: this._listeners = []; Daniel@0: this._listeners._ids = {}; // To prevent duplicate listeners Daniel@0: Daniel@0: // Initialize dependencies. Daniel@0: this._deps = {}; Daniel@0: for (var i=0, n=DEPS.length; i l._rank) { Daniel@0: var q = [l], Daniel@0: g = this._graph, cur; Daniel@0: while (q.length) { Daniel@0: cur = q.shift(); Daniel@0: cur._rank = g.rank(); Daniel@0: q.unshift.apply(q, cur.listeners()); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.removeListener = function(l) { Daniel@0: if (!this._listeners._ids[l._id]) return false; Daniel@0: Daniel@0: var idx = this._listeners.indexOf(l), Daniel@0: b = idx >= 0; Daniel@0: Daniel@0: if (b) { Daniel@0: this._listeners.splice(idx, 1); Daniel@0: this._listeners._ids[l._id] = null; Daniel@0: } Daniel@0: return b; Daniel@0: }; Daniel@0: Daniel@0: prototype.disconnect = function() { Daniel@0: this._listeners = []; Daniel@0: this._listeners._ids = {}; Daniel@0: }; Daniel@0: Daniel@0: // Evaluate this dataflow node for the current pulse. Daniel@0: // Subclasses should override to perform custom processing. Daniel@0: prototype.evaluate = function(pulse) { Daniel@0: return pulse; Daniel@0: }; Daniel@0: Daniel@0: // Should this node be re-evaluated for the current pulse? Daniel@0: // Searches pulse to see if any dependencies have updated. Daniel@0: prototype.reevaluate = function(pulse) { Daniel@0: var prop, dep, i, n, j, m; Daniel@0: Daniel@0: for (i=0, n=DEPS.length; i=0;) { Daniel@0: if (!handler || h[i].handler === handler) { Daniel@0: x = h.splice(i, 1)[0]; Daniel@0: this.removeListener(x.node); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Signal; Daniel@0: Daniel@0: },{"./ChangeSet":30,"./Node":36}],38:[function(require,module,exports){ Daniel@0: var tupleID = 0; Daniel@0: Daniel@0: function ingest(datum) { Daniel@0: datum = (datum === Object(datum)) ? datum : {data: datum}; Daniel@0: datum._id = ++tupleID; Daniel@0: if (datum._prev) datum._prev = null; Daniel@0: return datum; Daniel@0: } Daniel@0: Daniel@0: function idMap(a, ids) { Daniel@0: ids = ids || {}; Daniel@0: for (var i=0, n=a.length; i0;) { Daniel@0: idMap(arguments[i], ids); Daniel@0: } Daniel@0: return data.filter(function(x) { return !ids[x._id]; }); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: },{}],39:[function(require,module,exports){ Daniel@0: module.exports = { Daniel@0: ChangeSet: require('./ChangeSet'), Daniel@0: Collector: require('./Collector'), Daniel@0: DataSource: require('./DataSource'), Daniel@0: Dependencies: require('./Dependencies'), Daniel@0: Graph: require('./Graph'), Daniel@0: Node: require('./Node'), Daniel@0: Signal: require('./Signal'), Daniel@0: Tuple: require('./Tuple'), Daniel@0: debug: require('vega-logging').debug Daniel@0: }; Daniel@0: Daniel@0: },{"./ChangeSet":30,"./Collector":31,"./DataSource":32,"./Dependencies":33,"./Graph":34,"./Node":36,"./Signal":37,"./Tuple":38,"vega-logging":45}],40:[function(require,module,exports){ Daniel@0: function toMap(list) { Daniel@0: var map = {}, i, n; Daniel@0: for (i=0, n=list.length; i 0) { Daniel@0: return id; Daniel@0: } Daniel@0: if (constants.hasOwnProperty(id)) { Daniel@0: return constants[id]; Daniel@0: } Daniel@0: if (idWhiteList) { Daniel@0: if (idWhiteList.hasOwnProperty(id)) { Daniel@0: return id; Daniel@0: } else { Daniel@0: globals[id] = 1; Daniel@0: return lookupGlobal(id); Daniel@0: } Daniel@0: } Daniel@0: if (idBlackList && idBlackList.hasOwnProperty(id)) { Daniel@0: throw new Error('Illegal identifier: ' + id); Daniel@0: } Daniel@0: return id; Daniel@0: }, Daniel@0: 'Program': function(n) { Daniel@0: return n.body.map(codegen).join('\n'); Daniel@0: }, Daniel@0: 'MemberExpression': function(n) { Daniel@0: var d = !n.computed; Daniel@0: var o = codegen(n.object); Daniel@0: if (d) memberDepth += 1; Daniel@0: var p = codegen(n.property); Daniel@0: if (o === FIELD_VAR) { fields[p] = 1; } // HACKish... Daniel@0: if (d) memberDepth -= 1; Daniel@0: return o + (d ? '.'+p : '['+p+']'); Daniel@0: }, Daniel@0: 'CallExpression': function(n) { Daniel@0: if (n.callee.type !== 'Identifier') { Daniel@0: throw new Error('Illegal callee type: ' + n.callee.type); Daniel@0: } Daniel@0: var callee = n.callee.name; Daniel@0: var args = n.arguments; Daniel@0: var fn = functions.hasOwnProperty(callee) && functions[callee]; Daniel@0: if (!fn) throw new Error('Unrecognized function: ' + callee); Daniel@0: return fn instanceof Function ? Daniel@0: fn(args) : Daniel@0: fn + '(' + args.map(codegen).join(',') + ')'; Daniel@0: }, Daniel@0: 'ArrayExpression': function(n) { Daniel@0: return '[' + n.elements.map(codegen).join(',') + ']'; Daniel@0: }, Daniel@0: 'BinaryExpression': function(n) { Daniel@0: return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')'; Daniel@0: }, Daniel@0: 'UnaryExpression': function(n) { Daniel@0: return '(' + n.operator + codegen(n.argument) + ')'; Daniel@0: }, Daniel@0: 'ConditionalExpression': function(n) { Daniel@0: return '(' + codegen(n.test) + Daniel@0: '?' + codegen(n.consequent) + Daniel@0: ':' + codegen(n.alternate) + Daniel@0: ')'; Daniel@0: }, Daniel@0: 'LogicalExpression': function(n) { Daniel@0: return '(' + codegen(n.left) + n.operator + codegen(n.right) + ')'; Daniel@0: }, Daniel@0: 'ObjectExpression': function(n) { Daniel@0: return '{' + n.properties.map(codegen).join(',') + '}'; Daniel@0: }, Daniel@0: 'Property': function(n) { Daniel@0: memberDepth += 1; Daniel@0: var k = codegen(n.key); Daniel@0: memberDepth -= 1; Daniel@0: return k + ':' + codegen(n.value); Daniel@0: }, Daniel@0: 'ExpressionStatement': function(n) { Daniel@0: return codegen(n.expression); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: codegen_wrap.functions = functions; Daniel@0: codegen_wrap.constants = constants; Daniel@0: return codegen_wrap; Daniel@0: }; Daniel@0: Daniel@0: },{"./constants":41,"./functions":42}],41:[function(require,module,exports){ Daniel@0: module.exports = { Daniel@0: 'NaN': 'NaN', Daniel@0: 'E': 'Math.E', Daniel@0: 'LN2': 'Math.LN2', Daniel@0: 'LN10': 'Math.LN10', Daniel@0: 'LOG2E': 'Math.LOG2E', Daniel@0: 'LOG10E': 'Math.LOG10E', Daniel@0: 'PI': 'Math.PI', Daniel@0: 'SQRT1_2': 'Math.SQRT1_2', Daniel@0: 'SQRT2': 'Math.SQRT2' Daniel@0: }; Daniel@0: },{}],42:[function(require,module,exports){ Daniel@0: module.exports = function(codegen) { Daniel@0: Daniel@0: function fncall(name, args, cast, type) { Daniel@0: var obj = codegen(args[0]); Daniel@0: if (cast) { Daniel@0: obj = cast + '(' + obj + ')'; Daniel@0: if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')'; Daniel@0: } Daniel@0: return obj + '.' + name + (type < 0 ? '' : type === 0 ? Daniel@0: '()' : Daniel@0: '(' + args.slice(1).map(codegen).join(',') + ')'); Daniel@0: } Daniel@0: Daniel@0: function fn(name, cast, type) { Daniel@0: return function(args) { Daniel@0: return fncall(name, args, cast, type); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: var DATE = 'new Date', Daniel@0: STRING = 'String', Daniel@0: REGEXP = 'RegExp'; Daniel@0: Daniel@0: return { Daniel@0: // MATH functions Daniel@0: 'isNaN': 'isNaN', Daniel@0: 'isFinite': 'isFinite', Daniel@0: 'abs': 'Math.abs', Daniel@0: 'acos': 'Math.acos', Daniel@0: 'asin': 'Math.asin', Daniel@0: 'atan': 'Math.atan', Daniel@0: 'atan2': 'Math.atan2', Daniel@0: 'ceil': 'Math.ceil', Daniel@0: 'cos': 'Math.cos', Daniel@0: 'exp': 'Math.exp', Daniel@0: 'floor': 'Math.floor', Daniel@0: 'log': 'Math.log', Daniel@0: 'max': 'Math.max', Daniel@0: 'min': 'Math.min', Daniel@0: 'pow': 'Math.pow', Daniel@0: 'random': 'Math.random', Daniel@0: 'round': 'Math.round', Daniel@0: 'sin': 'Math.sin', Daniel@0: 'sqrt': 'Math.sqrt', Daniel@0: 'tan': 'Math.tan', Daniel@0: Daniel@0: 'clamp': function(args) { Daniel@0: if (args.length < 3) Daniel@0: throw new Error('Missing arguments to clamp function.'); Daniel@0: if (args.length > 3) Daniel@0: throw new Error('Too many arguments to clamp function.'); Daniel@0: var a = args.map(codegen); Daniel@0: return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))'; Daniel@0: }, Daniel@0: Daniel@0: // DATE functions Daniel@0: 'now': 'Date.now', Daniel@0: 'datetime': DATE, Daniel@0: 'date': fn('getDate', DATE, 0), Daniel@0: 'day': fn('getDay', DATE, 0), Daniel@0: 'year': fn('getFullYear', DATE, 0), Daniel@0: 'month': fn('getMonth', DATE, 0), Daniel@0: 'hours': fn('getHours', DATE, 0), Daniel@0: 'minutes': fn('getMinutes', DATE, 0), Daniel@0: 'seconds': fn('getSeconds', DATE, 0), Daniel@0: 'milliseconds': fn('getMilliseconds', DATE, 0), Daniel@0: 'time': fn('getTime', DATE, 0), Daniel@0: 'timezoneoffset': fn('getTimezoneOffset', DATE, 0), Daniel@0: 'utcdate': fn('getUTCDate', DATE, 0), Daniel@0: 'utcday': fn('getUTCDay', DATE, 0), Daniel@0: 'utcyear': fn('getUTCFullYear', DATE, 0), Daniel@0: 'utcmonth': fn('getUTCMonth', DATE, 0), Daniel@0: 'utchours': fn('getUTCHours', DATE, 0), Daniel@0: 'utcminutes': fn('getUTCMinutes', DATE, 0), Daniel@0: 'utcseconds': fn('getUTCSeconds', DATE, 0), Daniel@0: 'utcmilliseconds': fn('getUTCMilliseconds', DATE, 0), Daniel@0: Daniel@0: // shared sequence functions Daniel@0: 'length': fn('length', null, -1), Daniel@0: 'indexof': fn('indexOf', null), Daniel@0: 'lastindexof': fn('lastIndexOf', null), Daniel@0: Daniel@0: // STRING functions Daniel@0: 'parseFloat': 'parseFloat', Daniel@0: 'parseInt': 'parseInt', Daniel@0: 'upper': fn('toUpperCase', STRING, 0), Daniel@0: 'lower': fn('toLowerCase', STRING, 0), Daniel@0: 'slice': fn('slice', STRING), Daniel@0: 'substring': fn('substring', STRING), Daniel@0: Daniel@0: // REGEXP functions Daniel@0: 'regexp': REGEXP, Daniel@0: 'test': fn('test', REGEXP), Daniel@0: Daniel@0: // Control Flow functions Daniel@0: 'if': function(args) { Daniel@0: if (args.length < 3) Daniel@0: throw new Error('Missing arguments to if function.'); Daniel@0: if (args.length > 3) Daniel@0: throw new Error('Too many arguments to if function.'); Daniel@0: var a = args.map(codegen); Daniel@0: return a[0]+'?'+a[1]+':'+a[2]; Daniel@0: } Daniel@0: }; Daniel@0: }; Daniel@0: },{}],43:[function(require,module,exports){ Daniel@0: var parser = require('./parser'), Daniel@0: codegen = require('./codegen'); Daniel@0: Daniel@0: var expr = module.exports = { Daniel@0: parse: function(input, opt) { Daniel@0: return parser.parse('('+input+')', opt); Daniel@0: }, Daniel@0: code: function(opt) { Daniel@0: return codegen(opt); Daniel@0: }, Daniel@0: compiler: function(args, opt) { Daniel@0: args = args.slice(); Daniel@0: var generator = codegen(opt), Daniel@0: len = args.length, Daniel@0: compile = function(str) { Daniel@0: var value = generator(expr.parse(str)); Daniel@0: args[len] = '"use strict"; return (' + value.code + ');'; Daniel@0: value.fn = Function.apply(null, args); Daniel@0: return value; Daniel@0: }; Daniel@0: compile.codegen = generator; Daniel@0: return compile; Daniel@0: }, Daniel@0: functions: require('./functions'), Daniel@0: constants: require('./constants') Daniel@0: }; Daniel@0: Daniel@0: },{"./codegen":40,"./constants":41,"./functions":42,"./parser":44}],44:[function(require,module,exports){ Daniel@0: /* Daniel@0: The following expression parser is based on Esprima (http://esprima.org/). Daniel@0: Original header comment and license for Esprima is included here: Daniel@0: Daniel@0: Copyright (C) 2013 Ariya Hidayat Daniel@0: Copyright (C) 2013 Thaddee Tyl Daniel@0: Copyright (C) 2013 Mathias Bynens Daniel@0: Copyright (C) 2012 Ariya Hidayat Daniel@0: Copyright (C) 2012 Mathias Bynens Daniel@0: Copyright (C) 2012 Joost-Wim Boekesteijn Daniel@0: Copyright (C) 2012 Kris Kowal Daniel@0: Copyright (C) 2012 Yusuke Suzuki Daniel@0: Copyright (C) 2012 Arpad Borsos Daniel@0: Copyright (C) 2011 Ariya Hidayat Daniel@0: Daniel@0: Redistribution and use in source and binary forms, with or without Daniel@0: modification, are permitted provided that the following conditions are met: Daniel@0: Daniel@0: * Redistributions of source code must retain the above copyright Daniel@0: notice, this list of conditions and the following disclaimer. Daniel@0: * Redistributions in binary form must reproduce the above copyright Daniel@0: notice, this list of conditions and the following disclaimer in the Daniel@0: documentation and/or other materials provided with the distribution. Daniel@0: Daniel@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" Daniel@0: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE Daniel@0: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE Daniel@0: ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY Daniel@0: DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES Daniel@0: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; Daniel@0: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND Daniel@0: ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT Daniel@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF Daniel@0: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Daniel@0: */ Daniel@0: /* istanbul ignore next */ Daniel@0: module.exports = (function() { Daniel@0: 'use strict'; Daniel@0: Daniel@0: var Token, Daniel@0: TokenName, Daniel@0: Syntax, Daniel@0: PropertyKind, Daniel@0: Messages, Daniel@0: Regex, Daniel@0: source, Daniel@0: strict, Daniel@0: index, Daniel@0: lineNumber, Daniel@0: lineStart, Daniel@0: length, Daniel@0: lookahead, Daniel@0: state, Daniel@0: extra; Daniel@0: Daniel@0: Token = { Daniel@0: BooleanLiteral: 1, Daniel@0: EOF: 2, Daniel@0: Identifier: 3, Daniel@0: Keyword: 4, Daniel@0: NullLiteral: 5, Daniel@0: NumericLiteral: 6, Daniel@0: Punctuator: 7, Daniel@0: StringLiteral: 8, Daniel@0: RegularExpression: 9 Daniel@0: }; Daniel@0: Daniel@0: TokenName = {}; Daniel@0: TokenName[Token.BooleanLiteral] = 'Boolean'; Daniel@0: TokenName[Token.EOF] = ''; Daniel@0: TokenName[Token.Identifier] = 'Identifier'; Daniel@0: TokenName[Token.Keyword] = 'Keyword'; Daniel@0: TokenName[Token.NullLiteral] = 'Null'; Daniel@0: TokenName[Token.NumericLiteral] = 'Numeric'; Daniel@0: TokenName[Token.Punctuator] = 'Punctuator'; Daniel@0: TokenName[Token.StringLiteral] = 'String'; Daniel@0: TokenName[Token.RegularExpression] = 'RegularExpression'; Daniel@0: Daniel@0: Syntax = { Daniel@0: AssignmentExpression: 'AssignmentExpression', Daniel@0: ArrayExpression: 'ArrayExpression', Daniel@0: BinaryExpression: 'BinaryExpression', Daniel@0: CallExpression: 'CallExpression', Daniel@0: ConditionalExpression: 'ConditionalExpression', Daniel@0: ExpressionStatement: 'ExpressionStatement', Daniel@0: Identifier: 'Identifier', Daniel@0: Literal: 'Literal', Daniel@0: LogicalExpression: 'LogicalExpression', Daniel@0: MemberExpression: 'MemberExpression', Daniel@0: ObjectExpression: 'ObjectExpression', Daniel@0: Program: 'Program', Daniel@0: Property: 'Property', Daniel@0: UnaryExpression: 'UnaryExpression' Daniel@0: }; Daniel@0: Daniel@0: PropertyKind = { Daniel@0: Data: 1, Daniel@0: Get: 2, Daniel@0: Set: 4 Daniel@0: }; Daniel@0: Daniel@0: // Error messages should be identical to V8. Daniel@0: Messages = { Daniel@0: UnexpectedToken: 'Unexpected token %0', Daniel@0: UnexpectedNumber: 'Unexpected number', Daniel@0: UnexpectedString: 'Unexpected string', Daniel@0: UnexpectedIdentifier: 'Unexpected identifier', Daniel@0: UnexpectedReserved: 'Unexpected reserved word', Daniel@0: UnexpectedEOS: 'Unexpected end of input', Daniel@0: NewlineAfterThrow: 'Illegal newline after throw', Daniel@0: InvalidRegExp: 'Invalid regular expression', Daniel@0: UnterminatedRegExp: 'Invalid regular expression: missing /', Daniel@0: InvalidLHSInAssignment: 'Invalid left-hand side in assignment', Daniel@0: InvalidLHSInForIn: 'Invalid left-hand side in for-in', Daniel@0: MultipleDefaultsInSwitch: 'More than one default clause in switch statement', Daniel@0: NoCatchOrFinally: 'Missing catch or finally after try', Daniel@0: UnknownLabel: 'Undefined label \'%0\'', Daniel@0: Redeclaration: '%0 \'%1\' has already been declared', Daniel@0: IllegalContinue: 'Illegal continue statement', Daniel@0: IllegalBreak: 'Illegal break statement', Daniel@0: IllegalReturn: 'Illegal return statement', Daniel@0: StrictModeWith: 'Strict mode code may not include a with statement', Daniel@0: StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', Daniel@0: StrictVarName: 'Variable name may not be eval or arguments in strict mode', Daniel@0: StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', Daniel@0: StrictParamDupe: 'Strict mode function may not have duplicate parameter names', Daniel@0: StrictFunctionName: 'Function name may not be eval or arguments in strict mode', Daniel@0: StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', Daniel@0: StrictDelete: 'Delete of an unqualified identifier in strict mode.', Daniel@0: StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', Daniel@0: AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', Daniel@0: AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', Daniel@0: StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', Daniel@0: StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', Daniel@0: StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', Daniel@0: StrictReservedWord: 'Use of future reserved word in strict mode' Daniel@0: }; Daniel@0: Daniel@0: // See also tools/generate-unicode-regex.py. Daniel@0: Regex = { Daniel@0: NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]'), Daniel@0: NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]') Daniel@0: }; Daniel@0: Daniel@0: // Ensure the condition is true, otherwise throw an error. Daniel@0: // This is only to have a better contract semantic, i.e. another safety net Daniel@0: // to catch a logic error. The condition shall be fulfilled in normal case. Daniel@0: // Do NOT use this to enforce a certain condition on any user input. Daniel@0: Daniel@0: function assert(condition, message) { Daniel@0: if (!condition) { Daniel@0: throw new Error('ASSERT: ' + message); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function isDecimalDigit(ch) { Daniel@0: return (ch >= 0x30 && ch <= 0x39); // 0..9 Daniel@0: } Daniel@0: Daniel@0: function isHexDigit(ch) { Daniel@0: return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; Daniel@0: } Daniel@0: Daniel@0: function isOctalDigit(ch) { Daniel@0: return '01234567'.indexOf(ch) >= 0; Daniel@0: } Daniel@0: Daniel@0: // 7.2 White Space Daniel@0: Daniel@0: function isWhiteSpace(ch) { Daniel@0: return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || Daniel@0: (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0); Daniel@0: } Daniel@0: Daniel@0: // 7.3 Line Terminators Daniel@0: Daniel@0: function isLineTerminator(ch) { Daniel@0: return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029); Daniel@0: } Daniel@0: Daniel@0: // 7.6 Identifier Names and Identifiers Daniel@0: Daniel@0: function isIdentifierStart(ch) { Daniel@0: return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) Daniel@0: (ch >= 0x41 && ch <= 0x5A) || // A..Z Daniel@0: (ch >= 0x61 && ch <= 0x7A) || // a..z Daniel@0: (ch === 0x5C) || // \ (backslash) Daniel@0: ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); Daniel@0: } Daniel@0: Daniel@0: function isIdentifierPart(ch) { Daniel@0: return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) Daniel@0: (ch >= 0x41 && ch <= 0x5A) || // A..Z Daniel@0: (ch >= 0x61 && ch <= 0x7A) || // a..z Daniel@0: (ch >= 0x30 && ch <= 0x39) || // 0..9 Daniel@0: (ch === 0x5C) || // \ (backslash) Daniel@0: ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); Daniel@0: } Daniel@0: Daniel@0: // 7.6.1.2 Future Reserved Words Daniel@0: Daniel@0: function isFutureReservedWord(id) { Daniel@0: switch (id) { Daniel@0: case 'class': Daniel@0: case 'enum': Daniel@0: case 'export': Daniel@0: case 'extends': Daniel@0: case 'import': Daniel@0: case 'super': Daniel@0: return true; Daniel@0: default: Daniel@0: return false; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function isStrictModeReservedWord(id) { Daniel@0: switch (id) { Daniel@0: case 'implements': Daniel@0: case 'interface': Daniel@0: case 'package': Daniel@0: case 'private': Daniel@0: case 'protected': Daniel@0: case 'public': Daniel@0: case 'static': Daniel@0: case 'yield': Daniel@0: case 'let': Daniel@0: return true; Daniel@0: default: Daniel@0: return false; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // 7.6.1.1 Keywords Daniel@0: Daniel@0: function isKeyword(id) { Daniel@0: if (strict && isStrictModeReservedWord(id)) { Daniel@0: return true; Daniel@0: } Daniel@0: Daniel@0: // 'const' is specialized as Keyword in V8. Daniel@0: // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. Daniel@0: // Some others are from future reserved words. Daniel@0: Daniel@0: switch (id.length) { Daniel@0: case 2: Daniel@0: return (id === 'if') || (id === 'in') || (id === 'do'); Daniel@0: case 3: Daniel@0: return (id === 'var') || (id === 'for') || (id === 'new') || Daniel@0: (id === 'try') || (id === 'let'); Daniel@0: case 4: Daniel@0: return (id === 'this') || (id === 'else') || (id === 'case') || Daniel@0: (id === 'void') || (id === 'with') || (id === 'enum'); Daniel@0: case 5: Daniel@0: return (id === 'while') || (id === 'break') || (id === 'catch') || Daniel@0: (id === 'throw') || (id === 'const') || (id === 'yield') || Daniel@0: (id === 'class') || (id === 'super'); Daniel@0: case 6: Daniel@0: return (id === 'return') || (id === 'typeof') || (id === 'delete') || Daniel@0: (id === 'switch') || (id === 'export') || (id === 'import'); Daniel@0: case 7: Daniel@0: return (id === 'default') || (id === 'finally') || (id === 'extends'); Daniel@0: case 8: Daniel@0: return (id === 'function') || (id === 'continue') || (id === 'debugger'); Daniel@0: case 10: Daniel@0: return (id === 'instanceof'); Daniel@0: default: Daniel@0: return false; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function skipComment() { Daniel@0: var ch, start; Daniel@0: Daniel@0: start = (index === 0); Daniel@0: while (index < length) { Daniel@0: ch = source.charCodeAt(index); Daniel@0: Daniel@0: if (isWhiteSpace(ch)) { Daniel@0: ++index; Daniel@0: } else if (isLineTerminator(ch)) { Daniel@0: ++index; Daniel@0: if (ch === 0x0D && source.charCodeAt(index) === 0x0A) { Daniel@0: ++index; Daniel@0: } Daniel@0: ++lineNumber; Daniel@0: lineStart = index; Daniel@0: start = true; Daniel@0: } else { Daniel@0: break; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function scanHexEscape(prefix) { Daniel@0: var i, len, ch, code = 0; Daniel@0: Daniel@0: len = (prefix === 'u') ? 4 : 2; Daniel@0: for (i = 0; i < len; ++i) { Daniel@0: if (index < length && isHexDigit(source[index])) { Daniel@0: ch = source[index++]; Daniel@0: code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); Daniel@0: } else { Daniel@0: return ''; Daniel@0: } Daniel@0: } Daniel@0: return String.fromCharCode(code); Daniel@0: } Daniel@0: Daniel@0: function scanUnicodeCodePointEscape() { Daniel@0: var ch, code, cu1, cu2; Daniel@0: Daniel@0: ch = source[index]; Daniel@0: code = 0; Daniel@0: Daniel@0: // At least, one hex digit is required. Daniel@0: if (ch === '}') { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: while (index < length) { Daniel@0: ch = source[index++]; Daniel@0: if (!isHexDigit(ch)) { Daniel@0: break; Daniel@0: } Daniel@0: code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); Daniel@0: } Daniel@0: Daniel@0: if (code > 0x10FFFF || ch !== '}') { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: // UTF-16 Encoding Daniel@0: if (code <= 0xFFFF) { Daniel@0: return String.fromCharCode(code); Daniel@0: } Daniel@0: cu1 = ((code - 0x10000) >> 10) + 0xD800; Daniel@0: cu2 = ((code - 0x10000) & 1023) + 0xDC00; Daniel@0: return String.fromCharCode(cu1, cu2); Daniel@0: } Daniel@0: Daniel@0: function getEscapedIdentifier() { Daniel@0: var ch, id; Daniel@0: Daniel@0: ch = source.charCodeAt(index++); Daniel@0: id = String.fromCharCode(ch); Daniel@0: Daniel@0: // '\u' (U+005C, U+0075) denotes an escaped character. Daniel@0: if (ch === 0x5C) { Daniel@0: if (source.charCodeAt(index) !== 0x75) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: ++index; Daniel@0: ch = scanHexEscape('u'); Daniel@0: if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: id = ch; Daniel@0: } Daniel@0: Daniel@0: while (index < length) { Daniel@0: ch = source.charCodeAt(index); Daniel@0: if (!isIdentifierPart(ch)) { Daniel@0: break; Daniel@0: } Daniel@0: ++index; Daniel@0: id += String.fromCharCode(ch); Daniel@0: Daniel@0: // '\u' (U+005C, U+0075) denotes an escaped character. Daniel@0: if (ch === 0x5C) { Daniel@0: id = id.substr(0, id.length - 1); Daniel@0: if (source.charCodeAt(index) !== 0x75) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: ++index; Daniel@0: ch = scanHexEscape('u'); Daniel@0: if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: id += ch; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return id; Daniel@0: } Daniel@0: Daniel@0: function getIdentifier() { Daniel@0: var start, ch; Daniel@0: Daniel@0: start = index++; Daniel@0: while (index < length) { Daniel@0: ch = source.charCodeAt(index); Daniel@0: if (ch === 0x5C) { Daniel@0: // Blackslash (U+005C) marks Unicode escape sequence. Daniel@0: index = start; Daniel@0: return getEscapedIdentifier(); Daniel@0: } Daniel@0: if (isIdentifierPart(ch)) { Daniel@0: ++index; Daniel@0: } else { Daniel@0: break; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return source.slice(start, index); Daniel@0: } Daniel@0: Daniel@0: function scanIdentifier() { Daniel@0: var start, id, type; Daniel@0: Daniel@0: start = index; Daniel@0: Daniel@0: // Backslash (U+005C) starts an escaped character. Daniel@0: id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier(); Daniel@0: Daniel@0: // There is no keyword or literal with only one character. Daniel@0: // Thus, it must be an identifier. Daniel@0: if (id.length === 1) { Daniel@0: type = Token.Identifier; Daniel@0: } else if (isKeyword(id)) { Daniel@0: type = Token.Keyword; Daniel@0: } else if (id === 'null') { Daniel@0: type = Token.NullLiteral; Daniel@0: } else if (id === 'true' || id === 'false') { Daniel@0: type = Token.BooleanLiteral; Daniel@0: } else { Daniel@0: type = Token.Identifier; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: type: type, Daniel@0: value: id, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // 7.7 Punctuators Daniel@0: Daniel@0: function scanPunctuator() { Daniel@0: var start = index, Daniel@0: code = source.charCodeAt(index), Daniel@0: code2, Daniel@0: ch1 = source[index], Daniel@0: ch2, Daniel@0: ch3, Daniel@0: ch4; Daniel@0: Daniel@0: switch (code) { Daniel@0: Daniel@0: // Check for most common single-character punctuators. Daniel@0: case 0x2E: // . dot Daniel@0: case 0x28: // ( open bracket Daniel@0: case 0x29: // ) close bracket Daniel@0: case 0x3B: // ; semicolon Daniel@0: case 0x2C: // , comma Daniel@0: case 0x7B: // { open curly brace Daniel@0: case 0x7D: // } close curly brace Daniel@0: case 0x5B: // [ Daniel@0: case 0x5D: // ] Daniel@0: case 0x3A: // : Daniel@0: case 0x3F: // ? Daniel@0: case 0x7E: // ~ Daniel@0: ++index; Daniel@0: if (extra.tokenize) { Daniel@0: if (code === 0x28) { Daniel@0: extra.openParenToken = extra.tokens.length; Daniel@0: } else if (code === 0x7B) { Daniel@0: extra.openCurlyToken = extra.tokens.length; Daniel@0: } Daniel@0: } Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: String.fromCharCode(code), Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: Daniel@0: default: Daniel@0: code2 = source.charCodeAt(index + 1); Daniel@0: Daniel@0: // '=' (U+003D) marks an assignment or comparison operator. Daniel@0: if (code2 === 0x3D) { Daniel@0: switch (code) { Daniel@0: case 0x2B: // + Daniel@0: case 0x2D: // - Daniel@0: case 0x2F: // / Daniel@0: case 0x3C: // < Daniel@0: case 0x3E: // > Daniel@0: case 0x5E: // ^ Daniel@0: case 0x7C: // | Daniel@0: case 0x25: // % Daniel@0: case 0x26: // & Daniel@0: case 0x2A: // * Daniel@0: index += 2; Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: String.fromCharCode(code) + String.fromCharCode(code2), Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: Daniel@0: case 0x21: // ! Daniel@0: case 0x3D: // = Daniel@0: index += 2; Daniel@0: Daniel@0: // !== and === Daniel@0: if (source.charCodeAt(index) === 0x3D) { Daniel@0: ++index; Daniel@0: } Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: source.slice(start, index), Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // 4-character punctuator: >>>= Daniel@0: Daniel@0: ch4 = source.substr(index, 4); Daniel@0: Daniel@0: if (ch4 === '>>>=') { Daniel@0: index += 4; Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: ch4, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // 3-character punctuators: === !== >>> <<= >>= Daniel@0: Daniel@0: ch3 = ch4.substr(0, 3); Daniel@0: Daniel@0: if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') { Daniel@0: index += 3; Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: ch3, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // Other 2-character punctuators: ++ -- << >> && || Daniel@0: ch2 = ch3.substr(0, 2); Daniel@0: Daniel@0: if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') { Daniel@0: index += 2; Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: ch2, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // 1-character punctuators: < > = ! + - * % & | ^ / Daniel@0: Daniel@0: if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { Daniel@0: ++index; Daniel@0: return { Daniel@0: type: Token.Punctuator, Daniel@0: value: ch1, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: // 7.8.3 Numeric Literals Daniel@0: Daniel@0: function scanHexLiteral(start) { Daniel@0: var number = ''; Daniel@0: Daniel@0: while (index < length) { Daniel@0: if (!isHexDigit(source[index])) { Daniel@0: break; Daniel@0: } Daniel@0: number += source[index++]; Daniel@0: } Daniel@0: Daniel@0: if (number.length === 0) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: if (isIdentifierStart(source.charCodeAt(index))) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: type: Token.NumericLiteral, Daniel@0: value: parseInt('0x' + number, 16), Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function scanOctalLiteral(start) { Daniel@0: var number = '0' + source[index++]; Daniel@0: while (index < length) { Daniel@0: if (!isOctalDigit(source[index])) { Daniel@0: break; Daniel@0: } Daniel@0: number += source[index++]; Daniel@0: } Daniel@0: Daniel@0: if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: type: Token.NumericLiteral, Daniel@0: value: parseInt(number, 8), Daniel@0: octal: true, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function scanNumericLiteral() { Daniel@0: var number, start, ch; Daniel@0: Daniel@0: ch = source[index]; Daniel@0: assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), Daniel@0: 'Numeric literal must start with a decimal digit or a decimal point'); Daniel@0: Daniel@0: start = index; Daniel@0: number = ''; Daniel@0: if (ch !== '.') { Daniel@0: number = source[index++]; Daniel@0: ch = source[index]; Daniel@0: Daniel@0: // Hex number starts with '0x'. Daniel@0: // Octal number starts with '0'. Daniel@0: if (number === '0') { Daniel@0: if (ch === 'x' || ch === 'X') { Daniel@0: ++index; Daniel@0: return scanHexLiteral(start); Daniel@0: } Daniel@0: if (isOctalDigit(ch)) { Daniel@0: return scanOctalLiteral(start); Daniel@0: } Daniel@0: Daniel@0: // decimal number starts with '0' such as '09' is illegal. Daniel@0: if (ch && isDecimalDigit(ch.charCodeAt(0))) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: while (isDecimalDigit(source.charCodeAt(index))) { Daniel@0: number += source[index++]; Daniel@0: } Daniel@0: ch = source[index]; Daniel@0: } Daniel@0: Daniel@0: if (ch === '.') { Daniel@0: number += source[index++]; Daniel@0: while (isDecimalDigit(source.charCodeAt(index))) { Daniel@0: number += source[index++]; Daniel@0: } Daniel@0: ch = source[index]; Daniel@0: } Daniel@0: Daniel@0: if (ch === 'e' || ch === 'E') { Daniel@0: number += source[index++]; Daniel@0: Daniel@0: ch = source[index]; Daniel@0: if (ch === '+' || ch === '-') { Daniel@0: number += source[index++]; Daniel@0: } Daniel@0: if (isDecimalDigit(source.charCodeAt(index))) { Daniel@0: while (isDecimalDigit(source.charCodeAt(index))) { Daniel@0: number += source[index++]; Daniel@0: } Daniel@0: } else { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (isIdentifierStart(source.charCodeAt(index))) { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: type: Token.NumericLiteral, Daniel@0: value: parseFloat(number), Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // 7.8.4 String Literals Daniel@0: Daniel@0: function scanStringLiteral() { Daniel@0: var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart; Daniel@0: startLineNumber = lineNumber; Daniel@0: startLineStart = lineStart; Daniel@0: Daniel@0: quote = source[index]; Daniel@0: assert((quote === '\'' || quote === '"'), Daniel@0: 'String literal must starts with a quote'); Daniel@0: Daniel@0: start = index; Daniel@0: ++index; Daniel@0: Daniel@0: while (index < length) { Daniel@0: ch = source[index++]; Daniel@0: Daniel@0: if (ch === quote) { Daniel@0: quote = ''; Daniel@0: break; Daniel@0: } else if (ch === '\\') { Daniel@0: ch = source[index++]; Daniel@0: if (!ch || !isLineTerminator(ch.charCodeAt(0))) { Daniel@0: switch (ch) { Daniel@0: case 'u': Daniel@0: case 'x': Daniel@0: if (source[index] === '{') { Daniel@0: ++index; Daniel@0: str += scanUnicodeCodePointEscape(); Daniel@0: } else { Daniel@0: restore = index; Daniel@0: unescaped = scanHexEscape(ch); Daniel@0: if (unescaped) { Daniel@0: str += unescaped; Daniel@0: } else { Daniel@0: index = restore; Daniel@0: str += ch; Daniel@0: } Daniel@0: } Daniel@0: break; Daniel@0: case 'n': Daniel@0: str += '\n'; Daniel@0: break; Daniel@0: case 'r': Daniel@0: str += '\r'; Daniel@0: break; Daniel@0: case 't': Daniel@0: str += '\t'; Daniel@0: break; Daniel@0: case 'b': Daniel@0: str += '\b'; Daniel@0: break; Daniel@0: case 'f': Daniel@0: str += '\f'; Daniel@0: break; Daniel@0: case 'v': Daniel@0: str += '\x0B'; Daniel@0: break; Daniel@0: Daniel@0: default: Daniel@0: if (isOctalDigit(ch)) { Daniel@0: code = '01234567'.indexOf(ch); Daniel@0: Daniel@0: // \0 is not octal escape sequence Daniel@0: if (code !== 0) { Daniel@0: octal = true; Daniel@0: } Daniel@0: Daniel@0: if (index < length && isOctalDigit(source[index])) { Daniel@0: octal = true; Daniel@0: code = code * 8 + '01234567'.indexOf(source[index++]); Daniel@0: Daniel@0: // 3 digits are only allowed when string starts Daniel@0: // with 0, 1, 2, 3 Daniel@0: if ('0123'.indexOf(ch) >= 0 && Daniel@0: index < length && Daniel@0: isOctalDigit(source[index])) { Daniel@0: code = code * 8 + '01234567'.indexOf(source[index++]); Daniel@0: } Daniel@0: } Daniel@0: str += String.fromCharCode(code); Daniel@0: } else { Daniel@0: str += ch; Daniel@0: } Daniel@0: break; Daniel@0: } Daniel@0: } else { Daniel@0: ++lineNumber; Daniel@0: if (ch === '\r' && source[index] === '\n') { Daniel@0: ++index; Daniel@0: } Daniel@0: lineStart = index; Daniel@0: } Daniel@0: } else if (isLineTerminator(ch.charCodeAt(0))) { Daniel@0: break; Daniel@0: } else { Daniel@0: str += ch; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (quote !== '') { Daniel@0: throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: type: Token.StringLiteral, Daniel@0: value: str, Daniel@0: octal: octal, Daniel@0: startLineNumber: startLineNumber, Daniel@0: startLineStart: startLineStart, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function testRegExp(pattern, flags) { Daniel@0: var tmp = pattern, Daniel@0: value; Daniel@0: Daniel@0: if (flags.indexOf('u') >= 0) { Daniel@0: // Replace each astral symbol and every Unicode code point Daniel@0: // escape sequence with a single ASCII symbol to avoid throwing on Daniel@0: // regular expressions that are only valid in combination with the Daniel@0: // `/u` flag. Daniel@0: // Note: replacing with the ASCII symbol `x` might cause false Daniel@0: // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a Daniel@0: // perfectly valid pattern that is equivalent to `[a-b]`, but it Daniel@0: // would be replaced by `[x-b]` which throws an error. Daniel@0: tmp = tmp Daniel@0: .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) { Daniel@0: if (parseInt($1, 16) <= 0x10FFFF) { Daniel@0: return 'x'; Daniel@0: } Daniel@0: throwError({}, Messages.InvalidRegExp); Daniel@0: }) Daniel@0: .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); Daniel@0: } Daniel@0: Daniel@0: // First, detect invalid regular expressions. Daniel@0: try { Daniel@0: value = new RegExp(tmp); Daniel@0: } catch (e) { Daniel@0: throwError({}, Messages.InvalidRegExp); Daniel@0: } Daniel@0: Daniel@0: // Return a regular expression object for this pattern-flag pair, or Daniel@0: // `null` in case the current environment doesn't support the flags it Daniel@0: // uses. Daniel@0: try { Daniel@0: return new RegExp(pattern, flags); Daniel@0: } catch (exception) { Daniel@0: return null; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function scanRegExpBody() { Daniel@0: var ch, str, classMarker, terminated, body; Daniel@0: Daniel@0: ch = source[index]; Daniel@0: assert(ch === '/', 'Regular expression literal must start with a slash'); Daniel@0: str = source[index++]; Daniel@0: Daniel@0: classMarker = false; Daniel@0: terminated = false; Daniel@0: while (index < length) { Daniel@0: ch = source[index++]; Daniel@0: str += ch; Daniel@0: if (ch === '\\') { Daniel@0: ch = source[index++]; Daniel@0: // ECMA-262 7.8.5 Daniel@0: if (isLineTerminator(ch.charCodeAt(0))) { Daniel@0: throwError({}, Messages.UnterminatedRegExp); Daniel@0: } Daniel@0: str += ch; Daniel@0: } else if (isLineTerminator(ch.charCodeAt(0))) { Daniel@0: throwError({}, Messages.UnterminatedRegExp); Daniel@0: } else if (classMarker) { Daniel@0: if (ch === ']') { Daniel@0: classMarker = false; Daniel@0: } Daniel@0: } else { Daniel@0: if (ch === '/') { Daniel@0: terminated = true; Daniel@0: break; Daniel@0: } else if (ch === '[') { Daniel@0: classMarker = true; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (!terminated) { Daniel@0: throwError({}, Messages.UnterminatedRegExp); Daniel@0: } Daniel@0: Daniel@0: // Exclude leading and trailing slash. Daniel@0: body = str.substr(1, str.length - 2); Daniel@0: return { Daniel@0: value: body, Daniel@0: literal: str Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function scanRegExpFlags() { Daniel@0: var ch, str, flags, restore; Daniel@0: Daniel@0: str = ''; Daniel@0: flags = ''; Daniel@0: while (index < length) { Daniel@0: ch = source[index]; Daniel@0: if (!isIdentifierPart(ch.charCodeAt(0))) { Daniel@0: break; Daniel@0: } Daniel@0: Daniel@0: ++index; Daniel@0: if (ch === '\\' && index < length) { Daniel@0: ch = source[index]; Daniel@0: if (ch === 'u') { Daniel@0: ++index; Daniel@0: restore = index; Daniel@0: ch = scanHexEscape('u'); Daniel@0: if (ch) { Daniel@0: flags += ch; Daniel@0: for (str += '\\u'; restore < index; ++restore) { Daniel@0: str += source[restore]; Daniel@0: } Daniel@0: } else { Daniel@0: index = restore; Daniel@0: flags += 'u'; Daniel@0: str += '\\u'; Daniel@0: } Daniel@0: throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } else { Daniel@0: str += '\\'; Daniel@0: throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL'); Daniel@0: } Daniel@0: } else { Daniel@0: flags += ch; Daniel@0: str += ch; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: value: flags, Daniel@0: literal: str Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function scanRegExp() { Daniel@0: var start, body, flags, value; Daniel@0: Daniel@0: lookahead = null; Daniel@0: skipComment(); Daniel@0: start = index; Daniel@0: Daniel@0: body = scanRegExpBody(); Daniel@0: flags = scanRegExpFlags(); Daniel@0: value = testRegExp(body.value, flags.value); Daniel@0: Daniel@0: if (extra.tokenize) { Daniel@0: return { Daniel@0: type: Token.RegularExpression, Daniel@0: value: value, Daniel@0: regex: { Daniel@0: pattern: body.value, Daniel@0: flags: flags.value Daniel@0: }, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: literal: body.literal + flags.literal, Daniel@0: value: value, Daniel@0: regex: { Daniel@0: pattern: body.value, Daniel@0: flags: flags.value Daniel@0: }, Daniel@0: start: start, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function collectRegex() { Daniel@0: var pos, loc, regex, token; Daniel@0: Daniel@0: skipComment(); Daniel@0: Daniel@0: pos = index; Daniel@0: loc = { Daniel@0: start: { Daniel@0: line: lineNumber, Daniel@0: column: index - lineStart Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: regex = scanRegExp(); Daniel@0: Daniel@0: loc.end = { Daniel@0: line: lineNumber, Daniel@0: column: index - lineStart Daniel@0: }; Daniel@0: Daniel@0: if (!extra.tokenize) { Daniel@0: // Pop the previous token, which is likely '/' or '/=' Daniel@0: if (extra.tokens.length > 0) { Daniel@0: token = extra.tokens[extra.tokens.length - 1]; Daniel@0: if (token.range[0] === pos && token.type === 'Punctuator') { Daniel@0: if (token.value === '/' || token.value === '/=') { Daniel@0: extra.tokens.pop(); Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: extra.tokens.push({ Daniel@0: type: 'RegularExpression', Daniel@0: value: regex.literal, Daniel@0: regex: regex.regex, Daniel@0: range: [pos, index], Daniel@0: loc: loc Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: return regex; Daniel@0: } Daniel@0: Daniel@0: function isIdentifierName(token) { Daniel@0: return token.type === Token.Identifier || Daniel@0: token.type === Token.Keyword || Daniel@0: token.type === Token.BooleanLiteral || Daniel@0: token.type === Token.NullLiteral; Daniel@0: } Daniel@0: Daniel@0: function advanceSlash() { Daniel@0: var prevToken, Daniel@0: checkToken; Daniel@0: // Using the following algorithm: Daniel@0: // https://github.com/mozilla/sweet.js/wiki/design Daniel@0: prevToken = extra.tokens[extra.tokens.length - 1]; Daniel@0: if (!prevToken) { Daniel@0: // Nothing before that: it cannot be a division. Daniel@0: return collectRegex(); Daniel@0: } Daniel@0: if (prevToken.type === 'Punctuator') { Daniel@0: if (prevToken.value === ']') { Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: if (prevToken.value === ')') { Daniel@0: checkToken = extra.tokens[extra.openParenToken - 1]; Daniel@0: if (checkToken && Daniel@0: checkToken.type === 'Keyword' && Daniel@0: (checkToken.value === 'if' || Daniel@0: checkToken.value === 'while' || Daniel@0: checkToken.value === 'for' || Daniel@0: checkToken.value === 'with')) { Daniel@0: return collectRegex(); Daniel@0: } Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: if (prevToken.value === '}') { Daniel@0: // Dividing a function by anything makes little sense, Daniel@0: // but we have to check for that. Daniel@0: if (extra.tokens[extra.openCurlyToken - 3] && Daniel@0: extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') { Daniel@0: // Anonymous function. Daniel@0: checkToken = extra.tokens[extra.openCurlyToken - 4]; Daniel@0: if (!checkToken) { Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: } else if (extra.tokens[extra.openCurlyToken - 4] && Daniel@0: extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') { Daniel@0: // Named function. Daniel@0: checkToken = extra.tokens[extra.openCurlyToken - 5]; Daniel@0: if (!checkToken) { Daniel@0: return collectRegex(); Daniel@0: } Daniel@0: } else { Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: return collectRegex(); Daniel@0: } Daniel@0: if (prevToken.type === 'Keyword' && prevToken.value !== 'this') { Daniel@0: return collectRegex(); Daniel@0: } Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: Daniel@0: function advance() { Daniel@0: var ch; Daniel@0: Daniel@0: skipComment(); Daniel@0: Daniel@0: if (index >= length) { Daniel@0: return { Daniel@0: type: Token.EOF, Daniel@0: lineNumber: lineNumber, Daniel@0: lineStart: lineStart, Daniel@0: start: index, Daniel@0: end: index Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: ch = source.charCodeAt(index); Daniel@0: Daniel@0: if (isIdentifierStart(ch)) { Daniel@0: return scanIdentifier(); Daniel@0: } Daniel@0: Daniel@0: // Very common: ( and ) and ; Daniel@0: if (ch === 0x28 || ch === 0x29 || ch === 0x3B) { Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: Daniel@0: // String literal starts with single quote (U+0027) or double quote (U+0022). Daniel@0: if (ch === 0x27 || ch === 0x22) { Daniel@0: return scanStringLiteral(); Daniel@0: } Daniel@0: Daniel@0: Daniel@0: // Dot (.) U+002E can also start a floating-point number, hence the need Daniel@0: // to check the next character. Daniel@0: if (ch === 0x2E) { Daniel@0: if (isDecimalDigit(source.charCodeAt(index + 1))) { Daniel@0: return scanNumericLiteral(); Daniel@0: } Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: Daniel@0: if (isDecimalDigit(ch)) { Daniel@0: return scanNumericLiteral(); Daniel@0: } Daniel@0: Daniel@0: // Slash (/) U+002F can also start a regex. Daniel@0: if (extra.tokenize && ch === 0x2F) { Daniel@0: return advanceSlash(); Daniel@0: } Daniel@0: Daniel@0: return scanPunctuator(); Daniel@0: } Daniel@0: Daniel@0: function collectToken() { Daniel@0: var loc, token, value, entry; Daniel@0: Daniel@0: skipComment(); Daniel@0: loc = { Daniel@0: start: { Daniel@0: line: lineNumber, Daniel@0: column: index - lineStart Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: token = advance(); Daniel@0: loc.end = { Daniel@0: line: lineNumber, Daniel@0: column: index - lineStart Daniel@0: }; Daniel@0: Daniel@0: if (token.type !== Token.EOF) { Daniel@0: value = source.slice(token.start, token.end); Daniel@0: entry = { Daniel@0: type: TokenName[token.type], Daniel@0: value: value, Daniel@0: range: [token.start, token.end], Daniel@0: loc: loc Daniel@0: }; Daniel@0: if (token.regex) { Daniel@0: entry.regex = { Daniel@0: pattern: token.regex.pattern, Daniel@0: flags: token.regex.flags Daniel@0: }; Daniel@0: } Daniel@0: extra.tokens.push(entry); Daniel@0: } Daniel@0: Daniel@0: return token; Daniel@0: } Daniel@0: Daniel@0: function lex() { Daniel@0: var token; Daniel@0: Daniel@0: token = lookahead; Daniel@0: index = token.end; Daniel@0: lineNumber = token.lineNumber; Daniel@0: lineStart = token.lineStart; Daniel@0: Daniel@0: lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); Daniel@0: Daniel@0: index = token.end; Daniel@0: lineNumber = token.lineNumber; Daniel@0: lineStart = token.lineStart; Daniel@0: Daniel@0: return token; Daniel@0: } Daniel@0: Daniel@0: function peek() { Daniel@0: var pos, line, start; Daniel@0: Daniel@0: pos = index; Daniel@0: line = lineNumber; Daniel@0: start = lineStart; Daniel@0: lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); Daniel@0: index = pos; Daniel@0: lineNumber = line; Daniel@0: lineStart = start; Daniel@0: } Daniel@0: Daniel@0: function Position() { Daniel@0: this.line = lineNumber; Daniel@0: this.column = index - lineStart; Daniel@0: } Daniel@0: Daniel@0: function SourceLocation() { Daniel@0: this.start = new Position(); Daniel@0: this.end = null; Daniel@0: } Daniel@0: Daniel@0: function WrappingSourceLocation(startToken) { Daniel@0: if (startToken.type === Token.StringLiteral) { Daniel@0: this.start = { Daniel@0: line: startToken.startLineNumber, Daniel@0: column: startToken.start - startToken.startLineStart Daniel@0: }; Daniel@0: } else { Daniel@0: this.start = { Daniel@0: line: startToken.lineNumber, Daniel@0: column: startToken.start - startToken.lineStart Daniel@0: }; Daniel@0: } Daniel@0: this.end = null; Daniel@0: } Daniel@0: Daniel@0: function Node() { Daniel@0: // Skip comment. Daniel@0: index = lookahead.start; Daniel@0: if (lookahead.type === Token.StringLiteral) { Daniel@0: lineNumber = lookahead.startLineNumber; Daniel@0: lineStart = lookahead.startLineStart; Daniel@0: } else { Daniel@0: lineNumber = lookahead.lineNumber; Daniel@0: lineStart = lookahead.lineStart; Daniel@0: } Daniel@0: if (extra.range) { Daniel@0: this.range = [index, 0]; Daniel@0: } Daniel@0: if (extra.loc) { Daniel@0: this.loc = new SourceLocation(); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function WrappingNode(startToken) { Daniel@0: if (extra.range) { Daniel@0: this.range = [startToken.start, 0]; Daniel@0: } Daniel@0: if (extra.loc) { Daniel@0: this.loc = new WrappingSourceLocation(startToken); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: WrappingNode.prototype = Node.prototype = { Daniel@0: Daniel@0: finish: function () { Daniel@0: if (extra.range) { Daniel@0: this.range[1] = index; Daniel@0: } Daniel@0: if (extra.loc) { Daniel@0: this.loc.end = new Position(); Daniel@0: if (extra.source) { Daniel@0: this.loc.source = extra.source; Daniel@0: } Daniel@0: } Daniel@0: }, Daniel@0: Daniel@0: finishArrayExpression: function (elements) { Daniel@0: this.type = Syntax.ArrayExpression; Daniel@0: this.elements = elements; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishAssignmentExpression: function (operator, left, right) { Daniel@0: this.type = Syntax.AssignmentExpression; Daniel@0: this.operator = operator; Daniel@0: this.left = left; Daniel@0: this.right = right; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishBinaryExpression: function (operator, left, right) { Daniel@0: this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression; Daniel@0: this.operator = operator; Daniel@0: this.left = left; Daniel@0: this.right = right; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishCallExpression: function (callee, args) { Daniel@0: this.type = Syntax.CallExpression; Daniel@0: this.callee = callee; Daniel@0: this.arguments = args; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishConditionalExpression: function (test, consequent, alternate) { Daniel@0: this.type = Syntax.ConditionalExpression; Daniel@0: this.test = test; Daniel@0: this.consequent = consequent; Daniel@0: this.alternate = alternate; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishExpressionStatement: function (expression) { Daniel@0: this.type = Syntax.ExpressionStatement; Daniel@0: this.expression = expression; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishIdentifier: function (name) { Daniel@0: this.type = Syntax.Identifier; Daniel@0: this.name = name; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishLiteral: function (token) { Daniel@0: this.type = Syntax.Literal; Daniel@0: this.value = token.value; Daniel@0: this.raw = source.slice(token.start, token.end); Daniel@0: if (token.regex) { Daniel@0: if (this.raw == '//') { Daniel@0: this.raw = '/(?:)/'; Daniel@0: } Daniel@0: this.regex = token.regex; Daniel@0: } Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishMemberExpression: function (accessor, object, property) { Daniel@0: this.type = Syntax.MemberExpression; Daniel@0: this.computed = accessor === '['; Daniel@0: this.object = object; Daniel@0: this.property = property; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishObjectExpression: function (properties) { Daniel@0: this.type = Syntax.ObjectExpression; Daniel@0: this.properties = properties; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishProgram: function (body) { Daniel@0: this.type = Syntax.Program; Daniel@0: this.body = body; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishProperty: function (kind, key, value) { Daniel@0: this.type = Syntax.Property; Daniel@0: this.key = key; Daniel@0: this.value = value; Daniel@0: this.kind = kind; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: }, Daniel@0: Daniel@0: finishUnaryExpression: function (operator, argument) { Daniel@0: this.type = Syntax.UnaryExpression; Daniel@0: this.operator = operator; Daniel@0: this.argument = argument; Daniel@0: this.prefix = true; Daniel@0: this.finish(); Daniel@0: return this; Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: // Return true if there is a line terminator before the next token. Daniel@0: Daniel@0: function peekLineTerminator() { Daniel@0: var pos, line, start, found; Daniel@0: Daniel@0: pos = index; Daniel@0: line = lineNumber; Daniel@0: start = lineStart; Daniel@0: skipComment(); Daniel@0: found = lineNumber !== line; Daniel@0: index = pos; Daniel@0: lineNumber = line; Daniel@0: lineStart = start; Daniel@0: Daniel@0: return found; Daniel@0: } Daniel@0: Daniel@0: // Throw an exception Daniel@0: Daniel@0: function throwError(token, messageFormat) { Daniel@0: var error, Daniel@0: args = Array.prototype.slice.call(arguments, 2), Daniel@0: msg = messageFormat.replace( Daniel@0: /%(\d)/g, Daniel@0: function (whole, index) { Daniel@0: assert(index < args.length, 'Message reference must be in range'); Daniel@0: return args[index]; Daniel@0: } Daniel@0: ); Daniel@0: Daniel@0: if (typeof token.lineNumber === 'number') { Daniel@0: error = new Error('Line ' + token.lineNumber + ': ' + msg); Daniel@0: error.index = token.start; Daniel@0: error.lineNumber = token.lineNumber; Daniel@0: error.column = token.start - lineStart + 1; Daniel@0: } else { Daniel@0: error = new Error('Line ' + lineNumber + ': ' + msg); Daniel@0: error.index = index; Daniel@0: error.lineNumber = lineNumber; Daniel@0: error.column = index - lineStart + 1; Daniel@0: } Daniel@0: Daniel@0: error.description = msg; Daniel@0: throw error; Daniel@0: } Daniel@0: Daniel@0: function throwErrorTolerant() { Daniel@0: try { Daniel@0: throwError.apply(null, arguments); Daniel@0: } catch (e) { Daniel@0: if (extra.errors) { Daniel@0: extra.errors.push(e); Daniel@0: } else { Daniel@0: throw e; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: Daniel@0: // Throw an exception because of the token. Daniel@0: Daniel@0: function throwUnexpected(token) { Daniel@0: if (token.type === Token.EOF) { Daniel@0: throwError(token, Messages.UnexpectedEOS); Daniel@0: } Daniel@0: Daniel@0: if (token.type === Token.NumericLiteral) { Daniel@0: throwError(token, Messages.UnexpectedNumber); Daniel@0: } Daniel@0: Daniel@0: if (token.type === Token.StringLiteral) { Daniel@0: throwError(token, Messages.UnexpectedString); Daniel@0: } Daniel@0: Daniel@0: if (token.type === Token.Identifier) { Daniel@0: throwError(token, Messages.UnexpectedIdentifier); Daniel@0: } Daniel@0: Daniel@0: if (token.type === Token.Keyword) { Daniel@0: if (isFutureReservedWord(token.value)) { Daniel@0: throwError(token, Messages.UnexpectedReserved); Daniel@0: } else if (strict && isStrictModeReservedWord(token.value)) { Daniel@0: throwErrorTolerant(token, Messages.StrictReservedWord); Daniel@0: return; Daniel@0: } Daniel@0: throwError(token, Messages.UnexpectedToken, token.value); Daniel@0: } Daniel@0: Daniel@0: // BooleanLiteral, NullLiteral, or Punctuator. Daniel@0: throwError(token, Messages.UnexpectedToken, token.value); Daniel@0: } Daniel@0: Daniel@0: // Expect the next token to match the specified punctuator. Daniel@0: // If not, an exception will be thrown. Daniel@0: Daniel@0: function expect(value) { Daniel@0: var token = lex(); Daniel@0: if (token.type !== Token.Punctuator || token.value !== value) { Daniel@0: throwUnexpected(token); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: /** Daniel@0: * @name expectTolerant Daniel@0: * @description Quietly expect the given token value when in tolerant mode, otherwise delegates Daniel@0: * to expect(value) Daniel@0: * @param {String} value The value we are expecting the lookahead token to have Daniel@0: * @since 2.0 Daniel@0: */ Daniel@0: function expectTolerant(value) { Daniel@0: if (extra.errors) { Daniel@0: var token = lookahead; Daniel@0: if (token.type !== Token.Punctuator && token.value !== value) { Daniel@0: throwErrorTolerant(token, Messages.UnexpectedToken, token.value); Daniel@0: } else { Daniel@0: lex(); Daniel@0: } Daniel@0: } else { Daniel@0: expect(value); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // Return true if the next token matches the specified punctuator. Daniel@0: Daniel@0: function match(value) { Daniel@0: return lookahead.type === Token.Punctuator && lookahead.value === value; Daniel@0: } Daniel@0: Daniel@0: // Return true if the next token matches the specified keyword Daniel@0: Daniel@0: function matchKeyword(keyword) { Daniel@0: return lookahead.type === Token.Keyword && lookahead.value === keyword; Daniel@0: } Daniel@0: Daniel@0: function consumeSemicolon() { Daniel@0: var line; Daniel@0: Daniel@0: // Catch the very common case first: immediately a semicolon (U+003B). Daniel@0: if (source.charCodeAt(index) === 0x3B || match(';')) { Daniel@0: lex(); Daniel@0: return; Daniel@0: } Daniel@0: Daniel@0: line = lineNumber; Daniel@0: skipComment(); Daniel@0: if (lineNumber !== line) { Daniel@0: return; Daniel@0: } Daniel@0: Daniel@0: if (lookahead.type !== Token.EOF && !match('}')) { Daniel@0: throwUnexpected(lookahead); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // 11.1.4 Array Initialiser Daniel@0: Daniel@0: function parseArrayInitialiser() { Daniel@0: var elements = [], node = new Node(); Daniel@0: Daniel@0: expect('['); Daniel@0: Daniel@0: while (!match(']')) { Daniel@0: if (match(',')) { Daniel@0: lex(); Daniel@0: elements.push(null); Daniel@0: } else { Daniel@0: elements.push(parseAssignmentExpression()); Daniel@0: Daniel@0: if (!match(']')) { Daniel@0: expect(','); Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: lex(); Daniel@0: Daniel@0: return node.finishArrayExpression(elements); Daniel@0: } Daniel@0: Daniel@0: // 11.1.5 Object Initialiser Daniel@0: Daniel@0: function parseObjectPropertyKey() { Daniel@0: var token, node = new Node(); Daniel@0: Daniel@0: token = lex(); Daniel@0: Daniel@0: // Note: This function is called only from parseObjectProperty(), where Daniel@0: // EOF and Punctuator tokens are already filtered out. Daniel@0: Daniel@0: if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { Daniel@0: if (strict && token.octal) { Daniel@0: throwErrorTolerant(token, Messages.StrictOctalLiteral); Daniel@0: } Daniel@0: return node.finishLiteral(token); Daniel@0: } Daniel@0: Daniel@0: return node.finishIdentifier(token.value); Daniel@0: } Daniel@0: Daniel@0: function parseObjectProperty() { Daniel@0: var token, key, id, value, node = new Node(); Daniel@0: Daniel@0: token = lookahead; Daniel@0: Daniel@0: if (token.type === Token.Identifier) { Daniel@0: id = parseObjectPropertyKey(); Daniel@0: expect(':'); Daniel@0: value = parseAssignmentExpression(); Daniel@0: return node.finishProperty('init', id, value); Daniel@0: } Daniel@0: if (token.type === Token.EOF || token.type === Token.Punctuator) { Daniel@0: throwUnexpected(token); Daniel@0: } else { Daniel@0: key = parseObjectPropertyKey(); Daniel@0: expect(':'); Daniel@0: value = parseAssignmentExpression(); Daniel@0: return node.finishProperty('init', key, value); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function parseObjectInitialiser() { Daniel@0: var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node(); Daniel@0: Daniel@0: expect('{'); Daniel@0: Daniel@0: while (!match('}')) { Daniel@0: property = parseObjectProperty(); Daniel@0: Daniel@0: if (property.key.type === Syntax.Identifier) { Daniel@0: name = property.key.name; Daniel@0: } else { Daniel@0: name = toString(property.key.value); Daniel@0: } Daniel@0: kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; Daniel@0: Daniel@0: key = '$' + name; Daniel@0: if (Object.prototype.hasOwnProperty.call(map, key)) { Daniel@0: if (map[key] === PropertyKind.Data) { Daniel@0: if (strict && kind === PropertyKind.Data) { Daniel@0: throwErrorTolerant({}, Messages.StrictDuplicateProperty); Daniel@0: } else if (kind !== PropertyKind.Data) { Daniel@0: throwErrorTolerant({}, Messages.AccessorDataProperty); Daniel@0: } Daniel@0: } else { Daniel@0: if (kind === PropertyKind.Data) { Daniel@0: throwErrorTolerant({}, Messages.AccessorDataProperty); Daniel@0: } else if (map[key] & kind) { Daniel@0: throwErrorTolerant({}, Messages.AccessorGetSet); Daniel@0: } Daniel@0: } Daniel@0: map[key] |= kind; Daniel@0: } else { Daniel@0: map[key] = kind; Daniel@0: } Daniel@0: Daniel@0: properties.push(property); Daniel@0: Daniel@0: if (!match('}')) { Daniel@0: expectTolerant(','); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: expect('}'); Daniel@0: Daniel@0: return node.finishObjectExpression(properties); Daniel@0: } Daniel@0: Daniel@0: // 11.1.6 The Grouping Operator Daniel@0: Daniel@0: function parseGroupExpression() { Daniel@0: var expr; Daniel@0: Daniel@0: expect('('); Daniel@0: Daniel@0: ++state.parenthesisCount; Daniel@0: Daniel@0: expr = parseExpression(); Daniel@0: Daniel@0: expect(')'); Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: Daniel@0: // 11.1 Primary Expressions Daniel@0: Daniel@0: var legalKeywords = {"if":1, "this":1}; Daniel@0: Daniel@0: function parsePrimaryExpression() { Daniel@0: var type, token, expr, node; Daniel@0: Daniel@0: if (match('(')) { Daniel@0: return parseGroupExpression(); Daniel@0: } Daniel@0: Daniel@0: if (match('[')) { Daniel@0: return parseArrayInitialiser(); Daniel@0: } Daniel@0: Daniel@0: if (match('{')) { Daniel@0: return parseObjectInitialiser(); Daniel@0: } Daniel@0: Daniel@0: type = lookahead.type; Daniel@0: node = new Node(); Daniel@0: Daniel@0: if (type === Token.Identifier || legalKeywords[lookahead.value]) { Daniel@0: expr = node.finishIdentifier(lex().value); Daniel@0: } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { Daniel@0: if (strict && lookahead.octal) { Daniel@0: throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); Daniel@0: } Daniel@0: expr = node.finishLiteral(lex()); Daniel@0: } else if (type === Token.Keyword) { Daniel@0: throw new Error("Disabled."); Daniel@0: } else if (type === Token.BooleanLiteral) { Daniel@0: token = lex(); Daniel@0: token.value = (token.value === 'true'); Daniel@0: expr = node.finishLiteral(token); Daniel@0: } else if (type === Token.NullLiteral) { Daniel@0: token = lex(); Daniel@0: token.value = null; Daniel@0: expr = node.finishLiteral(token); Daniel@0: } else if (match('/') || match('/=')) { Daniel@0: if (typeof extra.tokens !== 'undefined') { Daniel@0: expr = node.finishLiteral(collectRegex()); Daniel@0: } else { Daniel@0: expr = node.finishLiteral(scanRegExp()); Daniel@0: } Daniel@0: peek(); Daniel@0: } else { Daniel@0: throwUnexpected(lex()); Daniel@0: } Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 11.2 Left-Hand-Side Expressions Daniel@0: Daniel@0: function parseArguments() { Daniel@0: var args = []; Daniel@0: Daniel@0: expect('('); Daniel@0: Daniel@0: if (!match(')')) { Daniel@0: while (index < length) { Daniel@0: args.push(parseAssignmentExpression()); Daniel@0: if (match(')')) { Daniel@0: break; Daniel@0: } Daniel@0: expectTolerant(','); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: expect(')'); Daniel@0: Daniel@0: return args; Daniel@0: } Daniel@0: Daniel@0: function parseNonComputedProperty() { Daniel@0: var token, node = new Node(); Daniel@0: Daniel@0: token = lex(); Daniel@0: Daniel@0: if (!isIdentifierName(token)) { Daniel@0: throwUnexpected(token); Daniel@0: } Daniel@0: Daniel@0: return node.finishIdentifier(token.value); Daniel@0: } Daniel@0: Daniel@0: function parseNonComputedMember() { Daniel@0: expect('.'); Daniel@0: Daniel@0: return parseNonComputedProperty(); Daniel@0: } Daniel@0: Daniel@0: function parseComputedMember() { Daniel@0: var expr; Daniel@0: Daniel@0: expect('['); Daniel@0: Daniel@0: expr = parseExpression(); Daniel@0: Daniel@0: expect(']'); Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: function parseLeftHandSideExpressionAllowCall() { Daniel@0: var expr, args, property, startToken, previousAllowIn = state.allowIn; Daniel@0: Daniel@0: startToken = lookahead; Daniel@0: state.allowIn = true; Daniel@0: expr = parsePrimaryExpression(); Daniel@0: Daniel@0: for (;;) { Daniel@0: if (match('.')) { Daniel@0: property = parseNonComputedMember(); Daniel@0: expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); Daniel@0: } else if (match('(')) { Daniel@0: args = parseArguments(); Daniel@0: expr = new WrappingNode(startToken).finishCallExpression(expr, args); Daniel@0: } else if (match('[')) { Daniel@0: property = parseComputedMember(); Daniel@0: expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); Daniel@0: } else { Daniel@0: break; Daniel@0: } Daniel@0: } Daniel@0: state.allowIn = previousAllowIn; Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 11.3 Postfix Expressions Daniel@0: Daniel@0: function parsePostfixExpression() { Daniel@0: var expr = parseLeftHandSideExpressionAllowCall(); Daniel@0: Daniel@0: if (lookahead.type === Token.Punctuator) { Daniel@0: if ((match('++') || match('--')) && !peekLineTerminator()) { Daniel@0: throw new Error("Disabled."); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 11.4 Unary Operators Daniel@0: Daniel@0: function parseUnaryExpression() { Daniel@0: var token, expr, startToken; Daniel@0: Daniel@0: if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { Daniel@0: expr = parsePostfixExpression(); Daniel@0: } else if (match('++') || match('--')) { Daniel@0: throw new Error("Disabled."); Daniel@0: } else if (match('+') || match('-') || match('~') || match('!')) { Daniel@0: startToken = lookahead; Daniel@0: token = lex(); Daniel@0: expr = parseUnaryExpression(); Daniel@0: expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); Daniel@0: } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { Daniel@0: throw new Error("Disabled."); Daniel@0: } else { Daniel@0: expr = parsePostfixExpression(); Daniel@0: } Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: function binaryPrecedence(token, allowIn) { Daniel@0: var prec = 0; Daniel@0: Daniel@0: if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { Daniel@0: return 0; Daniel@0: } Daniel@0: Daniel@0: switch (token.value) { Daniel@0: case '||': Daniel@0: prec = 1; Daniel@0: break; Daniel@0: Daniel@0: case '&&': Daniel@0: prec = 2; Daniel@0: break; Daniel@0: Daniel@0: case '|': Daniel@0: prec = 3; Daniel@0: break; Daniel@0: Daniel@0: case '^': Daniel@0: prec = 4; Daniel@0: break; Daniel@0: Daniel@0: case '&': Daniel@0: prec = 5; Daniel@0: break; Daniel@0: Daniel@0: case '==': Daniel@0: case '!=': Daniel@0: case '===': Daniel@0: case '!==': Daniel@0: prec = 6; Daniel@0: break; Daniel@0: Daniel@0: case '<': Daniel@0: case '>': Daniel@0: case '<=': Daniel@0: case '>=': Daniel@0: case 'instanceof': Daniel@0: prec = 7; Daniel@0: break; Daniel@0: Daniel@0: case 'in': Daniel@0: prec = allowIn ? 7 : 0; Daniel@0: break; Daniel@0: Daniel@0: case '<<': Daniel@0: case '>>': Daniel@0: case '>>>': Daniel@0: prec = 8; Daniel@0: break; Daniel@0: Daniel@0: case '+': Daniel@0: case '-': Daniel@0: prec = 9; Daniel@0: break; Daniel@0: Daniel@0: case '*': Daniel@0: case '/': Daniel@0: case '%': Daniel@0: prec = 11; Daniel@0: break; Daniel@0: Daniel@0: default: Daniel@0: break; Daniel@0: } Daniel@0: Daniel@0: return prec; Daniel@0: } Daniel@0: Daniel@0: // 11.5 Multiplicative Operators Daniel@0: // 11.6 Additive Operators Daniel@0: // 11.7 Bitwise Shift Operators Daniel@0: // 11.8 Relational Operators Daniel@0: // 11.9 Equality Operators Daniel@0: // 11.10 Binary Bitwise Operators Daniel@0: // 11.11 Binary Logical Operators Daniel@0: Daniel@0: function parseBinaryExpression() { Daniel@0: var marker, markers, expr, token, prec, stack, right, operator, left, i; Daniel@0: Daniel@0: marker = lookahead; Daniel@0: left = parseUnaryExpression(); Daniel@0: Daniel@0: token = lookahead; Daniel@0: prec = binaryPrecedence(token, state.allowIn); Daniel@0: if (prec === 0) { Daniel@0: return left; Daniel@0: } Daniel@0: token.prec = prec; Daniel@0: lex(); Daniel@0: Daniel@0: markers = [marker, lookahead]; Daniel@0: right = parseUnaryExpression(); Daniel@0: Daniel@0: stack = [left, token, right]; Daniel@0: Daniel@0: while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) { Daniel@0: Daniel@0: // Reduce: make a binary expression from the three topmost entries. Daniel@0: while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { Daniel@0: right = stack.pop(); Daniel@0: operator = stack.pop().value; Daniel@0: left = stack.pop(); Daniel@0: markers.pop(); Daniel@0: expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right); Daniel@0: stack.push(expr); Daniel@0: } Daniel@0: Daniel@0: // Shift. Daniel@0: token = lex(); Daniel@0: token.prec = prec; Daniel@0: stack.push(token); Daniel@0: markers.push(lookahead); Daniel@0: expr = parseUnaryExpression(); Daniel@0: stack.push(expr); Daniel@0: } Daniel@0: Daniel@0: // Final reduce to clean-up the stack. Daniel@0: i = stack.length - 1; Daniel@0: expr = stack[i]; Daniel@0: markers.pop(); Daniel@0: while (i > 1) { Daniel@0: expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr); Daniel@0: i -= 2; Daniel@0: } Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 11.12 Conditional Operator Daniel@0: Daniel@0: function parseConditionalExpression() { Daniel@0: var expr, previousAllowIn, consequent, alternate, startToken; Daniel@0: Daniel@0: startToken = lookahead; Daniel@0: Daniel@0: expr = parseBinaryExpression(); Daniel@0: Daniel@0: if (match('?')) { Daniel@0: lex(); Daniel@0: previousAllowIn = state.allowIn; Daniel@0: state.allowIn = true; Daniel@0: consequent = parseAssignmentExpression(); Daniel@0: state.allowIn = previousAllowIn; Daniel@0: expect(':'); Daniel@0: alternate = parseAssignmentExpression(); Daniel@0: Daniel@0: expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate); Daniel@0: } Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 11.13 Assignment Operators Daniel@0: Daniel@0: function parseAssignmentExpression() { Daniel@0: var oldParenthesisCount, token, expr, startToken; Daniel@0: Daniel@0: oldParenthesisCount = state.parenthesisCount; Daniel@0: Daniel@0: startToken = lookahead; Daniel@0: token = lookahead; Daniel@0: Daniel@0: expr = parseConditionalExpression(); Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 11.14 Comma Operator Daniel@0: Daniel@0: function parseExpression() { Daniel@0: var expr = parseAssignmentExpression(); Daniel@0: Daniel@0: if (match(',')) { Daniel@0: throw new Error("Disabled."); // no sequence expressions Daniel@0: } Daniel@0: Daniel@0: return expr; Daniel@0: } Daniel@0: Daniel@0: // 12.4 Expression Statement Daniel@0: Daniel@0: function parseExpressionStatement(node) { Daniel@0: var expr = parseExpression(); Daniel@0: consumeSemicolon(); Daniel@0: return node.finishExpressionStatement(expr); Daniel@0: } Daniel@0: Daniel@0: // 12 Statements Daniel@0: Daniel@0: function parseStatement() { Daniel@0: var type = lookahead.type, Daniel@0: expr, Daniel@0: node; Daniel@0: Daniel@0: if (type === Token.EOF) { Daniel@0: throwUnexpected(lookahead); Daniel@0: } Daniel@0: Daniel@0: if (type === Token.Punctuator && lookahead.value === '{') { Daniel@0: throw new Error("Disabled."); // block statement Daniel@0: } Daniel@0: Daniel@0: node = new Node(); Daniel@0: Daniel@0: if (type === Token.Punctuator) { Daniel@0: switch (lookahead.value) { Daniel@0: case ';': Daniel@0: throw new Error("Disabled."); // empty statement Daniel@0: case '(': Daniel@0: return parseExpressionStatement(node); Daniel@0: default: Daniel@0: break; Daniel@0: } Daniel@0: } else if (type === Token.Keyword) { Daniel@0: throw new Error("Disabled."); // keyword Daniel@0: } Daniel@0: Daniel@0: expr = parseExpression(); Daniel@0: consumeSemicolon(); Daniel@0: return node.finishExpressionStatement(expr); Daniel@0: } Daniel@0: Daniel@0: // 14 Program Daniel@0: Daniel@0: function parseSourceElement() { Daniel@0: if (lookahead.type === Token.Keyword) { Daniel@0: switch (lookahead.value) { Daniel@0: case 'const': Daniel@0: case 'let': Daniel@0: throw new Error("Disabled."); Daniel@0: case 'function': Daniel@0: throw new Error("Disabled."); Daniel@0: default: Daniel@0: return parseStatement(); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (lookahead.type !== Token.EOF) { Daniel@0: return parseStatement(); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function parseSourceElements() { Daniel@0: var sourceElement, sourceElements = [], token, directive, firstRestricted; Daniel@0: Daniel@0: while (index < length) { Daniel@0: token = lookahead; Daniel@0: if (token.type !== Token.StringLiteral) { Daniel@0: break; Daniel@0: } Daniel@0: Daniel@0: sourceElement = parseSourceElement(); Daniel@0: sourceElements.push(sourceElement); Daniel@0: if (sourceElement.expression.type !== Syntax.Literal) { Daniel@0: // this is not directive Daniel@0: break; Daniel@0: } Daniel@0: directive = source.slice(token.start + 1, token.end - 1); Daniel@0: if (directive === 'use strict') { Daniel@0: strict = true; Daniel@0: if (firstRestricted) { Daniel@0: throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); Daniel@0: } Daniel@0: } else { Daniel@0: if (!firstRestricted && token.octal) { Daniel@0: firstRestricted = token; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: while (index < length) { Daniel@0: sourceElement = parseSourceElement(); Daniel@0: if (typeof sourceElement === 'undefined') { Daniel@0: break; Daniel@0: } Daniel@0: sourceElements.push(sourceElement); Daniel@0: } Daniel@0: return sourceElements; Daniel@0: } Daniel@0: Daniel@0: function parseProgram() { Daniel@0: var body, node; Daniel@0: Daniel@0: skipComment(); Daniel@0: peek(); Daniel@0: node = new Node(); Daniel@0: strict = true; // assume strict Daniel@0: Daniel@0: body = parseSourceElements(); Daniel@0: return node.finishProgram(body); Daniel@0: } Daniel@0: Daniel@0: function filterTokenLocation() { Daniel@0: var i, entry, token, tokens = []; Daniel@0: Daniel@0: for (i = 0; i < extra.tokens.length; ++i) { Daniel@0: entry = extra.tokens[i]; Daniel@0: token = { Daniel@0: type: entry.type, Daniel@0: value: entry.value Daniel@0: }; Daniel@0: if (entry.regex) { Daniel@0: token.regex = { Daniel@0: pattern: entry.regex.pattern, Daniel@0: flags: entry.regex.flags Daniel@0: }; Daniel@0: } Daniel@0: if (extra.range) { Daniel@0: token.range = entry.range; Daniel@0: } Daniel@0: if (extra.loc) { Daniel@0: token.loc = entry.loc; Daniel@0: } Daniel@0: tokens.push(token); Daniel@0: } Daniel@0: Daniel@0: extra.tokens = tokens; Daniel@0: } Daniel@0: Daniel@0: function tokenize(code, options) { Daniel@0: var toString, Daniel@0: tokens; Daniel@0: Daniel@0: toString = String; Daniel@0: if (typeof code !== 'string' && !(code instanceof String)) { Daniel@0: code = toString(code); Daniel@0: } Daniel@0: Daniel@0: source = code; Daniel@0: index = 0; Daniel@0: lineNumber = (source.length > 0) ? 1 : 0; Daniel@0: lineStart = 0; Daniel@0: length = source.length; Daniel@0: lookahead = null; Daniel@0: state = { Daniel@0: allowIn: true, Daniel@0: labelSet: {}, Daniel@0: inFunctionBody: false, Daniel@0: inIteration: false, Daniel@0: inSwitch: false, Daniel@0: lastCommentStart: -1 Daniel@0: }; Daniel@0: Daniel@0: extra = {}; Daniel@0: Daniel@0: // Options matching. Daniel@0: options = options || {}; Daniel@0: Daniel@0: // Of course we collect tokens here. Daniel@0: options.tokens = true; Daniel@0: extra.tokens = []; Daniel@0: extra.tokenize = true; Daniel@0: // The following two fields are necessary to compute the Regex tokens. Daniel@0: extra.openParenToken = -1; Daniel@0: extra.openCurlyToken = -1; Daniel@0: Daniel@0: extra.range = (typeof options.range === 'boolean') && options.range; Daniel@0: extra.loc = (typeof options.loc === 'boolean') && options.loc; Daniel@0: Daniel@0: if (typeof options.tolerant === 'boolean' && options.tolerant) { Daniel@0: extra.errors = []; Daniel@0: } Daniel@0: Daniel@0: try { Daniel@0: peek(); Daniel@0: if (lookahead.type === Token.EOF) { Daniel@0: return extra.tokens; Daniel@0: } Daniel@0: Daniel@0: lex(); Daniel@0: while (lookahead.type !== Token.EOF) { Daniel@0: try { Daniel@0: lex(); Daniel@0: } catch (lexError) { Daniel@0: if (extra.errors) { Daniel@0: extra.errors.push(lexError); Daniel@0: // We have to break on the first error Daniel@0: // to avoid infinite loops. Daniel@0: break; Daniel@0: } else { Daniel@0: throw lexError; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: filterTokenLocation(); Daniel@0: tokens = extra.tokens; Daniel@0: if (typeof extra.errors !== 'undefined') { Daniel@0: tokens.errors = extra.errors; Daniel@0: } Daniel@0: } catch (e) { Daniel@0: throw e; Daniel@0: } finally { Daniel@0: extra = {}; Daniel@0: } Daniel@0: return tokens; Daniel@0: } Daniel@0: Daniel@0: function parse(code, options) { Daniel@0: var program, toString; Daniel@0: Daniel@0: toString = String; Daniel@0: if (typeof code !== 'string' && !(code instanceof String)) { Daniel@0: code = toString(code); Daniel@0: } Daniel@0: Daniel@0: source = code; Daniel@0: index = 0; Daniel@0: lineNumber = (source.length > 0) ? 1 : 0; Daniel@0: lineStart = 0; Daniel@0: length = source.length; Daniel@0: lookahead = null; Daniel@0: state = { Daniel@0: allowIn: true, Daniel@0: labelSet: {}, Daniel@0: parenthesisCount: 0, Daniel@0: inFunctionBody: false, Daniel@0: inIteration: false, Daniel@0: inSwitch: false, Daniel@0: lastCommentStart: -1 Daniel@0: }; Daniel@0: Daniel@0: extra = {}; Daniel@0: if (typeof options !== 'undefined') { Daniel@0: extra.range = (typeof options.range === 'boolean') && options.range; Daniel@0: extra.loc = (typeof options.loc === 'boolean') && options.loc; Daniel@0: Daniel@0: if (extra.loc && options.source !== null && options.source !== undefined) { Daniel@0: extra.source = toString(options.source); Daniel@0: } Daniel@0: Daniel@0: if (typeof options.tokens === 'boolean' && options.tokens) { Daniel@0: extra.tokens = []; Daniel@0: } Daniel@0: if (typeof options.tolerant === 'boolean' && options.tolerant) { Daniel@0: extra.errors = []; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: try { Daniel@0: program = parseProgram(); Daniel@0: if (typeof extra.tokens !== 'undefined') { Daniel@0: filterTokenLocation(); Daniel@0: program.tokens = extra.tokens; Daniel@0: } Daniel@0: if (typeof extra.errors !== 'undefined') { Daniel@0: program.errors = extra.errors; Daniel@0: } Daniel@0: } catch (e) { Daniel@0: throw e; Daniel@0: } finally { Daniel@0: extra = {}; Daniel@0: } Daniel@0: Daniel@0: return program; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: tokenize: tokenize, Daniel@0: parse: parse Daniel@0: }; Daniel@0: Daniel@0: })(); Daniel@0: },{}],45:[function(require,module,exports){ Daniel@0: var ts = Date.now(); Daniel@0: Daniel@0: function write(msg) { Daniel@0: msg = '[Vega Log] ' + msg; Daniel@0: console.log(msg); Daniel@0: } Daniel@0: Daniel@0: function error(msg) { Daniel@0: msg = '[Vega Err] ' + msg; Daniel@0: console.error(msg); Daniel@0: } Daniel@0: Daniel@0: function debug(input, args) { Daniel@0: if (!debug.enable) return; Daniel@0: var log = Function.prototype.bind.call(console.log, console); Daniel@0: var state = { Daniel@0: prevTime: Date.now() - ts, Daniel@0: stamp: input.stamp Daniel@0: }; Daniel@0: Daniel@0: if (input.add) { Daniel@0: state.add = input.add.length; Daniel@0: state.mod = input.mod.length; Daniel@0: state.rem = input.rem.length; Daniel@0: state.reflow = !!input.reflow; Daniel@0: } Daniel@0: Daniel@0: log.apply(console, (args.push(JSON.stringify(state)), args)); Daniel@0: ts = Date.now(); Daniel@0: } Daniel@0: Daniel@0: module.exports = { Daniel@0: log: write, Daniel@0: error: error, Daniel@0: debug: (debug.enable = false, debug) Daniel@0: }; Daniel@0: Daniel@0: },{}],46:[function(require,module,exports){ Daniel@0: module.exports = { Daniel@0: path: require('./path'), Daniel@0: render: require('./render'), Daniel@0: Item: require('./util/Item'), Daniel@0: bound: require('./util/bound'), Daniel@0: Bounds: require('./util/Bounds'), Daniel@0: Gradient: require('./util/Gradient'), Daniel@0: toJSON: require('./util/scene').toJSON, Daniel@0: fromJSON: require('./util/scene').fromJSON Daniel@0: }; Daniel@0: },{"./path":48,"./render":68,"./util/Bounds":74,"./util/Gradient":76,"./util/Item":78,"./util/bound":79,"./util/scene":82}],47:[function(require,module,exports){ Daniel@0: var segmentCache = {}, Daniel@0: bezierCache = {}, Daniel@0: join = [].join; Daniel@0: Daniel@0: // Copied from Inkscape svgtopdf, thanks! Daniel@0: function segments(x, y, rx, ry, large, sweep, rotateX, ox, oy) { Daniel@0: var key = join.call(arguments); Daniel@0: if (segmentCache[key]) { Daniel@0: return segmentCache[key]; Daniel@0: } Daniel@0: Daniel@0: var th = rotateX * (Math.PI/180); Daniel@0: var sin_th = Math.sin(th); Daniel@0: var cos_th = Math.cos(th); Daniel@0: rx = Math.abs(rx); Daniel@0: ry = Math.abs(ry); Daniel@0: var px = cos_th * (ox - x) * 0.5 + sin_th * (oy - y) * 0.5; Daniel@0: var py = cos_th * (oy - y) * 0.5 - sin_th * (ox - x) * 0.5; Daniel@0: var pl = (px*px) / (rx*rx) + (py*py) / (ry*ry); Daniel@0: if (pl > 1) { Daniel@0: pl = Math.sqrt(pl); Daniel@0: rx *= pl; Daniel@0: ry *= pl; Daniel@0: } Daniel@0: Daniel@0: var a00 = cos_th / rx; Daniel@0: var a01 = sin_th / rx; Daniel@0: var a10 = (-sin_th) / ry; Daniel@0: var a11 = (cos_th) / ry; Daniel@0: var x0 = a00 * ox + a01 * oy; Daniel@0: var y0 = a10 * ox + a11 * oy; Daniel@0: var x1 = a00 * x + a01 * y; Daniel@0: var y1 = a10 * x + a11 * y; Daniel@0: Daniel@0: var d = (x1-x0) * (x1-x0) + (y1-y0) * (y1-y0); Daniel@0: var sfactor_sq = 1 / d - 0.25; Daniel@0: if (sfactor_sq < 0) sfactor_sq = 0; Daniel@0: var sfactor = Math.sqrt(sfactor_sq); Daniel@0: if (sweep == large) sfactor = -sfactor; Daniel@0: var xc = 0.5 * (x0 + x1) - sfactor * (y1-y0); Daniel@0: var yc = 0.5 * (y0 + y1) + sfactor * (x1-x0); Daniel@0: Daniel@0: var th0 = Math.atan2(y0-yc, x0-xc); Daniel@0: var th1 = Math.atan2(y1-yc, x1-xc); Daniel@0: Daniel@0: var th_arc = th1-th0; Daniel@0: if (th_arc < 0 && sweep === 1){ Daniel@0: th_arc += 2 * Math.PI; Daniel@0: } else if (th_arc > 0 && sweep === 0) { Daniel@0: th_arc -= 2 * Math.PI; Daniel@0: } Daniel@0: Daniel@0: var segs = Math.ceil(Math.abs(th_arc / (Math.PI * 0.5 + 0.001))); Daniel@0: var result = []; Daniel@0: for (var i=0; i len) { Daniel@0: for (j=1, m=parsed.length; j=0;) { Daniel@0: if (h[i].type !== type) continue; Daniel@0: if (!handler || h[i].handler === handler) h.splice(i, 1); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.pickEvent = function(evt) { Daniel@0: var rect = this._canvas.getBoundingClientRect(), Daniel@0: pad = this._padding, x, y; Daniel@0: return this.pick(this._scene, Daniel@0: x = (evt.clientX - rect.left), Daniel@0: y = (evt.clientY - rect.top), Daniel@0: x - pad.left, y - pad.top); Daniel@0: }; Daniel@0: Daniel@0: // find the scenegraph item at the current mouse position Daniel@0: // x, y -- the absolute x, y mouse coordinates on the canvas element Daniel@0: // gx, gy -- the relative coordinates within the current group Daniel@0: prototype.pick = function(scene, x, y, gx, gy) { Daniel@0: var g = this.context(), Daniel@0: mark = marks[scene.marktype]; Daniel@0: return mark.pick.call(this, g, scene, x, y, gx, gy); Daniel@0: }; Daniel@0: Daniel@0: module.exports = CanvasHandler; Daniel@0: Daniel@0: },{"../../util/dom":81,"../Handler":51,"./marks":60}],54:[function(require,module,exports){ Daniel@0: var DOM = require('../../util/dom'), Daniel@0: Bounds = require('../../util/Bounds'), Daniel@0: ImageLoader = require('../../util/ImageLoader'), Daniel@0: Canvas = require('../../util/canvas'), Daniel@0: Renderer = require('../Renderer'), Daniel@0: marks = require('./marks'); Daniel@0: Daniel@0: function CanvasRenderer(loadConfig) { Daniel@0: Renderer.call(this); Daniel@0: this._loader = new ImageLoader(loadConfig); Daniel@0: } Daniel@0: Daniel@0: CanvasRenderer.RETINA = true; Daniel@0: Daniel@0: var base = Renderer.prototype; Daniel@0: var prototype = (CanvasRenderer.prototype = Object.create(base)); Daniel@0: prototype.constructor = CanvasRenderer; Daniel@0: Daniel@0: prototype.initialize = function(el, width, height, padding) { Daniel@0: this._canvas = Canvas.instance(width, height); Daniel@0: if (el) { Daniel@0: DOM.clear(el, 0).appendChild(this._canvas); Daniel@0: this._canvas.setAttribute('class', 'marks'); Daniel@0: } Daniel@0: return base.initialize.call(this, el, width, height, padding); Daniel@0: }; Daniel@0: Daniel@0: prototype.resize = function(width, height, padding) { Daniel@0: base.resize.call(this, width, height, padding); Daniel@0: Canvas.resize(this._canvas, this._width, this._height, Daniel@0: this._padding, CanvasRenderer.RETINA); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.canvas = function() { Daniel@0: return this._canvas; Daniel@0: }; Daniel@0: Daniel@0: prototype.context = function() { Daniel@0: return this._canvas ? this._canvas.getContext('2d') : null; Daniel@0: }; Daniel@0: Daniel@0: prototype.pendingImages = function() { Daniel@0: return this._loader.pending(); Daniel@0: }; Daniel@0: Daniel@0: function clipToBounds(g, items) { Daniel@0: if (!items) return null; Daniel@0: Daniel@0: var b = new Bounds(), i, n, item, mark, group; Daniel@0: for (i=0, n=items.length; i=0;) { Daniel@0: group = items[i]; Daniel@0: dx = group.x || 0; Daniel@0: dy = group.y || 0; Daniel@0: Daniel@0: g.save(); Daniel@0: g.translate(dx, dy); Daniel@0: for (j=group.items.length; --j >= 0;) { Daniel@0: subscene = group.items[j]; Daniel@0: if (subscene.interactive === false) continue; Daniel@0: hits = this.pick(subscene, x, y, gx-dx, gy-dy); Daniel@0: if (hits) { Daniel@0: g.restore(); Daniel@0: return hits; Daniel@0: } Daniel@0: } Daniel@0: g.restore(); Daniel@0: } Daniel@0: Daniel@0: return scene.interactive !== false ? pickSelf(g, scene, x, y, gx, gy) : null; Daniel@0: } Daniel@0: Daniel@0: var pickSelf = util.pick(hit); Daniel@0: Daniel@0: module.exports = { Daniel@0: draw: draw, Daniel@0: pick: pick Daniel@0: }; Daniel@0: Daniel@0: },{"./rect":63,"./util":67}],59:[function(require,module,exports){ Daniel@0: var util = require('./util'); Daniel@0: Daniel@0: function draw(g, scene, bounds) { Daniel@0: if (!scene.items || !scene.items.length) return; Daniel@0: Daniel@0: var renderer = this, Daniel@0: items = scene.items, o; Daniel@0: Daniel@0: for (var i=0, len=items.length; i= 0;) { Daniel@0: o = scene.items[i]; b = o.bounds; Daniel@0: // first hit test against bounding box Daniel@0: if ((b && !b.contains(gx, gy)) || !b) continue; Daniel@0: // if in bounding box, perform more careful test Daniel@0: if (test(g, o, x, y, gx, gy)) return o; Daniel@0: } Daniel@0: return null; Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function testPath(path, filled) { Daniel@0: return function(g, o, x, y) { Daniel@0: var item = Array.isArray(o) ? o[0] : o, Daniel@0: fill = (filled == null) ? item.fill : filled, Daniel@0: stroke = item.stroke && g.isPointInStroke, lw, lc; Daniel@0: Daniel@0: if (stroke) { Daniel@0: lw = item.strokeWidth; Daniel@0: lc = item.strokeCap; Daniel@0: g.lineWidth = lw != null ? lw : 1; Daniel@0: g.lineCap = lc != null ? lc : 'butt'; Daniel@0: } Daniel@0: Daniel@0: return path(g, o) ? false : Daniel@0: (fill && g.isPointInPath(x, y)) || Daniel@0: (stroke && g.isPointInStroke(x, y)); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function pickPath(path) { Daniel@0: return pick(testPath(path)); Daniel@0: } Daniel@0: Daniel@0: function fill(g, o, opacity) { Daniel@0: opacity *= (o.fillOpacity==null ? 1 : o.fillOpacity); Daniel@0: if (opacity > 0) { Daniel@0: g.globalAlpha = opacity; Daniel@0: g.fillStyle = color(g, o, o.fill); Daniel@0: return true; Daniel@0: } else { Daniel@0: return false; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function stroke(g, o, opacity) { Daniel@0: var lw = (lw = o.strokeWidth) != null ? lw : 1, lc; Daniel@0: if (lw <= 0) return false; Daniel@0: Daniel@0: opacity *= (o.strokeOpacity==null ? 1 : o.strokeOpacity); Daniel@0: if (opacity > 0) { Daniel@0: g.globalAlpha = opacity; Daniel@0: g.strokeStyle = color(g, o, o.stroke); Daniel@0: g.lineWidth = lw; Daniel@0: g.lineCap = (lc = o.strokeCap) != null ? lc : 'butt'; Daniel@0: g.vgLineDash(o.strokeDash || null); Daniel@0: g.vgLineDashOffset(o.strokeDashOffset || 0); Daniel@0: return true; Daniel@0: } else { Daniel@0: return false; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function color(g, o, value) { Daniel@0: return (value.id) ? Daniel@0: gradient(g, value, o.bounds) : Daniel@0: value; Daniel@0: } Daniel@0: Daniel@0: function gradient(g, p, b) { Daniel@0: var w = b.width(), Daniel@0: h = b.height(), Daniel@0: x1 = b.x1 + p.x1 * w, Daniel@0: y1 = b.y1 + p.y1 * h, Daniel@0: x2 = b.x1 + p.x2 * w, Daniel@0: y2 = b.y1 + p.y2 * h, Daniel@0: grad = g.createLinearGradient(x1, y1, x2, y2), Daniel@0: stop = p.stops, Daniel@0: i, n; Daniel@0: Daniel@0: for (i=0, n=stop.length; i=0;) { Daniel@0: if (h[i].type === type && !handler || h[i].handler === handler) { Daniel@0: svg.removeEventListener(name, h[i].listener); Daniel@0: h.splice(i, 1); Daniel@0: } Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: module.exports = SVGHandler; Daniel@0: Daniel@0: },{"../../util/dom":81,"../Handler":51}],70:[function(require,module,exports){ Daniel@0: var ImageLoader = require('../../util/ImageLoader'), Daniel@0: Renderer = require('../Renderer'), Daniel@0: text = require('../../util/text'), Daniel@0: DOM = require('../../util/dom'), Daniel@0: SVG = require('../../util/svg'), Daniel@0: ns = SVG.metadata.xmlns, Daniel@0: marks = require('./marks'); Daniel@0: Daniel@0: function SVGRenderer(loadConfig) { Daniel@0: Renderer.call(this); Daniel@0: this._loader = new ImageLoader(loadConfig); Daniel@0: this._dirtyID = 0; Daniel@0: } Daniel@0: Daniel@0: var base = Renderer.prototype; Daniel@0: var prototype = (SVGRenderer.prototype = Object.create(base)); Daniel@0: prototype.constructor = SVGRenderer; Daniel@0: Daniel@0: prototype.initialize = function(el, width, height, padding) { Daniel@0: if (el) { Daniel@0: this._svg = DOM.child(el, 0, 'svg', ns, 'marks'); Daniel@0: DOM.clear(el, 1); Daniel@0: // set the svg root group Daniel@0: this._root = DOM.child(this._svg, 0, 'g', ns); Daniel@0: DOM.clear(this._svg, 1); Daniel@0: } Daniel@0: Daniel@0: // create the svg definitions cache Daniel@0: this._defs = { Daniel@0: clip_id: 1, Daniel@0: gradient: {}, Daniel@0: clipping: {} Daniel@0: }; Daniel@0: Daniel@0: // set background color if defined Daniel@0: this.background(this._bgcolor); Daniel@0: Daniel@0: return base.initialize.call(this, el, width, height, padding); Daniel@0: }; Daniel@0: Daniel@0: prototype.background = function(bgcolor) { Daniel@0: if (arguments.length && this._svg) { Daniel@0: this._svg.style.setProperty('background-color', bgcolor); Daniel@0: } Daniel@0: return base.background.apply(this, arguments); Daniel@0: }; Daniel@0: Daniel@0: prototype.resize = function(width, height, padding) { Daniel@0: base.resize.call(this, width, height, padding); Daniel@0: Daniel@0: if (this._svg) { Daniel@0: var w = this._width, Daniel@0: h = this._height, Daniel@0: p = this._padding; Daniel@0: Daniel@0: this._svg.setAttribute('width', w + p.left + p.right); Daniel@0: this._svg.setAttribute('height', h + p.top + p.bottom); Daniel@0: Daniel@0: this._root.setAttribute('transform', 'translate('+p.left+','+p.top+')'); Daniel@0: } Daniel@0: Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.svg = function() { Daniel@0: if (!this._svg) return null; Daniel@0: Daniel@0: var attr = { Daniel@0: 'class': 'marks', Daniel@0: 'width': this._width + this._padding.left + this._padding.right, Daniel@0: 'height': this._height + this._padding.top + this._padding.bottom, Daniel@0: }; Daniel@0: for (var key in SVG.metadata) { Daniel@0: attr[key] = SVG.metadata[key]; Daniel@0: } Daniel@0: Daniel@0: return DOM.openTag('svg', attr) + this._svg.innerHTML + DOM.closeTag('svg'); Daniel@0: }; Daniel@0: Daniel@0: prototype.imageURL = function(url) { Daniel@0: return this._loader.imageURL(url); Daniel@0: }; Daniel@0: Daniel@0: Daniel@0: // -- Render entry point -- Daniel@0: Daniel@0: prototype.render = function(scene, items) { Daniel@0: if (this._dirtyCheck(items)) { Daniel@0: if (this._dirtyAll) this._resetDefs(); Daniel@0: this.draw(this._root, scene, -1); Daniel@0: DOM.clear(this._root, 1); Daniel@0: } Daniel@0: this.updateDefs(); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.draw = function(el, scene, index) { Daniel@0: this.drawMark(el, scene, index, marks[scene.marktype]); Daniel@0: }; Daniel@0: Daniel@0: Daniel@0: // -- Manage SVG definitions ('defs') block -- Daniel@0: Daniel@0: prototype.updateDefs = function() { Daniel@0: var svg = this._svg, Daniel@0: defs = this._defs, Daniel@0: el = defs.el, Daniel@0: index = 0, id; Daniel@0: Daniel@0: for (id in defs.gradient) { Daniel@0: if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns)); Daniel@0: updateGradient(el, defs.gradient[id], index++); Daniel@0: } Daniel@0: Daniel@0: for (id in defs.clipping) { Daniel@0: if (!el) el = (defs.el = DOM.child(svg, 0, 'defs', ns)); Daniel@0: updateClipping(el, defs.clipping[id], index++); Daniel@0: } Daniel@0: Daniel@0: // clean-up Daniel@0: if (el) { Daniel@0: if (index === 0) { Daniel@0: svg.removeChild(el); Daniel@0: defs.el = null; Daniel@0: } else { Daniel@0: DOM.clear(el, index); Daniel@0: } Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: function updateGradient(el, grad, index) { Daniel@0: var i, n, stop; Daniel@0: Daniel@0: el = DOM.child(el, index, 'linearGradient', ns); Daniel@0: el.setAttribute('id', grad.id); Daniel@0: el.setAttribute('x1', grad.x1); Daniel@0: el.setAttribute('x2', grad.x2); Daniel@0: el.setAttribute('y1', grad.y1); Daniel@0: el.setAttribute('y2', grad.y2); Daniel@0: Daniel@0: for (i=0, n=grad.stops.length; i 0) ? openTag('defs') + defs + closeTag('defs') : ''; Daniel@0: }; Daniel@0: Daniel@0: prototype.imageURL = function(url) { Daniel@0: return this._loader.imageURL(url); Daniel@0: }; Daniel@0: Daniel@0: var object; Daniel@0: Daniel@0: function emit(name, value, ns, prefixed) { Daniel@0: object[prefixed || name] = value; Daniel@0: } Daniel@0: Daniel@0: prototype.attributes = function(attr, item) { Daniel@0: object = {}; Daniel@0: attr(emit, item, this); Daniel@0: return object; Daniel@0: }; Daniel@0: Daniel@0: prototype.mark = function(scene) { Daniel@0: var mdef = MARKS[scene.marktype], Daniel@0: tag = mdef.tag, Daniel@0: attr = mdef.attr, Daniel@0: nest = mdef.nest || false, Daniel@0: data = nest ? Daniel@0: (scene.items && scene.items.length ? [scene.items[0]] : []) : Daniel@0: (scene.items || []), Daniel@0: defs = this._defs, Daniel@0: str = '', Daniel@0: style, i, item; Daniel@0: Daniel@0: if (tag !== 'g' && scene.interactive === false) { Daniel@0: style = 'style="pointer-events: none;"'; Daniel@0: } Daniel@0: Daniel@0: // render opening group tag Daniel@0: str += openTag('g', { Daniel@0: 'class': DOM.cssClass(scene) Daniel@0: }, style); Daniel@0: Daniel@0: // render contained elements Daniel@0: for (i=0; i/g, '>'); Daniel@0: } Daniel@0: Daniel@0: module.exports = SVGStringRenderer; Daniel@0: Daniel@0: },{"../../util/ImageLoader":77,"../../util/dom":81,"../../util/svg":83,"../../util/text":84,"../Renderer":52,"./marks":73}],72:[function(require,module,exports){ Daniel@0: module.exports = { Daniel@0: Handler: require('./SVGHandler'), Daniel@0: Renderer: require('./SVGRenderer'), Daniel@0: string: { Daniel@0: Renderer : require('./SVGStringRenderer') Daniel@0: } Daniel@0: }; Daniel@0: },{"./SVGHandler":69,"./SVGRenderer":70,"./SVGStringRenderer":71}],73:[function(require,module,exports){ Daniel@0: var text = require('../../util/text'), Daniel@0: SVG = require('../../util/svg'), Daniel@0: textAlign = SVG.textAlign, Daniel@0: path = SVG.path; Daniel@0: Daniel@0: function translateItem(o) { Daniel@0: return translate(o.x || 0, o.y || 0); Daniel@0: } Daniel@0: Daniel@0: function translate(x, y) { Daniel@0: return 'translate(' + x + ',' + y + ')'; Daniel@0: } Daniel@0: Daniel@0: module.exports = { Daniel@0: arc: { Daniel@0: tag: 'path', Daniel@0: type: 'arc', Daniel@0: attr: function(emit, o) { Daniel@0: emit('transform', translateItem(o)); Daniel@0: emit('d', path.arc(o)); Daniel@0: } Daniel@0: }, Daniel@0: area: { Daniel@0: tag: 'path', Daniel@0: type: 'area', Daniel@0: nest: true, Daniel@0: attr: function(emit, o) { Daniel@0: var items = o.mark.items; Daniel@0: if (items.length) emit('d', path.area(items)); Daniel@0: } Daniel@0: }, Daniel@0: group: { Daniel@0: tag: 'g', Daniel@0: type: 'group', Daniel@0: attr: function(emit, o, renderer) { Daniel@0: var id = null, defs, c; Daniel@0: emit('transform', translateItem(o)); Daniel@0: if (o.clip) { Daniel@0: defs = renderer._defs; Daniel@0: id = o.clip_id || (o.clip_id = 'clip' + defs.clip_id++); Daniel@0: c = defs.clipping[id] || (defs.clipping[id] = {id: id}); Daniel@0: c.width = o.width || 0; Daniel@0: c.height = o.height || 0; Daniel@0: } Daniel@0: emit('clip-path', id ? ('url(#' + id + ')') : null); Daniel@0: }, Daniel@0: background: function(emit, o) { Daniel@0: emit('class', 'background'); Daniel@0: emit('width', o.width || 0); Daniel@0: emit('height', o.height || 0); Daniel@0: } Daniel@0: }, Daniel@0: image: { Daniel@0: tag: 'image', Daniel@0: type: 'image', Daniel@0: attr: function(emit, o, renderer) { Daniel@0: var x = o.x || 0, Daniel@0: y = o.y || 0, Daniel@0: w = o.width || 0, Daniel@0: h = o.height || 0, Daniel@0: url = renderer.imageURL(o.url); Daniel@0: Daniel@0: x = x - (o.align === 'center' ? w/2 : o.align === 'right' ? w : 0); Daniel@0: y = y - (o.baseline === 'middle' ? h/2 : o.baseline === 'bottom' ? h : 0); Daniel@0: Daniel@0: emit('href', url, 'http://www.w3.org/1999/xlink', 'xlink:href'); Daniel@0: emit('transform', translate(x, y)); Daniel@0: emit('width', w); Daniel@0: emit('height', h); Daniel@0: } Daniel@0: }, Daniel@0: line: { Daniel@0: tag: 'path', Daniel@0: type: 'line', Daniel@0: nest: true, Daniel@0: attr: function(emit, o) { Daniel@0: var items = o.mark.items; Daniel@0: if (items.length) emit('d', path.line(items)); Daniel@0: } Daniel@0: }, Daniel@0: path: { Daniel@0: tag: 'path', Daniel@0: type: 'path', Daniel@0: attr: function(emit, o) { Daniel@0: emit('transform', translateItem(o)); Daniel@0: emit('d', o.path); Daniel@0: } Daniel@0: }, Daniel@0: rect: { Daniel@0: tag: 'rect', Daniel@0: type: 'rect', Daniel@0: nest: false, Daniel@0: attr: function(emit, o) { Daniel@0: emit('transform', translateItem(o)); Daniel@0: emit('width', o.width || 0); Daniel@0: emit('height', o.height || 0); Daniel@0: } Daniel@0: }, Daniel@0: rule: { Daniel@0: tag: 'line', Daniel@0: type: 'rule', Daniel@0: attr: function(emit, o) { Daniel@0: emit('transform', translateItem(o)); Daniel@0: emit('x2', o.x2 != null ? o.x2 - (o.x||0) : 0); Daniel@0: emit('y2', o.y2 != null ? o.y2 - (o.y||0) : 0); Daniel@0: } Daniel@0: }, Daniel@0: symbol: { Daniel@0: tag: 'path', Daniel@0: type: 'symbol', Daniel@0: attr: function(emit, o) { Daniel@0: emit('transform', translateItem(o)); Daniel@0: emit('d', path.symbol(o)); Daniel@0: } Daniel@0: }, Daniel@0: text: { Daniel@0: tag: 'text', Daniel@0: type: 'text', Daniel@0: nest: false, Daniel@0: attr: function(emit, o) { Daniel@0: var dx = (o.dx || 0), Daniel@0: dy = (o.dy || 0) + text.offset(o), Daniel@0: x = (o.x || 0), Daniel@0: y = (o.y || 0), Daniel@0: a = o.angle || 0, Daniel@0: r = o.radius || 0, t; Daniel@0: Daniel@0: if (r) { Daniel@0: t = (o.theta || 0) - Math.PI/2; Daniel@0: x += r * Math.cos(t); Daniel@0: y += r * Math.sin(t); Daniel@0: } Daniel@0: Daniel@0: emit('text-anchor', textAlign[o.align] || 'start'); Daniel@0: Daniel@0: if (a) { Daniel@0: t = translate(x, y) + ' rotate('+a+')'; Daniel@0: if (dx || dy) t += ' ' + translate(dx, dy); Daniel@0: } else { Daniel@0: t = translate(x+dx, y+dy); Daniel@0: } Daniel@0: emit('transform', t); Daniel@0: } Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: },{"../../util/svg":83,"../../util/text":84}],74:[function(require,module,exports){ Daniel@0: function Bounds(b) { Daniel@0: this.clear(); Daniel@0: if (b) this.union(b); Daniel@0: } Daniel@0: Daniel@0: var prototype = Bounds.prototype; Daniel@0: Daniel@0: prototype.clone = function() { Daniel@0: return new Bounds(this); Daniel@0: }; Daniel@0: Daniel@0: prototype.clear = function() { Daniel@0: this.x1 = +Number.MAX_VALUE; Daniel@0: this.y1 = +Number.MAX_VALUE; Daniel@0: this.x2 = -Number.MAX_VALUE; Daniel@0: this.y2 = -Number.MAX_VALUE; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.set = function(x1, y1, x2, y2) { Daniel@0: this.x1 = x1; Daniel@0: this.y1 = y1; Daniel@0: this.x2 = x2; Daniel@0: this.y2 = y2; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.add = function(x, y) { Daniel@0: if (x < this.x1) this.x1 = x; Daniel@0: if (y < this.y1) this.y1 = y; Daniel@0: if (x > this.x2) this.x2 = x; Daniel@0: if (y > this.y2) this.y2 = y; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.expand = function(d) { Daniel@0: this.x1 -= d; Daniel@0: this.y1 -= d; Daniel@0: this.x2 += d; Daniel@0: this.y2 += d; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.round = function() { Daniel@0: this.x1 = Math.floor(this.x1); Daniel@0: this.y1 = Math.floor(this.y1); Daniel@0: this.x2 = Math.ceil(this.x2); Daniel@0: this.y2 = Math.ceil(this.y2); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.translate = function(dx, dy) { Daniel@0: this.x1 += dx; Daniel@0: this.x2 += dx; Daniel@0: this.y1 += dy; Daniel@0: this.y2 += dy; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.rotate = function(angle, x, y) { Daniel@0: var cos = Math.cos(angle), Daniel@0: sin = Math.sin(angle), Daniel@0: cx = x - x*cos + y*sin, Daniel@0: cy = y - x*sin - y*cos, Daniel@0: x1 = this.x1, x2 = this.x2, Daniel@0: y1 = this.y1, y2 = this.y2; Daniel@0: Daniel@0: return this.clear() Daniel@0: .add(cos*x1 - sin*y1 + cx, sin*x1 + cos*y1 + cy) Daniel@0: .add(cos*x1 - sin*y2 + cx, sin*x1 + cos*y2 + cy) Daniel@0: .add(cos*x2 - sin*y1 + cx, sin*x2 + cos*y1 + cy) Daniel@0: .add(cos*x2 - sin*y2 + cx, sin*x2 + cos*y2 + cy); Daniel@0: }; Daniel@0: Daniel@0: prototype.union = function(b) { Daniel@0: if (b.x1 < this.x1) this.x1 = b.x1; Daniel@0: if (b.y1 < this.y1) this.y1 = b.y1; Daniel@0: if (b.x2 > this.x2) this.x2 = b.x2; Daniel@0: if (b.y2 > this.y2) this.y2 = b.y2; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.encloses = function(b) { Daniel@0: return b && ( Daniel@0: this.x1 <= b.x1 && Daniel@0: this.x2 >= b.x2 && Daniel@0: this.y1 <= b.y1 && Daniel@0: this.y2 >= b.y2 Daniel@0: ); Daniel@0: }; Daniel@0: Daniel@0: prototype.intersects = function(b) { Daniel@0: return b && !( Daniel@0: this.x2 < b.x1 || Daniel@0: this.x1 > b.x2 || Daniel@0: this.y2 < b.y1 || Daniel@0: this.y1 > b.y2 Daniel@0: ); Daniel@0: }; Daniel@0: Daniel@0: prototype.contains = function(x, y) { Daniel@0: return !( Daniel@0: x < this.x1 || Daniel@0: x > this.x2 || Daniel@0: y < this.y1 || Daniel@0: y > this.y2 Daniel@0: ); Daniel@0: }; Daniel@0: Daniel@0: prototype.width = function() { Daniel@0: return this.x2 - this.x1; Daniel@0: }; Daniel@0: Daniel@0: prototype.height = function() { Daniel@0: return this.y2 - this.y1; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Bounds; Daniel@0: Daniel@0: },{}],75:[function(require,module,exports){ Daniel@0: module.exports = function(b) { Daniel@0: function noop() { } Daniel@0: function add(x,y) { b.add(x, y); } Daniel@0: Daniel@0: return { Daniel@0: bounds: function(_) { Daniel@0: if (!arguments.length) return b; Daniel@0: return (b = _, this); Daniel@0: }, Daniel@0: beginPath: noop, Daniel@0: closePath: noop, Daniel@0: moveTo: add, Daniel@0: lineTo: add, Daniel@0: quadraticCurveTo: function(x1, y1, x2, y2) { Daniel@0: b.add(x1, y1); Daniel@0: b.add(x2, y2); Daniel@0: }, Daniel@0: bezierCurveTo: function(x1, y1, x2, y2, x3, y3) { Daniel@0: b.add(x1, y1); Daniel@0: b.add(x2, y2); Daniel@0: b.add(x3, y3); Daniel@0: } Daniel@0: }; Daniel@0: }; Daniel@0: Daniel@0: },{}],76:[function(require,module,exports){ Daniel@0: var gradient_id = 0; Daniel@0: Daniel@0: function Gradient(type) { Daniel@0: this.id = 'gradient_' + (gradient_id++); Daniel@0: this.type = type || 'linear'; Daniel@0: this.stops = []; Daniel@0: this.x1 = 0; Daniel@0: this.x2 = 1; Daniel@0: this.y1 = 0; Daniel@0: this.y2 = 0; Daniel@0: } Daniel@0: Daniel@0: var prototype = Gradient.prototype; Daniel@0: Daniel@0: prototype.stop = function(offset, color) { Daniel@0: this.stops.push({ Daniel@0: offset: offset, Daniel@0: color: color Daniel@0: }); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Gradient; Daniel@0: },{}],77:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var load = require('datalib/src/import/load'); Daniel@0: Daniel@0: function ImageLoader(loadConfig) { Daniel@0: this._pending = 0; Daniel@0: this._config = loadConfig || ImageLoader.Config; Daniel@0: } Daniel@0: Daniel@0: // Overridable global default load configuration Daniel@0: ImageLoader.Config = null; Daniel@0: Daniel@0: var prototype = ImageLoader.prototype; Daniel@0: Daniel@0: prototype.pending = function() { Daniel@0: return this._pending; Daniel@0: }; Daniel@0: Daniel@0: prototype.params = function(uri) { Daniel@0: var p = {url: uri}, k; Daniel@0: for (k in this._config) { p[k] = this._config[k]; } Daniel@0: return p; Daniel@0: }; Daniel@0: Daniel@0: prototype.imageURL = function(uri) { Daniel@0: return load.sanitizeUrl(this.params(uri)); Daniel@0: }; Daniel@0: Daniel@0: function browser(uri, callback) { Daniel@0: var url = load.sanitizeUrl(this.params(uri)); Daniel@0: if (!url) { // error Daniel@0: if (callback) callback(uri, null); Daniel@0: return null; Daniel@0: } Daniel@0: Daniel@0: var loader = this, Daniel@0: image = new Image(); Daniel@0: Daniel@0: loader._pending += 1; Daniel@0: Daniel@0: image.onload = function() { Daniel@0: loader._pending -= 1; Daniel@0: image.loaded = true; Daniel@0: if (callback) callback(null, image); Daniel@0: }; Daniel@0: image.src = url; Daniel@0: Daniel@0: return image; Daniel@0: } Daniel@0: Daniel@0: function server(uri, callback) { Daniel@0: var loader = this, Daniel@0: image = new ((typeof window !== "undefined" ? window['canvas'] : typeof global !== "undefined" ? global['canvas'] : null).Image)(); Daniel@0: Daniel@0: loader._pending += 1; Daniel@0: Daniel@0: load(this.params(uri), function(err, data) { Daniel@0: loader._pending -= 1; Daniel@0: if (err) { Daniel@0: if (callback) callback(err, null); Daniel@0: return null; Daniel@0: } Daniel@0: image.src = data; Daniel@0: image.loaded = true; Daniel@0: if (callback) callback(null, image); Daniel@0: }); Daniel@0: Daniel@0: return image; Daniel@0: } Daniel@0: Daniel@0: prototype.loadImage = function(uri, callback) { Daniel@0: return load.useXHR ? Daniel@0: browser.call(this, uri, callback) : Daniel@0: server.call(this, uri, callback); Daniel@0: }; Daniel@0: Daniel@0: module.exports = ImageLoader; Daniel@0: Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"datalib/src/import/load":20}],78:[function(require,module,exports){ Daniel@0: function Item(mark) { Daniel@0: this.mark = mark; Daniel@0: } Daniel@0: Daniel@0: var prototype = Item.prototype; Daniel@0: Daniel@0: prototype.hasPropertySet = function(name) { Daniel@0: var props = this.mark.def.properties; Daniel@0: return props && props[name] != null; Daniel@0: }; Daniel@0: Daniel@0: prototype.cousin = function(offset, index) { Daniel@0: if (offset === 0) return this; Daniel@0: offset = offset || -1; Daniel@0: var mark = this.mark, Daniel@0: group = mark.group, Daniel@0: iidx = index==null ? mark.items.indexOf(this) : index, Daniel@0: midx = group.items.indexOf(mark) + offset; Daniel@0: return group.items[midx].items[iidx]; Daniel@0: }; Daniel@0: Daniel@0: prototype.sibling = function(offset) { Daniel@0: if (offset === 0) return this; Daniel@0: offset = offset || -1; Daniel@0: var mark = this.mark, Daniel@0: iidx = mark.items.indexOf(this) + offset; Daniel@0: return mark.items[iidx]; Daniel@0: }; Daniel@0: Daniel@0: prototype.remove = function() { Daniel@0: var item = this, Daniel@0: list = item.mark.items, Daniel@0: i = list.indexOf(item); Daniel@0: if (i >= 0) { Daniel@0: if (i===list.length-1) { Daniel@0: list.pop(); Daniel@0: } else { Daniel@0: list.splice(i, 1); Daniel@0: } Daniel@0: } Daniel@0: return item; Daniel@0: }; Daniel@0: Daniel@0: prototype.touch = function() { Daniel@0: if (this.pathCache) this.pathCache = null; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Item; Daniel@0: },{}],79:[function(require,module,exports){ Daniel@0: var BoundsContext = require('./BoundsContext'), Daniel@0: Bounds = require('./Bounds'), Daniel@0: canvas = require('./canvas'), Daniel@0: svg = require('./svg'), Daniel@0: text = require('./text'), Daniel@0: paths = require('../path'), Daniel@0: parse = paths.parse, Daniel@0: drawPath = paths.render, Daniel@0: areaPath = svg.path.area, Daniel@0: linePath = svg.path.line, Daniel@0: halfpi = Math.PI / 2, Daniel@0: sqrt3 = Math.sqrt(3), Daniel@0: tan30 = Math.tan(30 * Math.PI / 180), Daniel@0: g2D = null, Daniel@0: bc = BoundsContext(); Daniel@0: Daniel@0: function context() { Daniel@0: return g2D || (g2D = canvas.instance(1,1).getContext('2d')); Daniel@0: } Daniel@0: Daniel@0: function strokeBounds(o, bounds) { Daniel@0: if (o.stroke && o.opacity !== 0 && o.stokeOpacity !== 0) { Daniel@0: bounds.expand(o.strokeWidth != null ? o.strokeWidth : 1); Daniel@0: } Daniel@0: return bounds; Daniel@0: } Daniel@0: Daniel@0: function pathBounds(o, path, bounds, x, y) { Daniel@0: if (path == null) { Daniel@0: bounds.set(0, 0, 0, 0); Daniel@0: } else { Daniel@0: drawPath(bc.bounds(bounds), path, x, y); Daniel@0: strokeBounds(o, bounds); Daniel@0: } Daniel@0: return bounds; Daniel@0: } Daniel@0: Daniel@0: function path(o, bounds) { Daniel@0: var p = o.path ? o.pathCache || (o.pathCache = parse(o.path)) : null; Daniel@0: return pathBounds(o, p, bounds, o.x, o.y); Daniel@0: } Daniel@0: Daniel@0: function area(mark, bounds) { Daniel@0: if (mark.items.length === 0) return bounds; Daniel@0: var items = mark.items, Daniel@0: item = items[0], Daniel@0: p = item.pathCache || (item.pathCache = parse(areaPath(items))); Daniel@0: return pathBounds(item, p, bounds); Daniel@0: } Daniel@0: Daniel@0: function line(mark, bounds) { Daniel@0: if (mark.items.length === 0) return bounds; Daniel@0: var items = mark.items, Daniel@0: item = items[0], Daniel@0: p = item.pathCache || (item.pathCache = parse(linePath(items))); Daniel@0: return pathBounds(item, p, bounds); Daniel@0: } Daniel@0: Daniel@0: function rect(o, bounds) { Daniel@0: var x, y; Daniel@0: return strokeBounds(o, bounds.set( Daniel@0: x = o.x || 0, Daniel@0: y = o.y || 0, Daniel@0: (x + o.width) || 0, Daniel@0: (y + o.height) || 0 Daniel@0: )); Daniel@0: } Daniel@0: Daniel@0: function image(o, bounds) { Daniel@0: var x = o.x || 0, Daniel@0: y = o.y || 0, Daniel@0: w = o.width || 0, Daniel@0: h = o.height || 0; Daniel@0: x = x - (o.align === 'center' ? w/2 : (o.align === 'right' ? w : 0)); Daniel@0: y = y - (o.baseline === 'middle' ? h/2 : (o.baseline === 'bottom' ? h : 0)); Daniel@0: return bounds.set(x, y, x+w, y+h); Daniel@0: } Daniel@0: Daniel@0: function rule(o, bounds) { Daniel@0: var x1, y1; Daniel@0: return strokeBounds(o, bounds.set( Daniel@0: x1 = o.x || 0, Daniel@0: y1 = o.y || 0, Daniel@0: o.x2 != null ? o.x2 : x1, Daniel@0: o.y2 != null ? o.y2 : y1 Daniel@0: )); Daniel@0: } Daniel@0: Daniel@0: function arc(o, bounds) { Daniel@0: var cx = o.x || 0, Daniel@0: cy = o.y || 0, Daniel@0: ir = o.innerRadius || 0, Daniel@0: or = o.outerRadius || 0, Daniel@0: sa = (o.startAngle || 0) - halfpi, Daniel@0: ea = (o.endAngle || 0) - halfpi, Daniel@0: xmin = Infinity, xmax = -Infinity, Daniel@0: ymin = Infinity, ymax = -Infinity, Daniel@0: a, i, n, x, y, ix, iy, ox, oy; Daniel@0: Daniel@0: var angles = [sa, ea], Daniel@0: s = sa - (sa % halfpi); Daniel@0: for (i=0; i<4 && s index) { Daniel@0: el.removeChild(el.childNodes[--curr]); Daniel@0: } Daniel@0: return el; Daniel@0: }, Daniel@0: remove: remove, Daniel@0: // generate css class name for mark Daniel@0: cssClass: function(mark) { Daniel@0: return 'mark-' + mark.marktype + (mark.name ? ' '+mark.name : ''); Daniel@0: }, Daniel@0: // generate string for an opening xml tag Daniel@0: // tag: the name of the xml tag Daniel@0: // attr: hash of attribute name-value pairs to include Daniel@0: // raw: additional raw string to include in tag markup Daniel@0: openTag: function(tag, attr, raw) { Daniel@0: var s = '<' + tag, key, val; Daniel@0: if (attr) { Daniel@0: for (key in attr) { Daniel@0: val = attr[key]; Daniel@0: if (val != null) { Daniel@0: s += ' ' + key + '="' + val + '"'; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: if (raw) s += ' ' + raw; Daniel@0: return s + '>'; Daniel@0: }, Daniel@0: // generate string for closing xml tag Daniel@0: // tag: the name of the xml tag Daniel@0: closeTag: function(tag) { Daniel@0: return ''; Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: },{}],82:[function(require,module,exports){ Daniel@0: var bound = require('../util/bound'); Daniel@0: Daniel@0: var sets = [ Daniel@0: 'items', Daniel@0: 'axisItems', Daniel@0: 'legendItems' Daniel@0: ]; Daniel@0: Daniel@0: var keys = [ Daniel@0: 'marktype', 'name', 'interactive', 'clip', Daniel@0: 'items', 'axisItems', 'legendItems', 'layer', Daniel@0: 'x', 'y', 'width', 'height', 'align', 'baseline', // layout Daniel@0: 'fill', 'fillOpacity', 'opacity', // fill Daniel@0: 'stroke', 'strokeOpacity', 'strokeWidth', 'strokeCap', // stroke Daniel@0: 'strokeDash', 'strokeDashOffset', // stroke dash Daniel@0: 'startAngle', 'endAngle', 'innerRadius', 'outerRadius', // arc Daniel@0: 'interpolate', 'tension', 'orient', // area, line Daniel@0: 'url', // image Daniel@0: 'path', // path Daniel@0: 'x2', 'y2', // rule Daniel@0: 'size', 'shape', // symbol Daniel@0: 'text', 'angle', 'theta', 'radius', 'dx', 'dy', // text Daniel@0: 'font', 'fontSize', 'fontWeight', 'fontStyle', 'fontVariant' // font Daniel@0: ]; Daniel@0: Daniel@0: function toJSON(scene, indent) { Daniel@0: return JSON.stringify(scene, keys, indent); Daniel@0: } Daniel@0: Daniel@0: function fromJSON(json) { Daniel@0: var scene = (typeof json === 'string' ? JSON.parse(json) : json); Daniel@0: return initialize(scene); Daniel@0: } Daniel@0: Daniel@0: function initialize(scene) { Daniel@0: var type = scene.marktype, Daniel@0: i, n, s, m, items; Daniel@0: Daniel@0: for (s=0, m=sets.length; s 0) { wait(); } else { callback(this.canvas()); } Daniel@0: }; Daniel@0: Daniel@0: prototype.svg = function() { Daniel@0: return (this._type === 'svg') ? this._renderer.svg() : null; Daniel@0: }; Daniel@0: Daniel@0: prototype.initialize = function() { Daniel@0: var w = this._width, Daniel@0: h = this._height, Daniel@0: bg = this._bgcolor, Daniel@0: pad = this._padding, Daniel@0: config = this.model().config(); Daniel@0: Daniel@0: if (this._viewport) { Daniel@0: w = this._viewport[0] - (pad ? pad.left + pad.right : 0); Daniel@0: h = this._viewport[1] - (pad ? pad.top + pad.bottom : 0); Daniel@0: } Daniel@0: Daniel@0: this._renderer = (this._renderer || new this._io.Renderer(config.load)) Daniel@0: .initialize(null, w, h, pad) Daniel@0: .background(bg); Daniel@0: Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: module.exports = HeadlessView; Daniel@0: },{"./View":87,"vega-scenegraph":46}],86:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: df = require('vega-dataflow'), Daniel@0: ChangeSet = df.ChangeSet, Daniel@0: Base = df.Graph.prototype, Daniel@0: Node = df.Node, // jshint ignore:line Daniel@0: GroupBuilder = require('../scene/GroupBuilder'), Daniel@0: visit = require('../scene/visit'), Daniel@0: config = require('./config'); Daniel@0: Daniel@0: function Model(cfg) { Daniel@0: this._defs = {}; Daniel@0: this._predicates = {}; Daniel@0: this._scene = null; Daniel@0: Daniel@0: this._node = null; Daniel@0: this._builder = null; // Top-level scenegraph builder Daniel@0: Daniel@0: this._reset = {axes: false, legends: false}; Daniel@0: Daniel@0: this.config(cfg); Daniel@0: Base.init.call(this); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Model.prototype = Object.create(Base)); Daniel@0: prototype.constructor = Model; Daniel@0: Daniel@0: prototype.defs = function(defs) { Daniel@0: if (!arguments.length) return this._defs; Daniel@0: this._defs = defs; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.config = function(cfg) { Daniel@0: if (!arguments.length) return this._config; Daniel@0: this._config = Object.create(config); Daniel@0: for (var name in cfg) { Daniel@0: var x = cfg[name], y = this._config[name]; Daniel@0: if (dl.isObject(x) && dl.isObject(y)) { Daniel@0: dl.extend(y, x); Daniel@0: } else { Daniel@0: this._config[name] = x; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.width = function(width) { Daniel@0: if (this._defs) this._defs.width = width; Daniel@0: if (this._defs && this._defs.marks) this._defs.marks.width = width; Daniel@0: if (this._scene) { Daniel@0: this._scene.items[0].width = width; Daniel@0: this._scene.items[0]._dirty = true; Daniel@0: } Daniel@0: this._reset.axes = true; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.height = function(height) { Daniel@0: if (this._defs) this._defs.height = height; Daniel@0: if (this._defs && this._defs.marks) this._defs.marks.height = height; Daniel@0: if (this._scene) { Daniel@0: this._scene.items[0].height = height; Daniel@0: this._scene.items[0]._dirty = true; Daniel@0: } Daniel@0: this._reset.axes = true; Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.node = function() { Daniel@0: return this._node || (this._node = new Node(this)); Daniel@0: }; Daniel@0: Daniel@0: prototype.data = function() { Daniel@0: var data = Base.data.apply(this, arguments); Daniel@0: if (arguments.length > 1) { // new Datasource Daniel@0: this.node().addListener(data.pipeline()[0]); Daniel@0: } Daniel@0: return data; Daniel@0: }; Daniel@0: Daniel@0: function predicates(name) { Daniel@0: var m = this, pred = {}; Daniel@0: if (!dl.isArray(name)) return this._predicates[name]; Daniel@0: name.forEach(function(n) { pred[n] = m._predicates[n]; }); Daniel@0: return pred; Daniel@0: } Daniel@0: Daniel@0: prototype.predicate = function(name, predicate) { Daniel@0: if (arguments.length === 1) return predicates.call(this, name); Daniel@0: return (this._predicates[name] = predicate); Daniel@0: }; Daniel@0: Daniel@0: prototype.predicates = function() { return this._predicates; }; Daniel@0: Daniel@0: prototype.scene = function(renderer) { Daniel@0: if (!arguments.length) return this._scene; Daniel@0: if (this._builder) this.node().removeListener(this._builder.disconnect()); Daniel@0: this._builder = new GroupBuilder(this, this._defs.marks, this._scene={}); Daniel@0: this.node().addListener(this._builder.connect()); Daniel@0: var p = this._builder.pipeline(); Daniel@0: p[p.length-1].addListener(renderer); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.reset = function() { Daniel@0: if (this._scene && this._reset.axes) { Daniel@0: visit(this._scene, function(item) { Daniel@0: if (item.axes) item.axes.forEach(function(axis) { axis.reset(); }); Daniel@0: }); Daniel@0: this._reset.axes = false; Daniel@0: } Daniel@0: if (this._scene && this._reset.legends) { Daniel@0: visit(this._scene, function(item) { Daniel@0: if (item.legends) item.legends.forEach(function(l) { l.reset(); }); Daniel@0: }); Daniel@0: this._reset.legends = false; Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.addListener = function(l) { Daniel@0: this.node().addListener(l); Daniel@0: }; Daniel@0: Daniel@0: prototype.removeListener = function(l) { Daniel@0: this.node().removeListener(l); Daniel@0: }; Daniel@0: Daniel@0: prototype.fire = function(cs) { Daniel@0: if (!cs) cs = ChangeSet.create(); Daniel@0: this.propagate(cs, this.node()); Daniel@0: }; Daniel@0: Daniel@0: module.exports = Model; Daniel@0: },{"../scene/GroupBuilder":110,"../scene/visit":115,"./config":88,"datalib":24,"vega-dataflow":39}],87:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: dl = require('datalib'), Daniel@0: df = require('vega-dataflow'), Daniel@0: sg = require('vega-scenegraph').render, Daniel@0: log = require('vega-logging'), Daniel@0: Deps = df.Dependencies, Daniel@0: parseStreams = require('../parse/streams'), Daniel@0: Encoder = require('../scene/Encoder'), Daniel@0: Transition = require('../scene/Transition'); Daniel@0: Daniel@0: function View(el, width, height) { Daniel@0: this._el = null; Daniel@0: this._model = null; Daniel@0: this._width = this.__width = width || 500; Daniel@0: this._height = this.__height = height || 300; Daniel@0: this._bgcolor = null; Daniel@0: this._autopad = 1; Daniel@0: this._padding = {top:0, left:0, bottom:0, right:0}; Daniel@0: this._viewport = null; Daniel@0: this._renderer = null; Daniel@0: this._handler = null; Daniel@0: this._streamer = null; // Targeted update for streaming changes Daniel@0: this._changeset = null; Daniel@0: this._repaint = true; // Full re-render on every re-init Daniel@0: this._renderers = sg; Daniel@0: this._io = null; Daniel@0: this._api = {}; // Stash streaming data API sandboxes. Daniel@0: } Daniel@0: Daniel@0: var prototype = View.prototype; Daniel@0: Daniel@0: prototype.model = function(model) { Daniel@0: if (!arguments.length) return this._model; Daniel@0: if (this._model !== model) { Daniel@0: this._model = model; Daniel@0: this._streamer = new df.Node(model); Daniel@0: this._streamer._rank = -1; // HACK: To reduce re-ranking churn. Daniel@0: this._changeset = df.ChangeSet.create(); Daniel@0: if (this._handler) this._handler.model(model); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: // Sandboxed streaming data API Daniel@0: function streaming(src) { Daniel@0: var view = this, Daniel@0: ds = this._model.data(src), Daniel@0: name = ds.name(), Daniel@0: listener = ds.pipeline()[0], Daniel@0: streamer = this._streamer, Daniel@0: api = {}; Daniel@0: Daniel@0: // If we have it stashed, don't create a new closure. Daniel@0: if (this._api[src]) return this._api[src]; Daniel@0: Daniel@0: api.insert = function(vals) { Daniel@0: ds.insert(dl.duplicate(vals)); // Don't pollute the environment Daniel@0: streamer.addListener(listener); Daniel@0: view._changeset.data[name] = 1; Daniel@0: return api; Daniel@0: }; Daniel@0: Daniel@0: api.update = function() { Daniel@0: streamer.addListener(listener); Daniel@0: view._changeset.data[name] = 1; Daniel@0: return (ds.update.apply(ds, arguments), api); Daniel@0: }; Daniel@0: Daniel@0: api.remove = function() { Daniel@0: streamer.addListener(listener); Daniel@0: view._changeset.data[name] = 1; Daniel@0: return (ds.remove.apply(ds, arguments), api); Daniel@0: }; Daniel@0: Daniel@0: api.values = function() { return ds.values(); }; Daniel@0: Daniel@0: return (this._api[src] = api); Daniel@0: } Daniel@0: Daniel@0: prototype.data = function(data) { Daniel@0: var v = this; Daniel@0: if (!arguments.length) return v._model.values(); Daniel@0: else if (dl.isString(data)) return streaming.call(v, data); Daniel@0: else if (dl.isObject(data)) { Daniel@0: dl.keys(data).forEach(function(k) { Daniel@0: var api = streaming.call(v, k); Daniel@0: data[k](api); Daniel@0: }); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.signal = function(name, value) { Daniel@0: var m = this._model, Daniel@0: cs = this._changeset, Daniel@0: streamer = this._streamer, Daniel@0: setter = name; Daniel@0: Daniel@0: if (!arguments.length) { Daniel@0: return m.values(Deps.SIGNALS); Daniel@0: } else if (arguments.length == 1 && dl.isString(name)) { Daniel@0: return m.values(Deps.SIGNALS, name); Daniel@0: } Daniel@0: Daniel@0: if (arguments.length == 2) { Daniel@0: setter = {}; Daniel@0: setter[name] = value; Daniel@0: } Daniel@0: Daniel@0: dl.keys(setter).forEach(function(k) { Daniel@0: streamer.addListener(m.signal(k).value(setter[k])); Daniel@0: cs.signals[k] = 1; Daniel@0: cs.reflow = true; Daniel@0: }); Daniel@0: Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.width = function(width) { Daniel@0: if (!arguments.length) return this.__width; Daniel@0: if (this.__width !== width) { Daniel@0: this._width = this.__width = width; Daniel@0: this.model().width(width); Daniel@0: this.initialize(); Daniel@0: if (this._strict) this._autopad = 1; Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.height = function(height) { Daniel@0: if (!arguments.length) return this.__height; Daniel@0: if (this.__height !== height) { Daniel@0: this._height = this.__height = height; Daniel@0: this.model().height(height); Daniel@0: this.initialize(); Daniel@0: if (this._strict) this._autopad = 1; Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.background = function(bgcolor) { Daniel@0: if (!arguments.length) return this._bgcolor; Daniel@0: if (this._bgcolor !== bgcolor) { Daniel@0: this._bgcolor = bgcolor; Daniel@0: this.initialize(); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.padding = function(pad) { Daniel@0: if (!arguments.length) return this._padding; Daniel@0: if (this._padding !== pad) { Daniel@0: if (dl.isString(pad)) { Daniel@0: this._autopad = 1; Daniel@0: this._padding = {top:0, left:0, bottom:0, right:0}; Daniel@0: this._strict = (pad === 'strict'); Daniel@0: } else { Daniel@0: this._autopad = 0; Daniel@0: this._padding = pad; Daniel@0: this._strict = false; Daniel@0: } Daniel@0: if (this._renderer) this._renderer.resize(this._width, this._height, pad); Daniel@0: if (this._handler) this._handler.padding(pad); Daniel@0: } Daniel@0: return (this._repaint = true, this); Daniel@0: }; Daniel@0: Daniel@0: prototype.autopad = function(opt) { Daniel@0: if (this._autopad < 1) return this; Daniel@0: else this._autopad = 0; Daniel@0: Daniel@0: var b = this.model().scene().bounds, Daniel@0: pad = this._padding, Daniel@0: config = this.model().config(), Daniel@0: inset = config.autopadInset, Daniel@0: l = b.x1 < 0 ? Math.ceil(-b.x1) + inset : 0, Daniel@0: t = b.y1 < 0 ? Math.ceil(-b.y1) + inset : 0, Daniel@0: r = b.x2 > this._width ? Math.ceil(+b.x2 - this._width) + inset : 0; Daniel@0: b = b.y2 > this._height ? Math.ceil(+b.y2 - this._height) + inset : 0; Daniel@0: pad = {left:l, top:t, right:r, bottom:b}; Daniel@0: Daniel@0: if (this._strict) { Daniel@0: this._autopad = 0; Daniel@0: this._padding = pad; Daniel@0: this._width = Math.max(0, this.__width - (l+r)); Daniel@0: this._height = Math.max(0, this.__height - (t+b)); Daniel@0: Daniel@0: this._model.width(this._width) Daniel@0: .height(this._height).reset(); Daniel@0: Daniel@0: this.initialize() Daniel@0: .update({props:'enter'}).update({props:'update'}); Daniel@0: } else { Daniel@0: this.padding(pad).update(opt); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.viewport = function(size) { Daniel@0: if (!arguments.length) return this._viewport; Daniel@0: if (this._viewport !== size) { Daniel@0: this._viewport = size; Daniel@0: this.initialize(); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.renderer = function(type) { Daniel@0: if (!arguments.length) return this._renderer; Daniel@0: if (this._renderers[type]) type = this._renderers[type]; Daniel@0: else if (dl.isString(type)) throw new Error('Unknown renderer: ' + type); Daniel@0: else if (!type) throw new Error('No renderer specified'); Daniel@0: Daniel@0: if (this._io !== type) { Daniel@0: this._io = type; Daniel@0: this._renderer = null; Daniel@0: this.initialize(); Daniel@0: if (this._build) this.render(); Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.initialize = function(el) { Daniel@0: var v = this, prevHandler, Daniel@0: w = v._width, h = v._height, pad = v._padding, bg = v._bgcolor, Daniel@0: config = this.model().config(); Daniel@0: Daniel@0: if (!arguments.length || el === null) { Daniel@0: el = this._el ? this._el.parentNode : null; Daniel@0: if (!el) return this; // This View cannot init w/o an Daniel@0: } Daniel@0: Daniel@0: // clear pre-existing container Daniel@0: d3.select(el).select('div.vega').remove(); Daniel@0: Daniel@0: // add div container Daniel@0: this._el = el = d3.select(el) Daniel@0: .append('div') Daniel@0: .attr('class', 'vega') Daniel@0: .style('position', 'relative') Daniel@0: .node(); Daniel@0: if (v._viewport) { Daniel@0: d3.select(el) Daniel@0: .style('width', (v._viewport[0] || w)+'px') Daniel@0: .style('height', (v._viewport[1] || h)+'px') Daniel@0: .style('overflow', 'auto'); Daniel@0: } Daniel@0: Daniel@0: // renderer Daniel@0: sg.canvas.Renderer.RETINA = config.render.retina; Daniel@0: v._renderer = (v._renderer || new this._io.Renderer(config.load)) Daniel@0: .initialize(el, w, h, pad) Daniel@0: .background(bg); Daniel@0: Daniel@0: // input handler Daniel@0: prevHandler = v._handler; Daniel@0: v._handler = new this._io.Handler() Daniel@0: .initialize(el, pad, v); Daniel@0: Daniel@0: if (prevHandler) { Daniel@0: prevHandler.handlers().forEach(function(h) { Daniel@0: v._handler.on(h.type, h.handler); Daniel@0: }); Daniel@0: } else { Daniel@0: // Register event listeners for signal stream definitions. Daniel@0: v._detach = parseStreams(this); Daniel@0: } Daniel@0: Daniel@0: return (this._repaint = true, this); Daniel@0: }; Daniel@0: Daniel@0: prototype.destroy = function() { Daniel@0: if (this._detach) this._detach(); Daniel@0: }; Daniel@0: Daniel@0: function build() { Daniel@0: var v = this; Daniel@0: v._renderNode = new df.Node(v._model) Daniel@0: .router(true); Daniel@0: Daniel@0: v._renderNode.evaluate = function(input) { Daniel@0: log.debug(input, ['rendering']); Daniel@0: Daniel@0: var s = v._model.scene(), Daniel@0: h = v._handler; Daniel@0: Daniel@0: if (h && h.scene) h.scene(s); Daniel@0: Daniel@0: if (input.trans) { Daniel@0: input.trans.start(function(items) { v._renderer.render(s, items); }); Daniel@0: } else if (v._repaint) { Daniel@0: v._renderer.render(s); Daniel@0: v._repaint = false; Daniel@0: } else if (input.dirty.length) { Daniel@0: v._renderer.render(s, input.dirty); Daniel@0: } Daniel@0: Daniel@0: if (input.dirty.length) { Daniel@0: input.dirty.forEach(function(i) { i._dirty = false; }); Daniel@0: s.items[0]._dirty = false; Daniel@0: } Daniel@0: Daniel@0: // For all updated datasources, clear their previous values. Daniel@0: for (var d in input.data) { v._model.data(d).synchronize(); } Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: return (v._model.scene(v._renderNode), true); Daniel@0: } Daniel@0: Daniel@0: prototype.update = function(opt) { Daniel@0: opt = opt || {}; Daniel@0: var v = this, Daniel@0: trans = opt.duration ? new Transition(opt.duration, opt.ease) : null; Daniel@0: Daniel@0: var cs = v._changeset; Daniel@0: if (trans) cs.trans = trans; Daniel@0: if (opt.props !== undefined) { Daniel@0: if (dl.keys(cs.data).length > 0) { Daniel@0: throw Error( Daniel@0: 'New data values are not reflected in the visualization.' + Daniel@0: ' Please call view.update() before updating a specified property set.' Daniel@0: ); Daniel@0: } Daniel@0: Daniel@0: cs.reflow = true; Daniel@0: cs.request = opt.props; Daniel@0: } Daniel@0: Daniel@0: var built = v._build; Daniel@0: v._build = v._build || build.call(this); Daniel@0: Daniel@0: // If specific items are specified, short-circuit dataflow graph. Daniel@0: // Else-If there are streaming updates, perform a targeted propagation. Daniel@0: // Otherwise, reevaluate the entire model (datasources + scene). Daniel@0: if (opt.items && built) { Daniel@0: Encoder.update(this._model, opt.trans, opt.props, opt.items, cs.dirty); Daniel@0: v._renderNode.evaluate(cs); Daniel@0: } else if (v._streamer.listeners().length && built) { Daniel@0: v._model.propagate(cs, v._streamer); Daniel@0: v._streamer.disconnect(); Daniel@0: } else { Daniel@0: v._model.fire(cs); Daniel@0: } Daniel@0: Daniel@0: v._changeset = df.ChangeSet.create(); Daniel@0: Daniel@0: return v.autopad(opt); Daniel@0: }; Daniel@0: Daniel@0: prototype.toImageURL = function(type) { Daniel@0: var v = this, Renderer; Daniel@0: Daniel@0: // lookup appropriate renderer Daniel@0: switch (type || 'png') { Daniel@0: case 'canvas': Daniel@0: case 'png': Daniel@0: Renderer = sg.canvas.Renderer; break; Daniel@0: case 'svg': Daniel@0: Renderer = sg.svg.string.Renderer; break; Daniel@0: default: throw Error('Unrecognized renderer type: ' + type); Daniel@0: } Daniel@0: Daniel@0: var retina = sg.canvas.Renderer.RETINA; Daniel@0: sg.canvas.Renderer.RETINA = false; // ignore retina screen Daniel@0: Daniel@0: // render the scenegraph Daniel@0: var ren = new Renderer(v._model.config.load) Daniel@0: .initialize(null, v._width, v._height, v._padding) Daniel@0: .render(v._model.scene()); Daniel@0: Daniel@0: sg.canvas.Renderer.RETINA = retina; // restore retina settings Daniel@0: Daniel@0: // return data url Daniel@0: if (type === 'svg') { Daniel@0: var blob = new Blob([ren.svg()], {type: 'image/svg+xml'}); Daniel@0: return window.URL.createObjectURL(blob); Daniel@0: } else { Daniel@0: return ren.canvas().toDataURL('image/png'); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: prototype.render = function(items) { Daniel@0: this._renderer.render(this._model.scene(), items); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.on = function() { Daniel@0: this._handler.on.apply(this._handler, arguments); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.onSignal = function(name, handler) { Daniel@0: this._model.signal(name).on(handler); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.off = function() { Daniel@0: this._handler.off.apply(this._handler, arguments); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: prototype.offSignal = function(name, handler) { Daniel@0: this._model.signal(name).off(handler); Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: View.factory = function(model) { Daniel@0: var HeadlessView = require('./HeadlessView'); Daniel@0: return function(opt) { Daniel@0: opt = opt || {}; Daniel@0: var defs = model.defs(); Daniel@0: var v = (opt.el ? new View() : new HeadlessView()) Daniel@0: .model(model) Daniel@0: .renderer(opt.renderer || 'canvas') Daniel@0: .width(defs.width) Daniel@0: .height(defs.height) Daniel@0: .background(defs.background) Daniel@0: .padding(defs.padding) Daniel@0: .viewport(defs.viewport) Daniel@0: .initialize(opt.el); Daniel@0: Daniel@0: if (opt.data) v.data(opt.data); Daniel@0: Daniel@0: if (opt.hover !== false && opt.el) { Daniel@0: v.on('mouseover', function(evt, item) { Daniel@0: if (item && item.hasPropertySet('hover')) { Daniel@0: this.update({props:'hover', items:item}); Daniel@0: } Daniel@0: }) Daniel@0: .on('mouseout', function(evt, item) { Daniel@0: if (item && item.hasPropertySet('hover')) { Daniel@0: this.update({props:'update', items:item}); Daniel@0: } Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: return v; Daniel@0: }; Daniel@0: }; Daniel@0: Daniel@0: module.exports = View; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"../parse/streams":105,"../scene/Encoder":109,"../scene/Transition":112,"./HeadlessView":85,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],88:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: config = {}; Daniel@0: Daniel@0: config.load = { Daniel@0: // base url for loading external data files Daniel@0: // used only for server-side operation Daniel@0: baseURL: '', Daniel@0: // Allows domain restriction when using data loading via XHR. Daniel@0: // To enable, set it to a list of allowed domains Daniel@0: // e.g., ['wikipedia.org', 'eff.org'] Daniel@0: domainWhiteList: false Daniel@0: }; Daniel@0: Daniel@0: // inset padding for automatic padding calculation Daniel@0: config.autopadInset = 5; Daniel@0: Daniel@0: // extensible scale lookup table Daniel@0: // all d3.scale.* instances also supported Daniel@0: config.scale = { Daniel@0: time: d3.time.scale, Daniel@0: utc: d3.time.scale.utc Daniel@0: }; Daniel@0: Daniel@0: // default rendering settings Daniel@0: config.render = { Daniel@0: retina: true Daniel@0: }; Daniel@0: Daniel@0: // default axis properties Daniel@0: config.axis = { Daniel@0: orient: 'bottom', Daniel@0: ticks: 10, Daniel@0: padding: 3, Daniel@0: axisColor: '#000', Daniel@0: gridColor: '#000', Daniel@0: gridOpacity: 0.15, Daniel@0: tickColor: '#000', Daniel@0: tickLabelColor: '#000', Daniel@0: axisWidth: 1, Daniel@0: tickWidth: 1, Daniel@0: tickSize: 6, Daniel@0: tickLabelFontSize: 11, Daniel@0: tickLabelFont: 'sans-serif', Daniel@0: titleColor: '#000', Daniel@0: titleFont: 'sans-serif', Daniel@0: titleFontSize: 11, Daniel@0: titleFontWeight: 'bold', Daniel@0: titleOffset: 35 Daniel@0: }; Daniel@0: Daniel@0: // default legend properties Daniel@0: config.legend = { Daniel@0: orient: 'right', Daniel@0: offset: 20, Daniel@0: padding: 3, Daniel@0: gradientStrokeColor: '#888', Daniel@0: gradientStrokeWidth: 1, Daniel@0: gradientHeight: 16, Daniel@0: gradientWidth: 100, Daniel@0: labelColor: '#000', Daniel@0: labelFontSize: 10, Daniel@0: labelFont: 'sans-serif', Daniel@0: labelAlign: 'left', Daniel@0: labelBaseline: 'middle', Daniel@0: labelOffset: 8, Daniel@0: symbolShape: 'circle', Daniel@0: symbolSize: 50, Daniel@0: symbolColor: '#888', Daniel@0: symbolStrokeWidth: 1, Daniel@0: titleColor: '#000', Daniel@0: titleFont: 'sans-serif', Daniel@0: titleFontSize: 11, Daniel@0: titleFontWeight: 'bold' Daniel@0: }; Daniel@0: Daniel@0: // default color values Daniel@0: config.color = { Daniel@0: rgb: [128, 128, 128], Daniel@0: lab: [50, 0, 0], Daniel@0: hcl: [0, 0, 50], Daniel@0: hsl: [0, 0, 0.5] Daniel@0: }; Daniel@0: Daniel@0: // default scale ranges Daniel@0: config.range = { Daniel@0: category10: d3.scale.category10().range(), Daniel@0: category20: d3.scale.category20().range(), Daniel@0: category20b: d3.scale.category20b().range(), Daniel@0: category20c: d3.scale.category20c().range(), Daniel@0: shapes: [ Daniel@0: 'circle', Daniel@0: 'cross', Daniel@0: 'diamond', Daniel@0: 'square', Daniel@0: 'triangle-down', Daniel@0: 'triangle-up' Daniel@0: ] Daniel@0: }; Daniel@0: Daniel@0: module.exports = config; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{}],89:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: parse = require('../parse'), Daniel@0: Scale = require('../scene/Scale'), Daniel@0: config = require('./config'); Daniel@0: Daniel@0: function compile(module, opt, schema) { Daniel@0: var s = module.schema; Daniel@0: if (!s) return; Daniel@0: if (s.refs) dl.extend(schema.refs, s.refs); Daniel@0: if (s.defs) dl.extend(schema.defs, s.defs); Daniel@0: } Daniel@0: Daniel@0: module.exports = function(opt) { Daniel@0: var schema = null; Daniel@0: opt = opt || {}; Daniel@0: Daniel@0: // Compile if we're not loading the schema from a URL. Daniel@0: // Load from a URL to extend the existing base schema. Daniel@0: if (opt.url) { Daniel@0: schema = dl.json(dl.extend({url: opt.url}, config.load)); Daniel@0: } else { Daniel@0: schema = { Daniel@0: "$schema": "http://json-schema.org/draft-04/schema#", Daniel@0: "title": "Vega Visualization Specification Language", Daniel@0: "defs": {}, Daniel@0: "refs": {}, Daniel@0: "$ref": "#/defs/spec" Daniel@0: }; Daniel@0: Daniel@0: dl.keys(parse).forEach(function(k) { compile(parse[k], opt, schema); }); Daniel@0: Daniel@0: // Scales aren't in the parser, add schema manually Daniel@0: compile(Scale, opt, schema); Daniel@0: } Daniel@0: Daniel@0: // Extend schema to support custom mark properties or property sets. Daniel@0: if (opt.properties) dl.keys(opt.properties).forEach(function(k) { Daniel@0: schema.defs.propset.properties[k] = {"$ref": "#/refs/"+opt.properties[k]+"Value"}; Daniel@0: }); Daniel@0: Daniel@0: if (opt.propertySets) dl.keys(opt.propertySets).forEach(function(k) { Daniel@0: schema.defs.mark.properties.properties.properties[k] = {"$ref": "#/defs/propset"}; Daniel@0: }); Daniel@0: Daniel@0: return schema; Daniel@0: }; Daniel@0: },{"../parse":95,"../scene/Scale":111,"./config":88,"datalib":24}],90:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: axs = require('../scene/axis'); Daniel@0: Daniel@0: var ORIENT = { Daniel@0: "x": "bottom", Daniel@0: "y": "left", Daniel@0: "top": "top", Daniel@0: "bottom": "bottom", Daniel@0: "left": "left", Daniel@0: "right": "right" Daniel@0: }; Daniel@0: Daniel@0: function parseAxes(model, spec, axes, group) { Daniel@0: var config = model.config(); Daniel@0: (spec || []).forEach(function(def, index) { Daniel@0: axes[index] = axes[index] || axs(model); Daniel@0: parseAxis(config, def, index, axes[index], group); Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: function parseAxis(config, def, index, axis, group) { Daniel@0: // axis scale Daniel@0: if (def.scale !== undefined) { Daniel@0: axis.scale(group.scale(def.scale)); Daniel@0: } Daniel@0: Daniel@0: // axis orientation Daniel@0: axis.orient(def.orient || ORIENT[def.type]); Daniel@0: // axis offset Daniel@0: axis.offset(def.offset || 0); Daniel@0: // axis layer Daniel@0: axis.layer(def.layer || "front"); Daniel@0: // axis grid lines Daniel@0: axis.grid(def.grid || false); Daniel@0: // axis title Daniel@0: axis.title(def.title || null); Daniel@0: // axis title offset Daniel@0: axis.titleOffset(def.titleOffset != null ? Daniel@0: def.titleOffset : config.axis.titleOffset); Daniel@0: // axis values Daniel@0: axis.tickValues(def.values || null); Daniel@0: // axis label formatting Daniel@0: axis.tickFormat(def.format || null); Daniel@0: axis.tickFormatType(def.formatType || null); Daniel@0: // axis tick subdivision Daniel@0: axis.tickSubdivide(def.subdivide || 0); Daniel@0: // axis tick padding Daniel@0: axis.tickPadding(def.tickPadding || config.axis.padding); Daniel@0: Daniel@0: // axis tick size(s) Daniel@0: var size = []; Daniel@0: if (def.tickSize !== undefined) { Daniel@0: for (var i=0; i<3; ++i) size.push(def.tickSize); Daniel@0: } else { Daniel@0: var ts = config.axis.tickSize; Daniel@0: size = [ts, ts, ts]; Daniel@0: } Daniel@0: if (def.tickSizeMajor != null) size[0] = def.tickSizeMajor; Daniel@0: if (def.tickSizeMinor != null) size[1] = def.tickSizeMinor; Daniel@0: if (def.tickSizeEnd != null) size[2] = def.tickSizeEnd; Daniel@0: if (size.length) { Daniel@0: axis.tickSize.apply(axis, size); Daniel@0: } Daniel@0: Daniel@0: // axis tick count Daniel@0: axis.tickCount(def.ticks || config.axis.ticks); Daniel@0: Daniel@0: // style properties Daniel@0: var p = def.properties; Daniel@0: if (p && p.ticks) { Daniel@0: axis.majorTickProperties(p.majorTicks ? Daniel@0: dl.extend({}, p.ticks, p.majorTicks) : p.ticks); Daniel@0: axis.minorTickProperties(p.minorTicks ? Daniel@0: dl.extend({}, p.ticks, p.minorTicks) : p.ticks); Daniel@0: } else { Daniel@0: axis.majorTickProperties(p && p.majorTicks || {}); Daniel@0: axis.minorTickProperties(p && p.minorTicks || {}); Daniel@0: } Daniel@0: axis.tickLabelProperties(p && p.labels || {}); Daniel@0: axis.titleProperties(p && p.title || {}); Daniel@0: axis.gridLineProperties(p && p.grid || {}); Daniel@0: axis.domainProperties(p && p.axis || {}); Daniel@0: } Daniel@0: Daniel@0: module.exports = parseAxes; Daniel@0: },{"../scene/axis":113,"datalib":24}],91:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null); Daniel@0: Daniel@0: function parseBg(bg) { Daniel@0: // return null if input is null or undefined Daniel@0: if (bg == null) return null; Daniel@0: // run through d3 rgb to sanity check Daniel@0: return d3.rgb(bg) + ""; Daniel@0: } Daniel@0: Daniel@0: module.exports = parseBg; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{}],92:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: log = require('vega-logging'), Daniel@0: parseTransforms = require('./transforms'), Daniel@0: parseModify = require('./modify'); Daniel@0: Daniel@0: function parseData(model, spec, callback) { Daniel@0: var config = model.config(), Daniel@0: count = 0; Daniel@0: Daniel@0: function loaded(d) { Daniel@0: return function(error, data) { Daniel@0: if (error) { Daniel@0: log.error('LOADING FAILED: ' + d.url + ' ' + error); Daniel@0: } else { Daniel@0: model.data(d.name).values(dl.read(data, d.format)); Daniel@0: } Daniel@0: if (--count === 0) callback(); Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // process each data set definition Daniel@0: (spec || []).forEach(function(d) { Daniel@0: if (d.url) { Daniel@0: count += 1; Daniel@0: dl.load(dl.extend({url: d.url}, config.load), loaded(d)); Daniel@0: } Daniel@0: parseData.datasource(model, d); Daniel@0: }); Daniel@0: Daniel@0: if (count === 0) setTimeout(callback, 1); Daniel@0: return spec; Daniel@0: } Daniel@0: Daniel@0: parseData.datasource = function(model, d) { Daniel@0: var transform = (d.transform || []).map(function(t) { Daniel@0: return parseTransforms(model, t); Daniel@0: }), Daniel@0: mod = (d.modify || []).map(function(m) { Daniel@0: return parseModify(model, m, d); Daniel@0: }), Daniel@0: ds = model.data(d.name, mod.concat(transform)); Daniel@0: Daniel@0: if (d.values) { Daniel@0: ds.values(dl.read(d.values, d.format)); Daniel@0: } else if (d.source) { Daniel@0: // Derived ds will be pulsed by its src rather than the model. Daniel@0: ds.source(d.source).addListener(ds); Daniel@0: model.removeListener(ds.pipeline()[0]); Daniel@0: } Daniel@0: Daniel@0: return ds; Daniel@0: }; Daniel@0: Daniel@0: module.exports = parseData; Daniel@0: },{"./modify":99,"./transforms":106,"datalib":24,"vega-logging":45}],93:[function(require,module,exports){ Daniel@0: module.exports = (function() { Daniel@0: /* Daniel@0: * Generated by PEG.js 0.8.0. Daniel@0: * Daniel@0: * http://pegjs.majda.cz/ Daniel@0: */ Daniel@0: Daniel@0: function peg$subclass(child, parent) { Daniel@0: function ctor() { this.constructor = child; } Daniel@0: ctor.prototype = parent.prototype; Daniel@0: child.prototype = new ctor(); Daniel@0: } Daniel@0: Daniel@0: function SyntaxError(message, expected, found, offset, line, column) { Daniel@0: this.message = message; Daniel@0: this.expected = expected; Daniel@0: this.found = found; Daniel@0: this.offset = offset; Daniel@0: this.line = line; Daniel@0: this.column = column; Daniel@0: Daniel@0: this.name = "SyntaxError"; Daniel@0: } Daniel@0: Daniel@0: peg$subclass(SyntaxError, Error); Daniel@0: Daniel@0: function parse(input) { Daniel@0: var options = arguments.length > 1 ? arguments[1] : {}, Daniel@0: Daniel@0: peg$FAILED = {}, Daniel@0: Daniel@0: peg$startRuleFunctions = { start: peg$parsestart }, Daniel@0: peg$startRuleFunction = peg$parsestart, Daniel@0: Daniel@0: peg$c0 = peg$FAILED, Daniel@0: peg$c1 = ",", Daniel@0: peg$c2 = { type: "literal", value: ",", description: "\",\"" }, Daniel@0: peg$c3 = function(o, m) { return [o].concat(m); }, Daniel@0: peg$c4 = function(o) { return [o]; }, Daniel@0: peg$c5 = "[", Daniel@0: peg$c6 = { type: "literal", value: "[", description: "\"[\"" }, Daniel@0: peg$c7 = "]", Daniel@0: peg$c8 = { type: "literal", value: "]", description: "\"]\"" }, Daniel@0: peg$c9 = ">", Daniel@0: peg$c10 = { type: "literal", value: ">", description: "\">\"" }, Daniel@0: peg$c11 = function(f1, f2, o) { return {start: f1, end: f2, middle: o}; }, Daniel@0: peg$c12 = [], Daniel@0: peg$c13 = function(s, f) { return (s.filters = f, s); }, Daniel@0: peg$c14 = function(s) { return s; }, Daniel@0: peg$c15 = "(", Daniel@0: peg$c16 = { type: "literal", value: "(", description: "\"(\"" }, Daniel@0: peg$c17 = ")", Daniel@0: peg$c18 = { type: "literal", value: ")", description: "\")\"" }, Daniel@0: peg$c19 = function(m) { return {stream: m}; }, Daniel@0: peg$c20 = "@", Daniel@0: peg$c21 = { type: "literal", value: "@", description: "\"@\"" }, Daniel@0: peg$c22 = ":", Daniel@0: peg$c23 = { type: "literal", value: ":", description: "\":\"" }, Daniel@0: peg$c24 = function(n, e) { return {event: e, name: n}; }, Daniel@0: peg$c25 = function(m, e) { return {event: e, mark: m}; }, Daniel@0: peg$c26 = function(t, e) { return {event: e, target: t}; }, Daniel@0: peg$c27 = function(e) { return {event: e}; }, Daniel@0: peg$c28 = function(s) { return {signal: s}; }, Daniel@0: peg$c29 = "rect", Daniel@0: peg$c30 = { type: "literal", value: "rect", description: "\"rect\"" }, Daniel@0: peg$c31 = "symbol", Daniel@0: peg$c32 = { type: "literal", value: "symbol", description: "\"symbol\"" }, Daniel@0: peg$c33 = "path", Daniel@0: peg$c34 = { type: "literal", value: "path", description: "\"path\"" }, Daniel@0: peg$c35 = "arc", Daniel@0: peg$c36 = { type: "literal", value: "arc", description: "\"arc\"" }, Daniel@0: peg$c37 = "area", Daniel@0: peg$c38 = { type: "literal", value: "area", description: "\"area\"" }, Daniel@0: peg$c39 = "line", Daniel@0: peg$c40 = { type: "literal", value: "line", description: "\"line\"" }, Daniel@0: peg$c41 = "rule", Daniel@0: peg$c42 = { type: "literal", value: "rule", description: "\"rule\"" }, Daniel@0: peg$c43 = "image", Daniel@0: peg$c44 = { type: "literal", value: "image", description: "\"image\"" }, Daniel@0: peg$c45 = "text", Daniel@0: peg$c46 = { type: "literal", value: "text", description: "\"text\"" }, Daniel@0: peg$c47 = "group", Daniel@0: peg$c48 = { type: "literal", value: "group", description: "\"group\"" }, Daniel@0: peg$c49 = "mousedown", Daniel@0: peg$c50 = { type: "literal", value: "mousedown", description: "\"mousedown\"" }, Daniel@0: peg$c51 = "mouseup", Daniel@0: peg$c52 = { type: "literal", value: "mouseup", description: "\"mouseup\"" }, Daniel@0: peg$c53 = "click", Daniel@0: peg$c54 = { type: "literal", value: "click", description: "\"click\"" }, Daniel@0: peg$c55 = "dblclick", Daniel@0: peg$c56 = { type: "literal", value: "dblclick", description: "\"dblclick\"" }, Daniel@0: peg$c57 = "wheel", Daniel@0: peg$c58 = { type: "literal", value: "wheel", description: "\"wheel\"" }, Daniel@0: peg$c59 = "keydown", Daniel@0: peg$c60 = { type: "literal", value: "keydown", description: "\"keydown\"" }, Daniel@0: peg$c61 = "keypress", Daniel@0: peg$c62 = { type: "literal", value: "keypress", description: "\"keypress\"" }, Daniel@0: peg$c63 = "keyup", Daniel@0: peg$c64 = { type: "literal", value: "keyup", description: "\"keyup\"" }, Daniel@0: peg$c65 = "mousewheel", Daniel@0: peg$c66 = { type: "literal", value: "mousewheel", description: "\"mousewheel\"" }, Daniel@0: peg$c67 = "mousemove", Daniel@0: peg$c68 = { type: "literal", value: "mousemove", description: "\"mousemove\"" }, Daniel@0: peg$c69 = "mouseout", Daniel@0: peg$c70 = { type: "literal", value: "mouseout", description: "\"mouseout\"" }, Daniel@0: peg$c71 = "mouseover", Daniel@0: peg$c72 = { type: "literal", value: "mouseover", description: "\"mouseover\"" }, Daniel@0: peg$c73 = "mouseenter", Daniel@0: peg$c74 = { type: "literal", value: "mouseenter", description: "\"mouseenter\"" }, Daniel@0: peg$c75 = "touchstart", Daniel@0: peg$c76 = { type: "literal", value: "touchstart", description: "\"touchstart\"" }, Daniel@0: peg$c77 = "touchmove", Daniel@0: peg$c78 = { type: "literal", value: "touchmove", description: "\"touchmove\"" }, Daniel@0: peg$c79 = "touchend", Daniel@0: peg$c80 = { type: "literal", value: "touchend", description: "\"touchend\"" }, Daniel@0: peg$c81 = function(e) { return e; }, Daniel@0: peg$c82 = /^[a-zA-Z0-9_\-]/, Daniel@0: peg$c83 = { type: "class", value: "[a-zA-Z0-9_\\-]", description: "[a-zA-Z0-9_\\-]" }, Daniel@0: peg$c84 = function(n) { return n.join(""); }, Daniel@0: peg$c85 = /^[a-zA-Z0-9\-_ #.>+~[\]=|\^$*]/, Daniel@0: peg$c86 = { type: "class", value: "[a-zA-Z0-9\\-_ #.>+~[\\]=|\\^$*]", description: "[a-zA-Z0-9\\-_ #.>+~[\\]=|\\^$*]" }, Daniel@0: peg$c87 = function(c) { return c.join(""); }, Daniel@0: peg$c88 = /^['"a-zA-Z0-9_().><=! \t-&|~]/, Daniel@0: peg$c89 = { type: "class", value: "['\"a-zA-Z0-9_().><=! \\t-&|~]", description: "['\"a-zA-Z0-9_().><=! \\t-&|~]" }, Daniel@0: peg$c90 = function(v) { return v.join(""); }, Daniel@0: peg$c91 = /^[ \t\r\n]/, Daniel@0: peg$c92 = { type: "class", value: "[ \\t\\r\\n]", description: "[ \\t\\r\\n]" }, Daniel@0: Daniel@0: peg$currPos = 0, Daniel@0: peg$reportedPos = 0, Daniel@0: peg$cachedPos = 0, Daniel@0: peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, Daniel@0: peg$maxFailPos = 0, Daniel@0: peg$maxFailExpected = [], Daniel@0: peg$silentFails = 0, Daniel@0: Daniel@0: peg$result; Daniel@0: Daniel@0: if ("startRule" in options) { Daniel@0: if (!(options.startRule in peg$startRuleFunctions)) { Daniel@0: throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); Daniel@0: } Daniel@0: Daniel@0: peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; Daniel@0: } Daniel@0: Daniel@0: function text() { Daniel@0: return input.substring(peg$reportedPos, peg$currPos); Daniel@0: } Daniel@0: Daniel@0: function offset() { Daniel@0: return peg$reportedPos; Daniel@0: } Daniel@0: Daniel@0: function line() { Daniel@0: return peg$computePosDetails(peg$reportedPos).line; Daniel@0: } Daniel@0: Daniel@0: function column() { Daniel@0: return peg$computePosDetails(peg$reportedPos).column; Daniel@0: } Daniel@0: Daniel@0: function expected(description) { Daniel@0: throw peg$buildException( Daniel@0: null, Daniel@0: [{ type: "other", description: description }], Daniel@0: peg$reportedPos Daniel@0: ); Daniel@0: } Daniel@0: Daniel@0: function error(message) { Daniel@0: throw peg$buildException(message, null, peg$reportedPos); Daniel@0: } Daniel@0: Daniel@0: function peg$computePosDetails(pos) { Daniel@0: function advance(details, startPos, endPos) { Daniel@0: var p, ch; Daniel@0: Daniel@0: for (p = startPos; p < endPos; p++) { Daniel@0: ch = input.charAt(p); Daniel@0: if (ch === "\n") { Daniel@0: if (!details.seenCR) { details.line++; } Daniel@0: details.column = 1; Daniel@0: details.seenCR = false; Daniel@0: } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { Daniel@0: details.line++; Daniel@0: details.column = 1; Daniel@0: details.seenCR = true; Daniel@0: } else { Daniel@0: details.column++; Daniel@0: details.seenCR = false; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (peg$cachedPos !== pos) { Daniel@0: if (peg$cachedPos > pos) { Daniel@0: peg$cachedPos = 0; Daniel@0: peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; Daniel@0: } Daniel@0: advance(peg$cachedPosDetails, peg$cachedPos, pos); Daniel@0: peg$cachedPos = pos; Daniel@0: } Daniel@0: Daniel@0: return peg$cachedPosDetails; Daniel@0: } Daniel@0: Daniel@0: function peg$fail(expected) { Daniel@0: if (peg$currPos < peg$maxFailPos) { return; } Daniel@0: Daniel@0: if (peg$currPos > peg$maxFailPos) { Daniel@0: peg$maxFailPos = peg$currPos; Daniel@0: peg$maxFailExpected = []; Daniel@0: } Daniel@0: Daniel@0: peg$maxFailExpected.push(expected); Daniel@0: } Daniel@0: Daniel@0: function peg$buildException(message, expected, pos) { Daniel@0: function cleanupExpected(expected) { Daniel@0: var i = 1; Daniel@0: Daniel@0: expected.sort(function(a, b) { Daniel@0: if (a.description < b.description) { Daniel@0: return -1; Daniel@0: } else if (a.description > b.description) { Daniel@0: return 1; Daniel@0: } else { Daniel@0: return 0; Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: while (i < expected.length) { Daniel@0: if (expected[i - 1] === expected[i]) { Daniel@0: expected.splice(i, 1); Daniel@0: } else { Daniel@0: i++; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function buildMessage(expected, found) { Daniel@0: function stringEscape(s) { Daniel@0: function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } Daniel@0: Daniel@0: return s Daniel@0: .replace(/\\/g, '\\\\') Daniel@0: .replace(/"/g, '\\"') Daniel@0: .replace(/\x08/g, '\\b') Daniel@0: .replace(/\t/g, '\\t') Daniel@0: .replace(/\n/g, '\\n') Daniel@0: .replace(/\f/g, '\\f') Daniel@0: .replace(/\r/g, '\\r') Daniel@0: .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) Daniel@0: .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) Daniel@0: .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) Daniel@0: .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); Daniel@0: } Daniel@0: Daniel@0: var expectedDescs = new Array(expected.length), Daniel@0: expectedDesc, foundDesc, i; Daniel@0: Daniel@0: for (i = 0; i < expected.length; i++) { Daniel@0: expectedDescs[i] = expected[i].description; Daniel@0: } Daniel@0: Daniel@0: expectedDesc = expected.length > 1 Daniel@0: ? expectedDescs.slice(0, -1).join(", ") Daniel@0: + " or " Daniel@0: + expectedDescs[expected.length - 1] Daniel@0: : expectedDescs[0]; Daniel@0: Daniel@0: foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; Daniel@0: Daniel@0: return "Expected " + expectedDesc + " but " + foundDesc + " found."; Daniel@0: } Daniel@0: Daniel@0: var posDetails = peg$computePosDetails(pos), Daniel@0: found = pos < input.length ? input.charAt(pos) : null; Daniel@0: Daniel@0: if (expected !== null) { Daniel@0: cleanupExpected(expected); Daniel@0: } Daniel@0: Daniel@0: return new SyntaxError( Daniel@0: message !== null ? message : buildMessage(expected, found), Daniel@0: expected, Daniel@0: found, Daniel@0: pos, Daniel@0: posDetails.line, Daniel@0: posDetails.column Daniel@0: ); Daniel@0: } Daniel@0: Daniel@0: function peg$parsestart() { Daniel@0: var s0; Daniel@0: Daniel@0: s0 = peg$parsemerged(); Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsemerged() { Daniel@0: var s0, s1, s2, s3, s4, s5; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parseordered(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: s2 = peg$parsesep(); Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 44) { Daniel@0: s3 = peg$c1; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s3 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c2); } Daniel@0: } Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: s4 = peg$parsesep(); Daniel@0: if (s4 !== peg$FAILED) { Daniel@0: s5 = peg$parsemerged(); Daniel@0: if (s5 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c3(s1, s5); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parseordered(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c4(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parseordered() { Daniel@0: var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: if (input.charCodeAt(peg$currPos) === 91) { Daniel@0: s1 = peg$c5; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s1 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c6); } Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: s2 = peg$parsesep(); Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: s3 = peg$parsefiltered(); Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: s4 = peg$parsesep(); Daniel@0: if (s4 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 44) { Daniel@0: s5 = peg$c1; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s5 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c2); } Daniel@0: } Daniel@0: if (s5 !== peg$FAILED) { Daniel@0: s6 = peg$parsesep(); Daniel@0: if (s6 !== peg$FAILED) { Daniel@0: s7 = peg$parsefiltered(); Daniel@0: if (s7 !== peg$FAILED) { Daniel@0: s8 = peg$parsesep(); Daniel@0: if (s8 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 93) { Daniel@0: s9 = peg$c7; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s9 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c8); } Daniel@0: } Daniel@0: if (s9 !== peg$FAILED) { Daniel@0: s10 = peg$parsesep(); Daniel@0: if (s10 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 62) { Daniel@0: s11 = peg$c9; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s11 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c10); } Daniel@0: } Daniel@0: if (s11 !== peg$FAILED) { Daniel@0: s12 = peg$parsesep(); Daniel@0: if (s12 !== peg$FAILED) { Daniel@0: s13 = peg$parseordered(); Daniel@0: if (s13 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c11(s3, s7, s13); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$parsefiltered(); Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsefiltered() { Daniel@0: var s0, s1, s2, s3; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parsestream(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: s2 = []; Daniel@0: s3 = peg$parsefilter(); Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: while (s3 !== peg$FAILED) { Daniel@0: s2.push(s3); Daniel@0: s3 = peg$parsefilter(); Daniel@0: } Daniel@0: } else { Daniel@0: s2 = peg$c0; Daniel@0: } Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c13(s1, s2); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parsestream(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c14(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsestream() { Daniel@0: var s0, s1, s2, s3, s4; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: if (input.charCodeAt(peg$currPos) === 40) { Daniel@0: s1 = peg$c15; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s1 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c16); } Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: s2 = peg$parsemerged(); Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 41) { Daniel@0: s3 = peg$c17; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s3 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c18); } Daniel@0: } Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c19(s2); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: if (input.charCodeAt(peg$currPos) === 64) { Daniel@0: s1 = peg$c20; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s1 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c21); } Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: s2 = peg$parsename(); Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 58) { Daniel@0: s3 = peg$c22; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s3 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c23); } Daniel@0: } Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: s4 = peg$parseeventType(); Daniel@0: if (s4 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c24(s2, s4); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parsemarkType(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 58) { Daniel@0: s2 = peg$c22; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c23); } Daniel@0: } Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: s3 = peg$parseeventType(); Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c25(s1, s3); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parsecss(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 58) { Daniel@0: s2 = peg$c22; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c23); } Daniel@0: } Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: s3 = peg$parseeventType(); Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c26(s1, s3); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parseeventType(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c27(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: if (s0 === peg$FAILED) { Daniel@0: s0 = peg$currPos; Daniel@0: s1 = peg$parsename(); Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c28(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsemarkType() { Daniel@0: var s0; Daniel@0: Daniel@0: if (input.substr(peg$currPos, 4) === peg$c29) { Daniel@0: s0 = peg$c29; Daniel@0: peg$currPos += 4; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c30); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 6) === peg$c31) { Daniel@0: s0 = peg$c31; Daniel@0: peg$currPos += 6; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c32); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 4) === peg$c33) { Daniel@0: s0 = peg$c33; Daniel@0: peg$currPos += 4; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c34); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 3) === peg$c35) { Daniel@0: s0 = peg$c35; Daniel@0: peg$currPos += 3; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c36); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 4) === peg$c37) { Daniel@0: s0 = peg$c37; Daniel@0: peg$currPos += 4; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c38); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 4) === peg$c39) { Daniel@0: s0 = peg$c39; Daniel@0: peg$currPos += 4; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c40); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 4) === peg$c41) { Daniel@0: s0 = peg$c41; Daniel@0: peg$currPos += 4; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c42); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 5) === peg$c43) { Daniel@0: s0 = peg$c43; Daniel@0: peg$currPos += 5; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c44); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 4) === peg$c45) { Daniel@0: s0 = peg$c45; Daniel@0: peg$currPos += 4; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c46); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 5) === peg$c47) { Daniel@0: s0 = peg$c47; Daniel@0: peg$currPos += 5; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c48); } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parseeventType() { Daniel@0: var s0; Daniel@0: Daniel@0: if (input.substr(peg$currPos, 9) === peg$c49) { Daniel@0: s0 = peg$c49; Daniel@0: peg$currPos += 9; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c50); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 7) === peg$c51) { Daniel@0: s0 = peg$c51; Daniel@0: peg$currPos += 7; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c52); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 5) === peg$c53) { Daniel@0: s0 = peg$c53; Daniel@0: peg$currPos += 5; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c54); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 8) === peg$c55) { Daniel@0: s0 = peg$c55; Daniel@0: peg$currPos += 8; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c56); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 5) === peg$c57) { Daniel@0: s0 = peg$c57; Daniel@0: peg$currPos += 5; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c58); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 7) === peg$c59) { Daniel@0: s0 = peg$c59; Daniel@0: peg$currPos += 7; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c60); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 8) === peg$c61) { Daniel@0: s0 = peg$c61; Daniel@0: peg$currPos += 8; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c62); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 5) === peg$c63) { Daniel@0: s0 = peg$c63; Daniel@0: peg$currPos += 5; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c64); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 10) === peg$c65) { Daniel@0: s0 = peg$c65; Daniel@0: peg$currPos += 10; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c66); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 9) === peg$c67) { Daniel@0: s0 = peg$c67; Daniel@0: peg$currPos += 9; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c68); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 8) === peg$c69) { Daniel@0: s0 = peg$c69; Daniel@0: peg$currPos += 8; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c70); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 9) === peg$c71) { Daniel@0: s0 = peg$c71; Daniel@0: peg$currPos += 9; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c72); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 10) === peg$c73) { Daniel@0: s0 = peg$c73; Daniel@0: peg$currPos += 10; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c74); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 10) === peg$c75) { Daniel@0: s0 = peg$c75; Daniel@0: peg$currPos += 10; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c76); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 9) === peg$c77) { Daniel@0: s0 = peg$c77; Daniel@0: peg$currPos += 9; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c78); } Daniel@0: } Daniel@0: if (s0 === peg$FAILED) { Daniel@0: if (input.substr(peg$currPos, 8) === peg$c79) { Daniel@0: s0 = peg$c79; Daniel@0: peg$currPos += 8; Daniel@0: } else { Daniel@0: s0 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c80); } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsefilter() { Daniel@0: var s0, s1, s2, s3; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: if (input.charCodeAt(peg$currPos) === 91) { Daniel@0: s1 = peg$c5; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s1 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c6); } Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: s2 = peg$parseexpr(); Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: if (input.charCodeAt(peg$currPos) === 93) { Daniel@0: s3 = peg$c7; Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s3 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c8); } Daniel@0: } Daniel@0: if (s3 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c81(s2); Daniel@0: s0 = s1; Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: } else { Daniel@0: peg$currPos = s0; Daniel@0: s0 = peg$c0; Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsename() { Daniel@0: var s0, s1, s2; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: s1 = []; Daniel@0: if (peg$c82.test(input.charAt(peg$currPos))) { Daniel@0: s2 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c83); } Daniel@0: } Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: while (s2 !== peg$FAILED) { Daniel@0: s1.push(s2); Daniel@0: if (peg$c82.test(input.charAt(peg$currPos))) { Daniel@0: s2 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c83); } Daniel@0: } Daniel@0: } Daniel@0: } else { Daniel@0: s1 = peg$c0; Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c84(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsecss() { Daniel@0: var s0, s1, s2; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: s1 = []; Daniel@0: if (peg$c85.test(input.charAt(peg$currPos))) { Daniel@0: s2 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c86); } Daniel@0: } Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: while (s2 !== peg$FAILED) { Daniel@0: s1.push(s2); Daniel@0: if (peg$c85.test(input.charAt(peg$currPos))) { Daniel@0: s2 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c86); } Daniel@0: } Daniel@0: } Daniel@0: } else { Daniel@0: s1 = peg$c0; Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c87(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parseexpr() { Daniel@0: var s0, s1, s2; Daniel@0: Daniel@0: s0 = peg$currPos; Daniel@0: s1 = []; Daniel@0: if (peg$c88.test(input.charAt(peg$currPos))) { Daniel@0: s2 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c89); } Daniel@0: } Daniel@0: if (s2 !== peg$FAILED) { Daniel@0: while (s2 !== peg$FAILED) { Daniel@0: s1.push(s2); Daniel@0: if (peg$c88.test(input.charAt(peg$currPos))) { Daniel@0: s2 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s2 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c89); } Daniel@0: } Daniel@0: } Daniel@0: } else { Daniel@0: s1 = peg$c0; Daniel@0: } Daniel@0: if (s1 !== peg$FAILED) { Daniel@0: peg$reportedPos = s0; Daniel@0: s1 = peg$c90(s1); Daniel@0: } Daniel@0: s0 = s1; Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: function peg$parsesep() { Daniel@0: var s0, s1; Daniel@0: Daniel@0: s0 = []; Daniel@0: if (peg$c91.test(input.charAt(peg$currPos))) { Daniel@0: s1 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s1 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c92); } Daniel@0: } Daniel@0: while (s1 !== peg$FAILED) { Daniel@0: s0.push(s1); Daniel@0: if (peg$c91.test(input.charAt(peg$currPos))) { Daniel@0: s1 = input.charAt(peg$currPos); Daniel@0: peg$currPos++; Daniel@0: } else { Daniel@0: s1 = peg$FAILED; Daniel@0: if (peg$silentFails === 0) { peg$fail(peg$c92); } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return s0; Daniel@0: } Daniel@0: Daniel@0: peg$result = peg$startRuleFunction(); Daniel@0: Daniel@0: if (peg$result !== peg$FAILED && peg$currPos === input.length) { Daniel@0: return peg$result; Daniel@0: } else { Daniel@0: if (peg$result !== peg$FAILED && peg$currPos < input.length) { Daniel@0: peg$fail({ type: "end", description: "end of input" }); Daniel@0: } Daniel@0: Daniel@0: throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: SyntaxError: SyntaxError, Daniel@0: parse: parse Daniel@0: }; Daniel@0: })(); Daniel@0: },{}],94:[function(require,module,exports){ Daniel@0: var expr = require('vega-expression'), Daniel@0: args = ['datum', 'event', 'signals']; Daniel@0: Daniel@0: module.exports = expr.compiler(args, { Daniel@0: idWhiteList: args, Daniel@0: fieldVar: args[0], Daniel@0: globalVar: args[2], Daniel@0: functions: function(codegen) { Daniel@0: var fn = expr.functions(codegen); Daniel@0: fn.eventItem = function() { return 'event.vg.item'; }; Daniel@0: fn.eventGroup = 'event.vg.getGroup'; Daniel@0: fn.eventX = 'event.vg.getX'; Daniel@0: fn.eventY = 'event.vg.getY'; Daniel@0: fn.open = 'window.open'; Daniel@0: return fn; Daniel@0: } Daniel@0: }); Daniel@0: },{"vega-expression":43}],95:[function(require,module,exports){ Daniel@0: module.exports = { Daniel@0: axes: require('./axes'), Daniel@0: background: require('./background'), Daniel@0: data: require('./data'), Daniel@0: events: require('./events'), Daniel@0: expr: require('./expr'), Daniel@0: legends: require('./legends'), Daniel@0: mark: require('./mark'), Daniel@0: marks: require('./marks'), Daniel@0: modify: require('./modify'), Daniel@0: padding: require('./padding'), Daniel@0: predicates: require('./predicates'), Daniel@0: properties: require('./properties'), Daniel@0: signals: require('./signals'), Daniel@0: spec: require('./spec'), Daniel@0: streams: require('./streams'), Daniel@0: transforms: require('./transforms') Daniel@0: }; Daniel@0: },{"./axes":90,"./background":91,"./data":92,"./events":93,"./expr":94,"./legends":96,"./mark":97,"./marks":98,"./modify":99,"./padding":100,"./predicates":101,"./properties":102,"./signals":103,"./spec":104,"./streams":105,"./transforms":106}],96:[function(require,module,exports){ Daniel@0: var lgnd = require('../scene/legend'); Daniel@0: Daniel@0: function parseLegends(model, spec, legends, group) { Daniel@0: (spec || []).forEach(function(def, index) { Daniel@0: legends[index] = legends[index] || lgnd(model); Daniel@0: parseLegend(def, index, legends[index], group); Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: function parseLegend(def, index, legend, group) { Daniel@0: // legend scales Daniel@0: legend.size (def.size ? group.scale(def.size) : null); Daniel@0: legend.shape (def.shape ? group.scale(def.shape) : null); Daniel@0: legend.fill (def.fill ? group.scale(def.fill) : null); Daniel@0: legend.stroke(def.stroke ? group.scale(def.stroke) : null); Daniel@0: Daniel@0: // legend orientation Daniel@0: if (def.orient) legend.orient(def.orient); Daniel@0: Daniel@0: // legend offset Daniel@0: if (def.offset != null) legend.offset(def.offset); Daniel@0: Daniel@0: // legend title Daniel@0: legend.title(def.title || null); Daniel@0: Daniel@0: // legend values Daniel@0: legend.values(def.values || null); Daniel@0: Daniel@0: // legend label formatting Daniel@0: legend.format(def.format !== undefined ? def.format : null); Daniel@0: Daniel@0: // style properties Daniel@0: var p = def.properties; Daniel@0: legend.titleProperties(p && p.title || {}); Daniel@0: legend.labelProperties(p && p.labels || {}); Daniel@0: legend.legendProperties(p && p.legend || {}); Daniel@0: legend.symbolProperties(p && p.symbols || {}); Daniel@0: legend.gradientProperties(p && p.gradient || {}); Daniel@0: } Daniel@0: Daniel@0: module.exports = parseLegends; Daniel@0: },{"../scene/legend":114}],97:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: parseProperties = require('./properties'); Daniel@0: Daniel@0: function parseMark(model, mark) { Daniel@0: var props = mark.properties, Daniel@0: group = mark.marks; Daniel@0: Daniel@0: // parse mark property definitions Daniel@0: dl.keys(props).forEach(function(k) { Daniel@0: props[k] = parseProperties(model, mark.type, props[k]); Daniel@0: }); Daniel@0: Daniel@0: // parse delay function Daniel@0: if (mark.delay) { Daniel@0: mark.delay = parseProperties(model, mark.type, {delay: mark.delay}); Daniel@0: } Daniel@0: Daniel@0: // recurse if group type Daniel@0: if (group) { Daniel@0: mark.marks = group.map(function(g) { return parseMark(model, g); }); Daniel@0: } Daniel@0: Daniel@0: return mark; Daniel@0: } Daniel@0: Daniel@0: module.exports = parseMark; Daniel@0: },{"./properties":102,"datalib":24}],98:[function(require,module,exports){ Daniel@0: var parseMark = require('./mark'); Daniel@0: Daniel@0: function parseRootMark(model, spec, width, height) { Daniel@0: return { Daniel@0: type: "group", Daniel@0: width: width, Daniel@0: height: height, Daniel@0: scales: spec.scales || [], Daniel@0: axes: spec.axes || [], Daniel@0: legends: spec.legends || [], Daniel@0: marks: (spec.marks || []).map(function(m) { return parseMark(model, m); }) Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: module.exports = parseRootMark; Daniel@0: },{"./mark":97}],99:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: log = require('vega-logging'), Daniel@0: df = require('vega-dataflow'), Daniel@0: Node = df.Node, // jshint ignore:line Daniel@0: Tuple = df.Tuple, Daniel@0: Deps = df.Dependencies; Daniel@0: Daniel@0: var Types = { Daniel@0: INSERT: "insert", Daniel@0: REMOVE: "remove", Daniel@0: TOGGLE: "toggle", Daniel@0: CLEAR: "clear" Daniel@0: }; Daniel@0: Daniel@0: var EMPTY = []; Daniel@0: Daniel@0: var filter = function(field, value, src, dest) { Daniel@0: for(var i = src.length-1; i >= 0; --i) { Daniel@0: if (src[i][field] == value) Daniel@0: dest.push.apply(dest, src.splice(i, 1)); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: function parseModify(model, def, ds) { Daniel@0: var signal = def.signal ? dl.field(def.signal) : null, Daniel@0: signalName = signal ? signal[0] : null, Daniel@0: predicate = def.predicate ? model.predicate(def.predicate.name || def.predicate) : null, Daniel@0: reeval = (predicate === null), Daniel@0: node = new Node(model).router(def.type === Types.CLEAR); Daniel@0: Daniel@0: node.evaluate = function(input) { Daniel@0: if (predicate !== null) { // TODO: predicate args Daniel@0: var db = model.values(Deps.DATA, predicate.data || EMPTY), Daniel@0: sg = model.values(Deps.SIGNALS, predicate.signals || EMPTY); Daniel@0: reeval = predicate.call(predicate, {}, db, sg, model._predicates); Daniel@0: } Daniel@0: Daniel@0: log.debug(input, [def.type+"ing", reeval]); Daniel@0: if (!reeval) return input; Daniel@0: Daniel@0: var datum = {}, Daniel@0: value = signal ? model.signalRef(def.signal) : null, Daniel@0: d = model.data(ds.name), Daniel@0: t = null; Daniel@0: Daniel@0: datum[def.field] = value; Daniel@0: Daniel@0: // We have to modify ds._data so that subsequent pulses contain Daniel@0: // our dynamic data. W/o modifying ds._data, only the output Daniel@0: // collector will contain dynamic tuples. Daniel@0: if (def.type === Types.INSERT) { Daniel@0: t = Tuple.ingest(datum); Daniel@0: input.add.push(t); Daniel@0: d._data.push(t); Daniel@0: } else if (def.type === Types.REMOVE) { Daniel@0: filter(def.field, value, input.add, input.rem); Daniel@0: filter(def.field, value, input.mod, input.rem); Daniel@0: d._data = d._data.filter(function(x) { return x[def.field] !== value; }); Daniel@0: } else if (def.type === Types.TOGGLE) { Daniel@0: var add = [], rem = []; Daniel@0: filter(def.field, value, input.rem, add); Daniel@0: filter(def.field, value, input.add, rem); Daniel@0: filter(def.field, value, input.mod, rem); Daniel@0: if (!(add.length || rem.length)) add.push(Tuple.ingest(datum)); Daniel@0: Daniel@0: input.add.push.apply(input.add, add); Daniel@0: d._data.push.apply(d._data, add); Daniel@0: input.rem.push.apply(input.rem, rem); Daniel@0: d._data = d._data.filter(function(x) { return rem.indexOf(x) === -1; }); Daniel@0: } else if (def.type === Types.CLEAR) { Daniel@0: input.rem.push.apply(input.rem, input.add); Daniel@0: input.rem.push.apply(input.rem, input.mod); Daniel@0: input.add = []; Daniel@0: input.mod = []; Daniel@0: d._data = []; Daniel@0: } Daniel@0: Daniel@0: input.fields[def.field] = 1; Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: if (signalName) node.dependency(Deps.SIGNALS, signalName); Daniel@0: Daniel@0: if (predicate) { Daniel@0: node.dependency(Deps.DATA, predicate.data); Daniel@0: node.dependency(Deps.SIGNALS, predicate.signals); Daniel@0: } Daniel@0: Daniel@0: return node; Daniel@0: } Daniel@0: Daniel@0: module.exports = parseModify; Daniel@0: },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],100:[function(require,module,exports){ Daniel@0: var dl = require('datalib'); Daniel@0: Daniel@0: function parsePadding(pad) { Daniel@0: if (pad == null) return "auto"; Daniel@0: else if (dl.isString(pad)) return pad==="strict" ? "strict" : "auto"; Daniel@0: else if (dl.isObject(pad)) return pad; Daniel@0: var p = dl.isNumber(pad) ? pad : 20; Daniel@0: return {top:p, left:p, right:p, bottom:p}; Daniel@0: } Daniel@0: Daniel@0: module.exports = parsePadding; Daniel@0: },{"datalib":24}],101:[function(require,module,exports){ Daniel@0: var dl = require('datalib'); Daniel@0: Daniel@0: var types = { Daniel@0: '=': parseComparator, Daniel@0: '==': parseComparator, Daniel@0: '!=': parseComparator, Daniel@0: '>': parseComparator, Daniel@0: '>=': parseComparator, Daniel@0: '<': parseComparator, Daniel@0: '<=': parseComparator, Daniel@0: 'and': parseLogical, Daniel@0: '&&': parseLogical, Daniel@0: 'or': parseLogical, Daniel@0: '||': parseLogical, Daniel@0: 'in': parseIn Daniel@0: }; Daniel@0: Daniel@0: var nullScale = function() { return 0; }; Daniel@0: nullScale.invert = nullScale; Daniel@0: Daniel@0: function parsePredicates(model, spec) { Daniel@0: (spec || []).forEach(function(s) { Daniel@0: var parse = types[s.type](model, s); Daniel@0: Daniel@0: /* jshint evil:true */ Daniel@0: var pred = Function("args", "db", "signals", "predicates", parse.code); Daniel@0: pred.root = function() { return model.scene().items[0]; }; // For global scales Daniel@0: pred.nullScale = nullScale; Daniel@0: pred.isFunction = dl.isFunction; Daniel@0: pred.signals = parse.signals; Daniel@0: pred.data = parse.data; Daniel@0: Daniel@0: model.predicate(s.name, pred); Daniel@0: }); Daniel@0: Daniel@0: return spec; Daniel@0: } Daniel@0: Daniel@0: function parseSignal(signal, signals) { Daniel@0: var s = dl.field(signal), Daniel@0: code = "signals["+s.map(dl.str).join("][")+"]"; Daniel@0: signals[s[0]] = 1; Daniel@0: return code; Daniel@0: } Daniel@0: Daniel@0: function parseOperands(model, operands) { Daniel@0: var decl = [], defs = [], Daniel@0: signals = {}, db = {}; Daniel@0: Daniel@0: function setSignal(s) { signals[s] = 1; } Daniel@0: function setData(d) { db[d] = 1; } Daniel@0: Daniel@0: dl.array(operands).forEach(function(o, i) { Daniel@0: var name = "o" + i, Daniel@0: def = ""; Daniel@0: Daniel@0: if (o.value !== undefined) { Daniel@0: def = dl.str(o.value); Daniel@0: } else if (o.arg) { Daniel@0: def = "args["+dl.str(o.arg)+"]"; Daniel@0: } else if (o.signal) { Daniel@0: def = parseSignal(o.signal, signals); Daniel@0: } else if (o.predicate) { Daniel@0: var ref = o.predicate, Daniel@0: predName = ref && (ref.name || ref), Daniel@0: pred = model.predicate(predName), Daniel@0: p = "predicates["+dl.str(predName)+"]"; Daniel@0: Daniel@0: pred.signals.forEach(setSignal); Daniel@0: pred.data.forEach(setData); Daniel@0: Daniel@0: if (dl.isObject(ref)) { Daniel@0: dl.keys(ref).forEach(function(k) { Daniel@0: if (k === "name") return; Daniel@0: var i = ref[k]; Daniel@0: def += "args["+dl.str(k)+"] = "; Daniel@0: if (i.signal) { Daniel@0: def += parseSignal(i.signal, signals); Daniel@0: } else if (i.arg) { Daniel@0: def += "args["+dl.str(i.arg)+"]"; Daniel@0: } Daniel@0: def += ", "; Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: def += p+".call("+p+", args, db, signals, predicates)"; Daniel@0: } Daniel@0: Daniel@0: decl.push(name); Daniel@0: defs.push(name+"=("+def+")"); Daniel@0: }); Daniel@0: Daniel@0: return { Daniel@0: code: "var " + decl.join(", ") + ";\n" + defs.join(";\n") + ";\n", Daniel@0: signals: dl.keys(signals), Daniel@0: data: dl.keys(db) Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function parseComparator(model, spec) { Daniel@0: var ops = parseOperands(model, spec.operands); Daniel@0: if (spec.type === '=') spec.type = '=='; Daniel@0: Daniel@0: ops.code += "o0 = o0 instanceof Date ? o0.getTime() : o0;\n" + Daniel@0: "o1 = o1 instanceof Date ? o1.getTime() : o1;\n"; Daniel@0: Daniel@0: return { Daniel@0: code: ops.code + "return " + ["o0", "o1"].join(spec.type) + ";", Daniel@0: signals: ops.signals, Daniel@0: data: ops.data Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function parseLogical(model, spec) { Daniel@0: var ops = parseOperands(model, spec.operands), Daniel@0: o = [], i = 0, len = spec.operands.length; Daniel@0: Daniel@0: while (o.push("o"+i++) < len); Daniel@0: if (spec.type === 'and') spec.type = '&&'; Daniel@0: else if (spec.type === 'or') spec.type = '||'; Daniel@0: Daniel@0: return { Daniel@0: code: ops.code + "return " + o.join(spec.type) + ";", Daniel@0: signals: ops.signals, Daniel@0: data: ops.data Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function parseIn(model, spec) { Daniel@0: var o = [spec.item], code = ""; Daniel@0: if (spec.range) o.push.apply(o, spec.range); Daniel@0: if (spec.scale) { Daniel@0: code = parseScale(spec.scale, o); Daniel@0: } Daniel@0: Daniel@0: var ops = parseOperands(model, o); Daniel@0: code = ops.code + code + "\n var ordSet = null;\n"; Daniel@0: Daniel@0: if (spec.data) { Daniel@0: var field = dl.field(spec.field).map(dl.str); Daniel@0: code += "var where = function(d) { return d["+field.join("][")+"] == o0 };\n"; Daniel@0: code += "return db["+dl.str(spec.data)+"].filter(where).length > 0;"; Daniel@0: } else if (spec.range) { Daniel@0: // TODO: inclusive/exclusive range? Daniel@0: if (spec.scale) { Daniel@0: code += "if (scale.length == 2) {\n" + // inverting ordinal scales Daniel@0: " ordSet = scale(o1, o2);\n" + Daniel@0: "} else {\n" + Daniel@0: " o1 = scale(o1);\no2 = scale(o2);\n" + Daniel@0: "}"; Daniel@0: } Daniel@0: Daniel@0: code += "return ordSet !== null ? ordSet.indexOf(o0) !== -1 :\n" + Daniel@0: " o1 < o2 ? o1 <= o0 && o0 <= o2 : o2 <= o0 && o0 <= o1;"; Daniel@0: } Daniel@0: Daniel@0: return { Daniel@0: code: code, Daniel@0: signals: ops.signals, Daniel@0: data: ops.data.concat(spec.data ? [spec.data] : []) Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: // Populate ops such that ultimate scale/inversion function will be in `scale` var. Daniel@0: function parseScale(spec, ops) { Daniel@0: var code = "var scale = ", Daniel@0: idx = ops.length; Daniel@0: Daniel@0: if (dl.isString(spec)) { Daniel@0: ops.push({ value: spec }); Daniel@0: code += "this.root().scale(o"+idx+")"; Daniel@0: } else if (spec.arg) { // Scale function is being passed as an arg Daniel@0: ops.push(spec); Daniel@0: code += "o"+idx; Daniel@0: } else if (spec.name) { // Full scale parameter {name: ..} Daniel@0: ops.push(dl.isString(spec.name) ? {value: spec.name} : spec.name); Daniel@0: code += "(this.isFunction(o"+idx+") ? o"+idx+" : "; Daniel@0: if (spec.scope) { Daniel@0: ops.push(spec.scope); Daniel@0: code += "((o"+(idx+1)+".scale || this.root().scale)(o"+idx+") || this.nullScale)"; Daniel@0: } else { Daniel@0: code += "this.root().scale(o"+idx+")"; Daniel@0: } Daniel@0: code += ")"; Daniel@0: } Daniel@0: Daniel@0: if (spec.invert === true) { // Allow spec.invert.arg? Daniel@0: code += ".invert"; Daniel@0: } Daniel@0: Daniel@0: return code+";\n"; Daniel@0: } Daniel@0: Daniel@0: module.exports = parsePredicates; Daniel@0: },{"datalib":24}],102:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: dl = require('datalib'), Daniel@0: log = require('vega-logging'), Daniel@0: Tuple = require('vega-dataflow').Tuple; Daniel@0: Daniel@0: var DEPS = ["signals", "scales", "data", "fields"]; Daniel@0: Daniel@0: function properties(model, mark, spec) { Daniel@0: var config = model.config(), Daniel@0: code = "", Daniel@0: names = dl.keys(spec), Daniel@0: i, len, name, ref, vars = {}, Daniel@0: deps = { Daniel@0: signals: {}, Daniel@0: scales: {}, Daniel@0: data: {}, Daniel@0: fields: {}, Daniel@0: nested: [], Daniel@0: _nRefs: {}, // Temp stash to de-dupe nested refs. Daniel@0: reflow: false Daniel@0: }; Daniel@0: Daniel@0: code += "var o = trans ? {} : item, d=0, set=this.tpl.set, tmpl=signals||{}, t;\n" + Daniel@0: // Stash for dl.template Daniel@0: "tmpl.datum = item.datum;\n" + Daniel@0: "tmpl.group = group;\n" + Daniel@0: "tmpl.parent = group.datum;\n"; Daniel@0: Daniel@0: function handleDep(p) { Daniel@0: if (ref[p] == null) return; Daniel@0: var k = dl.array(ref[p]), i, n; Daniel@0: for (i=0, n=k.length; i 0) ? "\n " : " "; Daniel@0: if (ref.rule) { Daniel@0: ref = rule(model, name, ref.rule); Daniel@0: code += "\n " + ref.code; Daniel@0: } else { Daniel@0: ref = valueRef(config, name, ref); Daniel@0: code += "d += set(o, "+dl.str(name)+", "+ref.val+");"; Daniel@0: } Daniel@0: Daniel@0: vars[name] = true; Daniel@0: DEPS.forEach(handleDep); Daniel@0: deps.reflow = deps.reflow || ref.reflow; Daniel@0: if (ref.nested.length) ref.nested.forEach(handleNestedRefs); Daniel@0: } Daniel@0: Daniel@0: // If nested references are present, sort them based on their level Daniel@0: // to speed up determination of whether encoders should be reeval'd. Daniel@0: dl.keys(deps._nRefs).forEach(function(k) { deps.nested.push(deps._nRefs[k]); }); Daniel@0: deps.nested.sort(function(a, b) { Daniel@0: a = a.level; Daniel@0: b = b.level; Daniel@0: return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; Daniel@0: }); Daniel@0: Daniel@0: if (vars.x2) { Daniel@0: if (vars.x) { Daniel@0: code += "\n if (o.x > o.x2) { " + Daniel@0: "\n t = o.x;" + Daniel@0: "\n d += set(o, 'x', o.x2);" + Daniel@0: "\n d += set(o, 'x2', t); " + Daniel@0: "\n };"; Daniel@0: code += "\n d += set(o, 'width', (o.x2 - o.x));"; Daniel@0: } else if (vars.width) { Daniel@0: code += "\n d += set(o, 'x', (o.x2 - o.width));"; Daniel@0: } else { Daniel@0: code += "\n d += set(o, 'x', o.x2);"; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (vars.xc) { Daniel@0: if (vars.width) { Daniel@0: code += "\n d += set(o, 'x', (o.xc - o.width/2));" ; Daniel@0: } else { Daniel@0: code += "\n d += set(o, 'x', o.xc);" ; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (vars.y2) { Daniel@0: if (vars.y) { Daniel@0: code += "\n if (o.y > o.y2) { " + Daniel@0: "\n t = o.y;" + Daniel@0: "\n d += set(o, 'y', o.y2);" + Daniel@0: "\n d += set(o, 'y2', t);" + Daniel@0: "\n };"; Daniel@0: code += "\n d += set(o, 'height', (o.y2 - o.y));"; Daniel@0: } else if (vars.height) { Daniel@0: code += "\n d += set(o, 'y', (o.y2 - o.height));"; Daniel@0: } else { Daniel@0: code += "\n d += set(o, 'y', o.y2);"; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (vars.yc) { Daniel@0: if (vars.height) { Daniel@0: code += "\n d += set(o, 'y', (o.yc - o.height/2));" ; Daniel@0: } else { Daniel@0: code += "\n d += set(o, 'y', o.yc);" ; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (hasPath(mark, vars)) code += "\n d += (item.touch(), 1);"; Daniel@0: code += "\n if (trans) trans.interpolate(item, o);"; Daniel@0: code += "\n return d > 0;"; Daniel@0: Daniel@0: try { Daniel@0: /* jshint evil:true */ Daniel@0: var encoder = Function('item', 'group', 'trans', 'db', Daniel@0: 'signals', 'predicates', code); Daniel@0: encoder.tpl = Tuple; Daniel@0: encoder.util = dl; Daniel@0: encoder.d3 = d3; // For color spaces Daniel@0: dl.extend(encoder, dl.template.context); Daniel@0: return { Daniel@0: encode: encoder, Daniel@0: signals: dl.keys(deps.signals), Daniel@0: scales: dl.keys(deps.scales), Daniel@0: data: dl.keys(deps.data), Daniel@0: fields: dl.keys(deps.fields), Daniel@0: nested: deps.nested, Daniel@0: reflow: deps.reflow Daniel@0: }; Daniel@0: } catch (e) { Daniel@0: log.error(e); Daniel@0: log.log(code); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function dependencies(a, b) { Daniel@0: if (!dl.isObject(a)) { Daniel@0: a = {reflow: false, nested: []}; Daniel@0: DEPS.forEach(function(d) { a[d] = []; }); Daniel@0: } Daniel@0: Daniel@0: if (dl.isObject(b)) { Daniel@0: a.reflow = a.reflow || b.reflow; Daniel@0: a.nested.push.apply(a.nested, b.nested); Daniel@0: DEPS.forEach(function(d) { a[d].push.apply(a[d], b[d]); }); Daniel@0: } Daniel@0: Daniel@0: return a; Daniel@0: } Daniel@0: Daniel@0: function hasPath(mark, vars) { Daniel@0: return vars.path || Daniel@0: ((mark==='area' || mark==='line') && Daniel@0: (vars.x || vars.x2 || vars.width || Daniel@0: vars.y || vars.y2 || vars.height || Daniel@0: vars.tension || vars.interpolate)); Daniel@0: } Daniel@0: Daniel@0: function rule(model, name, rules) { Daniel@0: var config = model.config(), Daniel@0: deps = dependencies(), Daniel@0: inputs = [], code = ''; Daniel@0: Daniel@0: (rules||[]).forEach(function(r, i) { Daniel@0: var def = r.predicate, Daniel@0: predName = def && (def.name || def), Daniel@0: pred = model.predicate(predName), Daniel@0: p = 'predicates['+dl.str(predName)+']', Daniel@0: input = [], args = name+'_arg'+i, Daniel@0: ref; Daniel@0: Daniel@0: if (dl.isObject(def)) { Daniel@0: dl.keys(def).forEach(function(k) { Daniel@0: if (k === 'name') return; Daniel@0: var ref = valueRef(config, i, def[k]); Daniel@0: input.push(dl.str(k)+': '+ref.val); Daniel@0: dependencies(deps, ref); Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: ref = valueRef(config, name, r); Daniel@0: dependencies(deps, ref); Daniel@0: Daniel@0: if (predName) { Daniel@0: deps.signals.push.apply(deps.signals, pred.signals); Daniel@0: deps.data.push.apply(deps.data, pred.data); Daniel@0: inputs.push(args+" = {\n "+input.join(",\n ")+"\n }"); Daniel@0: code += "if ("+p+".call("+p+","+args+", db, signals, predicates)) {" + Daniel@0: "\n d += set(o, "+dl.str(name)+", "+ref.val+");"; Daniel@0: code += rules[i+1] ? "\n } else " : " }"; Daniel@0: } else { Daniel@0: code += "{" + Daniel@0: "\n d += set(o, "+dl.str(name)+", "+ref.val+");"+ Daniel@0: "\n }\n"; Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: code = "var " + inputs.join(",\n ") + ";\n " + code; Daniel@0: return (deps.code = code, deps); Daniel@0: } Daniel@0: Daniel@0: function valueRef(config, name, ref) { Daniel@0: if (ref == null) return null; Daniel@0: Daniel@0: if (name==='fill' || name==='stroke') { Daniel@0: if (ref.c) { Daniel@0: return colorRef(config, 'hcl', ref.h, ref.c, ref.l); Daniel@0: } else if (ref.h || ref.s) { Daniel@0: return colorRef(config, 'hsl', ref.h, ref.s, ref.l); Daniel@0: } else if (ref.l || ref.a) { Daniel@0: return colorRef(config, 'lab', ref.l, ref.a, ref.b); Daniel@0: } else if (ref.r || ref.g || ref.b) { Daniel@0: return colorRef(config, 'rgb', ref.r, ref.g, ref.b); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // initialize value Daniel@0: var val = null, scale = null, Daniel@0: deps = dependencies(), Daniel@0: sgRef = null, fRef = null, sRef = null, tmpl = {}; Daniel@0: Daniel@0: if (ref.template !== undefined) { Daniel@0: val = dl.template.source(ref.template, 'tmpl', tmpl); Daniel@0: dl.keys(tmpl).forEach(function(k) { Daniel@0: var f = dl.field(k), Daniel@0: a = f.shift(); Daniel@0: if (a === 'parent' || a === 'group') { Daniel@0: deps.nested.push({ Daniel@0: parent: a === 'parent', Daniel@0: group: a === 'group', Daniel@0: level: 1 Daniel@0: }); Daniel@0: } else if (a === 'datum') { Daniel@0: deps.fields.push(f[0]); Daniel@0: } else { Daniel@0: deps.signals.push(a); Daniel@0: } Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: if (ref.value !== undefined) { Daniel@0: val = dl.str(ref.value); Daniel@0: } Daniel@0: Daniel@0: if (ref.signal !== undefined) { Daniel@0: sgRef = dl.field(ref.signal); Daniel@0: val = 'signals['+sgRef.map(dl.str).join('][')+']'; Daniel@0: deps.signals.push(sgRef.shift()); Daniel@0: } Daniel@0: Daniel@0: if (ref.field !== undefined) { Daniel@0: ref.field = dl.isString(ref.field) ? {datum: ref.field} : ref.field; Daniel@0: fRef = fieldRef(ref.field); Daniel@0: val = fRef.val; Daniel@0: dependencies(deps, fRef); Daniel@0: } Daniel@0: Daniel@0: if (ref.scale !== undefined) { Daniel@0: sRef = scaleRef(ref.scale); Daniel@0: scale = sRef.val; Daniel@0: dependencies(deps, sRef); Daniel@0: deps.scales.push(ref.scale.name || ref.scale); Daniel@0: Daniel@0: // run through scale function if val specified. Daniel@0: // if no val, scale function is predicate arg. Daniel@0: if (val !== null || ref.band || ref.mult || ref.offset) { Daniel@0: val = scale + (ref.band ? '.rangeBand()' : Daniel@0: '('+(val !== null ? val : 'item.datum.data')+')'); Daniel@0: } else { Daniel@0: val = scale; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: // multiply, offset, return value Daniel@0: val = '(' + (ref.mult?(dl.number(ref.mult)+' * '):'') + val + ')' + Daniel@0: (ref.offset ? ' + ' + dl.number(ref.offset) : ''); Daniel@0: Daniel@0: // Collate dependencies Daniel@0: return (deps.val = val, deps); Daniel@0: } Daniel@0: Daniel@0: function colorRef(config, type, x, y, z) { Daniel@0: var xx = x ? valueRef(config, '', x) : config.color[type][0], Daniel@0: yy = y ? valueRef(config, '', y) : config.color[type][1], Daniel@0: zz = z ? valueRef(config, '', z) : config.color[type][2], Daniel@0: deps = dependencies(); Daniel@0: Daniel@0: [xx, yy, zz].forEach(function(v) { Daniel@0: if (dl.isArray) return; Daniel@0: dependencies(deps, v); Daniel@0: }); Daniel@0: Daniel@0: var val = '(this.d3.' + type + '(' + [xx.val, yy.val, zz.val].join(',') + ') + "")'; Daniel@0: return (deps.val = val, deps); Daniel@0: } Daniel@0: Daniel@0: // {field: {datum: "foo"} } -> item.datum.foo Daniel@0: // {field: {group: "foo"} } -> group.foo Daniel@0: // {field: {parent: "foo"} } -> group.datum.foo Daniel@0: function fieldRef(ref) { Daniel@0: if (dl.isString(ref)) { Daniel@0: return {val: dl.field(ref).map(dl.str).join('][')}; Daniel@0: } Daniel@0: Daniel@0: // Resolve nesting/parent lookups Daniel@0: var l = ref.level || 1, Daniel@0: nested = (ref.group || ref.parent) && l, Daniel@0: scope = nested ? Array(l).join('group.mark.') : '', Daniel@0: r = fieldRef(ref.datum || ref.group || ref.parent || ref.signal), Daniel@0: val = r.val, Daniel@0: deps = dependencies(null, r); Daniel@0: Daniel@0: if (ref.datum) { Daniel@0: val = 'item.datum['+val+']'; Daniel@0: deps.fields.push(ref.datum); Daniel@0: } else if (ref.group) { Daniel@0: val = scope+'group['+val+']'; Daniel@0: deps.nested.push({ level: l, group: true }); Daniel@0: } else if (ref.parent) { Daniel@0: val = scope+'group.datum['+val+']'; Daniel@0: deps.nested.push({ level: l, parent: true }); Daniel@0: } else if (ref.signal) { Daniel@0: val = 'signals['+val+']'; Daniel@0: deps.signals.push(dl.field(ref.signal)[0]); Daniel@0: deps.reflow = true; Daniel@0: } Daniel@0: Daniel@0: return (deps.val = val, deps); Daniel@0: } Daniel@0: Daniel@0: // {scale: "x"} Daniel@0: // {scale: {name: "x"}}, Daniel@0: // {scale: fieldRef} Daniel@0: function scaleRef(ref) { Daniel@0: var scale = null, Daniel@0: fr = null, Daniel@0: deps = dependencies(); Daniel@0: Daniel@0: if (dl.isString(ref)) { Daniel@0: scale = dl.str(ref); Daniel@0: } else if (ref.name) { Daniel@0: scale = dl.isString(ref.name) ? dl.str(ref.name) : (fr = fieldRef(ref.name)).val; Daniel@0: } else { Daniel@0: scale = (fr = fieldRef(ref)).val; Daniel@0: } Daniel@0: Daniel@0: scale = '(item.mark._scaleRefs['+scale+'] = 1, group.scale('+scale+'))'; Daniel@0: if (ref.invert) scale += '.invert'; Daniel@0: Daniel@0: // Mark scale refs as they're dealt with separately in mark._scaleRefs. Daniel@0: if (fr) fr.nested.forEach(function(g) { g.scale = true; }); Daniel@0: return fr ? (fr.val = scale, fr) : (deps.val = scale, deps); Daniel@0: } Daniel@0: Daniel@0: module.exports = properties; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],103:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: SIGNALS = require('vega-dataflow').Dependencies.SIGNALS, Daniel@0: expr = require('./expr'); Daniel@0: Daniel@0: var RESERVED = ['datum', 'event', 'signals'] Daniel@0: .concat(dl.keys(expr.codegen.functions)); Daniel@0: Daniel@0: function parseSignals(model, spec) { Daniel@0: // process each signal definition Daniel@0: (spec || []).forEach(function(s) { Daniel@0: if (RESERVED.indexOf(s.name) !== -1) { Daniel@0: throw Error('Signal name "'+s.name+'" is a '+ Daniel@0: 'reserved keyword ('+RESERVED.join(', ')+').'); Daniel@0: } Daniel@0: Daniel@0: var signal = model.signal(s.name, s.init) Daniel@0: .verbose(s.verbose); Daniel@0: Daniel@0: if (s.init && s.init.expr) { Daniel@0: s.init.expr = expr(s.init.expr); Daniel@0: signal.value(exprVal(model, s.init)); Daniel@0: } Daniel@0: Daniel@0: if (s.expr) { Daniel@0: s.expr = expr(s.expr); Daniel@0: signal.evaluate = function(input) { Daniel@0: var val = exprVal(model, s); Daniel@0: if (val !== signal.value() || signal.verbose()) { Daniel@0: signal.value(val); Daniel@0: input.signals[s.name] = 1; Daniel@0: return input; Daniel@0: } Daniel@0: return model.doNotPropagate; Daniel@0: }; Daniel@0: signal.dependency(SIGNALS, s.expr.globals); Daniel@0: s.expr.globals.forEach(function(dep) { Daniel@0: model.signal(dep).addListener(signal); Daniel@0: }); Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: return spec; Daniel@0: } Daniel@0: Daniel@0: function exprVal(model, spec) { Daniel@0: var e = spec.expr, Daniel@0: val = e.fn(null, null, model.values(SIGNALS, e.globals)); Daniel@0: return spec.scale ? parseSignals.scale(model, spec, val) : val; Daniel@0: } Daniel@0: Daniel@0: parseSignals.scale = function scale(model, spec, value, datum, evt) { Daniel@0: var def = spec.scale, Daniel@0: name = def.name || def.signal || def, Daniel@0: scope = def.scope, e; Daniel@0: Daniel@0: if (scope) { Daniel@0: if (scope.signal) { Daniel@0: scope = model.signalRef(scope.signal); Daniel@0: } else if (dl.isString(scope)) { // Scope is an expression Daniel@0: e = def._expr = (def._expr || expr(scope)); Daniel@0: scope = e.fn(datum, evt, model.values(SIGNALS, e.globals)); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (!scope || !scope.scale) { Daniel@0: scope = (scope && scope.mark) ? scope.mark.group : model.scene().items[0]; Daniel@0: } Daniel@0: Daniel@0: var s = scope.scale(name); Daniel@0: return !s ? value : (def.invert ? s.invert(value) : s(value)); Daniel@0: }; Daniel@0: Daniel@0: module.exports = parseSignals; Daniel@0: },{"./expr":94,"datalib":24,"vega-dataflow":39}],104:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: log = require('vega-logging'), Daniel@0: Model = require('../core/Model'), Daniel@0: View = require('../core/View'); Daniel@0: Daniel@0: function parseSpec(spec, callback) { Daniel@0: var vf = arguments[arguments.length-1], Daniel@0: viewFactory = arguments.length > 2 && dl.isFunction(vf) ? vf : View.factory, Daniel@0: config = arguments[2] !== viewFactory ? arguments[2] : {}, Daniel@0: model = new Model(config); Daniel@0: Daniel@0: function parse(spec) { Daniel@0: // protect against subsequent spec modification Daniel@0: spec = dl.duplicate(spec); Daniel@0: Daniel@0: var parsers = require('./'), Daniel@0: width = spec.width || 500, Daniel@0: height = spec.height || 500, Daniel@0: viewport = spec.viewport || null; Daniel@0: Daniel@0: model.defs({ Daniel@0: width: width, Daniel@0: height: height, Daniel@0: viewport: viewport, Daniel@0: background: parsers.background(spec.background), Daniel@0: padding: parsers.padding(spec.padding), Daniel@0: signals: parsers.signals(model, spec.signals), Daniel@0: predicates: parsers.predicates(model, spec.predicates), Daniel@0: marks: parsers.marks(model, spec, width, height), Daniel@0: data: parsers.data(model, spec.data, function() { Daniel@0: callback(viewFactory(model)); Daniel@0: }) Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: if (dl.isObject(spec)) { Daniel@0: parse(spec); Daniel@0: } else if (dl.isString(spec)) { Daniel@0: var opts = dl.extend({url: spec}, model.config().load); Daniel@0: dl.load(opts, function(err, data) { Daniel@0: if (err) { Daniel@0: log.error('LOADING SPECIFICATION FAILED: ' + err.statusText); Daniel@0: } else { Daniel@0: try { Daniel@0: parse(JSON.parse(data)); Daniel@0: } catch (e) { Daniel@0: log.error('INVALID SPECIFICATION: Must be a valid JSON object. '+e); Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: } else { Daniel@0: log.error('INVALID SPECIFICATION: Must be a valid JSON object or URL.'); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: module.exports = parseSpec; Daniel@0: },{"../core/Model":86,"../core/View":87,"./":95,"datalib":24,"vega-logging":45}],105:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: dl = require('datalib'), Daniel@0: df = require('vega-dataflow'), Daniel@0: SIGNALS = df.Dependencies.SIGNALS, Daniel@0: parseSignals = require('./signals'), Daniel@0: selector = require('./events'), Daniel@0: expr = require('./expr'); Daniel@0: Daniel@0: var GATEKEEPER = '_vgGATEKEEPER'; Daniel@0: Daniel@0: var vgEvent = { Daniel@0: getGroup: function(name) { return name ? this.name[name] : this.group; }, Daniel@0: getXY: function(item) { Daniel@0: var p = {x: this.x, y: this.y}; Daniel@0: if (typeof item === 'string') { Daniel@0: item = this.name[item]; Daniel@0: } Daniel@0: for (; item; item = item.mark && item.mark.group) { Daniel@0: p.x -= item.x || 0; Daniel@0: p.y -= item.y || 0; Daniel@0: } Daniel@0: return p; Daniel@0: }, Daniel@0: getX: function(item) { return this.getXY(item).x; }, Daniel@0: getY: function(item) { return this.getXY(item).y; } Daniel@0: }; Daniel@0: Daniel@0: function parseStreams(view) { Daniel@0: var model = view.model(), Daniel@0: spec = model.defs().signals, Daniel@0: registry = {handlers: {}, nodes: {}}, Daniel@0: internal = dl.duplicate(registry), // Internal event processing Daniel@0: external = dl.duplicate(registry); // External event processing Daniel@0: Daniel@0: (spec || []).forEach(function(sig) { Daniel@0: var signal = model.signal(sig.name); Daniel@0: if (sig.expr) return; // Cannot have an expr and stream definition. Daniel@0: Daniel@0: (sig.streams || []).forEach(function(stream) { Daniel@0: var sel = selector.parse(stream.type), Daniel@0: exp = expr(stream.expr); Daniel@0: mergedStream(signal, sel, exp, stream); Daniel@0: }); Daniel@0: }); Daniel@0: Daniel@0: // We register the event listeners all together so that if multiple Daniel@0: // signals are registered on the same event, they will receive the Daniel@0: // new value on the same pulse. Daniel@0: dl.keys(internal.handlers).forEach(function(type) { Daniel@0: view.on(type, function(evt, item) { Daniel@0: evt.preventDefault(); // stop text selection Daniel@0: extendEvent(evt, item); Daniel@0: fire(internal, type, (item && item.datum) || {}, evt); Daniel@0: }); Daniel@0: }); Daniel@0: Daniel@0: // add external event listeners Daniel@0: dl.keys(external.handlers).forEach(function(type) { Daniel@0: if (typeof window === 'undefined') return; // No external support Daniel@0: Daniel@0: var h = external.handlers[type], Daniel@0: t = type.split(':'), // --> no element pseudo-selectors Daniel@0: elt = (t[0] === 'window') ? [window] : Daniel@0: window.document.querySelectorAll(t[0]); Daniel@0: Daniel@0: function handler(evt) { Daniel@0: extendEvent(evt); Daniel@0: fire(external, type, d3.select(this).datum(), evt); Daniel@0: } Daniel@0: Daniel@0: for (var i=0; i 0, Daniel@0: i, ilen, j, jlen, group, legend; Daniel@0: Daniel@0: if (input.add.length || input.rem.length || !items.length || Daniel@0: input.mod.length === items.length || Daniel@0: type === 'area' || type === 'line') { Daniel@0: bound.mark(this._mark, null, isGrp && !hasLegends); Daniel@0: } else { Daniel@0: input.mod.forEach(function(item) { bound.item(item); }); Daniel@0: } Daniel@0: Daniel@0: if (isGrp && hasLegends) { Daniel@0: for (i=0, ilen=items.length; i this._stamp) { Daniel@0: output = join.call(this, fcs, this._ds.values(), true, fullUpdate); Daniel@0: } Daniel@0: } else { Daniel@0: data = dl.isFunction(this._def.from) ? this._def.from() : [Sentinel]; Daniel@0: output = join.call(this, input, data); Daniel@0: } Daniel@0: Daniel@0: // Stash output before Bounder for downstream reactive geometry. Daniel@0: this._output = output = this._graph.evaluate(output, this._encoder); Daniel@0: Daniel@0: // Add any new scale references to the dependency list, and ensure Daniel@0: // they're connected. Daniel@0: if (update.nested && update.nested.length && this._status === CONNECTED) { Daniel@0: dl.keys(this._mark._scaleRefs).forEach(function(s) { Daniel@0: var scale = self._parent.scale(s); Daniel@0: if (!scale) return; Daniel@0: Daniel@0: scale.addListener(self); Daniel@0: self.dependency(Deps.SCALES, s); Daniel@0: self._encoder.dependency(Deps.SCALES, s); Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: // Supernodes calculate bounds too, but only on items marked dirty. Daniel@0: if (this._isSuper) { Daniel@0: output.mod = output.mod.filter(function(x) { return x._dirty; }); Daniel@0: output = this._graph.evaluate(output, this._bounder); Daniel@0: } Daniel@0: Daniel@0: return output; Daniel@0: }; Daniel@0: Daniel@0: function newItem() { Daniel@0: var item = Tuple.ingest(new Item(this._mark)); Daniel@0: Daniel@0: // For the root node's item Daniel@0: if (this._def.width) Tuple.set(item, 'width', this._def.width); Daniel@0: if (this._def.height) Tuple.set(item, 'height', this._def.height); Daniel@0: return item; Daniel@0: } Daniel@0: Daniel@0: function join(input, data, ds, fullUpdate) { Daniel@0: var output = ChangeSet.create(input), Daniel@0: keyf = keyFunction(this._def.key || (ds ? '_id' : null)), Daniel@0: prev = this._mark.items || [], Daniel@0: rem = ds ? input.rem : prev, Daniel@0: mod = Tuple.idMap((!ds || fullUpdate) ? data : input.mod), Daniel@0: next = [], Daniel@0: i, key, len, item, datum, enter, diff; Daniel@0: Daniel@0: // Only mark rems as exiting. Due to keyf, there may be an add/mod Daniel@0: // tuple that replaces it. Daniel@0: for (i=0, len=rem.length; i0) s += '|'; Daniel@0: s += String(f[i](d)); Daniel@0: } Daniel@0: return s; Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: module.exports = Builder; Daniel@0: },{"../parse/data":92,"./Bounder":107,"./Encoder":109,"datalib":24,"vega-dataflow":39,"vega-logging":45,"vega-scenegraph":46}],109:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: log = require('vega-logging'), Daniel@0: df = require('vega-dataflow'), Daniel@0: Node = df.Node, // jshint ignore:line Daniel@0: Deps = df.Dependencies, Daniel@0: bound = require('vega-scenegraph').bound; Daniel@0: Daniel@0: var EMPTY = {}; Daniel@0: Daniel@0: function Encoder(graph, mark, builder) { Daniel@0: var props = mark.def.properties || {}, Daniel@0: enter = props.enter, Daniel@0: update = props.update, Daniel@0: exit = props.exit; Daniel@0: Daniel@0: Node.prototype.init.call(this, graph); Daniel@0: Daniel@0: this._mark = mark; Daniel@0: this._builder = builder; Daniel@0: var s = this._scales = []; Daniel@0: Daniel@0: // Only scales used in the 'update' property set are set as Daniel@0: // encoder depedencies to have targeted reevaluations. However, Daniel@0: // we still want scales in 'enter' and 'exit' to be evaluated Daniel@0: // before the encoder. Daniel@0: if (enter) s.push.apply(s, enter.scales); Daniel@0: Daniel@0: if (update) { Daniel@0: this.dependency(Deps.DATA, update.data); Daniel@0: this.dependency(Deps.SIGNALS, update.signals); Daniel@0: this.dependency(Deps.FIELDS, update.fields); Daniel@0: this.dependency(Deps.SCALES, update.scales); Daniel@0: s.push.apply(s, update.scales); Daniel@0: } Daniel@0: Daniel@0: if (exit) s.push.apply(s, exit.scales); Daniel@0: Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var proto = (Encoder.prototype = new Node()); Daniel@0: Daniel@0: proto.evaluate = function(input) { Daniel@0: log.debug(input, ['encoding', this._mark.def.type]); Daniel@0: var graph = this._graph, Daniel@0: props = this._mark.def.properties || {}, Daniel@0: items = this._mark.items, Daniel@0: enter = props.enter, Daniel@0: update = props.update, Daniel@0: exit = props.exit, Daniel@0: dirty = input.dirty, Daniel@0: preds = graph.predicates(), Daniel@0: req = input.request, Daniel@0: group = this._mark.group, Daniel@0: guide = group && (group.mark.axis || group.mark.legend), Daniel@0: db = EMPTY, sg = EMPTY, i, len, item, prop; Daniel@0: Daniel@0: if (req && !guide) { Daniel@0: if ((prop = props[req]) && input.mod.length) { Daniel@0: db = prop.data ? graph.values(Deps.DATA, prop.data) : null; Daniel@0: sg = prop.signals ? graph.values(Deps.SIGNALS, prop.signals) : null; Daniel@0: Daniel@0: for (i=0, len=input.mod.length; i this._stamp) return true; Daniel@0: } Daniel@0: Daniel@0: return false; Daniel@0: } Daniel@0: Daniel@0: // Short-circuit encoder if user specifies items Daniel@0: Encoder.update = function(graph, trans, request, items, dirty) { Daniel@0: items = dl.array(items); Daniel@0: var preds = graph.predicates(), Daniel@0: db = graph.values(Deps.DATA), Daniel@0: sg = graph.values(Deps.SIGNALS), Daniel@0: i, len, item, props, prop; Daniel@0: Daniel@0: for (i=0, len=items.length; i 0, Daniel@0: hasAxes = dl.array(this._def.axes).length > 0, Daniel@0: hasLegends = dl.array(this._def.legends).length > 0, Daniel@0: i, j, c, len, group, pipeline, def, inline = false; Daniel@0: Daniel@0: for (i=0, len=input.add.length; i=0; --i) { Daniel@0: group = input.add[i]; Daniel@0: for (j=this._children[group._id].length-1; j>=0; --j) { Daniel@0: c = this._children[group._id][j]; Daniel@0: c.builder.connect(); Daniel@0: pipeline = c.builder.pipeline(); Daniel@0: def = c.builder._def; Daniel@0: Daniel@0: // This new child needs to be built during this propagation cycle. Daniel@0: // We could add its builder as a listener off the _recursor node, Daniel@0: // but try to inline it if we can to minimize graph dispatches. Daniel@0: inline = (def.type !== Types.GROUP); Daniel@0: inline = inline && (this._graph.data(c.from) !== undefined); Daniel@0: inline = inline && (pipeline[pipeline.length-1].listeners().length === 1); // Reactive geom source Daniel@0: inline = inline && (def.from && !def.from.mark); // Reactive geom target Daniel@0: c.inline = inline; Daniel@0: Daniel@0: if (inline) this._graph.evaluate(input, c.builder); Daniel@0: else this._recursor.addListener(c.builder); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function removeTemp(c) { Daniel@0: if (c.type == Types.MARK && !c.inline && Daniel@0: builder._graph.data(c.from) !== undefined) { Daniel@0: builder._recursor.removeListener(c.builder); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function updateAxis(a) { Daniel@0: var scale = a.scale(); Daniel@0: if (!input.scales[scale.scaleName]) return; Daniel@0: a.reset().def(); Daniel@0: } Daniel@0: Daniel@0: function updateLegend(l) { Daniel@0: var scale = l.size() || l.shape() || l.fill() || l.stroke(); Daniel@0: if (!input.scales[scale.scaleName]) return; Daniel@0: l.reset().def(); Daniel@0: } Daniel@0: Daniel@0: for (i=0, len=input.mod.length; i rng[1]) { Daniel@0: start = rng[1] || 0; Daniel@0: rng = [start + (bw * len + space), start]; Daniel@0: } else { Daniel@0: start = rng[0] || 0; Daniel@0: rng = [start, start + (bw * len + space)]; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: str = typeof rng[0] === 'string'; Daniel@0: if (str || rng.length > 2 || rng.length===1 || dataDrivenRange) { Daniel@0: scale.range(rng); // color or shape values Daniel@0: } else if (points && round) { Daniel@0: scale.rangeRoundPoints(rng, pad); Daniel@0: } else if (points) { Daniel@0: scale.rangePoints(rng, pad); Daniel@0: } else if (round) { Daniel@0: scale.rangeRoundBands(rng, pad, outer); Daniel@0: } else { Daniel@0: scale.rangeBands(rng, pad, outer); Daniel@0: } Daniel@0: Daniel@0: if (!scale.invert) { Daniel@0: scale.invert = function(x, y) { Daniel@0: if (arguments.length === 1) { Daniel@0: return scale.domain()[d3.bisect(scale.range(), x) - 1]; Daniel@0: } else if (arguments.length === 2) { // Invert extents Daniel@0: if (!dl.isNumber(x) || !dl.isNumber(y)) { Daniel@0: throw Error('Extents to ordinal invert are not numbers ('+x+', '+y+').'); Daniel@0: } Daniel@0: Daniel@0: var points = [], Daniel@0: rng = scale.range(), Daniel@0: i = 0, len = rng.length, r; Daniel@0: Daniel@0: for(; i 0) return; Daniel@0: if (exponent && def.type===Types.POWER) scale.exponent(exponent); Daniel@0: if (clamp) scale.clamp(true); Daniel@0: if (nice) { Daniel@0: if (def.type === Types.TIME) { Daniel@0: interval = d3.time[nice]; Daniel@0: if (!interval) log.error('Unrecognized interval: ' + interval); Daniel@0: scale.nice(interval); Daniel@0: } else { Daniel@0: scale.nice(); Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function isUniques(scale) { Daniel@0: return scale.type === Types.ORDINAL || scale.type === Types.QUANTILE; Daniel@0: } Daniel@0: Daniel@0: function getRefs(def) { Daniel@0: return def.fields || dl.array(def); Daniel@0: } Daniel@0: Daniel@0: function inherits(refs) { Daniel@0: return refs.some(function(r) { Daniel@0: if (!r.data) return true; Daniel@0: return r.data && dl.array(r.field).some(function(f) { Daniel@0: return f.parent; Daniel@0: }); Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: function getFields(ref, group) { Daniel@0: return dl.array(ref.field).map(function(f) { Daniel@0: return f.parent ? Daniel@0: dl.accessor(f.parent)(group.datum) : Daniel@0: f; // String or {'signal'} Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: // Scale datarefs can be computed over multiple schema types. Daniel@0: // This function determines the type of aggregator created, and Daniel@0: // what data is sent to it: values, tuples, or multi-tuples that must Daniel@0: // be standardized into a consistent schema. Daniel@0: function aggrType(def, scale) { Daniel@0: var refs = getRefs(def); Daniel@0: Daniel@0: // If we're operating over only a single domain, send full tuples Daniel@0: // through for efficiency (fewer accessor creations/calls) Daniel@0: if (refs.length == 1 && dl.array(refs[0].field).length == 1) { Daniel@0: return Aggregate.TYPES.TUPLE; Daniel@0: } Daniel@0: Daniel@0: // With quantitative scales, we only care about min/max. Daniel@0: if (!isUniques(scale)) return Aggregate.TYPES.VALUE; Daniel@0: Daniel@0: // If we don't sort, then we can send values directly to aggrs as well Daniel@0: if (!dl.isObject(def.sort)) return Aggregate.TYPES.VALUE; Daniel@0: Daniel@0: return Aggregate.TYPES.MULTI; Daniel@0: } Daniel@0: Daniel@0: function getCache(which, def, scale, group) { Daniel@0: var refs = getRefs(def), Daniel@0: inherit = inherits(refs), Daniel@0: atype = aggrType(def, scale), Daniel@0: uniques = isUniques(scale), Daniel@0: sort = def.sort, Daniel@0: ck = '_'+which, Daniel@0: fields = getFields(refs[0], group); Daniel@0: Daniel@0: if (scale[ck] || this[ck]) return scale[ck] || this[ck]; Daniel@0: Daniel@0: var cache = new Aggregate(this._graph).type(atype), Daniel@0: groupby, summarize; Daniel@0: Daniel@0: // If a scale's dataref doesn't inherit data from the group, we can Daniel@0: // store the dataref aggregator at the Scale (dataflow node) level. Daniel@0: if (inherit) { Daniel@0: scale[ck] = cache; Daniel@0: } else { Daniel@0: this[ck] = cache; Daniel@0: } Daniel@0: Daniel@0: if (uniques) { Daniel@0: if (atype === Aggregate.TYPES.VALUE) { Daniel@0: groupby = [{ name: DataRef.GROUPBY, get: dl.identity }]; Daniel@0: summarize = {'*': DataRef.COUNT}; Daniel@0: } else if (atype === Aggregate.TYPES.TUPLE) { Daniel@0: groupby = [{ name: DataRef.GROUPBY, get: dl.$(fields[0]) }]; Daniel@0: summarize = dl.isObject(sort) ? [{ Daniel@0: field: DataRef.VALUE, Daniel@0: get: dl.$(sort.field), Daniel@0: ops: [sort.op] Daniel@0: }] : {'*': DataRef.COUNT}; Daniel@0: } else { // atype === Aggregate.TYPES.MULTI Daniel@0: groupby = DataRef.GROUPBY; Daniel@0: summarize = [{ field: DataRef.VALUE, ops: [sort.op] }]; Daniel@0: } Daniel@0: } else { Daniel@0: groupby = []; Daniel@0: summarize = [{ Daniel@0: field: DataRef.VALUE, Daniel@0: get: (atype == Aggregate.TYPES.TUPLE) ? dl.$(fields[0]) : dl.identity, Daniel@0: ops: [DataRef.MIN, DataRef.MAX], Daniel@0: as: [DataRef.MIN, DataRef.MAX] Daniel@0: }]; Daniel@0: } Daniel@0: Daniel@0: cache.param('groupby', groupby) Daniel@0: .param('summarize', summarize); Daniel@0: Daniel@0: return (cache._lastUpdate = -1, cache); Daniel@0: } Daniel@0: Daniel@0: function dataRef(which, def, scale, group) { Daniel@0: if (def == null) { return []; } Daniel@0: if (dl.isArray(def)) return def.map(signal.bind(this)); Daniel@0: Daniel@0: var self = this, graph = this._graph, Daniel@0: refs = getRefs(def), Daniel@0: inherit = inherits(refs), Daniel@0: atype = aggrType(def, scale), Daniel@0: cache = getCache.apply(this, arguments), Daniel@0: sort = def.sort, Daniel@0: uniques = isUniques(scale), Daniel@0: i, rlen, j, flen, ref, fields, field, data, from, so, cmp; Daniel@0: Daniel@0: function addDep(s) { Daniel@0: self.dependency(Deps.SIGNALS, s); Daniel@0: } Daniel@0: Daniel@0: if (inherit || (!inherit && cache._lastUpdate < this._stamp)) { Daniel@0: for (i=0, rlen=refs.length; i 1) f = 1; Daniel@0: e = curr.ease(f); Daniel@0: Daniel@0: for (i=0, n=curr.length; i 0 ? (e = 1e-12, Math.ceil) : (e = -1e-12, Math.floor), Daniel@0: e; Daniel@0: function log(x) { Daniel@0: return (domain[0] < 0 ? Daniel@0: -Math.log(x > 0 ? 0 : -x) : Daniel@0: Math.log(x < 0 ? 0 : x)) / Math.log(base); Daniel@0: } Daniel@0: function pow(x) { Daniel@0: return domain[0] < 0 ? -Math.pow(base, -x) : Math.pow(base, x); Daniel@0: } Daniel@0: return function(d) { Daniel@0: return pow(v(log(d) + e)) / d >= k ? f(d) : ''; Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function getFormatter(formatType, str) { Daniel@0: var fmt = dl.format, Daniel@0: log = scale.type === 'log', Daniel@0: domain, f; Daniel@0: Daniel@0: switch (formatType) { Daniel@0: case NUMBER: Daniel@0: domain = scale.domain(); Daniel@0: f = fmt.auto.number(domain, tickCount, str || (log ? '.1r' : null)); Daniel@0: return log ? logFilter(domain, tickCount, f) : f; Daniel@0: case TIME: return (str ? fmt : fmt.auto).time(str); Daniel@0: case UTC: return (str ? fmt : fmt.auto).utc(str); Daniel@0: default: return String; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function getTicks(format) { Daniel@0: var major = tickValues || (scale.ticks ? scale.ticks(tickCount) : scale.domain()), Daniel@0: minor = axisSubdivide(scale, major, tickSubdivide).map(ingest); Daniel@0: major = major.map(function(d) { return (d = ingest(d), d.label = format(d.data), d); }); Daniel@0: return [major, minor]; Daniel@0: } Daniel@0: Daniel@0: axis.def = function() { Daniel@0: if (!axisDef.type) axis_def(scale); Daniel@0: Daniel@0: var ticks = getTicks(getTickFormat()); Daniel@0: var tdata = title ? [title].map(ingest) : []; Daniel@0: Daniel@0: axisDef.marks[0].from = function() { return grid ? ticks[0] : []; }; Daniel@0: axisDef.marks[1].from = function() { return ticks[0]; }; Daniel@0: axisDef.marks[2].from = function() { return ticks[1]; }; Daniel@0: axisDef.marks[3].from = axisDef.marks[1].from; Daniel@0: axisDef.marks[4].from = function() { return [1]; }; Daniel@0: axisDef.marks[5].from = function() { return tdata; }; Daniel@0: axisDef.offset = offset; Daniel@0: axisDef.orient = orient; Daniel@0: axisDef.layer = layer; Daniel@0: Daniel@0: return axisDef; Daniel@0: }; Daniel@0: Daniel@0: function axis_def(scale) { Daniel@0: // setup scale mapping Daniel@0: var newScale, oldScale, range; Daniel@0: if (scale.type === ORDINAL) { Daniel@0: newScale = {scale: scale.scaleName, offset: 0.5 + scale.rangeBand()/2}; Daniel@0: oldScale = newScale; Daniel@0: } else { Daniel@0: newScale = {scale: scale.scaleName, offset: 0.5}; Daniel@0: oldScale = {scale: scale.scaleName+':prev', offset: 0.5}; Daniel@0: } Daniel@0: range = axisScaleRange(scale); Daniel@0: Daniel@0: // setup axis marks Daniel@0: dl.extend(m.gridLines, axisTicks(config)); Daniel@0: dl.extend(m.majorTicks, axisTicks(config)); Daniel@0: dl.extend(m.minorTicks, axisTicks(config)); Daniel@0: dl.extend(m.tickLabels, axisTickLabels(config)); Daniel@0: dl.extend(m.domain, axisDomain(config)); Daniel@0: dl.extend(m.title, axisTitle(config)); Daniel@0: m.gridLines.properties.enter.stroke = {value: config.axis.gridColor}; Daniel@0: m.gridLines.properties.enter.strokeOpacity = {value: config.axis.gridOpacity}; Daniel@0: Daniel@0: // extend axis marks based on axis orientation Daniel@0: axisTicksExtend(orient, m.gridLines, oldScale, newScale, Infinity); Daniel@0: axisTicksExtend(orient, m.majorTicks, oldScale, newScale, tickMajorSize); Daniel@0: axisTicksExtend(orient, m.minorTicks, oldScale, newScale, tickMinorSize); Daniel@0: axisLabelExtend(orient, m.tickLabels, oldScale, newScale, tickMajorSize, tickPadding); Daniel@0: Daniel@0: axisDomainExtend(orient, m.domain, range, tickEndSize); Daniel@0: axisTitleExtend(orient, m.title, range, titleOffset); // TODO get offset Daniel@0: Daniel@0: // add / override custom style properties Daniel@0: dl.extend(m.gridLines.properties.update, gridLineStyle); Daniel@0: dl.extend(m.majorTicks.properties.update, majorTickStyle); Daniel@0: dl.extend(m.minorTicks.properties.update, minorTickStyle); Daniel@0: dl.extend(m.tickLabels.properties.update, tickLabelStyle); Daniel@0: dl.extend(m.domain.properties.update, domainStyle); Daniel@0: dl.extend(m.title.properties.update, titleStyle); Daniel@0: Daniel@0: var marks = [m.gridLines, m.majorTicks, m.minorTicks, m.tickLabels, m.domain, m.title]; Daniel@0: dl.extend(axisDef, { Daniel@0: type: 'group', Daniel@0: interactive: false, Daniel@0: properties: { Daniel@0: enter: { Daniel@0: encode: axisUpdate, Daniel@0: scales: [scale.scaleName], Daniel@0: signals: [], data: [] Daniel@0: }, Daniel@0: update: { Daniel@0: encode: axisUpdate, Daniel@0: scales: [scale.scaleName], Daniel@0: signals: [], data: [] Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: axisDef.marks = marks.map(function(m) { return parseMark(model, m); }); Daniel@0: } Daniel@0: Daniel@0: axis.scale = function(x) { Daniel@0: if (!arguments.length) return scale; Daniel@0: if (scale !== x) { scale = x; reset(); } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.orient = function(x) { Daniel@0: if (!arguments.length) return orient; Daniel@0: if (orient !== x) { Daniel@0: orient = x in axisOrients ? x + '' : config.axis.orient; Daniel@0: reset(); Daniel@0: } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.title = function(x) { Daniel@0: if (!arguments.length) return title; Daniel@0: if (title !== x) { title = x; reset(); } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickCount = function(x) { Daniel@0: if (!arguments.length) return tickCount; Daniel@0: tickCount = x; Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickValues = function(x) { Daniel@0: if (!arguments.length) return tickValues; Daniel@0: tickValues = x; Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickFormat = function(x) { Daniel@0: if (!arguments.length) return tickFormatString; Daniel@0: if (tickFormatString !== x) { Daniel@0: tickFormatString = x; Daniel@0: reset(); Daniel@0: } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickFormatType = function(x) { Daniel@0: if (!arguments.length) return tickFormatType; Daniel@0: if (tickFormatType !== x) { Daniel@0: tickFormatType = x; Daniel@0: reset(); Daniel@0: } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickSize = function(x, y) { Daniel@0: if (!arguments.length) return tickMajorSize; Daniel@0: var n = arguments.length - 1, Daniel@0: major = +x, Daniel@0: minor = n > 1 ? +y : tickMajorSize, Daniel@0: end = n > 0 ? +arguments[n] : tickMajorSize; Daniel@0: Daniel@0: if (tickMajorSize !== major || Daniel@0: tickMinorSize !== minor || Daniel@0: tickEndSize !== end) { Daniel@0: reset(); Daniel@0: } Daniel@0: Daniel@0: tickMajorSize = major; Daniel@0: tickMinorSize = minor; Daniel@0: tickEndSize = end; Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickSubdivide = function(x) { Daniel@0: if (!arguments.length) return tickSubdivide; Daniel@0: tickSubdivide = +x; Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.offset = function(x) { Daniel@0: if (!arguments.length) return offset; Daniel@0: offset = dl.isObject(x) ? x : +x; Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickPadding = function(x) { Daniel@0: if (!arguments.length) return tickPadding; Daniel@0: if (tickPadding !== +x) { tickPadding = +x; reset(); } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.titleOffset = function(x) { Daniel@0: if (!arguments.length) return titleOffset; Daniel@0: if (titleOffset !== +x) { titleOffset = +x; reset(); } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.layer = function(x) { Daniel@0: if (!arguments.length) return layer; Daniel@0: if (layer !== x) { layer = x; reset(); } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.grid = function(x) { Daniel@0: if (!arguments.length) return grid; Daniel@0: if (grid !== x) { grid = x; reset(); } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.gridLineProperties = function(x) { Daniel@0: if (!arguments.length) return gridLineStyle; Daniel@0: if (gridLineStyle !== x) { gridLineStyle = x; } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.majorTickProperties = function(x) { Daniel@0: if (!arguments.length) return majorTickStyle; Daniel@0: if (majorTickStyle !== x) { majorTickStyle = x; } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.minorTickProperties = function(x) { Daniel@0: if (!arguments.length) return minorTickStyle; Daniel@0: if (minorTickStyle !== x) { minorTickStyle = x; } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.tickLabelProperties = function(x) { Daniel@0: if (!arguments.length) return tickLabelStyle; Daniel@0: if (tickLabelStyle !== x) { tickLabelStyle = x; } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.titleProperties = function(x) { Daniel@0: if (!arguments.length) return titleStyle; Daniel@0: if (titleStyle !== x) { titleStyle = x; } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.domainProperties = function(x) { Daniel@0: if (!arguments.length) return domainStyle; Daniel@0: if (domainStyle !== x) { domainStyle = x; } Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: axis.reset = function() { Daniel@0: reset(); Daniel@0: return axis; Daniel@0: }; Daniel@0: Daniel@0: return axis; Daniel@0: } Daniel@0: Daniel@0: var axisOrients = {top: 1, right: 1, bottom: 1, left: 1}; Daniel@0: Daniel@0: function axisSubdivide(scale, ticks, m) { Daniel@0: var subticks = []; Daniel@0: if (m && ticks.length > 1) { Daniel@0: var extent = axisScaleExtent(scale.domain()), Daniel@0: i = -1, Daniel@0: n = ticks.length, Daniel@0: d = (ticks[1] - ticks[0]) / ++m, Daniel@0: j, Daniel@0: v; Daniel@0: while (++i < n) { Daniel@0: for (j = m; --j > 0;) { Daniel@0: if ((v = +ticks[i] - j * d) >= extent[0]) { Daniel@0: subticks.push(v); Daniel@0: } Daniel@0: } Daniel@0: } Daniel@0: for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) { Daniel@0: subticks.push(v); Daniel@0: } Daniel@0: } Daniel@0: return subticks; Daniel@0: } Daniel@0: Daniel@0: function axisScaleExtent(domain) { Daniel@0: var start = domain[0], stop = domain[domain.length - 1]; Daniel@0: return start < stop ? [start, stop] : [stop, start]; Daniel@0: } Daniel@0: Daniel@0: function axisScaleRange(scale) { Daniel@0: return scale.rangeExtent ? Daniel@0: scale.rangeExtent() : Daniel@0: axisScaleExtent(scale.range()); Daniel@0: } Daniel@0: Daniel@0: var axisAlign = { Daniel@0: bottom: 'center', Daniel@0: top: 'center', Daniel@0: left: 'right', Daniel@0: right: 'left' Daniel@0: }; Daniel@0: Daniel@0: var axisBaseline = { Daniel@0: bottom: 'top', Daniel@0: top: 'bottom', Daniel@0: left: 'middle', Daniel@0: right: 'middle' Daniel@0: }; Daniel@0: Daniel@0: function axisLabelExtend(orient, labels, oldScale, newScale, size, pad) { Daniel@0: size = Math.max(size, 0) + pad; Daniel@0: if (orient === 'left' || orient === 'top') { Daniel@0: size *= -1; Daniel@0: } Daniel@0: if (orient === 'top' || orient === 'bottom') { Daniel@0: dl.extend(labels.properties.enter, { Daniel@0: x: oldScale, Daniel@0: y: {value: size}, Daniel@0: }); Daniel@0: dl.extend(labels.properties.update, { Daniel@0: x: newScale, Daniel@0: y: {value: size}, Daniel@0: align: {value: 'center'}, Daniel@0: baseline: {value: axisBaseline[orient]} Daniel@0: }); Daniel@0: } else { Daniel@0: dl.extend(labels.properties.enter, { Daniel@0: x: {value: size}, Daniel@0: y: oldScale, Daniel@0: }); Daniel@0: dl.extend(labels.properties.update, { Daniel@0: x: {value: size}, Daniel@0: y: newScale, Daniel@0: align: {value: axisAlign[orient]}, Daniel@0: baseline: {value: 'middle'} Daniel@0: }); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function axisTicksExtend(orient, ticks, oldScale, newScale, size) { Daniel@0: var sign = (orient === 'left' || orient === 'top') ? -1 : 1; Daniel@0: if (size === Infinity) { Daniel@0: size = (orient === 'top' || orient === 'bottom') ? Daniel@0: {field: {group: 'height', level: 2}, mult: -sign} : Daniel@0: {field: {group: 'width', level: 2}, mult: -sign}; Daniel@0: } else { Daniel@0: size = {value: sign * size}; Daniel@0: } Daniel@0: if (orient === 'top' || orient === 'bottom') { Daniel@0: dl.extend(ticks.properties.enter, { Daniel@0: x: oldScale, Daniel@0: y: {value: 0}, Daniel@0: y2: size Daniel@0: }); Daniel@0: dl.extend(ticks.properties.update, { Daniel@0: x: newScale, Daniel@0: y: {value: 0}, Daniel@0: y2: size Daniel@0: }); Daniel@0: dl.extend(ticks.properties.exit, { Daniel@0: x: newScale, Daniel@0: }); Daniel@0: } else { Daniel@0: dl.extend(ticks.properties.enter, { Daniel@0: x: {value: 0}, Daniel@0: x2: size, Daniel@0: y: oldScale Daniel@0: }); Daniel@0: dl.extend(ticks.properties.update, { Daniel@0: x: {value: 0}, Daniel@0: x2: size, Daniel@0: y: newScale Daniel@0: }); Daniel@0: dl.extend(ticks.properties.exit, { Daniel@0: y: newScale, Daniel@0: }); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function axisTitleExtend(orient, title, range, offset) { Daniel@0: var mid = ~~((range[0] + range[1]) / 2), Daniel@0: sign = (orient === 'top' || orient === 'left') ? -1 : 1; Daniel@0: Daniel@0: if (orient === 'bottom' || orient === 'top') { Daniel@0: dl.extend(title.properties.update, { Daniel@0: x: {value: mid}, Daniel@0: y: {value: sign*offset}, Daniel@0: angle: {value: 0} Daniel@0: }); Daniel@0: } else { Daniel@0: dl.extend(title.properties.update, { Daniel@0: x: {value: sign*offset}, Daniel@0: y: {value: mid}, Daniel@0: angle: {value: orient === 'left' ? -90 : 90} Daniel@0: }); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function axisDomainExtend(orient, domain, range, size) { Daniel@0: var path; Daniel@0: if (orient === 'top' || orient === 'left') { Daniel@0: size = -1 * size; Daniel@0: } Daniel@0: if (orient === 'bottom' || orient === 'top') { Daniel@0: path = 'M' + range[0] + ',' + size + 'V0H' + range[1] + 'V' + size; Daniel@0: } else { Daniel@0: path = 'M' + size + ',' + range[0] + 'H0V' + range[1] + 'H' + size; Daniel@0: } Daniel@0: domain.properties.update.path = {value: path}; Daniel@0: } Daniel@0: Daniel@0: function axisUpdate(item, group, trans) { Daniel@0: var o = trans ? {} : item, Daniel@0: offset = item.mark.def.offset, Daniel@0: orient = item.mark.def.orient, Daniel@0: width = group.width, Daniel@0: height = group.height; // TODO fallback to global w,h? Daniel@0: Daniel@0: if (dl.isArray(offset)) { Daniel@0: var ofx = offset[0], Daniel@0: ofy = offset[1]; Daniel@0: Daniel@0: switch (orient) { Daniel@0: case 'left': { Tuple.set(o, 'x', -ofx); Tuple.set(o, 'y', ofy); break; } Daniel@0: case 'right': { Tuple.set(o, 'x', width + ofx); Tuple.set(o, 'y', ofy); break; } Daniel@0: case 'bottom': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', height + ofy); break; } Daniel@0: case 'top': { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', -ofy); break; } Daniel@0: default: { Tuple.set(o, 'x', ofx); Tuple.set(o, 'y', ofy); } Daniel@0: } Daniel@0: } else { Daniel@0: if (dl.isObject(offset)) { Daniel@0: offset = -group.scale(offset.scale)(offset.value); Daniel@0: } Daniel@0: Daniel@0: switch (orient) { Daniel@0: case 'left': { Tuple.set(o, 'x', -offset); Tuple.set(o, 'y', 0); break; } Daniel@0: case 'right': { Tuple.set(o, 'x', width + offset); Tuple.set(o, 'y', 0); break; } Daniel@0: case 'bottom': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', height + offset); break; } Daniel@0: case 'top': { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', -offset); break; } Daniel@0: default: { Tuple.set(o, 'x', 0); Tuple.set(o, 'y', 0); } Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: if (trans) trans.interpolate(item, o); Daniel@0: return true; Daniel@0: } Daniel@0: Daniel@0: function axisTicks(config) { Daniel@0: return { Daniel@0: type: 'rule', Daniel@0: interactive: false, Daniel@0: key: 'data', Daniel@0: properties: { Daniel@0: enter: { Daniel@0: stroke: {value: config.axis.tickColor}, Daniel@0: strokeWidth: {value: config.axis.tickWidth}, Daniel@0: opacity: {value: 1e-6} Daniel@0: }, Daniel@0: exit: { opacity: {value: 1e-6} }, Daniel@0: update: { opacity: {value: 1} } Daniel@0: } Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function axisTickLabels(config) { Daniel@0: return { Daniel@0: type: 'text', Daniel@0: interactive: true, Daniel@0: key: 'data', Daniel@0: properties: { Daniel@0: enter: { Daniel@0: fill: {value: config.axis.tickLabelColor}, Daniel@0: font: {value: config.axis.tickLabelFont}, Daniel@0: fontSize: {value: config.axis.tickLabelFontSize}, Daniel@0: opacity: {value: 1e-6}, Daniel@0: text: {field: 'label'} Daniel@0: }, Daniel@0: exit: { opacity: {value: 1e-6} }, Daniel@0: update: { opacity: {value: 1} } Daniel@0: } Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function axisTitle(config) { Daniel@0: return { Daniel@0: type: 'text', Daniel@0: interactive: true, Daniel@0: properties: { Daniel@0: enter: { Daniel@0: font: {value: config.axis.titleFont}, Daniel@0: fontSize: {value: config.axis.titleFontSize}, Daniel@0: fontWeight: {value: config.axis.titleFontWeight}, Daniel@0: fill: {value: config.axis.titleColor}, Daniel@0: align: {value: 'center'}, Daniel@0: baseline: {value: 'middle'}, Daniel@0: text: {field: 'data'} Daniel@0: }, Daniel@0: update: {} Daniel@0: } Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: function axisDomain(config) { Daniel@0: return { Daniel@0: type: 'path', Daniel@0: interactive: false, Daniel@0: properties: { Daniel@0: enter: { Daniel@0: x: {value: 0.5}, Daniel@0: y: {value: 0.5}, Daniel@0: stroke: {value: config.axis.axisColor}, Daniel@0: strokeWidth: {value: config.axis.axisWidth} Daniel@0: }, Daniel@0: update: {} Daniel@0: } Daniel@0: }; Daniel@0: } Daniel@0: Daniel@0: module.exports = axs; Daniel@0: },{"../parse/mark":97,"datalib":24,"vega-dataflow":39}],114:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: dl = require('datalib'), Daniel@0: Gradient = require('vega-scenegraph').Gradient, Daniel@0: parseProperties = require('../parse/properties'), Daniel@0: parseMark = require('../parse/mark'); Daniel@0: Daniel@0: function lgnd(model) { Daniel@0: var size = null, Daniel@0: shape = null, Daniel@0: fill = null, Daniel@0: stroke = null, Daniel@0: spacing = null, Daniel@0: values = null, Daniel@0: format = null, Daniel@0: formatString = null, Daniel@0: config = model.config(), Daniel@0: title, Daniel@0: orient = 'right', Daniel@0: offset = config.legend.offset, Daniel@0: padding = config.legend.padding, Daniel@0: tickArguments = [5], Daniel@0: legendStyle = {}, Daniel@0: symbolStyle = {}, Daniel@0: gradientStyle = {}, Daniel@0: titleStyle = {}, Daniel@0: labelStyle = {}, Daniel@0: m = { // Legend marks as references for updates Daniel@0: titles: {}, Daniel@0: symbols: {}, Daniel@0: labels: {}, Daniel@0: gradient: {} Daniel@0: }; Daniel@0: Daniel@0: var legend = {}, Daniel@0: legendDef = {}; Daniel@0: Daniel@0: function reset() { legendDef.type = null; } Daniel@0: function ingest(d, i) { return {data: d, index: i}; } Daniel@0: Daniel@0: legend.def = function() { Daniel@0: var scale = size || shape || fill || stroke; Daniel@0: Daniel@0: format = !formatString ? null : ((scale.type === 'time') ? Daniel@0: dl.format.time(formatString) : dl.format.number(formatString)); Daniel@0: Daniel@0: if (!legendDef.type) { Daniel@0: legendDef = (scale===fill || scale===stroke) && !discrete(scale.type) ? Daniel@0: quantDef(scale) : ordinalDef(scale); Daniel@0: } Daniel@0: legendDef.orient = orient; Daniel@0: legendDef.offset = offset; Daniel@0: legendDef.padding = padding; Daniel@0: return legendDef; Daniel@0: }; Daniel@0: Daniel@0: function discrete(type) { Daniel@0: return type==='ordinal' || type==='quantize' || Daniel@0: type==='quantile' || type==='threshold'; Daniel@0: } Daniel@0: Daniel@0: function ordinalDef(scale) { Daniel@0: var def = o_legend_def(size, shape, fill, stroke); Daniel@0: Daniel@0: // generate data Daniel@0: var data = (values == null ? Daniel@0: (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : Daniel@0: values).map(ingest); Daniel@0: var fmt = format==null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : String) : format; Daniel@0: Daniel@0: // determine spacing between legend entries Daniel@0: var fs, range, offset, pad=5, domain = d3.range(data.length); Daniel@0: if (size) { Daniel@0: range = data.map(function(x) { return Math.sqrt(size(x.data)); }); Daniel@0: offset = d3.max(range); Daniel@0: range = range.reduce(function(a,b,i,z) { Daniel@0: if (i > 0) a[i] = a[i-1] + z[i-1]/2 + pad; Daniel@0: return (a[i] += b/2, a); }, [0]).map(Math.round); Daniel@0: } else { Daniel@0: offset = Math.round(Math.sqrt(config.legend.symbolSize)); Daniel@0: range = spacing || Daniel@0: (fs = labelStyle.fontSize) && (fs.value + pad) || Daniel@0: (config.legend.labelFontSize + pad); Daniel@0: range = domain.map(function(d,i) { Daniel@0: return Math.round(offset/2 + i*range); Daniel@0: }); Daniel@0: } Daniel@0: Daniel@0: // account for padding and title size Daniel@0: var sz = padding, ts; Daniel@0: if (title) { Daniel@0: ts = titleStyle.fontSize; Daniel@0: sz += 5 + ((ts && ts.value) || config.legend.titleFontSize); Daniel@0: } Daniel@0: for (var i=0, n=range.length; i'}, Daniel@0: summarize: { Daniel@0: type: 'custom', Daniel@0: set: function(summarize) { Daniel@0: var signalDeps = {}, Daniel@0: tx = this._transform, Daniel@0: i, len, f, fields, name, ops; Daniel@0: Daniel@0: if (!dl.isArray(fields = summarize)) { // Object syntax from dl Daniel@0: fields = []; Daniel@0: for (name in summarize) { Daniel@0: ops = dl.array(summarize[name]); Daniel@0: fields.push({field: name, ops: ops}); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: function sg(x) { if (x.signal) signalDeps[x.signal] = 1; } Daniel@0: Daniel@0: for (i=0, len=fields.length; i', default: [5, 2]} Daniel@0: }); Daniel@0: Daniel@0: this._output = {bin: 'bin'}; Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Bin.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Bin; Daniel@0: Daniel@0: prototype.transform = function(input) { Daniel@0: log.debug(input, ['binning']); Daniel@0: Daniel@0: var output = this._output.bin, Daniel@0: step = this.param('step'), Daniel@0: steps = this.param('steps'), Daniel@0: minstep = this.param('minstep'), Daniel@0: get = this.param('field').accessor, Daniel@0: opt = { Daniel@0: min: this.param('min'), Daniel@0: max: this.param('max'), Daniel@0: base: this.param('base'), Daniel@0: maxbins: this.param('maxbins'), Daniel@0: div: this.param('div') Daniel@0: }; Daniel@0: Daniel@0: if (step) opt.step = step; Daniel@0: if (steps) opt.steps = steps; Daniel@0: if (minstep) opt.minstep = minstep; Daniel@0: var b = bins(opt); Daniel@0: Daniel@0: function update(d) { Daniel@0: var v = get(d); Daniel@0: v = v == null ? null Daniel@0: : b.start + b.step * ~~((v - b.start) / b.step); Daniel@0: Tuple.set(d, output, v); Daniel@0: } Daniel@0: input.add.forEach(update); Daniel@0: input.mod.forEach(update); Daniel@0: input.rem.forEach(update); Daniel@0: Daniel@0: input.fields[output] = 1; Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Bin; Daniel@0: },{"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],119:[function(require,module,exports){ Daniel@0: var df = require('vega-dataflow'), Daniel@0: Tuple = df.Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'); Daniel@0: Daniel@0: function CountPattern(graph) { Daniel@0: Transform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: field: {type: 'field', default: 'data'}, Daniel@0: pattern: {type: 'value', default: '[\\w\']+'}, Daniel@0: case: {type: 'value', default: 'lower'}, Daniel@0: stopwords: {type: 'value', default: ''} Daniel@0: }); Daniel@0: Daniel@0: this._output = {text: 'text', count: 'count'}; Daniel@0: Daniel@0: return this.router(true).produces(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (CountPattern.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = CountPattern; Daniel@0: Daniel@0: prototype.transform = function(input, reset) { Daniel@0: log.debug(input, ['countpattern']); Daniel@0: Daniel@0: var get = this.param('field').accessor, Daniel@0: pattern = this.param('pattern'), Daniel@0: stop = this.param('stopwords'), Daniel@0: rem = false; Daniel@0: Daniel@0: // update parameters Daniel@0: if (this._stop !== stop) { Daniel@0: this._stop = stop; Daniel@0: this._stop_re = new RegExp('^' + stop + '$', 'i'); Daniel@0: reset = true; Daniel@0: } Daniel@0: Daniel@0: if (this._pattern !== pattern) { Daniel@0: this._pattern = pattern; Daniel@0: this._match = new RegExp(this._pattern, 'g'); Daniel@0: reset = true; Daniel@0: } Daniel@0: Daniel@0: if (reset) this._counts = {}; Daniel@0: Daniel@0: function curr(t) { return (Tuple.prev_init(t), get(t)); } Daniel@0: function prev(t) { return get(Tuple.prev(t)); } Daniel@0: Daniel@0: this._add(input.add, curr); Daniel@0: if (!reset) this._rem(input.rem, prev); Daniel@0: if (reset || (rem = input.fields[get.field])) { Daniel@0: if (rem) this._rem(input.mod, prev); Daniel@0: this._add(input.mod, curr); Daniel@0: } Daniel@0: Daniel@0: // generate output tuples Daniel@0: return this._changeset(input); Daniel@0: }; Daniel@0: Daniel@0: prototype._changeset = function(input) { Daniel@0: var counts = this._counts, Daniel@0: tuples = this._tuples || (this._tuples = {}), Daniel@0: change = df.ChangeSet.create(input), Daniel@0: out = this._output, w, t, c; Daniel@0: Daniel@0: for (w in counts) { Daniel@0: t = tuples[w]; Daniel@0: c = counts[w] || 0; Daniel@0: if (!t && c) { Daniel@0: tuples[w] = (t = Tuple.ingest({})); Daniel@0: t[out.text] = w; Daniel@0: t[out.count] = c; Daniel@0: change.add.push(t); Daniel@0: } else if (c === 0) { Daniel@0: if (t) change.rem.push(t); Daniel@0: delete counts[w]; Daniel@0: delete tuples[w]; Daniel@0: } else if (t[out.count] !== c) { Daniel@0: Tuple.set(t, out.count, c); Daniel@0: change.mod.push(t); Daniel@0: } Daniel@0: } Daniel@0: return change; Daniel@0: }; Daniel@0: Daniel@0: prototype._tokenize = function(text) { Daniel@0: switch (this.param('case')) { Daniel@0: case 'upper': text = text.toUpperCase(); break; Daniel@0: case 'lower': text = text.toLowerCase(); break; Daniel@0: } Daniel@0: return text.match(this._match); Daniel@0: }; Daniel@0: Daniel@0: prototype._add = function(tuples, get) { Daniel@0: var counts = this._counts, Daniel@0: stop = this._stop_re, Daniel@0: tok, i, j, t; Daniel@0: Daniel@0: for (j=0; j c.s) { // Removed tuples haven't been filtered yet Daniel@0: c.c = c.c.filter(function(y) { Daniel@0: var t = y[cross._output[left ? 'right' : 'left']]; Daniel@0: return cross._cache[t._id] !== null; Daniel@0: }); Daniel@0: c.s = this._lastRem; Daniel@0: } Daniel@0: Daniel@0: output.mod.push.apply(output.mod, c.c); Daniel@0: } Daniel@0: Daniel@0: function rem(output, x) { Daniel@0: output.rem.push.apply(output.rem, this._cache[x._id].c); Daniel@0: this._cache[x._id] = null; Daniel@0: this._lastRem = this._stamp; Daniel@0: } Daniel@0: Daniel@0: function upFields(input, output) { Daniel@0: if (input.add.length || input.rem.length) { Daniel@0: output.fields[this._output.left] = 1; Daniel@0: output.fields[this._output.right] = 1; Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: prototype.batchTransform = function(input, data) { Daniel@0: log.debug(input, ['crossing']); Daniel@0: Daniel@0: var w = this.param('with'), Daniel@0: f = this.param('filter'), Daniel@0: diag = this.param('diagonal'), Daniel@0: graph = this._graph, Daniel@0: signals = graph.values(SIGNALS, this.dependency(SIGNALS)), Daniel@0: test = f ? function(x) {return f(x, null, signals); } : null, Daniel@0: selfCross = (!w.name), Daniel@0: woutput = selfCross ? input : w.source.last(), Daniel@0: wdata = selfCross ? data : w.source.values(), Daniel@0: output = ChangeSet.create(input), Daniel@0: r = rem.bind(this, output); Daniel@0: Daniel@0: input.rem.forEach(r); Daniel@0: input.add.forEach(add.bind(this, output, true, wdata, diag, test)); Daniel@0: Daniel@0: if (!selfCross && woutput.stamp > this._lastWith) { Daniel@0: woutput.rem.forEach(r); Daniel@0: woutput.add.forEach(add.bind(this, output, false, data, diag, test)); Daniel@0: woutput.mod.forEach(mod.bind(this, output, false)); Daniel@0: upFields.call(this, woutput, output); Daniel@0: this._lastWith = woutput.stamp; Daniel@0: } Daniel@0: Daniel@0: // Mods need to come after all removals have been run. Daniel@0: input.mod.forEach(mod.bind(this, output, true)); Daniel@0: upFields.call(this, input, output); Daniel@0: Daniel@0: return output; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Cross; Daniel@0: },{"./BatchTransform":117,"./Transform":135,"vega-dataflow":39,"vega-logging":45}],121:[function(require,module,exports){ Daniel@0: var Transform = require('./Transform'), Daniel@0: Aggregate = require('./Aggregate'); Daniel@0: Daniel@0: function Facet(graph) { Daniel@0: Transform.addParameters(this, { Daniel@0: transform: { Daniel@0: type: "custom", Daniel@0: set: function(pipeline) { Daniel@0: return (this._transform._pipeline = pipeline, this._transform); Daniel@0: }, Daniel@0: get: function() { Daniel@0: var parse = require('../parse/transforms'), Daniel@0: facet = this._transform; Daniel@0: return facet._pipeline.map(function(t) { Daniel@0: return parse(facet._graph, t); Daniel@0: }); Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: this._pipeline = []; Daniel@0: return Aggregate.call(this, graph); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Facet.prototype = Object.create(Aggregate.prototype)); Daniel@0: prototype.constructor = Facet; Daniel@0: Daniel@0: prototype.aggr = function() { Daniel@0: return Aggregate.prototype.aggr.call(this).facet(this); Daniel@0: }; Daniel@0: Daniel@0: module.exports = Facet; Daniel@0: },{"../parse/transforms":106,"./Aggregate":116,"./Transform":135}],122:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: Aggregator = dl.Aggregator, Daniel@0: Base = Aggregator.prototype, Daniel@0: df = require('vega-dataflow'), Daniel@0: Tuple = df.Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: facetID = 0; Daniel@0: Daniel@0: function Facetor() { Daniel@0: Aggregator.call(this); Daniel@0: this._facet = null; Daniel@0: this._facetID = ++facetID; Daniel@0: } Daniel@0: Daniel@0: var prototype = (Facetor.prototype = Object.create(Base)); Daniel@0: prototype.constructor = Facetor; Daniel@0: Daniel@0: prototype.facet = function(f) { Daniel@0: return arguments.length ? (this._facet = f, this) : this._facet; Daniel@0: }; Daniel@0: Daniel@0: prototype._ingest = function(t) { Daniel@0: return Tuple.ingest(t, null); Daniel@0: }; Daniel@0: Daniel@0: prototype._assign = Tuple.set; Daniel@0: Daniel@0: function disconnect_cell(facet) { Daniel@0: log.debug({}, ['disconnecting cell', this.tuple._id]); Daniel@0: var pipeline = this.ds.pipeline(); Daniel@0: facet.removeListener(pipeline[0]); Daniel@0: facet._graph.removeListener(pipeline[0]); Daniel@0: facet._graph.disconnect(pipeline); Daniel@0: } Daniel@0: Daniel@0: prototype._newcell = function(x, key) { Daniel@0: var cell = Base._newcell.call(this, x, key), Daniel@0: facet = this._facet; Daniel@0: Daniel@0: if (facet) { Daniel@0: var graph = facet._graph, Daniel@0: tuple = cell.tuple, Daniel@0: pipeline = facet.param('transform'); Daniel@0: cell.ds = graph.data(tuple._facetID, pipeline, tuple); Daniel@0: cell.disconnect = disconnect_cell; Daniel@0: facet.addListener(pipeline[0]); Daniel@0: } Daniel@0: Daniel@0: return cell; Daniel@0: }; Daniel@0: Daniel@0: prototype._newtuple = function(x, key) { Daniel@0: var t = Base._newtuple.call(this, x); Daniel@0: if (this._facet) { Daniel@0: Tuple.set(t, 'key', key); Daniel@0: Tuple.set(t, '_facetID', this._facetID + '_' + key); Daniel@0: } Daniel@0: return t; Daniel@0: }; Daniel@0: Daniel@0: prototype.clear = function() { Daniel@0: if (this._facet) { Daniel@0: for (var k in this._cells) { Daniel@0: this._cells[k].disconnect(this._facet); Daniel@0: } Daniel@0: } Daniel@0: return Base.clear.call(this); Daniel@0: }; Daniel@0: Daniel@0: prototype._on_add = function(x, cell) { Daniel@0: if (this._facet) cell.ds._input.add.push(x); Daniel@0: }; Daniel@0: Daniel@0: prototype._on_rem = function(x, cell) { Daniel@0: if (this._facet) cell.ds._input.rem.push(x); Daniel@0: }; Daniel@0: Daniel@0: prototype._on_mod = function(x, prev, cell0, cell1) { Daniel@0: if (this._facet) { // Propagate tuples Daniel@0: if (cell0 === cell1) { Daniel@0: cell0.ds._input.mod.push(x); Daniel@0: } else { Daniel@0: cell0.ds._input.rem.push(x); Daniel@0: cell1.ds._input.add.push(x); Daniel@0: } Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: prototype._on_drop = function(cell) { Daniel@0: if (this._facet) cell.disconnect(this._facet); Daniel@0: }; Daniel@0: Daniel@0: prototype._on_keep = function(cell) { Daniel@0: // propagate sort, signals, fields, etc. Daniel@0: if (this._facet) df.ChangeSet.copy(this._input, cell.ds._input); Daniel@0: }; Daniel@0: Daniel@0: module.exports = Facetor; Daniel@0: },{"datalib":24,"vega-dataflow":39,"vega-logging":45}],123:[function(require,module,exports){ Daniel@0: var df = require('vega-dataflow'), Daniel@0: SIGNALS = df.Dependencies.SIGNALS, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'); Daniel@0: Daniel@0: function Filter(graph) { Daniel@0: Transform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, {test: {type: 'expr'}}); Daniel@0: Daniel@0: this._skip = {}; Daniel@0: return this.router(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Filter.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Filter; Daniel@0: Daniel@0: prototype.transform = function(input) { Daniel@0: log.debug(input, ['filtering']); Daniel@0: Daniel@0: var output = df.ChangeSet.create(input), Daniel@0: graph = this._graph, Daniel@0: skip = this._skip, Daniel@0: test = this.param('test'), Daniel@0: signals = graph.values(SIGNALS, this.dependency(SIGNALS)); Daniel@0: Daniel@0: input.rem.forEach(function(x) { Daniel@0: if (skip[x._id] !== 1) output.rem.push(x); Daniel@0: else skip[x._id] = 0; Daniel@0: }); Daniel@0: Daniel@0: input.add.forEach(function(x) { Daniel@0: if (test(x, null, signals)) output.add.push(x); Daniel@0: else skip[x._id] = 1; Daniel@0: }); Daniel@0: Daniel@0: input.mod.forEach(function(x) { Daniel@0: var b = test(x, null, signals), Daniel@0: s = (skip[x._id] === 1); Daniel@0: if (b && s) { Daniel@0: skip[x._id] = 0; Daniel@0: output.add.push(x); Daniel@0: } else if (b && !s) { Daniel@0: output.mod.push(x); Daniel@0: } else if (!b && s) { Daniel@0: // do nothing, keep skip true Daniel@0: } else { // !b && !s Daniel@0: output.rem.push(x); Daniel@0: skip[x._id] = 1; Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: return output; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Filter; Daniel@0: },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],124:[function(require,module,exports){ Daniel@0: var df = require('vega-dataflow'), Daniel@0: Tuple = df.Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'); Daniel@0: Daniel@0: function Fold(graph) { Daniel@0: Transform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: fields: {type: 'array'} Daniel@0: }); Daniel@0: Daniel@0: this._output = {key: 'key', value: 'value'}; Daniel@0: this._cache = {}; Daniel@0: Daniel@0: return this.router(true).produces(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Fold.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Fold; Daniel@0: Daniel@0: prototype._reset = function(input, output) { Daniel@0: for (var id in this._cache) { Daniel@0: output.rem.push.apply(output.rem, this._cache[id]); Daniel@0: } Daniel@0: this._cache = {}; Daniel@0: }; Daniel@0: Daniel@0: prototype._tuple = function(x, i, len) { Daniel@0: var list = this._cache[x._id] || (this._cache[x._id] = Array(len)); Daniel@0: return list[i] ? Tuple.rederive(x, list[i]) : (list[i] = Tuple.derive(x)); Daniel@0: }; Daniel@0: Daniel@0: prototype._fn = function(data, on, out) { Daniel@0: var i, j, n, m, d, t; Daniel@0: for (i=0, n=data.length; i', default: [500, 500]}, Daniel@0: bound: {type: 'value', default: true}, Daniel@0: links: {type: 'data'}, Daniel@0: Daniel@0: // TODO: for now force these to be value params only (pun-intended) Daniel@0: // Can update to include fields after Parameter refactoring. Daniel@0: linkStrength: {type: 'value', default: 1}, Daniel@0: linkDistance: {type: 'value', default: 20}, Daniel@0: charge: {type: 'value', default: -30}, Daniel@0: Daniel@0: chargeDistance: {type: 'value', default: Infinity}, Daniel@0: friction: {type: 'value', default: 0.9}, Daniel@0: theta: {type: 'value', default: 0.8}, Daniel@0: gravity: {type: 'value', default: 0.1}, Daniel@0: alpha: {type: 'value', default: 0.1}, Daniel@0: iterations: {type: 'value', default: 500}, Daniel@0: Daniel@0: interactive: {type: 'value', default: this._interactive}, Daniel@0: active: {type: 'value', default: this._prev}, Daniel@0: fixed: {type: 'data'} Daniel@0: }); Daniel@0: Daniel@0: this._output = { Daniel@0: 'x': 'layout_x', Daniel@0: 'y': 'layout_y' Daniel@0: }; Daniel@0: Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Force.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Force; Daniel@0: Daniel@0: prototype.transform = function(nodeInput, reset) { Daniel@0: log.debug(nodeInput, ['force']); Daniel@0: reset = reset - (nodeInput.signals.active ? 1 : 0); Daniel@0: Daniel@0: // get variables Daniel@0: var interactive = this.param('interactive'), Daniel@0: linkSource = this.param('links').source, Daniel@0: linkInput = linkSource.last(), Daniel@0: active = this.param('active'), Daniel@0: output = this._output, Daniel@0: layout = this._layout, Daniel@0: nodes = this._nodes, Daniel@0: links = this._links; Daniel@0: Daniel@0: // configure nodes, links and layout Daniel@0: if (linkInput.stamp < nodeInput.stamp) linkInput = null; Daniel@0: this.configure(nodeInput, linkInput, interactive, reset); Daniel@0: Daniel@0: // run batch layout Daniel@0: if (!interactive) { Daniel@0: var iterations = this.param('iterations'); Daniel@0: for (var i=0; i'}, Daniel@0: translate: {type: 'array'}, Daniel@0: rotate: {type: 'array'}, Daniel@0: scale: {type: 'value'}, Daniel@0: precision: {type: 'value'}, Daniel@0: clipAngle: {type: 'value'}, Daniel@0: clipExtent: {type: 'value'} Daniel@0: }; Daniel@0: Daniel@0: Geo.d3Projection = function() { Daniel@0: var p = this.param('projection'), Daniel@0: param = Geo.Parameters, Daniel@0: proj, name, value; Daniel@0: Daniel@0: if (p !== this._mode) { Daniel@0: this._mode = p; Daniel@0: this._projection = d3.geo[p](); Daniel@0: } Daniel@0: proj = this._projection; Daniel@0: Daniel@0: for (name in param) { Daniel@0: if (name === 'projection' || !proj[name]) continue; Daniel@0: value = this.param(name); Daniel@0: if (value === undefined || (dl.isArray(value) && value.length === 0)) { Daniel@0: continue; Daniel@0: } Daniel@0: if (value !== proj[name]()) { Daniel@0: proj[name](value); Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: return proj; Daniel@0: }; Daniel@0: Daniel@0: var prototype = (Geo.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Geo; Daniel@0: Daniel@0: prototype.transform = function(input) { Daniel@0: log.debug(input, ['geo']); Daniel@0: Daniel@0: var output = this._output, Daniel@0: lon = this.param('lon').accessor, Daniel@0: lat = this.param('lat').accessor, Daniel@0: proj = Geo.d3Projection.call(this); Daniel@0: Daniel@0: function set(t) { Daniel@0: var ll = [lon(t), lat(t)]; Daniel@0: var xy = proj(ll) || [null, null]; Daniel@0: Tuple.set(t, output.x, xy[0]); Daniel@0: Tuple.set(t, output.y, xy[1]); Daniel@0: } Daniel@0: Daniel@0: input.add.forEach(set); Daniel@0: if (this.reevaluate(input)) { Daniel@0: input.mod.forEach(set); Daniel@0: input.rem.forEach(set); Daniel@0: } Daniel@0: Daniel@0: input.fields[output.x] = 1; Daniel@0: input.fields[output.y] = 1; Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Geo; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],128:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: dl = require('datalib'), Daniel@0: Tuple = require('vega-dataflow').Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Geo = require('./Geo'), Daniel@0: Transform = require('./Transform'); Daniel@0: Daniel@0: function GeoPath(graph) { Daniel@0: Transform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, Geo.Parameters); Daniel@0: Transform.addParameters(this, { Daniel@0: field: {type: 'field', default: null}, Daniel@0: }); Daniel@0: Daniel@0: this._output = { Daniel@0: 'path': 'layout_path' Daniel@0: }; Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (GeoPath.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = GeoPath; Daniel@0: Daniel@0: prototype.transform = function(input) { Daniel@0: log.debug(input, ['geopath']); Daniel@0: Daniel@0: var output = this._output, Daniel@0: geojson = this.param('field').accessor || dl.identity, Daniel@0: proj = Geo.d3Projection.call(this), Daniel@0: path = d3.geo.path().projection(proj); Daniel@0: Daniel@0: function set(t) { Daniel@0: Tuple.set(t, output.path, path(geojson(t))); Daniel@0: } Daniel@0: Daniel@0: input.add.forEach(set); Daniel@0: if (this.reevaluate(input)) { Daniel@0: input.mod.forEach(set); Daniel@0: input.rem.forEach(set); Daniel@0: } Daniel@0: Daniel@0: input.fields[output.path] = 1; Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: module.exports = GeoPath; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"./Geo":127,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],129:[function(require,module,exports){ Daniel@0: var Tuple = require('vega-dataflow').Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'); Daniel@0: Daniel@0: function LinkPath(graph) { Daniel@0: Transform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: sourceX: {type: 'field', default: '_source.layout_x'}, Daniel@0: sourceY: {type: 'field', default: '_source.layout_y'}, Daniel@0: targetX: {type: 'field', default: '_target.layout_x'}, Daniel@0: targetY: {type: 'field', default: '_target.layout_y'}, Daniel@0: tension: {type: 'value', default: 0.2}, Daniel@0: shape: {type: 'value', default: 'line'} Daniel@0: }); Daniel@0: Daniel@0: this._output = {'path': 'layout_path'}; Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (LinkPath.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = LinkPath; Daniel@0: Daniel@0: function line(sx, sy, tx, ty) { Daniel@0: return 'M' + sx + ',' + sy + Daniel@0: 'L' + tx + ',' + ty; Daniel@0: } Daniel@0: Daniel@0: function curve(sx, sy, tx, ty, tension) { Daniel@0: var dx = tx - sx, Daniel@0: dy = ty - sy, Daniel@0: ix = tension * (dx + dy), Daniel@0: iy = tension * (dy - dx); Daniel@0: return 'M' + sx + ',' + sy + Daniel@0: 'C' + (sx+ix) + ',' + (sy+iy) + Daniel@0: ' ' + (tx+iy) + ',' + (ty-ix) + Daniel@0: ' ' + tx + ',' + ty; Daniel@0: } Daniel@0: Daniel@0: function diagonalX(sx, sy, tx, ty) { Daniel@0: var m = (sx + tx) / 2; Daniel@0: return 'M' + sx + ',' + sy + Daniel@0: 'C' + m + ',' + sy + Daniel@0: ' ' + m + ',' + ty + Daniel@0: ' ' + tx + ',' + ty; Daniel@0: } Daniel@0: Daniel@0: function diagonalY(sx, sy, tx, ty) { Daniel@0: var m = (sy + ty) / 2; Daniel@0: return 'M' + sx + ',' + sy + Daniel@0: 'C' + sx + ',' + m + Daniel@0: ' ' + tx + ',' + m + Daniel@0: ' ' + tx + ',' + ty; Daniel@0: } Daniel@0: Daniel@0: var shapes = { Daniel@0: line: line, Daniel@0: curve: curve, Daniel@0: diagonal: diagonalX, Daniel@0: diagonalX: diagonalX, Daniel@0: diagonalY: diagonalY Daniel@0: }; Daniel@0: Daniel@0: prototype.transform = function(input) { Daniel@0: log.debug(input, ['linkpath']); Daniel@0: Daniel@0: var output = this._output, Daniel@0: shape = shapes[this.param('shape')] || shapes.line, Daniel@0: sourceX = this.param('sourceX').accessor, Daniel@0: sourceY = this.param('sourceY').accessor, Daniel@0: targetX = this.param('targetX').accessor, Daniel@0: targetY = this.param('targetY').accessor, Daniel@0: tension = this.param('tension'); Daniel@0: Daniel@0: function set(t) { Daniel@0: var path = shape(sourceX(t), sourceY(t), targetX(t), targetY(t), tension); Daniel@0: Tuple.set(t, output.path, path); Daniel@0: } Daniel@0: Daniel@0: input.add.forEach(set); Daniel@0: if (this.reevaluate(input)) { Daniel@0: input.mod.forEach(set); Daniel@0: input.rem.forEach(set); Daniel@0: } Daniel@0: Daniel@0: input.fields[output.path] = 1; Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: module.exports = LinkPath; Daniel@0: },{"./Transform":135,"vega-dataflow":39,"vega-logging":45}],130:[function(require,module,exports){ Daniel@0: var Tuple = require('vega-dataflow').Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'); Daniel@0: Daniel@0: function Lookup(graph) { Daniel@0: Transform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: on: {type: 'data'}, Daniel@0: onKey: {type: 'field', default: null}, Daniel@0: as: {type: 'array'}, Daniel@0: keys: {type: 'array', default: ['data']}, Daniel@0: default: {type: 'value'} Daniel@0: }); Daniel@0: Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Lookup.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Lookup; Daniel@0: Daniel@0: prototype.transform = function(input, reset) { Daniel@0: log.debug(input, ['lookup']); Daniel@0: Daniel@0: var on = this.param('on'), Daniel@0: onLast = on.source.last(), Daniel@0: onData = on.source.values(), Daniel@0: onKey = this.param('onKey'), Daniel@0: onF = onKey.field, Daniel@0: keys = this.param('keys'), Daniel@0: get = keys.accessor, Daniel@0: as = this.param('as'), Daniel@0: defaultValue = this.param('default'), Daniel@0: lut = this._lut, Daniel@0: i, v; Daniel@0: Daniel@0: // build lookup table on init, withKey modified, or tuple add/rem Daniel@0: if (lut == null || this._on !== onF || onF && onLast.fields[onF] || Daniel@0: onLast.add.length || onLast.rem.length) Daniel@0: { Daniel@0: if (onF) { // build hash from withKey field Daniel@0: onKey = onKey.accessor; Daniel@0: for (lut={}, i=0; i'} }); Daniel@0: this.router(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Sort.prototype = Object.create(Transform.prototype)); Daniel@0: prototype.constructor = Sort; Daniel@0: Daniel@0: prototype.transform = function(input) { Daniel@0: log.debug(input, ['sorting']); Daniel@0: Daniel@0: if (input.add.length || input.mod.length || input.rem.length) { Daniel@0: input.sort = dl.comparator(this.param('by').field); Daniel@0: } Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Sort; Daniel@0: },{"./Transform":135,"datalib":24,"vega-logging":45}],134:[function(require,module,exports){ Daniel@0: var dl = require('datalib'), Daniel@0: Tuple = require('vega-dataflow').Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'), Daniel@0: BatchTransform = require('./BatchTransform'); Daniel@0: Daniel@0: function Stack(graph) { Daniel@0: BatchTransform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: groupby: {type: 'array'}, Daniel@0: sortby: {type: 'array'}, Daniel@0: field: {type: 'field'}, Daniel@0: offset: {type: 'value', default: 'zero'} Daniel@0: }); Daniel@0: Daniel@0: this._output = { Daniel@0: 'start': 'layout_start', Daniel@0: 'end': 'layout_end', Daniel@0: 'mid': 'layout_mid' Daniel@0: }; Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Stack.prototype = Object.create(BatchTransform.prototype)); Daniel@0: prototype.constructor = Stack; Daniel@0: Daniel@0: prototype.batchTransform = function(input, data) { Daniel@0: log.debug(input, ['stacking']); Daniel@0: Daniel@0: var groupby = this.param('groupby').accessor, Daniel@0: sortby = dl.comparator(this.param('sortby').field), Daniel@0: field = this.param('field').accessor, Daniel@0: offset = this.param('offset'), Daniel@0: output = this._output; Daniel@0: Daniel@0: // partition, sum, and sort the stack groups Daniel@0: var groups = partition(data, groupby, sortby, field); Daniel@0: Daniel@0: // compute stack layouts per group Daniel@0: for (var i=0, max=groups.max; i max) max = s; Daniel@0: if (sortby != null) g.sort(sortby); Daniel@0: } Daniel@0: groups.max = max; Daniel@0: Daniel@0: return groups; Daniel@0: } Daniel@0: Daniel@0: module.exports = Stack; Daniel@0: },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],135:[function(require,module,exports){ Daniel@0: var df = require('vega-dataflow'), Daniel@0: Base = df.Node.prototype, // jshint ignore:line Daniel@0: Deps = df.Dependencies, Daniel@0: Parameter = require('./Parameter'); Daniel@0: Daniel@0: function Transform(graph) { Daniel@0: if (graph) Base.init.call(this, graph); Daniel@0: } Daniel@0: Daniel@0: Transform.addParameters = function(proto, params) { Daniel@0: proto._parameters = proto._parameters || {}; Daniel@0: for (var name in params) { Daniel@0: var p = params[name], Daniel@0: param = new Parameter(name, p.type, proto); Daniel@0: Daniel@0: proto._parameters[name] = param; Daniel@0: Daniel@0: if (p.type === 'custom') { Daniel@0: if (p.set) param.set = p.set.bind(param); Daniel@0: if (p.get) param.get = p.get.bind(param); Daniel@0: } Daniel@0: Daniel@0: if (p.hasOwnProperty('default')) param.set(p.default); Daniel@0: } Daniel@0: }; Daniel@0: Daniel@0: var prototype = (Transform.prototype = Object.create(Base)); Daniel@0: prototype.constructor = Transform; Daniel@0: Daniel@0: prototype.param = function(name, value) { Daniel@0: var param = this._parameters[name]; Daniel@0: return (param === undefined) ? this : Daniel@0: (arguments.length === 1) ? param.get() : param.set(value); Daniel@0: }; Daniel@0: Daniel@0: // Perform transformation. Subclasses should override. Daniel@0: prototype.transform = function(input/*, reset */) { Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: prototype.evaluate = function(input) { Daniel@0: // Many transforms store caches that must be invalidated if Daniel@0: // a signal value has changed. Daniel@0: var reset = this._stamp < input.stamp && Daniel@0: this.dependency(Deps.SIGNALS).reduce(function(c, s) { Daniel@0: return c += input.signals[s] ? 1 : 0; Daniel@0: }, 0); Daniel@0: return this.transform(input, reset); Daniel@0: }; Daniel@0: Daniel@0: prototype.output = function(map) { Daniel@0: for (var key in this._output) { Daniel@0: if (map[key] !== undefined) { Daniel@0: this._output[key] = map[key]; Daniel@0: } Daniel@0: } Daniel@0: return this; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Transform; Daniel@0: },{"./Parameter":131,"vega-dataflow":39}],136:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: dl = require('datalib'), Daniel@0: Tuple = require('vega-dataflow').Tuple, Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'), Daniel@0: BatchTransform = require('./BatchTransform'); Daniel@0: Daniel@0: var defaultRatio = 0.5 * (1 + Math.sqrt(5)); Daniel@0: Daniel@0: function Treemap(graph) { Daniel@0: BatchTransform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: // hierarchy parameters Daniel@0: sort: {type: 'array', default: ['-value']}, Daniel@0: children: {type: 'field', default: 'children'}, Daniel@0: field: {type: 'field', default: 'value'}, Daniel@0: // treemap parameters Daniel@0: size: {type: 'array', default: [500, 500]}, Daniel@0: round: {type: 'value', default: true}, Daniel@0: sticky: {type: 'value', default: false}, Daniel@0: ratio: {type: 'value', default: defaultRatio}, Daniel@0: padding: {type: 'value', default: null}, Daniel@0: mode: {type: 'value', default: 'squarify'} Daniel@0: }); Daniel@0: Daniel@0: this._layout = d3.layout.treemap(); Daniel@0: Daniel@0: this._output = { Daniel@0: 'x': 'layout_x', Daniel@0: 'y': 'layout_y', Daniel@0: 'width': 'layout_width', Daniel@0: 'height': 'layout_height', Daniel@0: 'depth': 'layout_depth', Daniel@0: }; Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Treemap.prototype = Object.create(BatchTransform.prototype)); Daniel@0: prototype.constructor = Treemap; Daniel@0: Daniel@0: prototype.batchTransform = function(input, data) { Daniel@0: log.debug(input, ['treemap']); Daniel@0: Daniel@0: // get variables Daniel@0: var layout = this._layout, Daniel@0: output = this._output; Daniel@0: Daniel@0: // configure layout Daniel@0: layout Daniel@0: .sort(dl.comparator(this.param('sort').field)) Daniel@0: .children(this.param('children').accessor) Daniel@0: .value(this.param('field').accessor) Daniel@0: .size(this.param('size')) Daniel@0: .round(this.param('round')) Daniel@0: .sticky(this.param('sticky')) Daniel@0: .ratio(this.param('ratio')) Daniel@0: .padding(this.param('padding')) Daniel@0: .mode(this.param('mode')) Daniel@0: .nodes(data[0]); Daniel@0: Daniel@0: // copy layout values to nodes Daniel@0: data.forEach(function(n) { Daniel@0: Tuple.set(n, output.x, n.x); Daniel@0: Tuple.set(n, output.y, n.y); Daniel@0: Tuple.set(n, output.width, n.dx); Daniel@0: Tuple.set(n, output.height, n.dy); Daniel@0: Tuple.set(n, output.depth, n.depth); Daniel@0: }); Daniel@0: Daniel@0: // return changeset Daniel@0: input.fields[output.x] = 1; Daniel@0: input.fields[output.y] = 1; Daniel@0: input.fields[output.width] = 1; Daniel@0: input.fields[output.height] = 1; Daniel@0: return input; Daniel@0: }; Daniel@0: Daniel@0: module.exports = Treemap; Daniel@0: }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) Daniel@0: Daniel@0: },{"./BatchTransform":117,"./Transform":135,"datalib":24,"vega-dataflow":39,"vega-logging":45}],137:[function(require,module,exports){ Daniel@0: (function (global){ Daniel@0: var d3 = (typeof window !== "undefined" ? window['d3'] : typeof global !== "undefined" ? global['d3'] : null), Daniel@0: Tuple = require('vega-dataflow/src/Tuple'), Daniel@0: log = require('vega-logging'), Daniel@0: Transform = require('./Transform'), Daniel@0: BatchTransform = require('./BatchTransform'); Daniel@0: Daniel@0: function Voronoi(graph) { Daniel@0: BatchTransform.prototype.init.call(this, graph); Daniel@0: Transform.addParameters(this, { Daniel@0: clipExtent: {type: 'array', default: [[-1e5,-1e5],[1e5,1e5]]}, Daniel@0: x: {type: 'field', default: 'layout_x'}, Daniel@0: y: {type: 'field', default: 'layout_y'} Daniel@0: }); Daniel@0: Daniel@0: this._layout = d3.geom.voronoi(); Daniel@0: this._output = {'path': 'layout_path'}; Daniel@0: Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Voronoi.prototype = Object.create(BatchTransform.prototype)); Daniel@0: prototype.constructor = Voronoi; Daniel@0: Daniel@0: prototype.batchTransform = function(input, data) { Daniel@0: log.debug(input, ['voronoi']); Daniel@0: Daniel@0: // get variables Daniel@0: var pathname = this._output.path; Daniel@0: Daniel@0: // configure layout Daniel@0: var polygons = this._layout Daniel@0: .clipExtent(this.param('clipExtent')) Daniel@0: .x(this.param('x').accessor) Daniel@0: .y(this.param('y').accessor) Daniel@0: (data); Daniel@0: Daniel@0: // build and assign path strings Daniel@0: for (var i=0; i', default: [900, 500]}, Daniel@0: text: {type: 'field', default: 'data'}, Daniel@0: rotate: {type: 'field|value', default: 0}, Daniel@0: font: {type: 'field|value', default: {value: 'sans-serif'}}, Daniel@0: fontSize: {type: 'field|value', default: 14}, Daniel@0: fontStyle: {type: 'field|value', default: {value: 'normal'}}, Daniel@0: fontWeight: {type: 'field|value', default: {value: 'normal'}}, Daniel@0: fontScale: {type: 'array', default: [10, 50]}, Daniel@0: padding: {type: 'value', default: 1}, Daniel@0: spiral: {type: 'value', default: 'archimedean'} Daniel@0: }); Daniel@0: Daniel@0: this._layout = d3_cloud(); Daniel@0: Daniel@0: this._output = { Daniel@0: 'x': 'layout_x', Daniel@0: 'y': 'layout_y', Daniel@0: 'font': 'layout_font', Daniel@0: 'fontSize': 'layout_fontSize', Daniel@0: 'fontStyle': 'layout_fontStyle', Daniel@0: 'fontWeight': 'layout_fontWeight', Daniel@0: 'rotate': 'layout_rotate', Daniel@0: }; Daniel@0: Daniel@0: return this.mutates(true); Daniel@0: } Daniel@0: Daniel@0: var prototype = (Wordcloud.prototype = Object.create(BatchTransform.prototype)); Daniel@0: prototype.constructor = Wordcloud; Daniel@0: Daniel@0: function get(p) { Daniel@0: return (p && p.accessor) || p; Daniel@0: } Daniel@0: Daniel@0: function wrap(tuple) { Daniel@0: var x = Object.create(tuple); Daniel@0: x._tuple = tuple; Daniel@0: return x; Daniel@0: } Daniel@0: Daniel@0: prototype.batchTransform = function(input, data) { Daniel@0: log.debug(input, ['wordcloud']); Daniel@0: Daniel@0: // get variables Daniel@0: var layout = this._layout, Daniel@0: output = this._output, Daniel@0: fontSize = this.param('fontSize'), Daniel@0: range = fontSize.accessor && this.param('fontScale'), Daniel@0: size, scale; Daniel@0: fontSize = fontSize.accessor || d3.functor(fontSize); Daniel@0: Daniel@0: // create font size scaling function as needed Daniel@0: if (range.length) { Daniel@0: scale = d3.scale.sqrt() Daniel@0: .domain(dl.extent(data, size=fontSize)) Daniel@0: .range(range); Daniel@0: fontSize = function(x) { return scale(size(x)); }; Daniel@0: } Daniel@0: Daniel@0: // configure layout Daniel@0: layout Daniel@0: .size(this.param('size')) Daniel@0: .text(get(this.param('text'))) Daniel@0: .padding(this.param('padding')) Daniel@0: .spiral(this.param('spiral')) Daniel@0: .rotate(get(this.param('rotate'))) Daniel@0: .font(get(this.param('font'))) Daniel@0: .fontStyle(get(this.param('fontStyle'))) Daniel@0: .fontWeight(get(this.param('fontWeight'))) Daniel@0: .fontSize(fontSize) Daniel@0: .words(data.map(wrap)) // wrap to avoid tuple writes Daniel@0: .on('end', function(words) { Daniel@0: var size = layout.size(), Daniel@0: dx = size[0] >> 1, Daniel@0: dy = size[1] >> 1, Daniel@0: w, t, i, len; Daniel@0: Daniel@0: for (i=0, len=words.length; i