diff --git a/dist/cedar.js b/dist/cedar.js
new file mode 100644
index 00000000..7a0c9818
--- /dev/null
+++ b/dist/cedar.js
@@ -0,0 +1,1372 @@
+/**
+* arcgis-cedar - v0.9.1 - Thu Mar 02 2017 08:51:29 GMT-0500 (EST)
+* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
+* Apache-2.0
+*/
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('d3'), require('vega')) :
+ typeof define === 'function' && define.amd ? define(['d3', 'vega'], factory) :
+ (global.Cedar = factory(global.d3,global.vg));
+}(this, (function (d3,vg) { 'use strict';
+
+var version = "0.9.1";
+
+/**
+ * Merges n objects
+ * @param {object} source Empty object that other objects will be merged into
+ * @return {Object} Merged objects
+ */
+function mixin (source) {
+ var i$1 = arguments.length, argsArray = Array(i$1);
+ while ( i$1-- ) argsArray[i$1] = arguments[i$1];
+
+ var args = [].concat( argsArray );
+ for (var i = 1; i < args.length; i++) {
+ d3.entries(args[i]).forEach(function (p) {
+ source[p.key] = p.value;
+ });
+ }
+ return source;
+}
+
+/**
+ * Recursively merge properties of two objects
+ */
+function mergeRecursive (obj1, obj2) {
+ for (var p in obj2) {
+ if (obj2.hasOwnProperty(p)) {
+ try {
+ // Property in destination object set; update its value.
+ if (obj2[p].constructor === Object || obj2[p].constructor === Array) {
+ obj1[p] = mergeRecursive(obj1[p], obj2[p]);
+ } else {
+ obj1[p] = obj2[p];
+ }
+ } catch (e) {
+ // Property in destination object not set; create it and set its value
+ obj1[p] = obj2[p];
+ }
+ }
+ }
+ return obj1;
+}
+
+/**
+ * Token replacement on a string
+ * @param {string} template string template
+ * @param {object} params Object hash that maps to the tokens to be replaced
+ * @return {string} string with values replaced
+ */
+function supplant (template, params) {
+ var t = template.replace(/{([^{}]*)}/g,
+ function (a, b) {
+ var r = getTokenValue(params, b);
+
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
+ }
+ );
+ return t.replace(/"{([^{}]*)}"/g,
+ function (a, b) {
+ var r = getTokenValue(params, b);
+ return (!!r && r.constructor === Array) ? JSON.stringify(r) : a;
+ });
+}
+
+/**
+ * Get the value of a token from a hash
+ * @param {object} tokens Hash {a: 'a', b: { c: 'c'} }
+ * @param {string} tokenName Property name: 'a' would yield 'a', 'b.c' would yield 'c'
+ * @return {Any} Returns value contained within property
+ * Pulled from gulp-token-replace (MIT license)
+ * https://github.com/Pictela/gulp-token-replace/blob/master/index.js
+ */
+function getTokenValue (tokens, tokenName) {
+ var tmpTokens = tokens;
+ var tokenNameParts = tokenName.split('.');
+ for (var i = 0; i < tokenNameParts.length; i++) {
+ if (tmpTokens.hasOwnProperty(tokenNameParts[i])) {
+ tmpTokens = tmpTokens[tokenNameParts[i]];
+ } else {
+ return null;
+ }
+ }
+ return tmpTokens;
+}
+
+ /**
+ * Helper function that validates that the
+ * mappings hash contains values for all
+ * the inputs
+ * @param {array} inputs Array of inputs
+ * @param {object} mappings Hash of mappings
+ * @return {array} Missing mappings
+ * @access private
+ */
+function validateMappings (inputs, mappings) {
+ return inputs.filter(function (input) {
+ if (input.required && !mappings[input.name]) {
+ return input;
+ }
+ });
+}
+
+ /**
+ * Validate that the incoming data has the fields expected
+ * in the mappings
+ * @access private
+ */
+function validateData (data, mappings) {
+ var missingInputs = [];
+ if (!data.features || !Array.isArray(data.features)) {
+ throw new Error('Data is expected to have features array!');
+ }
+ var firstRow = data.features[0].attributes;
+ for (var key in mappings) {
+ if (mappings.hasOwnProperty(key)) {
+ var fld = getMappingFieldName(key, mappings[key].field);
+ if (!firstRow.hasOwnProperty(fld)) {
+ missingInputs.push(fld);
+ }
+ }
+ }
+ return missingInputs;
+}
+
+ /**
+ * TODO does nothing, must figure out.
+ * Centralize and abstract the computation of
+ * expected field names, based on the mapping name
+ * @access private
+ */
+function getMappingFieldName (mappingName, fieldName) {
+ // this function why?
+
+ var name = fieldName;
+ // if(mappingName.toLowerCase() === 'count'){
+ // name = fieldName + '_SUM';
+ // }
+ return name;
+}
+
+var utils = {
+ mixin: mixin,
+ supplant: supplant,
+ mergeRecursive: mergeRecursive,
+ getTokenValue: getTokenValue,
+ validateMappings: validateMappings,
+ validateData: validateData,
+ getMappingFieldName: getMappingFieldName
+};
+
+/**
+ * Return a default definition Object
+ * @return {Object} Default definition
+ */
+function defaultDefinition () {
+ return {
+ dataset: {
+ query: defaultQuery()
+ },
+ template: {}
+ };
+}
+
+/**
+ * Return AGO query defaults
+ * @return {Object} Default query
+ */
+function defaultQuery () {
+ return {
+ where: '1=1',
+ returnGeometry: false,
+ returnDistinctValues: false,
+ returnIdsOnly: false,
+ returnCountOnly: false,
+ outFields: '*',
+ sqlFormat: 'standard',
+ f: 'json'
+ };
+}
+
+/**
+ * Ensure that all required inputs exist in mappings
+ * @param {object} mappings Mappings object
+ * @param {array} inputs Array of inputs in specification
+ * @return {object} Returns mappings
+ */
+function applyDefaultsToMappings (mappings, inputs) {
+ var errs = [];
+ // iterate over inputs
+ for (var i = 0; i < inputs.length; i++) {
+ var input = inputs[i];
+
+ // If required but not there
+ if (input.required && !mappings[input.name]) {
+ errs.push(input.name);
+ }
+
+ // if it's not required, has a default and not in the mappings
+ if (!input.required && !mappings[input.name] && input['default']) {
+ // add the default
+ mappings[input.name] = input['default'];
+ }
+ }
+ if (errs.length > 0) {
+ throw new Error(("Required Mappings Missing: " + (errs.join(','))));
+ } else {
+ return mappings;
+ }
+}
+
+/**
+ * Convert datasets to dataset
+ */
+function convertDatasetsToDataset (datasets, series, chartType, dataset) {
+ // console.log('Datasets and dataset are:', datasets, dataset);
+ if (!dataset) {
+ dataset = {
+ query: this.defaultQuery()
+ };
+ }
+ // Mappings held here
+ var mappings = {};
+ // Queries held here
+ var queries = [];
+ // Urls held here
+ var urls = [];
+ // Data held here
+ var data = [];
+
+ datasets.forEach(function (dtst) {
+ // Push queries data and urls first
+ if (dtst.query) {
+ queries.push(dtst.query);
+ }
+ if (dtst.url) {
+ urls.push(dtst.url);
+ }
+ if (dtst.data) {
+ data.push(dtst.data);
+ }
+ // Construct mappings
+ // Grouped bar chart here
+ if (chartType === 'grouped') {
+ if (!mappings.group) {
+ mappings.group = series[0].category;
+ }
+ if (!mappings.x) {
+ mappings.x = {
+ field: [],
+ label: series[0].value.label
+ };
+ }
+ if (series.length > 1) {
+ series.forEach(function (attr) {
+ mappings.x.field.push(("attributes." + (attr.value.field)));
+ });
+ } else {
+ mappings.x.field.push(("attributes." + (series[0].value.field)));
+ }
+
+ // Bubble Chart starts here
+ } else if (chartType === 'bubble') {
+ mappings.x = series[0].category;
+ mappings.y = series[0].value;
+ mappings.size = series[0].size;
+
+ // Scatter plot starts here
+ } else if (chartType === 'scatter') {
+ mappings.x = series[0].category;
+ mappings.y = series[0].value;
+ mappings.color = series[0].color;
+
+ // Pie Chart starts here
+ } else if (chartType === 'pie') {
+ mappings.label = series[0].category;
+ mappings.y = series[0].value;
+ mappings.radius = series[0].radius;
+
+ // Bar horizontal starts here
+ } else if (chartType === 'bar-horizontal') {
+ mappings.y = series[0].category;
+ mappings.x = series[0].value;
+
+ // Timeline chart starts here
+ } else if (chartType === 'time') {
+ mappings.time = series[0].category;
+ mappings.value = series[0].value;
+
+ // time-trendline chart starts here
+ } else if (chartType === 'time-trendline') {
+ mappings.time = series[0].category;
+ mappings.value = series[0].value;
+ mappings.trendline = series[0].trendline;
+
+ // X Y only charts here
+ } else {
+ mappings.x = series[0].category;
+ mappings.y = series[0].value;
+ }
+ });
+
+ var builtDataset = {
+ query: convertQueries(queries, dataset.query),
+ mappings: mappings
+ };
+ if (data.length > 0) {
+ builtDataset.data = data[0];
+ }
+
+ if (urls.length > 0) {
+ builtDataset.url = convertUrls(urls);
+ }
+
+ return builtDataset;
+}
+
+/**
+ * Convert over query
+ */
+function convertQueries (queries, defaultQuery) {
+ if (queries.length > 1) {
+ console.warn('Warning, currently multiple queries is not supported. Reverting to default.', queries);
+ return defaultQuery;
+ }
+ return queries[0] ? queries[0] : defaultQuery; // Might not have a query passed in so check and if it hasn't then return default query
+}
+
+/**
+ * Convert over URLs
+ */
+function convertUrls (urls) {
+ if (urls.length > 1) {
+ console.warn('Warning, currently multiple URLS are not supported. Using first url', urls);
+ return urls[0];
+ }
+ return urls[0];
+}
+
+var specUtils = {
+ defaultDefinition: defaultDefinition,
+ defaultQuery: defaultQuery,
+ applyDefaultsToMappings: applyDefaultsToMappings,
+ convertDatasetsToDataset: convertDatasetsToDataset
+};
+
+/**
+ * Takes in params, iterates over them, encodes and returns stringified and encoded query
+ *
+ * @param {object} params - merged default and user defined parameters
+ *
+ * @returns {string} - stringified and encoded query
+ */
+function serializeQueryParams (params) {
+ var str = [];
+ for (var param in params) {
+ if (params.hasOwnProperty(param)) {
+ var val = params[param];
+ if (typeof val !== 'string') {
+ val = JSON.stringify(val);
+ }
+ str.push(((encodeURIComponent(param)) + "=" + (encodeURIComponent(val))));
+ }
+ }
+ var queryString = str.join('&');
+ return queryString;
+}
+
+/**
+ * Helper function to request JSON from a url
+ * @param {string} url URL to request from
+ * @param {Function} callback Callback function
+ * @param {number} timeout Timeout on request
+ * @return {object} Response object
+ */
+function getJson$1 (url, callback, timeout) {
+ var cb = function (err, data) {
+ // if timeout error then return a timeout error
+ if (err && err.response === '') {
+ callback(new Error('This service is taking too long to respond, unable to chart'));
+ } else if (err) {
+ // Other errors return generic error.
+ callback(new Error(("Error loading " + url + " with a response of: " + (err.message))));
+ } else {
+ callback(null, JSON.parse(data.responseText));
+ }
+ };
+ if (url.length > 2000) {
+ var uri = url.split('?');
+ d3.xhr(uri[0])
+ .on('beforesend', function (xhr$$1) { xhr$$1.timeout = timeout; xhr$$1.ontimeout = xhr$$1.onload; })
+ .header('Content-Type', 'application/x-www-form-urlencoded')
+ .post(uri[1], cb);
+ } else {
+ d3.xhr(url)
+ .on('beforesend', function (xhr$$1) { xhr$$1.timeout = timeout; xhr$$1.ontimeout = xhr$$1.onload; })
+ .get(cb);
+ }
+}
+
+/**
+ * Given a dataset hash create a feature service request
+ * @param {object} dataset Dataset object
+ * @param {object} queryFromSpec Query passed in by the user
+ * @return {string} url string
+ */
+function createFeatureServiceRequest (dataset, queryFromSpec) {
+ var mergedQuery = mixin({}, defaultQuery(), queryFromSpec);
+
+ // Handle bbox
+ if (mergedQuery.bbox) {
+ // make sure a geometry was not also passed in
+ if (mergedQuery.geometry) {
+ throw new Error('Dataset.query can not have both a geometry and a bbox specified');
+ }
+ // Get the bbox (w,s,e,n)
+ var bboxArr = mergedQuery.bbox.split(',');
+
+ // Remove it so it's not serialized as-is
+ delete mergedQuery.bbox;
+
+ // cook it into a json string
+ mergedQuery.geometry = JSON.stringify({
+ xmin: bboxArr[0],
+ ymin: bboxArr[2],
+ xmax: bboxArr[1],
+ ymax: bboxArr[3]
+ });
+ // set spatial ref as geographic
+ mergedQuery.inSR = '4326';
+ }
+
+ if (!mergedQuery.groupByFieldsForStatistics && !!dataset.mappings.group) {
+ mergedQuery.groupByFieldsForStatistics = dataset.mappings.group.field;
+ }
+ if (!mergedQuery.outStatistics && !!dataset.mappings.count) {
+ // TODO Why are we explicitlystating _SUM as a stats type?
+ mergedQuery.orderByFields = (dataset.mappings.count.field) + "_SUM";
+ mergedQuery.outStatistics = JSON.stringify([{
+ statisticType: 'sum',
+ onStatisticField: dataset.mappings.count.field,
+ outStatisticFieldName: ((dataset.mappings.count.field) + "_SUM")
+ }]);
+ }
+
+ // iterate the mappings keys to check for sort
+ // -----------------------------------------------------------------
+ // This approach would seem 'clean' but if there are multiple fields
+ // to sort by, the order would be determined by how javascript decides to
+ // iterate the mappings property hash.
+ // Thus, using mappings.sort gives the developer explicit control
+ // -----------------------------------------------------------------
+ // var sort = [];
+ // for (var property in dataset.mappings) {
+ // if (dataset.mappings.hasOwnProperty(property)) {
+ // if(dataset.mappings[property].sort){
+ // //ok - build up the sort
+ // sort.push(dataset.mappings[property].field + ' ' + dataset.mappings[property].sort);
+ // }
+ // }
+ // }
+ // if(sort.length > 0){
+ // mergedQuery.orderByFields = sort.join(',');
+ // }
+ // -----------------------------------------------------------------
+ // check for a sort passed directly in
+
+ if (dataset.mappings.sort) {
+ mergedQuery.orderByFields = dataset.mappings.sort;
+ }
+
+ var url = (dataset.url) + "/query?" + (serializeQueryParams(mergedQuery));
+
+ if (dataset.token) {
+ url = url + "&token=" + (dataset.token);
+ }
+
+ return url;
+}
+
+var requestUtils = {
+ getJson: getJson$1,
+ createFeatureServiceRequest: createFeatureServiceRequest
+};
+
+// import specTemplates from './charts/specs';
+// get cedar root URL for loading chart specs
+var baseUrl = (function () {
+ var cdnProtocol = 'http:';
+ var cdnUrl = '//esri.github.io/cedar/js';
+ var src;
+ if (window && window.document) {
+ src = (window.document.currentScript && window.document.currentScript.src);
+ if (src) {
+ // real browser, get base url from current script
+ return src.substr(0, src.lastIndexOf('/'));
+ } else {
+ // ie, set base url to CDN
+ // NOTE: could fallback to CDN only if can't find any scripts named cedar
+ return (window.document.location ? window.document.location.protocol : cdnProtocol) + cdnUrl;
+ }
+ } else {
+ // node, set base url to CDN
+ return cdnProtocol + cdnUrl;
+ }
+})();
+
+var Cedar = function Cedar (options) {
+ var this$1 = this;
+
+ this.version = version;
+ // Pull templates in
+ // this.chartTypes = specTemplates;
+
+ var opts = options || {};
+
+ var spec;
+
+ this.baseUrl = baseUrl;
+ this.chartTypes = ['bar', 'bar-horizontal', 'bubble', 'grouped', 'pie', 'scatter', 'sparkline', 'time', 'time-trendline'];
+
+ // Cedar configs such as size..
+ this.width = undefined;
+ this.height = undefined;
+ this.autolabels = true;
+ this.maxLabelLength = undefined;
+
+ // Array to hold event handlers
+ this._events = [];
+
+ // initialize internal definition
+ this._definition = specUtils.defaultDefinition();
+
+ // initialize vega view aka chart
+ this._view = undefined;
+
+ // the vega tooltip
+ this._tooltip = undefined;
+
+ // transform function
+ this._transform = undefined;
+
+ // Queue to hold methods called while xhrs are in progress
+ this._methodQueue = [];
+
+ // Set a base timeout
+ this._timeout = undefined;
+
+ // override the base timeout
+ if (opts.timeout) {
+ this._timeout = opts.timeout;
+ }
+
+ // override the base url
+ if (opts.baseUrl) {
+ this.baseUrl = opts.baseUrl;
+ }
+
+ /**
+ * Flag used to determine if the library is waiting for an xhr to return.
+ * @access private
+ */
+ this._pendingXhr = false;
+
+ /**
+ * Definition
+ */
+
+ if (opts.definition) {
+ if (typeof opts.definition === 'object') {
+ // hold onto the definition
+ this._definition = opts.definition;
+ } else if (typeof opts.definition === 'string') {
+ // assume it's a url (relative or absolute) and fetch the def object
+ this._pendingXhr = true;
+ requestUtils.getJson(opts.definition, function (err, data) {
+ if (err) {
+ throw new Error('Error fetching definition object', err);
+ }
+ this$1._pendingXhr = false;
+ this$1._definition = data;
+ this$1._purgeMethodQueue();
+ }, this._timeout);
+ } else {
+ throw new Error('parameter definition must be an object or string (url)');
+ }
+ }
+
+ // if there are overrides
+ if (opts.override) {
+ this._definition.override = opts.override;
+ }
+
+ /**
+ * Specs
+ */
+
+ // first, check for pre-defined chart type passed in as 'type'
+ this._chartType = opts.type;
+ spec = this._getSpecificationUrl(opts.type);
+
+ // If url or object passed use that...
+ if (opts.specification) {
+ spec = opts.specification;
+ }
+
+ if (spec) {
+ // is it an object or string, assumed to be url
+ if (typeof spec === 'object') {
+ // hold onto the template
+ this._definition.specification = spec;
+ } else if (typeof spec === 'string') {
+ // assume it's a url (rel or abs) and fetch the template object
+ this._pendingXhr = true;
+ this._pendingXhr = true;
+ requestUtils.getJson(spec, function (err, data) {
+ if (err) {
+ throw new Error('Error fetching template object', err);
+ }
+ this$1._pendingXhr = false;
+ this$1._definition.specification = data;
+ this$1._purgeMethodQueue();
+ }, this._timeout);
+ } else {
+ throw new Error('parameter specification must be an object or string (url)');
+ }
+ }
+
+ // Allow a dataset to be passed in....
+ if (opts.dataset && typeof opts.dataset === 'object') {
+ opts.dataset.query = utils.mixin({}, specUtils.defaultQuery(), opts.dataset.query);
+ // Assign it
+ this._definition.dataset = opts.dataset;
+ }
+
+ // Allow datasets to be passed in
+ if (opts.datasets && Array.isArray(opts.datasets)) {
+ this._definition.datasets = opts.datasets;
+ }
+
+ // Allow series to be passed in
+ if (opts.series && Array.isArray(opts.series)) {
+ this._definition.series = opts.series;
+ }
+
+ /**
+ * Tooltip
+ */
+ // allow a tooltip to be passed in...
+ if (opts.tooltip && typeof opts.tooltip === 'object') {
+ this.tooltip = opts.tooltip;
+ } else {
+ // Build a default tooltip based on first two imputs....
+ var inputs = [];
+ for (var input in this._definition.dataset.mappings) {
+ if (this$1._definition.dataset.mappings.hasOwnProperty(input)) {
+ var field = this$1._definition.dataset.mappings[input].field;
+ if (field !== undefined && field !== null) {
+ inputs.push(field);
+ }
+ }
+ }
+ if (inputs.length >= 2) {
+ this.tooltip = {
+ 'title': ("{" + (inputs[0]) + "}"),
+ 'content': ("{" + (inputs[1]) + "}")
+ };
+ }
+ }
+
+ /**
+ * tranform
+ */
+ // Allow a transform func to pass in
+ if (opts.transform && typeof opts.transform === 'function') {
+ this._transform = opts.transform;
+ }
+};
+
+var prototypeAccessors = { dataset: {},datasets: {},series: {},specification: {},override: {},tooltip: {},transform: {} };
+
+/**
+ * Properties
+ */
+// Dataset - old api
+prototypeAccessors.dataset.get = function () {
+ return this._definition.dataset;
+};
+prototypeAccessors.dataset.set = function (val) {
+ this._definition.dataset = val;
+};
+
+// Datasets - new api
+prototypeAccessors.datasets.get = function () {
+ return this._definition.datasets;
+};
+prototypeAccessors.datasets.set = function (val) {
+ this._definition.datasets = val;
+};
+
+// Series - new api
+prototypeAccessors.series.get = function () {
+ return this._definition.series;
+};
+prototypeAccessors.series.set = function (val) {
+ this._definition.series = val;
+};
+
+// Specification
+prototypeAccessors.specification.get = function () {
+ return this._definition.specification;
+};
+prototypeAccessors.specification.set = function (val) {
+ this._definition.specification = val;
+};
+
+// override
+prototypeAccessors.override.get = function () {
+ return this._definition.override;
+};
+prototypeAccessors.override.set = function (val) {
+ this._definition.override = val;
+ // return this.update(); // TODO is this the best way?
+};
+
+// Tooltip
+prototypeAccessors.tooltip.get = function () {
+ return this._definition.tooltip;
+};
+prototypeAccessors.tooltip.set = function (val) {
+ this._definition.tooltip = val;
+ if (this._definition.tooltip.id === undefined || this._definition.tooltip.id === null) {
+ this._definition.tooltip.id = "cedar-" + (Date.now());
+ }
+};
+
+// transform
+prototypeAccessors.transform.get = function () {
+ return this._transform;
+};
+prototypeAccessors.transform.set = function (val) {
+ this._transform = val;
+};
+
+Cedar.prototype._getSpecificationUrl = function _getSpecificationUrl (spec) {
+ if (this.chartTypes.indexOf(spec) !== -1) {
+ spec = (this.baseUrl) + "/charts/" + (this.chartTypes[this.chartTypes.indexOf(spec)]) + ".json";
+ }
+ return spec;
+};
+
+/**
+ * Inspect the current state of the Object
+ * and determine if we have sufficient information
+ * to render the chart
+ * @return {object} Hash of the draw state + any missing requirements
+ */
+Cedar.prototype.canDraw = function canDraw () {
+ // dataset?
+ // dataset.url || dataset.data?
+ // dataset.mappings?
+ // specification?
+ // specification.template?
+ // specification.inputs?
+ // specification.inputs ~ dataset.mappings?
+
+ return {drawable: true, errs: []};
+};
+
+/**
+ * Draw the chart into the DOM element
+ *
+ * @example
+ *
+ * var chart = new Cedar({
+ * "type": "scatter",
+ * "dataset":{
+ * "url":"http://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Education_WebMercator/MapServer/5",
+ * "query":{},
+ * "mappings":{
+ * "x": {"field":"POPULATION_ENROLLED_2008","label":"Enrolment 2008"},
+ * "y": {"field":"SQUARE_FOOTAGE","label":"Square Footage"},
+ * "color":{"field":"FACUSE","label":"Facility Type"}
+ * }
+ * }
+ * });
+ *
+ * chart.show({
+ * elementId: "#chart"
+ * });
+ *
+ * @param{object} options
+ * @param {String} options.elementId [required] Id of the Dom element into which the chart will be rendered
+ * @param {String} options.renderer "canvas" or "svg" (default: `svg`)
+ * @param {Boolean} options.autolabels place axis labels outside any tick labels (default: false)
+ * @param {String} options.token Token to be used if the data or spec are on a secured server
+ */
+Cedar.prototype.show = function show (options, clb) {
+ if (this._pendingXhr) {
+ // TODO addToMethodQueue
+ this._addToMethodQueue('show', [options, clb]);
+ } else {
+ var err;
+ // ensure we got an elementId
+ if (!options.elementId) {
+ err = 'Cedar.show requires options.elementId';
+ }
+ // Check if element exists in the page
+ if (d3.select(options.elementId)[0][0] === null) {
+ err = "Element " + (options.elementId) + " is not present in the DOM";
+ }
+
+ // hold onto the id
+ this._elementId = options.elementId;
+ this._renderer = options.renderer || 'svg'; // default to svg
+ this.width = options.width || this.height;
+ this.height = options.height || this.height;
+ if (options.autolabels !== undefined && options.autolabels !== null) {
+ this.autolabels = options.autolabels;
+ }
+
+ if (options.maxLabelLength) {
+ // check if truncate label length has been passed in
+ this.maxLabelLength = options.maxLabelLength;
+ }
+
+ // hold onto the token
+ if (options.token) {
+ this._token = options.token;
+ }
+
+ if (err) {
+ throw new Error(err);
+ }
+
+ var chk = this.canDraw();
+
+ if (chk.drawable) {
+ this.update(clb);
+ } else {
+ // report the issues
+ var errs = chk.issues.join(',');
+ throw new Error(("Chart can not be drawn because: " + errs));
+ }
+ }
+};
+
+/**
+ * Draw the chart based on any changes to data or specifications
+ * Should be called after a user modifies
+ * the dataset, query, mappings, chart specification or element size
+ *
+ * @example
+ * dataset = {"url": "...", "mappings": {"x": {"field": "STATE"}, "y": {"field": "POPULATION"}}};
+ * chart = new Cedar({ "type": "bar", "dataset": dataset });
+ * chart.show({elementId: "#chart"});
+ * chart.dataset.query.where = "POPULATION>30000";
+ * chart.update();
+ */
+Cedar.prototype.update = function update (clb) {
+ var this$1 = this;
+
+ if (this._view) {
+ this.emit('update-start');
+ }
+
+ if (this._pendingXhr) {
+ this._addToMethodQueue('update');
+ } else {
+ if (this._view) {
+ // remove handlers
+ // TODO Remove existing handlers
+ this._remove(this._view);
+ }
+
+ try {
+ if (this._definition.datasets && this._definition.series) {
+ this._definition.dataset = specUtils.convertDatasetsToDataset(this._definition.datasets, this._definition.series, this._chartType, this._definition.dataset);
+ if (!this._definition.tooltip) {
+ this.tooltip = {
+ 'title': ("{" + (this._definition.series[0].category.field) + "}"),
+ 'content': ("{" + (this._definition.series[0].value.field) + "}")
+ };
+ }
+ }
+
+ // Creates the HTML Div and styling if not already created
+ if (this._definition.tooltip) {
+ this._createTooltip(this._definition.tooltip.id);
+ }
+ // Ensure we have required inputs or defaults
+ var compiledMappings = specUtils.applyDefaultsToMappings(this._definition.dataset.mappings, this._definition.specification.inputs);
+
+ var queryFromSpec = utils.mixin({}, this._definition.specification.query, this._definition.dataset.query);
+ queryFromSpec = JSON.parse(utils.supplant(JSON.stringify(queryFromSpec), compiledMappings));
+
+ // allow binding to query properties
+ compiledMappings.query = queryFromSpec;
+
+ // compile the template + mappings --> vega spec
+ var spec = JSON.parse(utils.supplant(JSON.stringify(this._definition.specification.template), compiledMappings));
+
+ // merge in user specified style overrides
+ spec = utils.mergeRecursive(spec, this._definition.override);
+
+ // if the spec has a url in the data node, delete it TODO: need to readress this.
+ if (spec.data[0].url) {
+ delete spec.data[0].url;
+ }
+
+ if (this._definition.dataset.data) {
+ // create the data node using the passed in data
+ spec.data[0].values = this._definition.dataset.data; // TODO: only works on first spec, need to address for multiple datasets.
+
+ // Send to vega
+ this._renderSpec(spec, clb);
+ } else {
+ // We need to fetch the data so....
+ var url = requestUtils.createFeatureServiceRequest(this._definition.dataset, queryFromSpec);
+
+ // create a callback closure to carry the spec
+ var cb = function (err, data) {
+ // Normalize error response
+ if (!err && !!data.error) {
+ err = new Error(data.error.message || data.error.details[0]);
+ }
+ // if no errors then continue...
+ if (!err) {
+ if (this$1._transform && typeof this$1._transform === 'function') {
+ data = this$1._transform(data, this$1._definition.dataset);
+ }
+ // TODO add error handlers for xhr and AGS errors.
+ spec.data[0].values = data;
+ // send to vega
+ this$1._renderSpec(spec, clb);
+ } else {
+ // optional callback
+ if (!!clb && typeof clb === 'function') {
+ clb(err, data);
+ }
+ }
+ };
+
+ // fetch the data from the service
+ requestUtils.getJson(url, cb, this._timeout);
+ }
+ } catch (ex) {
+ throw (ex);
+ }
+ }
+};
+
+/**
+ * RENDER CHART FUNCTIONS
+ *
+ *
+ * Render a compiled Vega specification using vega runtime
+ */
+
+Cedar.prototype._renderSpec = function _renderSpec (spec, clb) {
+ var this$1 = this;
+
+ if (this.autolabels === true) {
+ spec = this._placeLabels(spec);
+ spec = this._placeaAxisTicks(spec);
+ }
+ // Use vega to parse the spec
+ // It will handle the spec as an object or url
+ vg.parse.spec(spec, function (err, chartCtor) {
+ // create the view
+ this$1._view = chartCtor({
+ el: this$1._elementId,
+ renderer: this$1._renderer
+ });
+
+ var width = this$1.width || parseInt(d3.select(this$1._elementId).style('width'), 10) || 500;
+ var height = this$1.height || parseInt(d3.select(this$1._elementId).style('height'), 10) || 500;
+
+ // render into the element
+ this$1._view.width(width).height(height).update();
+
+ // attach event proxies
+ this$1._attach(this$1._view);
+
+ if (this$1._view) {
+ this$1.emit('update-end');
+ }
+
+ // expose errors
+ if (!!clb && typeof clb === 'function') {
+ clb(err, spec);
+ }
+ });
+};
+
+/**
+ * AXIS TICK FUNCTIONS START HERE
+ *
+ *
+ * Automatically determines axis title placement
+ *
+ * Calculates the maximum length of a tick label and adds padding
+ */
+
+Cedar.prototype._placeLabels = function _placeLabels (spec) {
+ var this$1 = this;
+
+ try {
+ var fields = {};
+ var lengths = {};
+ var inputs = [];
+ // Get all inputs that may be axes
+ for (var input in this._definition.dataset.mappings) {
+ // check also if property is not inherited from prototype
+ if (this$1._definition.dataset.mappings.hasOwnProperty(input)) {
+ var field = this$1._definition.dataset.mappings[input].field;
+ if (field) {
+ inputs.push(input);
+ fields[input] = field;
+ lengths[input] = 0;
+ }
+ }
+ }
+ var length = 0;
+
+ // find the max length value for each axis
+ spec.data[0].values.features.forEach(function (feature) {
+ inputs.forEach(function (axis) {
+ length = (feature.attributes[fields[axis]] || '').toString().length;
+ if (this$1.maxLabelLength) {
+ // Need to make sure that the gap between title and labels isn't ridiculous
+ length = length < (this$1.maxLabelLength + 1) ? length : this$1.maxLabelLength;
+ }
+ if (length > lengths[axis]) {
+ lengths[axis] = length;
+ }
+ });
+ });
+
+ // Change each axis title offset based on longest value
+ inputs.forEach(function (axis, index) {
+ var angle = 0;
+ if (!!spec.axes && !!spec.axes[index]) {
+ if (spec.axes[index].properties.labels.angle) {
+ angle = spec.axes[index].properties.labels.angle.value;
+ }
+ if (spec.axes[index].type === 'y') {
+ angle = 100 - angle;
+ }
+ if (this$1.maxLabelLength) {
+ // Set max length of axes titles
+ spec.axes[index].properties.labels.text = {'template': ("{{ datum.data | truncate:\"" + (this$1.maxLabelLength) + "\"}}")};
+ }
+ // set title offset
+ spec.axes[index].titleOffset = Math.abs(lengths[axis] * angle / 100 * 8) + 35;
+ }
+ });
+ return spec;
+ } catch (ex) {
+ throw (ex);
+ }
+};
+
+/**
+ * Automatically determines number of axis tick marks
+ *
+ * Calculates the maximum length of a tick label and adds padding
+ * TODO: remove expectation that there are both x,y axes
+ */
+
+Cedar.prototype._placeaAxisTicks = function _placeaAxisTicks (spec) {
+ if (spec.axes) {
+ try {
+ var width = this.width || parseInt(d3.select(this._elementId).style('width'), 10) || 500;
+ var height = this.height || parseInt(d3.select(this._elementId).style('height'), 10) || 500;
+
+ spec.axes[0].ticks = width / 100;
+ if (spec.axes[1]) {
+ spec.axes[1].ticks = height / 30;
+ }
+ } catch (ex) {
+ throw (ex);
+ }
+ }
+ return spec;
+};
+
+/**
+ * TOOLTIP LOGIC HERE
+ *
+ * Instantiates the tooltip element and styling
+ * @access private
+ */
+Cedar.prototype._createTooltip = function _createTooltip (elem) {
+ var this$1 = this;
+
+ var tooltipDiv = document.getElementById(elem);
+
+ // Check if tooltip has been created or not...
+ if (tooltipDiv) {
+ return tooltipDiv;
+ }
+
+ // TODO: remove inline CSS
+ var style = document.createElement('style');
+ style.type = 'text/css';
+ style.innerHTML = '.cedar-tooltip {background-color: white; padding: 3px 10px; color: #333; margin: -30px 0 0 20px; position: absolute; z-index: 2000; font-size: 10px; border: 1px solid #BBB;} .cedar-tooltip .title {font-size: 13pt; font-weight: bold; } .cedar-tooltip .content {font-size: 10pt; } ';
+ document.getElementsByTagName('head')[0].appendChild(style);
+
+ tooltipDiv = document.createElement('div');
+ tooltipDiv.className = 'cedar-tooltip';
+ tooltipDiv.id = elem;
+ tooltipDiv.cssText = 'display: none';
+ // We need tooltip at the top of the page
+ document.body.insertBefore(tooltipDiv, document.body.firstChild);
+
+ this.on('mouseout', function (event, data) {
+ this$1._updateTooltip(event, null);
+ });
+ this.on('mousemove', function (event, data) {
+ this$1._updateTooltip(event, data);
+ });
+ return tooltipDiv;
+};
+
+/**
+ * Places the tooltipe and fills in content
+ *
+ * @access private
+ */
+Cedar.prototype._updateTooltip = function _updateTooltip (event, data) {
+ var cedartip = document.getElementById(this._definition.tooltip.id);
+ if (!data) {
+ cedartip.style.display = 'none';
+ return;
+ }
+ cedartip.style.top = (event.pageY) + "px";
+ cedartip.style.left = (event.pageX) + "px";
+ cedartip.style.display = 'block';
+
+ var content = "" + (this._definition.tooltip.title) + "
";
+ content += "
" + (this._definition.tooltip.content) + "
"; + + cedartip.innerHTML = content.replace(/\{(\w+)\}/g, function (match, $1) { + return data[$1]; + }); +}; + + /** + * EVENT LOGIC HERE + * + * + * Add a handler for the named event. + * Events: + *- mouseover + *- mouseout + *- click + *- update-start + *- update-end + * + * + * + * Callback from Cedar events + *- callback Cedar~eventCallback + *- param {Object} event - event response such as mouse location + *- param {Object} data - chart data object + * + * @example + * var chart = new Cedar({ ... }); + * chart.on('mouseover', function(event, data) { + * console.log("Mouse Location:", [event.offsetX, event.offsetY]); + * console.log("Data value:", data[Object.keys(data)[0]]); + * }); + * + * @param {String} eventName name of the event that invokes callback + * @param {Cedar~eventCallback} callback - The callback that handles the event. + */ +Cedar.prototype.on = function on (evtName, callback) { + this._events.push({type: evtName, callback: callback}); +}; +/** + * Remove a hanlder for the named event + */ +Cedar.prototype.off = function off (evtName, callback) { + this._events.forEach(function (registeredEvent, index, object) { + if (registeredEvent.type === evtName && registeredEvent.callback === callback) { + object.splice(index, 1); + } + }); +}; + +/** + * Trigger a callback + * @param {string} eventName - ["mouseover","mouseout","click","update-start","update-end"] + */ +Cedar.prototype.emit = function emit (eventName) { + if (!!this._view._handler._handlers[ eventName ] && !!this._view._handler._handlers[ eventName ][0]) { + this._view._handler._handlers[ eventName ][0].handler(); + } +}; + +/** + * Attach the generic proxy hanlders to the chart view + * @access private + */ +Cedar.prototype._attach = function _attach (view) { + view.on('mouseover', this._handler('mouseover')); + view.on('mouseout', this._handler('mouseout')); + view.on('mousemove', this._handler('mousemove')); + view.on('click', this._handler('click')); + view.on('update-start', this._handler('update-start')); + view.on('update-end', this._handler('update-end')); +}; + +/** + * Remove all event handlers from the view + * @access private + */ +Cedar.prototype._remove = function _remove (view) { + view.off('mouseover'); + view.off('mouseout'); + view.off('mousemove'); + view.off('click'); + view.off('update-start'); + view.off('update-end'); +}; + +/** + * Creates an entry in the method queue, executed + * once a pending xhr is completed + * @access private + */ +Cedar.prototype._addToMethodQueue = function _addToMethodQueue (name$$1, args) { + this._methodQueue.push({ method: name$$1, args: args }); +}; + +/** + * empties the method queue by calling the queued methods + * This helps build a more syncronous api, while still + * doing async things in the code + * @access private + */ +Cedar.prototype._purgeMethodQueue = function _purgeMethodQueue () { + var this$1 = this; + + if (this._methodQueue.length > 0) { + this._methodQueue.forEach(function (action, index) { + this$1[action.method].apply(this$1, action.args); + }); + } +}; + +/** + * Generic event handler proxy + * @access private + */ +Cedar.prototype._handler = function _handler (evtName) { + var this$1 = this; + + // return a handler function w/ the events hash closed over + var handler = function (evt, item) { + this$1._events.forEach(function (registeredHandler) { + if (registeredHandler.type === evtName) { + // invoke the callback with the data + if (item) { + registeredHandler.callback(evt, item.datum.attributes); + } else { + registeredHandler.callback(evt, null); + } + } + }); + }; + return handler; +}; + +/** + * SELECT LOGIC STARTS HERE + * + * Highlight marker based on attribute value + * + * @example + * chart = new Cedar({...}); + * chart.select({key: 'ZIP_CODE', value: '20002'}); + * + * @param {object} options - Object(key, value) to match. Calls hover on work + * @returns {Array} items - array of chart objects that match the criteria + */ + +Cedar.prototype.select = function select (options) { + var this$1 = this; + + var view = this._view; + var items = view.model().scene().items[0].items[0].items; + + items.forEach(function (item) { + if (item.datum.attributes[options.key] === options.value) { + if (item.hasPropertySet('hover')) { + this$1._view.update({props: 'hover', items: item}); + } + } + }); + + return items; +}; + + /** + * Removes highlighted chart items + * + * If "options" are used, only clear specific items, otherwise clears all highlights. + * @param {Object} options - Object(key, value) to match. Calls hover on mark + * @returns {Array} items - array of chart objects that match the criteria, or null if all items. + */ + +Cedar.prototype.clearSelection = function clearSelection (options) { + var this$1 = this; + + var view = this._view; + + if (!!options && !!options.key) { + var items = view.model().scene().items[0].items[0].items; + items.forEach(function (item) { + if (item.datum.attributes[options.key] === options.value) { + this$1._view.update({props: 'update', items: item}); + } + }); + return items; + } else { + // clear all + this._view.update(); + return null; + } +}; + +Cedar.getJson = function getJson (url, callback, timeout) { + return requestUtils.getJson(url, callback, timeout); +}; + +/** + * Other now exposed utils! + */ +Cedar._validateMappings = function _validateMappings (inputs, mappings) { + return utils.validateMappings(inputs, mappings); +}; +Cedar._validateData = function _validateData (data, mappings) { + return utils.validateData(data, mappings); +}; +Cedar._createFeatureServiceRequest = function _createFeatureServiceRequest (dataset, queryFromSpec) { + return requestUtils.createFeatureServiceRequest(dataset, queryFromSpec); +}; +Cedar._getMappingFieldName = function _getMappingFieldName (mappingName, fieldName) { + return utils.getMappingFieldName(mappingName, fieldName); +}; +// TODO: remove once we have a better way to unit test +Cedar._convertDatasetsToDataset = function _convertDatasetsToDataset (datasets, dataset, chartType) { + return specUtils.convertDatasetsToDataset(datasets, dataset, chartType); +}; + +Object.defineProperties( Cedar.prototype, prototypeAccessors ); + +return Cedar; + +}))); +//# sourceMappingURL=cedar.js.map diff --git a/dist/cedar.js.map b/dist/cedar.js.map new file mode 100644 index 00000000..6b8329b2 --- /dev/null +++ b/dist/cedar.js.map @@ -0,0 +1 @@ +{"version":3,"file":null,"sources":["../src/utils/utils.js","../src/utils/spec.js","../src/utils/request.js","../src/cedar.js"],"sourcesContent":["import * as d3 from 'd3';\n/**\n * Merges n objects\n * @param {object} source Empty object that other objects will be merged into\n * @return {Object} Merged objects\n */\nexport function mixin (source) {\n const args = [...arguments];\n for (let i = 1; i < args.length; i++) {\n d3.entries(args[i]).forEach((p) => {\n source[p.key] = p.value;\n });\n }\n return source;\n}\n\n/**\n * Recursively merge properties of two objects\n */\nexport function mergeRecursive (obj1, obj2) {\n for (let p in obj2) {\n if (obj2.hasOwnProperty(p)) {\n try {\n // Property in destination object set; update its value.\n if (obj2[p].constructor === Object || obj2[p].constructor === Array) {\n obj1[p] = mergeRecursive(obj1[p], obj2[p]);\n } else {\n obj1[p] = obj2[p];\n }\n } catch (e) {\n // Property in destination object not set; create it and set its value\n obj1[p] = obj2[p];\n }\n }\n }\n return obj1;\n}\n\n/**\n * Token replacement on a string\n * @param {string} template string template\n * @param {object} params Object hash that maps to the tokens to be replaced\n * @return {string} string with values replaced\n */\nexport function supplant (template, params) {\n const t = template.replace(/{([^{}]*)}/g,\n (a, b) => {\n const r = getTokenValue(params, b);\n\n return typeof r === 'string' || typeof r === 'number' ? r : a;\n }\n );\n return t.replace(/\"{([^{}]*)}\"/g,\n (a, b) => {\n let r = getTokenValue(params, b);\n return (!!r && r.constructor === Array) ? JSON.stringify(r) : a;\n });\n}\n\n/**\n * Get the value of a token from a hash\n * @param {object} tokens Hash {a: 'a', b: { c: 'c'} }\n * @param {string} tokenName Property name: 'a' would yield 'a', 'b.c' would yield 'c'\n * @return {Any} Returns value contained within property\n * Pulled from gulp-token-replace (MIT license)\n * https://github.com/Pictela/gulp-token-replace/blob/master/index.js\n */\nexport function getTokenValue (tokens, tokenName) {\n let tmpTokens = tokens;\n let tokenNameParts = tokenName.split('.');\n for (let i = 0; i < tokenNameParts.length; i++) {\n if (tmpTokens.hasOwnProperty(tokenNameParts[i])) {\n tmpTokens = tmpTokens[tokenNameParts[i]];\n } else {\n return null;\n }\n }\n return tmpTokens;\n}\n\n /**\n * Helper function that validates that the\n * mappings hash contains values for all\n * the inputs\n * @param {array} inputs Array of inputs\n * @param {object} mappings Hash of mappings\n * @return {array} Missing mappings\n * @access private\n */\nexport function validateMappings (inputs, mappings) {\n return inputs.filter((input) => {\n if (input.required && !mappings[input.name]) {\n return input;\n }\n });\n}\n\n /**\n * Validate that the incoming data has the fields expected\n * in the mappings\n * @access private\n */\nexport function validateData (data, mappings) {\n const missingInputs = [];\n if (!data.features || !Array.isArray(data.features)) {\n throw new Error('Data is expected to have features array!');\n }\n const firstRow = data.features[0].attributes;\n for (let key in mappings) {\n if (mappings.hasOwnProperty(key)) {\n let fld = getMappingFieldName(key, mappings[key].field);\n if (!firstRow.hasOwnProperty(fld)) {\n missingInputs.push(fld);\n }\n }\n }\n return missingInputs;\n}\n\n /**\n * TODO does nothing, must figure out.\n * Centralize and abstract the computation of\n * expected field names, based on the mapping name\n * @access private\n */\nexport function getMappingFieldName (mappingName, fieldName) {\n // this function why?\n\n let name = fieldName;\n // if(mappingName.toLowerCase() === 'count'){\n // name = fieldName + '_SUM';\n // }\n return name;\n}\n\nconst utils = {\n mixin,\n supplant,\n mergeRecursive,\n getTokenValue,\n validateMappings,\n validateData,\n getMappingFieldName\n};\n\nexport default utils;\n","/**\n * Return a default definition Object\n * @return {Object} Default definition\n */\nexport function defaultDefinition () {\n return {\n dataset: {\n query: defaultQuery()\n },\n template: {}\n };\n}\n\n/**\n * Return AGO query defaults\n * @return {Object} Default query\n */\nexport function defaultQuery () {\n return {\n where: '1=1',\n returnGeometry: false,\n returnDistinctValues: false,\n returnIdsOnly: false,\n returnCountOnly: false,\n outFields: '*',\n sqlFormat: 'standard',\n f: 'json'\n };\n}\n\n/**\n * Ensure that all required inputs exist in mappings\n * @param {object} mappings Mappings object\n * @param {array} inputs Array of inputs in specification\n * @return {object} Returns mappings\n */\nexport function applyDefaultsToMappings (mappings, inputs) {\n const errs = [];\n // iterate over inputs\n for (let i = 0; i < inputs.length; i++) {\n const input = inputs[i];\n\n // If required but not there\n if (input.required && !mappings[input.name]) {\n errs.push(input.name);\n }\n\n // if it's not required, has a default and not in the mappings\n if (!input.required && !mappings[input.name] && input['default']) {\n // add the default\n mappings[input.name] = input['default'];\n }\n }\n if (errs.length > 0) {\n throw new Error(`Required Mappings Missing: ${errs.join(',')}`);\n } else {\n return mappings;\n }\n}\n\n/**\n * Convert datasets to dataset\n */\nexport function convertDatasetsToDataset (datasets, series, chartType, dataset) {\n // console.log('Datasets and dataset are:', datasets, dataset);\n if (!dataset) {\n dataset = {\n query: this.defaultQuery()\n };\n }\n // Mappings held here\n const mappings = {};\n // Queries held here\n const queries = [];\n // Urls held here\n const urls = [];\n // Data held here\n const data = [];\n\n datasets.forEach((dtst) => {\n // Push queries data and urls first\n if (dtst.query) {\n queries.push(dtst.query);\n }\n if (dtst.url) {\n urls.push(dtst.url);\n }\n if (dtst.data) {\n data.push(dtst.data);\n }\n // Construct mappings\n // Grouped bar chart here\n if (chartType === 'grouped') {\n if (!mappings.group) {\n mappings.group = series[0].category;\n }\n if (!mappings.x) {\n mappings.x = {\n field: [],\n label: series[0].value.label\n };\n }\n if (series.length > 1) {\n series.forEach((attr) => {\n mappings.x.field.push(`attributes.${attr.value.field}`);\n });\n } else {\n mappings.x.field.push(`attributes.${series[0].value.field}`);\n }\n\n // Bubble Chart starts here\n } else if (chartType === 'bubble') {\n mappings.x = series[0].category;\n mappings.y = series[0].value;\n mappings.size = series[0].size;\n\n // Scatter plot starts here\n } else if (chartType === 'scatter') {\n mappings.x = series[0].category;\n mappings.y = series[0].value;\n mappings.color = series[0].color;\n\n // Pie Chart starts here\n } else if (chartType === 'pie') {\n mappings.label = series[0].category;\n mappings.y = series[0].value;\n mappings.radius = series[0].radius;\n\n // Bar horizontal starts here\n } else if (chartType === 'bar-horizontal') {\n mappings.y = series[0].category;\n mappings.x = series[0].value;\n\n // Timeline chart starts here\n } else if (chartType === 'time') {\n mappings.time = series[0].category;\n mappings.value = series[0].value;\n\n // time-trendline chart starts here\n } else if (chartType === 'time-trendline') {\n mappings.time = series[0].category;\n mappings.value = series[0].value;\n mappings.trendline = series[0].trendline;\n\n // X Y only charts here\n } else {\n mappings.x = series[0].category;\n mappings.y = series[0].value;\n }\n });\n\n const builtDataset = {\n query: convertQueries(queries, dataset.query),\n mappings\n };\n if (data.length > 0) {\n builtDataset.data = data[0];\n }\n\n if (urls.length > 0) {\n builtDataset.url = convertUrls(urls);\n }\n\n return builtDataset;\n}\n\n/**\n * Convert over query\n */\nfunction convertQueries (queries, defaultQuery) {\n if (queries.length > 1) {\n console.warn('Warning, currently multiple queries is not supported. Reverting to default.', queries);\n return defaultQuery;\n }\n return queries[0] ? queries[0] : defaultQuery; // Might not have a query passed in so check and if it hasn't then return default query\n}\n\n/**\n * Convert over URLs\n */\nfunction convertUrls (urls) {\n if (urls.length > 1) {\n console.warn('Warning, currently multiple URLS are not supported. Using first url', urls);\n return urls[0];\n }\n return urls[0];\n}\n\nconst specUtils = {\n defaultDefinition,\n defaultQuery,\n applyDefaultsToMappings,\n convertDatasetsToDataset\n};\n\nexport default specUtils;\n","import * as d3 from 'd3';\nimport { mixin } from './utils';\nimport { defaultQuery } from './spec';\n\n/**\n * Takes in params, iterates over them, encodes and returns stringified and encoded query\n *\n * @param {object} params - merged default and user defined parameters\n *\n * @returns {string} - stringified and encoded query\n */\nfunction serializeQueryParams (params) {\n const str = [];\n for (const param in params) {\n if (params.hasOwnProperty(param)) {\n let val = params[param];\n if (typeof val !== 'string') {\n val = JSON.stringify(val);\n }\n str.push(`${encodeURIComponent(param)}=${encodeURIComponent(val)}`);\n }\n }\n const queryString = str.join('&');\n return queryString;\n}\n\n/**\n * Helper function to request JSON from a url\n * @param {string} url URL to request from\n * @param {Function} callback Callback function\n * @param {number} timeout Timeout on request\n * @return {object} Response object\n */\nexport function getJson (url, callback, timeout) {\n const cb = (err, data) => {\n // if timeout error then return a timeout error\n if (err && err.response === '') {\n callback(new Error('This service is taking too long to respond, unable to chart'));\n } else if (err) {\n // Other errors return generic error.\n callback(new Error(`Error loading ${url} with a response of: ${err.message}`));\n } else {\n callback(null, JSON.parse(data.responseText));\n }\n };\n if (url.length > 2000) {\n const uri = url.split('?');\n d3.xhr(uri[0])\n .on('beforesend', (xhr) => { xhr.timeout = timeout; xhr.ontimeout = xhr.onload; })\n .header('Content-Type', 'application/x-www-form-urlencoded')\n .post(uri[1], cb);\n } else {\n d3.xhr(url)\n .on('beforesend', (xhr) => { xhr.timeout = timeout; xhr.ontimeout = xhr.onload; })\n .get(cb);\n }\n}\n\n/**\n * Given a dataset hash create a feature service request\n * @param {object} dataset Dataset object\n * @param {object} queryFromSpec Query passed in by the user\n * @return {string} url string\n */\nexport function createFeatureServiceRequest (dataset, queryFromSpec) {\n const mergedQuery = mixin({}, defaultQuery(), queryFromSpec);\n\n // Handle bbox\n if (mergedQuery.bbox) {\n // make sure a geometry was not also passed in\n if (mergedQuery.geometry) {\n throw new Error('Dataset.query can not have both a geometry and a bbox specified');\n }\n // Get the bbox (w,s,e,n)\n const bboxArr = mergedQuery.bbox.split(',');\n\n // Remove it so it's not serialized as-is\n delete mergedQuery.bbox;\n\n // cook it into a json string\n mergedQuery.geometry = JSON.stringify({\n xmin: bboxArr[0],\n ymin: bboxArr[2],\n xmax: bboxArr[1],\n ymax: bboxArr[3]\n });\n // set spatial ref as geographic\n mergedQuery.inSR = '4326';\n }\n\n if (!mergedQuery.groupByFieldsForStatistics && !!dataset.mappings.group) {\n mergedQuery.groupByFieldsForStatistics = dataset.mappings.group.field;\n }\n if (!mergedQuery.outStatistics && !!dataset.mappings.count) {\n // TODO Why are we explicitlystating _SUM as a stats type?\n mergedQuery.orderByFields = `${dataset.mappings.count.field}_SUM`;\n mergedQuery.outStatistics = JSON.stringify([{\n statisticType: 'sum',\n onStatisticField: dataset.mappings.count.field,\n outStatisticFieldName: `${dataset.mappings.count.field}_SUM`\n }]);\n }\n\n // iterate the mappings keys to check for sort\n // -----------------------------------------------------------------\n // This approach would seem 'clean' but if there are multiple fields\n // to sort by, the order would be determined by how javascript decides to\n // iterate the mappings property hash.\n // Thus, using mappings.sort gives the developer explicit control\n // -----------------------------------------------------------------\n // var sort = [];\n // for (var property in dataset.mappings) {\n // if (dataset.mappings.hasOwnProperty(property)) {\n // if(dataset.mappings[property].sort){\n // //ok - build up the sort\n // sort.push(dataset.mappings[property].field + ' ' + dataset.mappings[property].sort);\n // }\n // }\n // }\n // if(sort.length > 0){\n // mergedQuery.orderByFields = sort.join(',');\n // }\n // -----------------------------------------------------------------\n // check for a sort passed directly in\n\n if (dataset.mappings.sort) {\n mergedQuery.orderByFields = dataset.mappings.sort;\n }\n\n let url = `${dataset.url}/query?${serializeQueryParams(mergedQuery)}`;\n\n if (dataset.token) {\n url = `${url}&token=${dataset.token}`;\n }\n\n return url;\n}\n\nconst requestUtils = {\n getJson,\n createFeatureServiceRequest\n};\n\nexport default requestUtils;\n","import { version } from '../package.json';\nimport utils from './utils/utils';\nimport requestUtils from './utils/request';\nimport specUtils from './utils/spec';\n// import specTemplates from './charts/specs';\nimport * as d3 from 'd3';\nimport * as vg from 'vega';\n\n// get cedar root URL for loading chart specs\nconst baseUrl = (function () {\n var cdnProtocol = 'http:';\n var cdnUrl = '//esri.github.io/cedar/js';\n var src;\n if (window && window.document) {\n src = (window.document.currentScript && window.document.currentScript.src);\n if (src) {\n // real browser, get base url from current script\n return src.substr(0, src.lastIndexOf('/'));\n } else {\n // ie, set base url to CDN\n // NOTE: could fallback to CDN only if can't find any scripts named cedar\n return (window.document.location ? window.document.location.protocol : cdnProtocol) + cdnUrl;\n }\n } else {\n // node, set base url to CDN\n return cdnProtocol + cdnUrl;\n }\n})();\n\nexport default class Cedar {\n /**\n * Creates a new Chart object.\n *\n * @example\n * var chart = new Cedar({\n * \"type\": \"bar\"\n * \"dataset\":\n * \"url\":\"http://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Education_WebMercator/MapServer/5\",\n * \"query\": {\n * \"groupByFieldsForStatistics\": \"FACUSE\",\n * \"outStatistics\": [{\n * \"statisticType\": \"sum\",\n * \"onStatisticField\": \"TOTAL_STUD\",\n * \"outStatisticFieldName\": \"TOTAL_STUD_SUM\"\n * }]\n * },\n * \"mappings\":{\n * \"sort\": \"TOTAL_STUD_SUM DESC\",\n * \"x\": {\"field\":\"FACUSE\",\"label\":\"Facility Use\"},\n * \"y\": {\"field\":\"TOTAL_STUD_SUM\",\"label\":\"Total Students\"}\n * }\n * }\n * });\n *\n * @param {Object} options\n * @param {String} options.type - Chart type as a chartType (\"bar\") or a URL to a Cedar specification\n * @param {Object} options.dataset - Dataset definition including Source and Style mappings\n * @param {String} options.dataset.url - GeoService Layer URL\n *\n * \"url\":\"http://.../rest/services/DATA/Education/MapServer/5\"\n * @param {Object} options.dataset.query - GeoServices Layer query parameters (where, bbox, outStatistics) [optional]\n *\n * \"query\": {\n * \"groupByFieldsForStatistics\": \"FACUSE\",\n * \"outStatistics\": [{\n * \"statisticType\": \"sum\",\n * \"onStatisticField\": \"TOTAL_STUD\",\n * \"outStatisticFieldName\": \"TOTAL_STUD_SUM\" }] }\n * @param {Object} options.dataset.data - Inline feature collection, alternative to data from a URL\n *\n * \"data\": {\"features\":[{\"attributes\":{\"ZIP_CODE\":20005,\"TOTAL_STUD_SUM\":327}}]}\n * @param {Object} options.dataset.mappings - Relates data items to the chart style definition\n * @param {Object} options.override - Changes to the \"options.type\" chart specification\n * @param {Object} options.tooltip - Optional on-hover tooltip. Element has class=\"cedar-tooltip\" for styling.\n * @param {String} options.tooltip.id - Optional HTML element to use for tooltip. (default: unique id created)\n * @param {String} options.tooltip.title - Templated tooltip heading. Uses \"{Variable} template format\"\n * @param {String} options.tooltip.content - Templated tooltip body text. Uses \"{Variable} template format\"\n * @return {Object} new Cedar chart object\n */\n constructor (options) {\n this.version = version;\n // Pull templates in\n // this.chartTypes = specTemplates;\n\n let opts = options || {};\n\n let spec;\n\n this.baseUrl = baseUrl;\n this.chartTypes = ['bar', 'bar-horizontal', 'bubble', 'grouped', 'pie', 'scatter', 'sparkline', 'time', 'time-trendline'];\n\n // Cedar configs such as size..\n this.width = undefined;\n this.height = undefined;\n this.autolabels = true;\n this.maxLabelLength = undefined;\n\n // Array to hold event handlers\n this._events = [];\n\n // initialize internal definition\n this._definition = specUtils.defaultDefinition();\n\n // initialize vega view aka chart\n this._view = undefined;\n\n // the vega tooltip\n this._tooltip = undefined;\n\n // transform function\n this._transform = undefined;\n\n // Queue to hold methods called while xhrs are in progress\n this._methodQueue = [];\n\n // Set a base timeout\n this._timeout = undefined;\n\n // override the base timeout\n if (opts.timeout) {\n this._timeout = opts.timeout;\n }\n\n // override the base url\n if (opts.baseUrl) {\n this.baseUrl = opts.baseUrl;\n }\n\n /**\n * Flag used to determine if the library is waiting for an xhr to return.\n * @access private\n */\n this._pendingXhr = false;\n\n /**\n * Definition\n */\n\n if (opts.definition) {\n if (typeof opts.definition === 'object') {\n // hold onto the definition\n this._definition = opts.definition;\n } else if (typeof opts.definition === 'string') {\n // assume it's a url (relative or absolute) and fetch the def object\n this._pendingXhr = true;\n requestUtils.getJson(opts.definition, (err, data) => {\n if (err) {\n throw new Error('Error fetching definition object', err);\n }\n this._pendingXhr = false;\n this._definition = data;\n this._purgeMethodQueue();\n }, this._timeout);\n } else {\n throw new Error('parameter definition must be an object or string (url)');\n }\n }\n\n // if there are overrides\n if (opts.override) {\n this._definition.override = opts.override;\n }\n\n /**\n * Specs\n */\n\n // first, check for pre-defined chart type passed in as 'type'\n this._chartType = opts.type;\n spec = this._getSpecificationUrl(opts.type);\n\n // If url or object passed use that...\n if (opts.specification) {\n spec = opts.specification;\n }\n\n if (spec) {\n // is it an object or string, assumed to be url\n if (typeof spec === 'object') {\n // hold onto the template\n this._definition.specification = spec;\n } else if (typeof spec === 'string') {\n // assume it's a url (rel or abs) and fetch the template object\n this._pendingXhr = true;\n this._pendingXhr = true;\n requestUtils.getJson(spec, (err, data) => {\n if (err) {\n throw new Error('Error fetching template object', err);\n }\n this._pendingXhr = false;\n this._definition.specification = data;\n this._purgeMethodQueue();\n }, this._timeout);\n } else {\n throw new Error('parameter specification must be an object or string (url)');\n }\n }\n\n // Allow a dataset to be passed in....\n if (opts.dataset && typeof opts.dataset === 'object') {\n opts.dataset.query = utils.mixin({}, specUtils.defaultQuery(), opts.dataset.query);\n // Assign it\n this._definition.dataset = opts.dataset;\n }\n\n // Allow datasets to be passed in\n if (opts.datasets && Array.isArray(opts.datasets)) {\n this._definition.datasets = opts.datasets;\n }\n\n // Allow series to be passed in\n if (opts.series && Array.isArray(opts.series)) {\n this._definition.series = opts.series;\n }\n\n /**\n * Tooltip\n */\n // allow a tooltip to be passed in...\n if (opts.tooltip && typeof opts.tooltip === 'object') {\n this.tooltip = opts.tooltip;\n } else {\n // Build a default tooltip based on first two imputs....\n const inputs = [];\n for (let input in this._definition.dataset.mappings) {\n if (this._definition.dataset.mappings.hasOwnProperty(input)) {\n const field = this._definition.dataset.mappings[input].field;\n if (field !== undefined && field !== null) {\n inputs.push(field);\n }\n }\n }\n if (inputs.length >= 2) {\n this.tooltip = {\n 'title': `{${inputs[0]}}`,\n 'content': `{${inputs[1]}}`\n };\n }\n }\n\n /**\n * tranform\n */\n // Allow a transform func to pass in\n if (opts.transform && typeof opts.transform === 'function') {\n this._transform = opts.transform;\n }\n }\n\n /**\n * Properties\n */\n // Dataset - old api\n get dataset () {\n return this._definition.dataset;\n }\n set dataset (val) {\n this._definition.dataset = val;\n }\n\n // Datasets - new api\n get datasets () {\n return this._definition.datasets;\n }\n set datasets (val) {\n this._definition.datasets = val;\n }\n\n // Series - new api\n get series () {\n return this._definition.series;\n }\n set series (val) {\n this._definition.series = val;\n }\n\n // Specification\n get specification () {\n return this._definition.specification;\n }\n set specification (val) {\n this._definition.specification = val;\n }\n\n // override\n get override () {\n return this._definition.override;\n }\n set override (val) {\n this._definition.override = val;\n // return this.update(); // TODO is this the best way?\n }\n\n // Tooltip\n get tooltip () {\n return this._definition.tooltip;\n }\n set tooltip (val) {\n this._definition.tooltip = val;\n if (this._definition.tooltip.id === undefined || this._definition.tooltip.id === null) {\n this._definition.tooltip.id = `cedar-${Date.now()}`;\n }\n }\n\n // transform\n get transform () {\n return this._transform;\n }\n set transform (val) {\n this._transform = val;\n }\n\n _getSpecificationUrl (spec) {\n if (this.chartTypes.indexOf(spec) !== -1) {\n spec = `${this.baseUrl}/charts/${this.chartTypes[this.chartTypes.indexOf(spec)]}.json`;\n }\n return spec;\n }\n\n /**\n * Inspect the current state of the Object\n * and determine if we have sufficient information\n * to render the chart\n * @return {object} Hash of the draw state + any missing requirements\n */\n canDraw () {\n // dataset?\n // dataset.url || dataset.data?\n // dataset.mappings?\n // specification?\n // specification.template?\n // specification.inputs?\n // specification.inputs ~ dataset.mappings?\n\n return {drawable: true, errs: []};\n }\n\n /**\n * Draw the chart into the DOM element\n *\n * @example\n *\n * var chart = new Cedar({\n * \"type\": \"scatter\",\n * \"dataset\":{\n * \"url\":\"http://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Education_WebMercator/MapServer/5\",\n * \"query\":{},\n * \"mappings\":{\n * \"x\": {\"field\":\"POPULATION_ENROLLED_2008\",\"label\":\"Enrolment 2008\"},\n * \"y\": {\"field\":\"SQUARE_FOOTAGE\",\"label\":\"Square Footage\"},\n * \"color\":{\"field\":\"FACUSE\",\"label\":\"Facility Type\"}\n * }\n * }\n * });\n *\n * chart.show({\n * elementId: \"#chart\"\n * });\n *\n * @param {object} options\n * @param {String} options.elementId [required] Id of the Dom element into which the chart will be rendered\n * @param {String} options.renderer \"canvas\" or \"svg\" (default: `svg`)\n * @param {Boolean} options.autolabels place axis labels outside any tick labels (default: false)\n * @param {String} options.token Token to be used if the data or spec are on a secured server\n */\n show (options, clb) {\n if (this._pendingXhr) {\n // TODO addToMethodQueue\n this._addToMethodQueue('show', [options, clb]);\n } else {\n let err;\n // ensure we got an elementId\n if (!options.elementId) {\n err = 'Cedar.show requires options.elementId';\n }\n // Check if element exists in the page\n if (d3.select(options.elementId)[0][0] === null) {\n err = `Element ${options.elementId} is not present in the DOM`;\n }\n\n // hold onto the id\n this._elementId = options.elementId;\n this._renderer = options.renderer || 'svg'; // default to svg\n this.width = options.width || this.height;\n this.height = options.height || this.height;\n if (options.autolabels !== undefined && options.autolabels !== null) {\n this.autolabels = options.autolabels;\n }\n\n if (options.maxLabelLength) {\n // check if truncate label length has been passed in\n this.maxLabelLength = options.maxLabelLength;\n }\n\n // hold onto the token\n if (options.token) {\n this._token = options.token;\n }\n\n if (err) {\n throw new Error(err);\n }\n\n var chk = this.canDraw();\n\n if (chk.drawable) {\n this.update(clb);\n } else {\n // report the issues\n const errs = chk.issues.join(',');\n throw new Error(`Chart can not be drawn because: ${errs}`);\n }\n }\n }\n\n /**\n * Draw the chart based on any changes to data or specifications\n * Should be called after a user modifies\n * the dataset, query, mappings, chart specification or element size\n *\n * @example\n * dataset = {\"url\": \"...\", \"mappings\": {\"x\": {\"field\": \"STATE\"}, \"y\": {\"field\": \"POPULATION\"}}};\n * chart = new Cedar({ \"type\": \"bar\", \"dataset\": dataset });\n * chart.show({elementId: \"#chart\"});\n * chart.dataset.query.where = \"POPULATION>30000\";\n * chart.update();\n */\n update (clb) {\n if (this._view) {\n this.emit('update-start');\n }\n\n if (this._pendingXhr) {\n this._addToMethodQueue('update');\n } else {\n if (this._view) {\n // remove handlers\n // TODO Remove existing handlers\n this._remove(this._view);\n }\n\n try {\n if (this._definition.datasets && this._definition.series) {\n this._definition.dataset = specUtils.convertDatasetsToDataset(this._definition.datasets, this._definition.series, this._chartType, this._definition.dataset);\n if (!this._definition.tooltip) {\n this.tooltip = {\n 'title': `{${this._definition.series[0].category.field}}`,\n 'content': `{${this._definition.series[0].value.field}}`\n };\n }\n }\n\n // Creates the HTML Div and styling if not already created\n if (this._definition.tooltip) {\n this._createTooltip(this._definition.tooltip.id);\n }\n // Ensure we have required inputs or defaults\n let compiledMappings = specUtils.applyDefaultsToMappings(this._definition.dataset.mappings, this._definition.specification.inputs);\n\n let queryFromSpec = utils.mixin({}, this._definition.specification.query, this._definition.dataset.query);\n queryFromSpec = JSON.parse(utils.supplant(JSON.stringify(queryFromSpec), compiledMappings));\n\n // allow binding to query properties\n compiledMappings.query = queryFromSpec;\n\n // compile the template + mappings --> vega spec\n let spec = JSON.parse(utils.supplant(JSON.stringify(this._definition.specification.template), compiledMappings));\n\n // merge in user specified style overrides\n spec = utils.mergeRecursive(spec, this._definition.override);\n\n // if the spec has a url in the data node, delete it TODO: need to readress this.\n if (spec.data[0].url) {\n delete spec.data[0].url;\n }\n\n if (this._definition.dataset.data) {\n // create the data node using the passed in data\n spec.data[0].values = this._definition.dataset.data; // TODO: only works on first spec, need to address for multiple datasets.\n\n // Send to vega\n this._renderSpec(spec, clb);\n } else {\n // We need to fetch the data so....\n const url = requestUtils.createFeatureServiceRequest(this._definition.dataset, queryFromSpec);\n\n // create a callback closure to carry the spec\n const cb = (err, data) => {\n // Normalize error response\n if (!err && !!data.error) {\n err = new Error(data.error.message || data.error.details[0]);\n }\n // if no errors then continue...\n if (!err) {\n if (this._transform && typeof this._transform === 'function') {\n data = this._transform(data, this._definition.dataset);\n }\n // TODO add error handlers for xhr and AGS errors.\n spec.data[0].values = data;\n // send to vega\n this._renderSpec(spec, clb);\n } else {\n // optional callback\n if (!!clb && typeof clb === 'function') {\n clb(err, data);\n }\n }\n };\n\n // fetch the data from the service\n requestUtils.getJson(url, cb, this._timeout);\n }\n } catch (ex) {\n throw (ex);\n }\n }\n }\n\n /**\n * RENDER CHART FUNCTIONS\n *\n *\n * Render a compiled Vega specification using vega runtime\n */\n\n _renderSpec (spec, clb) {\n if (this.autolabels === true) {\n spec = this._placeLabels(spec);\n spec = this._placeaAxisTicks(spec);\n }\n // Use vega to parse the spec\n // It will handle the spec as an object or url\n vg.parse.spec(spec, (err, chartCtor) => {\n // create the view\n this._view = chartCtor({\n el: this._elementId,\n renderer: this._renderer\n });\n\n const width = this.width || parseInt(d3.select(this._elementId).style('width'), 10) || 500;\n const height = this.height || parseInt(d3.select(this._elementId).style('height'), 10) || 500;\n\n // render into the element\n this._view.width(width).height(height).update();\n\n // attach event proxies\n this._attach(this._view);\n\n if (this._view) {\n this.emit('update-end');\n }\n\n // expose errors\n if (!!clb && typeof clb === 'function') {\n clb(err, spec);\n }\n });\n }\n\n /**\n * AXIS TICK FUNCTIONS START HERE\n *\n *\n * Automatically determines axis title placement\n *\n * Calculates the maximum length of a tick label and adds padding\n */\n\n _placeLabels (spec) {\n try {\n const fields = {};\n const lengths = {};\n const inputs = [];\n // Get all inputs that may be axes\n for (let input in this._definition.dataset.mappings) {\n // check also if property is not inherited from prototype\n if (this._definition.dataset.mappings.hasOwnProperty(input)) {\n const field = this._definition.dataset.mappings[input].field;\n if (field) {\n inputs.push(input);\n fields[input] = field;\n lengths[input] = 0;\n }\n }\n }\n let length = 0;\n\n // find the max length value for each axis\n spec.data[0].values.features.forEach((feature) => {\n inputs.forEach((axis) => {\n length = (feature.attributes[fields[axis]] || '').toString().length;\n if (this.maxLabelLength) {\n // Need to make sure that the gap between title and labels isn't ridiculous\n length = length < (this.maxLabelLength + 1) ? length : this.maxLabelLength;\n }\n if (length > lengths[axis]) {\n lengths[axis] = length;\n }\n });\n });\n\n // Change each axis title offset based on longest value\n inputs.forEach((axis, index) => {\n let angle = 0;\n if (!!spec.axes && !!spec.axes[index]) {\n if (spec.axes[index].properties.labels.angle) {\n angle = spec.axes[index].properties.labels.angle.value;\n }\n if (spec.axes[index].type === 'y') {\n angle = 100 - angle;\n }\n if (this.maxLabelLength) {\n // Set max length of axes titles\n spec.axes[index].properties.labels.text = {'template': `{{ datum.data | truncate:\"${this.maxLabelLength}\"}}`};\n }\n // set title offset\n spec.axes[index].titleOffset = Math.abs(lengths[axis] * angle / 100 * 8) + 35;\n }\n });\n return spec;\n } catch (ex) {\n throw (ex);\n }\n }\n\n /**\n * Automatically determines number of axis tick marks\n *\n * Calculates the maximum length of a tick label and adds padding\n * TODO: remove expectation that there are both x,y axes\n */\n\n _placeaAxisTicks (spec) {\n if (spec.axes) {\n try {\n const width = this.width || parseInt(d3.select(this._elementId).style('width'), 10) || 500;\n const height = this.height || parseInt(d3.select(this._elementId).style('height'), 10) || 500;\n\n spec.axes[0].ticks = width / 100;\n if (spec.axes[1]) {\n spec.axes[1].ticks = height / 30;\n }\n } catch (ex) {\n throw (ex);\n }\n }\n return spec;\n }\n\n /**\n * TOOLTIP LOGIC HERE\n *\n * Instantiates the tooltip element and styling\n * @access private\n */\n _createTooltip (elem) {\n let tooltipDiv = document.getElementById(elem);\n\n // Check if tooltip has been created or not...\n if (tooltipDiv) {\n return tooltipDiv;\n }\n\n // TODO: remove inline CSS\n let style = document.createElement('style');\n style.type = 'text/css';\n style.innerHTML = '.cedar-tooltip {background-color: white; padding: 3px 10px; color: #333; margin: -30px 0 0 20px; position: absolute; z-index: 2000; font-size: 10px; border: 1px solid #BBB;} .cedar-tooltip .title {font-size: 13pt; font-weight: bold; } .cedar-tooltip .content {font-size: 10pt; } ';\n document.getElementsByTagName('head')[0].appendChild(style);\n\n tooltipDiv = document.createElement('div');\n tooltipDiv.className = 'cedar-tooltip';\n tooltipDiv.id = elem;\n tooltipDiv.cssText = 'display: none';\n // We need tooltip at the top of the page\n document.body.insertBefore(tooltipDiv, document.body.firstChild);\n\n this.on('mouseout', (event, data) => {\n this._updateTooltip(event, null);\n });\n this.on('mousemove', (event, data) => {\n this._updateTooltip(event, data);\n });\n return tooltipDiv;\n }\n\n /**\n * Places the tooltipe and fills in content\n *\n * @access private\n */\n _updateTooltip (event, data) {\n let cedartip = document.getElementById(this._definition.tooltip.id);\n if (!data) {\n cedartip.style.display = 'none';\n return;\n }\n cedartip.style.top = `${event.pageY}px`;\n cedartip.style.left = `${event.pageX}px`;\n cedartip.style.display = 'block';\n\n let content = `${this._definition.tooltip.title}${this._definition.tooltip.content}
`;\n\n cedartip.innerHTML = content.replace(/\\{(\\w+)\\}/g, (match, $1) => {\n return data[$1];\n });\n }\n\n /**\n * EVENT LOGIC HERE\n *\n *\n * Add a handler for the named event.\n * Events:\n * - mouseover\n * - mouseout\n * - click\n * - update-start\n * - update-end\n *\n *\n *\n * Callback from Cedar events\n * - callback Cedar~eventCallback\n * - param {Object} event - event response such as mouse location\n * - param {Object} data - chart data object\n *\n * @example\n * var chart = new Cedar({ ... });\n * chart.on('mouseover', function(event, data) {\n * console.log(\"Mouse Location:\", [event.offsetX, event.offsetY]);\n * console.log(\"Data value:\", data[Object.keys(data)[0]]);\n * });\n *\n * @param {String} eventName name of the event that invokes callback\n * @param {Cedar~eventCallback} callback - The callback that handles the event.\n */\n on (evtName, callback) {\n this._events.push({type: evtName, callback});\n }\n /**\n * Remove a hanlder for the named event\n */\n off (evtName, callback) {\n this._events.forEach((registeredEvent, index, object) => {\n if (registeredEvent.type === evtName && registeredEvent.callback === callback) {\n object.splice(index, 1);\n }\n });\n }\n\n /**\n * Trigger a callback\n * @param {string} eventName - [\"mouseover\",\"mouseout\",\"click\",\"update-start\",\"update-end\"]\n */\n emit (eventName) {\n if (!!this._view._handler._handlers[ eventName ] && !!this._view._handler._handlers[ eventName ][0]) {\n this._view._handler._handlers[ eventName ][0].handler();\n }\n }\n\n /**\n * Attach the generic proxy hanlders to the chart view\n * @access private\n */\n _attach (view) {\n view.on('mouseover', this._handler('mouseover'));\n view.on('mouseout', this._handler('mouseout'));\n view.on('mousemove', this._handler('mousemove'));\n view.on('click', this._handler('click'));\n view.on('update-start', this._handler('update-start'));\n view.on('update-end', this._handler('update-end'));\n }\n\n /**\n * Remove all event handlers from the view\n * @access private\n */\n _remove (view) {\n view.off('mouseover');\n view.off('mouseout');\n view.off('mousemove');\n view.off('click');\n view.off('update-start');\n view.off('update-end');\n }\n\n /**\n * Creates an entry in the method queue, executed\n * once a pending xhr is completed\n * @access private\n */\n _addToMethodQueue (name, args) {\n this._methodQueue.push({ method: name, args: args });\n }\n\n /**\n * empties the method queue by calling the queued methods\n * This helps build a more syncronous api, while still\n * doing async things in the code\n * @access private\n */\n _purgeMethodQueue () {\n if (this._methodQueue.length > 0) {\n this._methodQueue.forEach((action, index) => {\n this[action.method].apply(this, action.args);\n });\n }\n }\n\n /**\n * Generic event handler proxy\n * @access private\n */\n _handler (evtName) {\n // return a handler function w/ the events hash closed over\n const handler = (evt, item) => {\n this._events.forEach((registeredHandler) => {\n if (registeredHandler.type === evtName) {\n // invoke the callback with the data\n if (item) {\n registeredHandler.callback(evt, item.datum.attributes);\n } else {\n registeredHandler.callback(evt, null);\n }\n }\n });\n };\n return handler;\n }\n\n /**\n * SELECT LOGIC STARTS HERE\n *\n * Highlight marker based on attribute value\n *\n * @example\n * chart = new Cedar({...});\n * chart.select({key: 'ZIP_CODE', value: '20002'});\n *\n * @param {object} options - Object(key, value) to match. Calls hover on work\n * @returns {Array} items - array of chart objects that match the criteria\n */\n\n select (options) {\n let view = this._view;\n let items = view.model().scene().items[0].items[0].items;\n\n items.forEach((item) => {\n if (item.datum.attributes[options.key] === options.value) {\n if (item.hasPropertySet('hover')) {\n this._view.update({props: 'hover', items: item});\n }\n }\n });\n\n return items;\n }\n\n /**\n * Removes highlighted chart items\n *\n * If \"options\" are used, only clear specific items, otherwise clears all highlights.\n * @param {Object} options - Object(key, value) to match. Calls hover on mark\n * @returns {Array} items - array of chart objects that match the criteria, or null if all items.\n */\n\n clearSelection (options) {\n let view = this._view;\n\n if (!!options && !!options.key) {\n let items = view.model().scene().items[0].items[0].items;\n items.forEach((item) => {\n if (item.datum.attributes[options.key] === options.value) {\n this._view.update({props: 'update', items: item});\n }\n });\n return items;\n } else {\n // clear all\n this._view.update();\n return null;\n }\n }\n\n static getJson (url, callback, timeout) {\n return requestUtils.getJson(url, callback, timeout);\n }\n\n /**\n * Other now exposed utils!\n */\n static _validateMappings (inputs, mappings) {\n return utils.validateMappings(inputs, mappings);\n }\n static _validateData (data, mappings) {\n return utils.validateData(data, mappings);\n }\n static _createFeatureServiceRequest (dataset, queryFromSpec) {\n return requestUtils.createFeatureServiceRequest(dataset, queryFromSpec);\n }\n static _getMappingFieldName (mappingName, fieldName) {\n return utils.getMappingFieldName(mappingName, fieldName);\n }\n // TODO: remove once we have a better way to unit test\n static _convertDatasetsToDataset (datasets, dataset, chartType) {\n return specUtils.convertDatasetsToDataset(datasets, dataset, chartType);\n }\n}\n"],"names":["const","let","d3.entries","getJson","d3.xhr","xhr","this","d3.select","vg.parse","name"],"mappings":";;;;;;;;;;;;;;;;;;AAMA,AAAO,SAAS,KAAK,EAAE,MAAM,EAAE;;;;EAC7BA,IAAM,IAAI,GAAG,sBAAc,CAAC;EAC5B,KAAKC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;IACpCC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAC,CAAC,EAAE;MAC9B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;KACzB,CAAC,CAAC;GACJ;EACD,OAAO,MAAM,CAAC;CACf;;;;;AAKD,AAAO,SAAS,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE;EAC1C,KAAKD,IAAI,CAAC,IAAI,IAAI,EAAE;IAClB,IAAI,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE;MAC1B,IAAI;;QAEF,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,KAAK,EAAE;UACnE,IAAI,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SAC5C,MAAM;UACL,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;SACnB;OACF,CAAC,OAAO,CAAC,EAAE;;QAEV,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;OACnB;KACF;GACF;EACD,OAAO,IAAI,CAAC;CACb;;;;;;;;AAQD,AAAO,SAAS,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE;EAC1CD,IAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa;IACtC,UAAC,CAAC,EAAE,CAAC,EAAE;MACLA,IAAM,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;;MAEnC,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC;KAC/D;GACF,CAAC;EACF,OAAO,CAAC,CAAC,OAAO,CAAC,eAAe;IAC9B,UAAC,CAAC,EAAE,CAAC,EAAE;MACLC,IAAI,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;MACjC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,KAAK,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;KACjE,CAAC,CAAC;CACN;;;;;;;;;;AAUD,AAAO,SAAS,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE;EAChDA,IAAI,SAAS,GAAG,MAAM,CAAC;EACvBA,IAAI,cAAc,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;EAC1C,KAAKA,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;IAC9C,IAAI,SAAS,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE;MAC/C,SAAS,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;KAC1C,MAAM;MACL,OAAO,IAAI,CAAC;KACb;GACF;EACD,OAAO,SAAS,CAAC;CAClB;;;;;;;;;;;AAWD,AAAO,SAAS,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE;EAClD,OAAO,MAAM,CAAC,MAAM,CAAC,UAAC,KAAK,EAAE;IAC3B,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;MAC3C,OAAO,KAAK,CAAC;KACd;GACF,CAAC,CAAC;CACJ;;;;;;;AAOD,AAAO,SAAS,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE;EAC5CD,IAAM,aAAa,GAAG,EAAE,CAAC;EACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;IACnD,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;GAC7D;EACDA,IAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;EAC7C,KAAKC,IAAI,GAAG,IAAI,QAAQ,EAAE;IACxB,IAAI,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;MAChCA,IAAI,GAAG,GAAG,mBAAmB,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;MACxD,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;QACjC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;OACzB;KACF;GACF;EACD,OAAO,aAAa,CAAC;CACtB;;;;;;;;AAQD,AAAO,SAAS,mBAAmB,EAAE,WAAW,EAAE,SAAS,EAAE;;;EAG3DA,IAAI,IAAI,GAAG,SAAS,CAAC;;;;EAIrB,OAAO,IAAI,CAAC;CACb;;AAEDD,IAAM,KAAK,GAAG;EACZ,OAAA,KAAK;EACL,UAAA,QAAQ;EACR,gBAAA,cAAc;EACd,eAAA,aAAa;EACb,kBAAA,gBAAgB;EAChB,cAAA,YAAY;EACZ,qBAAA,mBAAmB;CACpB,CAAC,AAEF,AAAqB;;ACjJrB;;;;AAIA,AAAO,SAAS,iBAAiB,IAAI;EACnC,OAAO;IACL,OAAO,EAAE;MACP,KAAK,EAAE,YAAY,EAAE;KACtB;IACD,QAAQ,EAAE,EAAE;GACb,CAAC;CACH;;;;;;AAMD,AAAO,SAAS,YAAY,IAAI;EAC9B,OAAO;IACL,KAAK,EAAE,KAAK;IACZ,cAAc,EAAE,KAAK;IACrB,oBAAoB,EAAE,KAAK;IAC3B,aAAa,EAAE,KAAK;IACpB,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,UAAU;IACrB,CAAC,EAAE,MAAM;GACV,CAAC;CACH;;;;;;;;AAQD,AAAO,SAAS,uBAAuB,EAAE,QAAQ,EAAE,MAAM,EAAE;EACzDA,IAAM,IAAI,GAAG,EAAE,CAAC;;EAEhB,KAAKC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;IACtCD,IAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;;;IAGxB,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;MAC3C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;KACvB;;;IAGD,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE;;MAEhE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;KACzC;GACF;EACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;IACnB,MAAM,IAAI,KAAK,CAAC,CAAA,6BAA4B,IAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC,CAAC;GACjE,MAAM;IACL,OAAO,QAAQ,CAAC;GACjB;CACF;;;;;AAKD,AAAO,SAAS,wBAAwB,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE;;EAE9E,IAAI,CAAC,OAAO,EAAE;IACZ,OAAO,GAAG;MACR,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE;KAC3B,CAAC;GACH;;EAEDA,IAAM,QAAQ,GAAG,EAAE,CAAC;;EAEpBA,IAAM,OAAO,GAAG,EAAE,CAAC;;EAEnBA,IAAM,IAAI,GAAG,EAAE,CAAC;;EAEhBA,IAAM,IAAI,GAAG,EAAE,CAAC;;EAEhB,QAAQ,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE;;IAEtB,IAAI,IAAI,CAAC,KAAK,EAAE;MACd,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KAC1B;IACD,IAAI,IAAI,CAAC,GAAG,EAAE;MACZ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KACrB;IACD,IAAI,IAAI,CAAC,IAAI,EAAE;MACb,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KACtB;;;IAGD,IAAI,SAAS,KAAK,SAAS,EAAE;MAC3B,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;QACnB,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;OACrC;MACD,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE;QACf,QAAQ,CAAC,CAAC,GAAG;UACX,KAAK,EAAE,EAAE;UACT,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;SAC7B,CAAC;OACH;MACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;QACrB,MAAM,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE;UACpB,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA,aAAY,IAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAA,CAAE,CAAC,CAAC;SACzD,CAAC,CAAC;OACJ,MAAM;QACL,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA,aAAY,IAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA,CAAE,CAAC,CAAC;OAC9D;;;KAGF,MAAM,IAAI,SAAS,KAAK,QAAQ,EAAE;MACjC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MAChC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;MAC7B,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;;;KAGhC,MAAM,IAAI,SAAS,KAAK,SAAS,EAAE;MAClC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MAChC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;MAC7B,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;;;KAGlC,MAAM,IAAI,SAAS,KAAK,KAAK,EAAE;MAC9B,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MACpC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;MAC7B,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;;;KAGpC,MAAM,IAAI,SAAS,KAAK,gBAAgB,EAAE;MACzC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MAChC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;;;KAG9B,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE;MAC/B,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MACnC,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;;;KAGlC,MAAM,IAAI,SAAS,KAAK,gBAAgB,EAAE;MACzC,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MACnC,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;MACjC,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;;;KAG1C,MAAM;MACL,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;MAChC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;KAC9B;GACF,CAAC,CAAC;;EAEHA,IAAM,YAAY,GAAG;IACnB,KAAK,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC;IAC7C,UAAA,QAAQ;GACT,CAAC;EACF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;IACnB,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;GAC7B;;EAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;IACnB,YAAY,CAAC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;GACtC;;EAED,OAAO,YAAY,CAAC;CACrB;;;;;AAKD,SAAS,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE;EAC9C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;IACtB,OAAO,CAAC,IAAI,CAAC,6EAA6E,EAAE,OAAO,CAAC,CAAC;IACrG,OAAO,YAAY,CAAC;GACrB;EACD,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;CAC/C;;;;;AAKD,SAAS,WAAW,EAAE,IAAI,EAAE;EAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;IACnB,OAAO,CAAC,IAAI,CAAC,qEAAqE,EAAE,IAAI,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;GAChB;EACD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;CAChB;;AAEDA,IAAM,SAAS,GAAG;EAChB,mBAAA,iBAAiB;EACjB,cAAA,YAAY;EACZ,yBAAA,uBAAuB;EACvB,0BAAA,wBAAwB;CACzB,CAAC,AAEF,AAAyB;;;;;;;;;ACxLzB,SAAS,oBAAoB,EAAE,MAAM,EAAE;EACrCA,IAAM,GAAG,GAAG,EAAE,CAAC;EACf,KAAKA,IAAM,KAAK,IAAI,MAAM,EAAE;IAC1B,IAAI,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE;MAChCC,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;MACxB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;OAC3B;MACD,GAAG,CAAC,IAAI,CAAC,CAAA,CAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA,MAAE,IAAE,kBAAkB,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC,CAAC;KACrE;GACF;EACDD,IAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;EAClC,OAAO,WAAW,CAAC;CACpB;;;;;;;;;AASD,AAAO,SAASG,SAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE;EAC/CH,IAAM,EAAE,GAAG,UAAC,GAAG,EAAE,IAAI,EAAE;;IAErB,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,EAAE;MAC9B,QAAQ,CAAC,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC,CAAC;KACpF,MAAM,IAAI,GAAG,EAAE;;MAEd,QAAQ,CAAC,IAAI,KAAK,CAAC,CAAA,gBAAe,GAAE,GAAG,0BAAsB,IAAE,GAAG,CAAC,OAAO,CAAA,CAAE,CAAC,CAAC,CAAC;KAChF,MAAM;MACL,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;KAC/C;GACF,CAAC;EACF,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE;IACrBA,IAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3BI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;OACX,EAAE,CAAC,YAAY,EAAE,UAACC,MAAG,EAAE,EAAKA,MAAG,CAAC,OAAO,GAAG,OAAO,CAAC,CAACA,MAAG,CAAC,SAAS,GAAGA,MAAG,CAAC,MAAM,CAAC,EAAE,CAAC;OACjF,MAAM,CAAC,cAAc,EAAE,mCAAmC,CAAC;OAC3D,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;GACrB,MAAM;IACLD,MAAM,CAAC,GAAG,CAAC;OACR,EAAE,CAAC,YAAY,EAAE,UAACC,MAAG,EAAE,EAAKA,MAAG,CAAC,OAAO,GAAG,OAAO,CAAC,CAACA,MAAG,CAAC,SAAS,GAAGA,MAAG,CAAC,MAAM,CAAC,EAAE,CAAC;OACjF,GAAG,CAAC,EAAE,CAAC,CAAC;GACZ;CACF;;;;;;;;AAQD,AAAO,SAAS,2BAA2B,EAAE,OAAO,EAAE,aAAa,EAAE;EACnEL,IAAM,WAAW,GAAG,KAAK,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;;;EAG7D,IAAI,WAAW,CAAC,IAAI,EAAE;;IAEpB,IAAI,WAAW,CAAC,QAAQ,EAAE;MACxB,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;KACpF;;IAEDA,IAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;;;IAG5C,OAAO,WAAW,CAAC,IAAI,CAAC;;;IAGxB,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;MACpC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;MAChB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;MAChB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;MAChB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;KACjB,CAAC,CAAC;;IAEH,WAAW,CAAC,IAAI,GAAG,MAAM,CAAC;GAC3B;;EAED,IAAI,CAAC,WAAW,CAAC,0BAA0B,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE;IACvE,WAAW,CAAC,0BAA0B,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;GACvE;EACD,IAAI,CAAC,WAAW,CAAC,aAAa,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE;;IAE1D,WAAW,CAAC,aAAa,GAAG,CAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAA,SAAK,CAAE;IAClE,WAAW,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;MAC1C,aAAa,EAAE,KAAK;MACpB,gBAAgB,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK;MAC9C,qBAAqB,EAAE,CAAA,CAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAA,SAAK,CAAC;KAC7D,CAAC,CAAC,CAAC;GACL;;;;;;;;;;;;;;;;;;;;;;;;EAwBD,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;IACzB,WAAW,CAAC,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;GACnD;;EAEDC,IAAI,GAAG,GAAG,CAAG,OAAO,CAAC,GAAG,CAAA,YAAQ,IAAE,oBAAoB,CAAC,WAAW,CAAC,CAAA,CAAG;;EAEtE,IAAI,OAAO,CAAC,KAAK,EAAE;IACjB,GAAG,GAAG,GAAM,YAAQ,IAAE,OAAO,CAAC,KAAK,CAAA,CAAG;GACvC;;EAED,OAAO,GAAG,CAAC;CACZ;;AAEDD,IAAM,YAAY,GAAG;EACnB,SAAAG,SAAO;EACP,6BAAA,2BAA2B;CAC5B,CAAC,AAEF,AAA4B;;;AC1I5B,AACA;AAGAH,IAAM,OAAO,GAAG,CAAC,YAAY;EAC3B,IAAI,WAAW,GAAG,OAAO,CAAC;EAC1B,IAAI,MAAM,GAAG,2BAA2B,CAAC;EACzC,IAAI,GAAG,CAAC;EACR,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE;IAC7B,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3E,IAAI,GAAG,EAAE;;MAEP,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;KAC5C,MAAM;;;MAGL,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,MAAM,CAAC;KAC9F;GACF,MAAM;;IAEL,OAAO,WAAW,GAAG,MAAM,CAAC;GAC7B;CACF,CAAC,EAAE,CAAC;;AAEL,IAAqB,KAAK,GAAC,cAkDd,EAAE,OAAO,EAAE;;;EACtB,IAAM,CAAC,OAAO,GAAG,OAAO,CAAC;;;;EAIzB,IAAM,IAAI,GAAG,OAAO,IAAI,EAAE,CAAC;;EAE3B,IAAM,IAAI,CAAC;;EAEX,IAAM,CAAC,OAAO,GAAG,OAAO,CAAC;EACzB,IAAM,CAAC,UAAU,GAAG,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;;;EAG5H,IAAM,CAAC,KAAK,GAAG,SAAS,CAAC;EACzB,IAAM,CAAC,MAAM,GAAG,SAAS,CAAC;EAC1B,IAAM,CAAC,UAAU,GAAG,IAAI,CAAC;EACzB,IAAM,CAAC,cAAc,GAAG,SAAS,CAAC;;;EAGlC,IAAM,CAAC,OAAO,GAAG,EAAE,CAAC;;;EAGpB,IAAM,CAAC,WAAW,GAAG,SAAS,CAAC,iBAAiB,EAAE,CAAC;;;EAGnD,IAAM,CAAC,KAAK,GAAG,SAAS,CAAC;;;EAGzB,IAAM,CAAC,QAAQ,GAAG,SAAS,CAAC;;;EAG5B,IAAM,CAAC,UAAU,GAAG,SAAS,CAAC;;;EAG9B,IAAM,CAAC,YAAY,GAAG,EAAE,CAAC;;;EAGzB,IAAM,CAAC,QAAQ,GAAG,SAAS,CAAC;;;EAG5B,IAAM,IAAI,CAAC,OAAO,EAAE;IAClB,IAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;GAC9B;;;EAGH,IAAM,IAAI,CAAC,OAAO,EAAE;IAClB,IAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;GAC7B;;;;;;EAMH,IAAM,CAAC,WAAW,GAAG,KAAK,CAAC;;;;;;EAM3B,IAAM,IAAI,CAAC,UAAU,EAAE;IACrB,IAAM,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE;;MAEzC,IAAM,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;KACpC,MAAM,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE;;MAEhD,IAAM,CAAC,WAAW,GAAG,IAAI,CAAC;MAC1B,YAAc,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,UAAC,GAAG,EAAE,IAAI,EAAE;QAClD,IAAM,GAAG,EAAE;UACT,MAAQ,IAAI,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;SAC1D;QACH,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;QAC3B,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,MAAM,CAAC,iBAAiB,EAAE,CAAC;OAC1B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;KACnB,MAAM;MACP,MAAQ,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;KAC3E;GACF;;;EAGH,IAAM,IAAI,CAAC,QAAQ,EAAE;IACnB,IAAM,CAAC,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;GAC3C;;;;;;;EAOH,IAAM,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC;EAC9B,IAAM,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;;EAG9C,IAAM,IAAI,CAAC,aAAa,EAAE;IACxB,IAAM,GAAG,IAAI,CAAC,aAAa,CAAC;GAC3B;;EAEH,IAAM,IAAI,EAAE;;IAEV,IAAM,OAAO,IAAI,KAAK,QAAQ,EAAE;;MAE9B,IAAM,CAAC,WAAW,CAAC,aAAa,GAAG,IAAI,CAAC;KACvC,MAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;;MAErC,IAAM,CAAC,WAAW,GAAG,IAAI,CAAC;MAC1B,IAAM,CAAC,WAAW,GAAG,IAAI,CAAC;MAC1B,YAAc,CAAC,OAAO,CAAC,IAAI,EAAE,UAAC,GAAG,EAAE,IAAI,EAAE;QACvC,IAAM,GAAG,EAAE;UACT,MAAQ,IAAI,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;SACxD;QACH,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;QAC3B,MAAM,CAAC,WAAW,CAAC,aAAa,GAAG,IAAI,CAAC;QACxC,MAAM,CAAC,iBAAiB,EAAE,CAAC;OAC1B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;KACnB,MAAM;MACP,MAAQ,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;KAC9E;GACF;;;EAGH,IAAM,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE;IACtD,IAAM,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;;IAErF,IAAM,CAAC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;GACzC;;;EAGH,IAAM,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;IACnD,IAAM,CAAC,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;GAC3C;;;EAGH,IAAM,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;IAC/C,IAAM,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;GACvC;;;;;;EAMH,IAAM,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE;IACtD,IAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;GAC7B,MAAM;;IAEP,IAAQ,MAAM,GAAG,EAAE,CAAC;IACpB,KAAOC,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE;MACrD,IAAMK,MAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE;QAC7D,IAAQ,KAAK,GAAGA,MAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;QAC/D,IAAM,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE;UAC3C,MAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACpB;OACF;KACF;IACH,IAAM,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;MACxB,IAAM,CAAC,OAAO,GAAG;QACf,OAAS,EAAE,CAAA,GAAE,IAAE,MAAM,CAAC,CAAC,CAAC,CAAA,MAAE,CAAC;QAC3B,SAAW,EAAE,CAAA,GAAE,IAAE,MAAM,CAAC,CAAC,CAAC,CAAA,MAAE,CAAC;OAC5B,CAAC;KACH;GACF;;;;;;EAMH,IAAM,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,UAAU,EAAE;IAC5D,IAAM,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;GAClC;CACF;;0HAAA;;;;;;AAMH,mBAAE,OAAW,mBAAI;EACf,OAAS,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;CACjC,CAAA;AACH,mBAAE,OAAW,iBAAE,GAAG,EAAE;EAClB,IAAM,CAAC,WAAW,CAAC,OAAO,GAAG,GAAG,CAAC;CAChC,CAAA;;;AAGH,mBAAE,QAAY,mBAAI;EAChB,OAAS,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;CAClC,CAAA;AACH,mBAAE,QAAY,iBAAE,GAAG,EAAE;EACnB,IAAM,CAAC,WAAW,CAAC,QAAQ,GAAG,GAAG,CAAC;CACjC,CAAA;;;AAGH,mBAAE,MAAU,mBAAI;EACd,OAAS,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;CAChC,CAAA;AACH,mBAAE,MAAU,iBAAE,GAAG,EAAE;EACjB,IAAM,CAAC,WAAW,CAAC,MAAM,GAAG,GAAG,CAAC;CAC/B,CAAA;;;AAGH,mBAAE,aAAiB,mBAAI;EACrB,OAAS,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC;CACvC,CAAA;AACH,mBAAE,aAAiB,iBAAE,GAAG,EAAE;EACxB,IAAM,CAAC,WAAW,CAAC,aAAa,GAAG,GAAG,CAAC;CACtC,CAAA;;;AAGH,mBAAE,QAAY,mBAAI;EAChB,OAAS,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;CAClC,CAAA;AACH,mBAAE,QAAY,iBAAE,GAAG,EAAE;EACnB,IAAM,CAAC,WAAW,CAAC,QAAQ,GAAG,GAAG,CAAC;;CAEjC,CAAA;;;AAGH,mBAAE,OAAW,mBAAI;EACf,OAAS,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;CACjC,CAAA;AACH,mBAAE,OAAW,iBAAE,GAAG,EAAE;EAClB,IAAM,CAAC,WAAW,CAAC,OAAO,GAAG,GAAG,CAAC;EACjC,IAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,KAAK,IAAI,EAAE;IACvF,IAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,QAAO,IAAE,IAAI,CAAC,GAAG,EAAE,CAAA,CAAG;GACrD;CACF,CAAA;;;AAGH,mBAAE,SAAa,mBAAI;EACjB,OAAS,IAAI,CAAC,UAAU,CAAC;CACxB,CAAA;AACH,mBAAE,SAAa,iBAAE,GAAG,EAAE;EACpB,IAAM,CAAC,UAAU,GAAG,GAAG,CAAC;CACvB,CAAA;;AAEH,gBAAE,oBAAoB,kCAAE,IAAI,EAAE;EAC5B,IAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE;IAC1C,IAAM,GAAG,CAAG,IAAI,CAAC,OAAO,CAAA,aAAS,IAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA,UAAM,CAAE;GACxF;EACH,OAAS,IAAI,CAAC;CACb,CAAA;;;;;;;;AAQH,gBAAE,OAAO,uBAAI;;;;;;;;;EASX,OAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;CACnC,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BH,gBAAE,IAAI,kBAAE,OAAO,EAAE,GAAG,EAAE;EACpB,IAAM,IAAI,CAAC,WAAW,EAAE;;IAEtB,IAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;GAChD,MAAM;IACP,IAAM,GAAG,CAAC;;IAEV,IAAM,CAAC,OAAO,CAAC,SAAS,EAAE;MACxB,GAAK,GAAG,uCAAuC,CAAC;KAC/C;;IAEH,IAAMC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;MACjD,GAAK,GAAG,UAAS,IAAE,OAAO,CAAC,SAAS,CAAA,+BAA2B,CAAE;KAChE;;;IAGH,IAAM,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IACtC,IAAM,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC7C,IAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;IAC5C,IAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAC9C,IAAM,OAAO,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE;MACrE,IAAM,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;KACtC;;IAEH,IAAM,OAAO,CAAC,cAAc,EAAE;;MAE5B,IAAM,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;KAC9C;;;IAGH,IAAM,OAAO,CAAC,KAAK,EAAE;MACnB,IAAM,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;KAC7B;;IAEH,IAAM,GAAG,EAAE;MACT,MAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;KACtB;;IAEH,IAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;;IAE3B,IAAM,GAAG,CAAC,QAAQ,EAAE;MAClB,IAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;KAClB,MAAM;;MAEP,IAAQ,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;MACpC,MAAQ,IAAI,KAAK,CAAC,CAAA,kCAAiC,GAAE,IAAI,CAAE,CAAC,CAAC;KAC5D;GACF;CACF,CAAA;;;;;;;;;;;;;;AAcH,gBAAE,MAAM,oBAAE,GAAG,EAAE;;;EACb,IAAM,IAAI,CAAC,KAAK,EAAE;IAChB,IAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;GAC3B;;EAEH,IAAM,IAAI,CAAC,WAAW,EAAE;IACtB,IAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;GAClC,MAAM;IACP,IAAM,IAAI,CAAC,KAAK,EAAE;;;MAGhB,IAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KAC1B;;IAEH,IAAM;MACJ,IAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE;QAC1D,IAAM,CAAC,WAAW,CAAC,OAAO,GAAG,SAAS,CAAC,wBAAwB,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC/J,IAAM,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;UAC/B,IAAM,CAAC,OAAO,GAAG;YACf,OAAS,EAAE,CAAA,GAAE,IAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAA,MAAE,CAAC;YAC3D,SAAW,EAAE,CAAA,GAAE,IAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA,MAAE,CAAC;WACzD,CAAC;SACH;OACF;;;MAGH,IAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;QAC9B,IAAM,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;OAClD;;MAEH,IAAM,gBAAgB,GAAG,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;;MAErI,IAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;MAC5G,aAAe,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;;;MAG9F,gBAAkB,CAAC,KAAK,GAAG,aAAa,CAAC;;;MAGzC,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;;;MAGnH,IAAM,GAAG,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;;;MAG/D,IAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;QACtB,OAAS,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;OACzB;;MAEH,IAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE;;QAEnC,IAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;;;QAGtD,IAAM,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;OAC7B,MAAM;;QAEP,IAAQ,GAAG,GAAG,YAAY,CAAC,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;;;QAGhG,IAAQ,EAAE,GAAG,UAAC,GAAG,EAAE,IAAI,EAAE;;UAEvB,IAAM,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE;YAC1B,GAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;WAC9D;;UAEH,IAAM,CAAC,GAAG,EAAE;YACV,IAAMD,MAAI,CAAC,UAAU,IAAI,OAAOA,MAAI,CAAC,UAAU,KAAK,UAAU,EAAE;cAC9D,IAAM,GAAGA,MAAI,CAAC,UAAU,CAAC,IAAI,EAAEA,MAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;aACxD;;YAEH,IAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;;YAE7B,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;WAC7B,MAAM;;YAEP,IAAM,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE;cACxC,GAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;aAChB;WACF;SACF,CAAC;;;QAGJ,YAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;OAC9C;KACF,CAAC,OAAO,EAAE,EAAE;MACb,MAAQ,CAAC,EAAE,CAAC,CAAC;KACZ;GACF;CACF,CAAA;;;;;;;;;AASH,gBAAE,WAAW,yBAAE,IAAI,EAAE,GAAG,EAAE;;;EACxB,IAAM,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE;IAC9B,IAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,IAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;GACpC;;;EAGHE,QAAU,CAAC,IAAI,CAAC,IAAI,EAAE,UAAC,GAAG,EAAE,SAAS,EAAE;;IAErC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC;MACvB,EAAI,EAAEF,MAAI,CAAC,UAAU;MACrB,QAAU,EAAEA,MAAI,CAAC,SAAS;KACzB,CAAC,CAAC;;IAEL,IAAQ,KAAK,GAAGA,MAAI,CAAC,KAAK,IAAI,QAAQ,CAACC,SAAS,CAACD,MAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IAC7F,IAAQ,MAAM,GAAGA,MAAI,CAAC,MAAM,IAAI,QAAQ,CAACC,SAAS,CAACD,MAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;;;IAGhG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;;;IAGlD,MAAM,CAAC,OAAO,CAACA,MAAI,CAAC,KAAK,CAAC,CAAC;;IAE3B,IAAMA,MAAI,CAAC,KAAK,EAAE;MAChB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;KACzB;;;IAGH,IAAM,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE;MACxC,GAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;KAChB;GACF,CAAC,CAAC;CACJ,CAAA;;;;;;;;;;;AAWH,gBAAE,YAAY,0BAAE,IAAI,EAAE;;;EACpB,IAAM;IACJ,IAAQ,MAAM,GAAG,EAAE,CAAC;IACpB,IAAQ,OAAO,GAAG,EAAE,CAAC;IACrB,IAAQ,MAAM,GAAG,EAAE,CAAC;;IAEpB,KAAOL,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE;;MAErD,IAAMK,MAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE;QAC7D,IAAQ,KAAK,GAAGA,MAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;QAC/D,IAAM,KAAK,EAAE;UACX,MAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;UACrB,MAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;UACxB,OAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACpB;OACF;KACF;IACH,IAAM,MAAM,GAAG,CAAC,CAAC;;;IAGjB,IAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAC,OAAO,EAAE;MAC/C,MAAQ,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE;QACtB,MAAQ,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC;QACtE,IAAMA,MAAI,CAAC,cAAc,EAAE;;UAEzB,MAAQ,GAAG,MAAM,GAAG,CAACA,MAAI,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,MAAM,GAAGA,MAAI,CAAC,cAAc,CAAC;SAC5E;QACH,IAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE;UAC5B,OAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;SACxB;OACF,CAAC,CAAC;KACJ,CAAC,CAAC;;;IAGL,MAAQ,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE,KAAK,EAAE;MAC7B,IAAM,KAAK,GAAG,CAAC,CAAC;MAChB,IAAM,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACvC,IAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE;UAC9C,KAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;SACxD;QACH,IAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,GAAG,EAAE;UACnC,KAAO,GAAG,GAAG,GAAG,KAAK,CAAC;SACrB;QACH,IAAMA,MAAI,CAAC,cAAc,EAAE;;UAEzB,IAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAA,6BAA2B,IAAEA,MAAI,CAAC,cAAc,CAAA,SAAI,CAAC,CAAC,CAAC;SAC/G;;QAEH,IAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;OAC/E;KACF,CAAC,CAAC;IACL,OAAS,IAAI,CAAC;GACb,CAAC,OAAO,EAAE,EAAE;IACb,MAAQ,CAAC,EAAE,CAAC,CAAC;GACZ;CACF,CAAA;;;;;;;;;AASH,gBAAE,gBAAgB,8BAAE,IAAI,EAAE;EACxB,IAAM,IAAI,CAAC,IAAI,EAAE;IACf,IAAM;MACJ,IAAQ,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAACC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;MAC7F,IAAQ,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAACA,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;;MAEhG,IAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,GAAG,GAAG,CAAC;MACnC,IAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QAClB,IAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,EAAE,CAAC;OAClC;KACF,CAAC,OAAO,EAAE,EAAE;MACb,MAAQ,CAAC,EAAE,CAAC,CAAC;KACZ;GACF;EACH,OAAS,IAAI,CAAC;CACb,CAAA;;;;;;;;AAQH,gBAAE,cAAc,4BAAE,IAAI,EAAE;;;EACtB,IAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;;;EAGjD,IAAM,UAAU,EAAE;IAChB,OAAS,UAAU,CAAC;GACnB;;;EAGH,IAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;EAC9C,KAAO,CAAC,IAAI,GAAG,UAAU,CAAC;EAC1B,KAAO,CAAC,SAAS,GAAG,yRAAyR,CAAC;EAC9S,QAAU,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;;EAE9D,UAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;EAC7C,UAAY,CAAC,SAAS,GAAG,eAAe,CAAC;EACzC,UAAY,CAAC,EAAE,GAAG,IAAI,CAAC;EACvB,UAAY,CAAC,OAAO,GAAG,eAAe,CAAC;;EAEvC,QAAU,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;;EAEnE,IAAM,CAAC,EAAE,CAAC,UAAU,EAAE,UAAC,KAAK,EAAE,IAAI,EAAE;IAClC,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;GAClC,CAAC,CAAC;EACL,IAAM,CAAC,EAAE,CAAC,WAAW,EAAE,UAAC,KAAK,EAAE,IAAI,EAAE;IACnC,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;GAClC,CAAC,CAAC;EACL,OAAS,UAAU,CAAC;CACnB,CAAA;;;;;;;AAOH,gBAAE,cAAc,4BAAE,KAAK,EAAE,IAAI,EAAE;EAC7B,IAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;EACtE,IAAM,CAAC,IAAI,EAAE;IACX,QAAU,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAClC,OAAS;GACR;EACH,QAAU,CAAC,KAAK,CAAC,GAAG,GAAG,CAAG,KAAK,CAAC,KAAK,CAAA,OAAG,CAAE;EAC1C,QAAU,CAAC,KAAK,CAAC,IAAI,GAAG,CAAG,KAAK,CAAC,KAAK,CAAA,OAAG,CAAE;EAC3C,QAAU,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;;EAEnC,IAAM,OAAO,GAAG,sBAAqB,IAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAA,kBAAc,CAAE;EACrF,OAAS,IAAI,qBAAoB,IAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAA,SAAK,CAAE;;EAE1E,QAAU,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,UAAC,KAAK,EAAE,EAAE,EAAE;IAC/D,OAAS,IAAI,CAAC,EAAE,CAAC,CAAC;GACjB,CAAC,CAAC;CACJ,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BH,gBAAE,EAAE,gBAAE,OAAO,EAAE,QAAQ,EAAE;EACvB,IAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,UAAA,QAAQ,CAAC,CAAC,CAAC;CAC9C,CAAA;;;;AAIH,gBAAE,GAAG,iBAAE,OAAO,EAAE,QAAQ,EAAE;EACxB,IAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE;IACtD,IAAM,eAAe,CAAC,IAAI,KAAK,OAAO,IAAI,eAAe,CAAC,QAAQ,KAAK,QAAQ,EAAE;MAC/E,MAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;KACzB;GACF,CAAC,CAAC;CACJ,CAAA;;;;;;AAMH,gBAAE,IAAI,kBAAE,SAAS,EAAE;EACjB,IAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE;IACrG,IAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;GACzD;CACF,CAAA;;;;;;AAMH,gBAAE,OAAO,qBAAE,IAAI,EAAE;EACf,IAAM,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;EACnD,IAAM,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;EACnD,IAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;EAC3C,IAAM,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;EACzD,IAAM,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;CACpD,CAAA;;;;;;AAMH,gBAAE,OAAO,qBAAE,IAAI,EAAE;EACf,IAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;EACxB,IAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;EACvB,IAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;EACxB,IAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;EACpB,IAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;EAC3B,IAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;CACxB,CAAA;;;;;;;AAOH,gBAAE,iBAAiB,+BAAEE,OAAI,EAAE,IAAI,EAAE;EAC/B,IAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAEA,OAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;CACtD,CAAA;;;;;;;;AAQH,gBAAE,iBAAiB,iCAAI;;;EACrB,IAAM,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;IAClC,IAAM,CAAC,YAAY,CAAC,OAAO,CAAC,UAAC,MAAM,EAAE,KAAK,EAAE;MAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAACH,MAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;KAC9C,CAAC,CAAC;GACJ;CACF,CAAA;;;;;;AAMH,gBAAE,QAAQ,sBAAE,OAAO,EAAE;;;;EAEnB,IAAQ,OAAO,GAAG,UAAC,GAAG,EAAE,IAAI,EAAE;IAC5B,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAC,iBAAiB,EAAE;MACzC,IAAM,iBAAiB,CAAC,IAAI,KAAK,OAAO,EAAE;;QAExC,IAAM,IAAI,EAAE;UACV,iBAAmB,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;SACxD,MAAM;UACP,iBAAmB,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;SACvC;OACF;KACF,CAAC,CAAC;GACJ,CAAC;EACJ,OAAS,OAAO,CAAC;CAChB,CAAA;;;;;;;;;;;;;;;AAeH,gBAAE,MAAM,oBAAE,OAAO,EAAE;;;EACjB,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;EACxB,IAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;;EAE3D,KAAO,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE;IACrB,IAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE;MAC1D,IAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;QAClC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;OAClD;KACF;GACF,CAAC,CAAC;;EAEL,OAAS,KAAK,CAAC;CACd,CAAA;;;;;;;;;;AAUH,gBAAE,cAAc,4BAAE,OAAO,EAAE;;;EACzB,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;;EAExB,IAAM,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;IAChC,IAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3D,KAAO,CAAC,OAAO,CAAC,UAAC,IAAI,EAAE;MACrB,IAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE;QAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;OACnD;KACF,CAAC,CAAC;IACL,OAAS,KAAK,CAAC;GACd,MAAM;;IAEP,IAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACtB,OAAS,IAAI,CAAC;GACb;CACF,CAAA;;AAEH,MAAE,OAAc,qBAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE;EACxC,OAAS,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;CACrD,CAAA;;;;;AAKH,MAAE,iBAAwB,+BAAE,MAAM,EAAE,QAAQ,EAAE;EAC5C,OAAS,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACjD,CAAA;AACH,MAAE,aAAoB,2BAAE,IAAI,EAAE,QAAQ,EAAE;EACtC,OAAS,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;CAC3C,CAAA;AACH,MAAE,4BAAmC,0CAAE,OAAO,EAAE,aAAa,EAAE;EAC7D,OAAS,YAAY,CAAC,2BAA2B,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;CACzE,CAAA;AACH,MAAE,oBAA2B,kCAAE,WAAW,EAAE,SAAS,EAAE;EACrD,OAAS,KAAK,CAAC,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;CAC1D,CAAA;;AAEH,MAAE,yBAAgC,uCAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;EAChE,OAAS,SAAS,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;CACzE,CAAA;;+DACF,AAAA;;;;"} \ No newline at end of file diff --git a/dist/cedar.min.js b/dist/cedar.min.js new file mode 100644 index 00000000..24eb479e --- /dev/null +++ b/dist/cedar.min.js @@ -0,0 +1,7 @@ +/** +* arcgis-cedar - v0.9.1 - Thu Mar 02 2017 08:51:30 GMT-0500 (EST) +* Copyright (c) 2017 Environmental Systems Research Institute, Inc. +* Apache-2.0 +*/ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("d3"),require("vega")):"function"==typeof define&&define.amd?define(["d3","vega"],e):t.Cedar=e(t.d3,t.vg)}(this,function(t,e){"use strict";function i(e){for(var i=arguments.length,n=Array(i);i--;)n[i]=arguments[i];for(var r=[].concat(n),o=1;o"+this._definition.tooltip.content+"
",i.innerHTML=n.replace(/\{(\w+)\}/g,function(t,i){return e[i]})},S.prototype.on=function(t,e){this._events.push({type:t,callback:e})},S.prototype.off=function(t,e){this._events.forEach(function(i,n,r){i.type===t&&i.callback===e&&r.splice(n,1)})},S.prototype.emit=function(t){this._view._handler._handlers[t]&&this._view._handler._handlers[t][0]&&this._view._handler._handlers[t][0].handler()},S.prototype._attach=function(t){t.on("mouseover",this._handler("mouseover")),t.on("mouseout",this._handler("mouseout")),t.on("mousemove",this._handler("mousemove")),t.on("click",this._handler("click")),t.on("update-start",this._handler("update-start")),t.on("update-end",this._handler("update-end"))},S.prototype._remove=function(t){t.off("mouseover"),t.off("mouseout"),t.off("mousemove"),t.off("click"),t.off("update-start"),t.off("update-end")},S.prototype._addToMethodQueue=function(t,e){this._methodQueue.push({method:t,args:e})},S.prototype._purgeMethodQueue=function(){var t=this;this._methodQueue.length>0&&this._methodQueue.forEach(function(e,i){t[e.method].apply(t,e.args)})},S.prototype._handler=function(t){var e=this,i=function(i,n){e._events.forEach(function(e){e.type===t&&(n?e.callback(i,n.datum.attributes):e.callback(i,null))})};return i},S.prototype.select=function(t){var e=this,i=this._view,n=i.model().scene().items[0].items[0].items;return n.forEach(function(i){i.datum.attributes[t.key]===t.value&&i.hasPropertySet("hover")&&e._view.update({props:"hover",items:i})}),n},S.prototype.clearSelection=function(t){var e=this,i=this._view;if(t&&t.key){var n=i.model().scene().items[0].items[0].items;return n.forEach(function(i){i.datum.attributes[t.key]===t.value&&e._view.update({props:"update",items:i})}),n}return this._view.update(),null},S.getJson=function(t,e,i){return w.getJson(t,e,i)},S._validateMappings=function(t,e){return y.validateMappings(t,e)},S._validateData=function(t,e){return y.validateData(t,e)},S._createFeatureServiceRequest=function(t,e){return w.createFeatureServiceRequest(t,e)},S._getMappingFieldName=function(t,e){return y.getMappingFieldName(t,e)},S._convertDatasetsToDataset=function(t,e,i){return b.convertDatasetsToDataset(t,e,i)},Object.defineProperties(S.prototype,E),S}); +//# sourceMappingURL=cedar.min.js.map diff --git a/dist/cedar.min.js.map b/dist/cedar.min.js.map new file mode 100644 index 00000000..4e7050f3 --- /dev/null +++ b/dist/cedar.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":null,"sources":["../src/utils/utils.js","../src/utils/spec.js","../src/utils/request.js","../src/cedar.js"],"sourcesContent":["import * as d3 from 'd3';\n/**\n * Merges n objects\n * @param {object} source Empty object that other objects will be merged into\n * @return {Object} Merged objects\n */\nexport function mixin (source) {\n const args = [...arguments];\n for (let i = 1; i < args.length; i++) {\n d3.entries(args[i]).forEach((p) => {\n source[p.key] = p.value;\n });\n }\n return source;\n}\n\n/**\n * Recursively merge properties of two objects\n */\nexport function mergeRecursive (obj1, obj2) {\n for (let p in obj2) {\n if (obj2.hasOwnProperty(p)) {\n try {\n // Property in destination object set; update its value.\n if (obj2[p].constructor === Object || obj2[p].constructor === Array) {\n obj1[p] = mergeRecursive(obj1[p], obj2[p]);\n } else {\n obj1[p] = obj2[p];\n }\n } catch (e) {\n // Property in destination object not set; create it and set its value\n obj1[p] = obj2[p];\n }\n }\n }\n return obj1;\n}\n\n/**\n * Token replacement on a string\n * @param {string} template string template\n * @param {object} params Object hash that maps to the tokens to be replaced\n * @return {string} string with values replaced\n */\nexport function supplant (template, params) {\n const t = template.replace(/{([^{}]*)}/g,\n (a, b) => {\n const r = getTokenValue(params, b);\n\n return typeof r === 'string' || typeof r === 'number' ? r : a;\n }\n );\n return t.replace(/\"{([^{}]*)}\"/g,\n (a, b) => {\n let r = getTokenValue(params, b);\n return (!!r && r.constructor === Array) ? JSON.stringify(r) : a;\n });\n}\n\n/**\n * Get the value of a token from a hash\n * @param {object} tokens Hash {a: 'a', b: { c: 'c'} }\n * @param {string} tokenName Property name: 'a' would yield 'a', 'b.c' would yield 'c'\n * @return {Any} Returns value contained within property\n * Pulled from gulp-token-replace (MIT license)\n * https://github.com/Pictela/gulp-token-replace/blob/master/index.js\n */\nexport function getTokenValue (tokens, tokenName) {\n let tmpTokens = tokens;\n let tokenNameParts = tokenName.split('.');\n for (let i = 0; i < tokenNameParts.length; i++) {\n if (tmpTokens.hasOwnProperty(tokenNameParts[i])) {\n tmpTokens = tmpTokens[tokenNameParts[i]];\n } else {\n return null;\n }\n }\n return tmpTokens;\n}\n\n /**\n * Helper function that validates that the\n * mappings hash contains values for all\n * the inputs\n * @param {array} inputs Array of inputs\n * @param {object} mappings Hash of mappings\n * @return {array} Missing mappings\n * @access private\n */\nexport function validateMappings (inputs, mappings) {\n return inputs.filter((input) => {\n if (input.required && !mappings[input.name]) {\n return input;\n }\n });\n}\n\n /**\n * Validate that the incoming data has the fields expected\n * in the mappings\n * @access private\n */\nexport function validateData (data, mappings) {\n const missingInputs = [];\n if (!data.features || !Array.isArray(data.features)) {\n throw new Error('Data is expected to have features array!');\n }\n const firstRow = data.features[0].attributes;\n for (let key in mappings) {\n if (mappings.hasOwnProperty(key)) {\n let fld = getMappingFieldName(key, mappings[key].field);\n if (!firstRow.hasOwnProperty(fld)) {\n missingInputs.push(fld);\n }\n }\n }\n return missingInputs;\n}\n\n /**\n * TODO does nothing, must figure out.\n * Centralize and abstract the computation of\n * expected field names, based on the mapping name\n * @access private\n */\nexport function getMappingFieldName (mappingName, fieldName) {\n // this function why?\n\n let name = fieldName;\n // if(mappingName.toLowerCase() === 'count'){\n // name = fieldName + '_SUM';\n // }\n return name;\n}\n\nconst utils = {\n mixin,\n supplant,\n mergeRecursive,\n getTokenValue,\n validateMappings,\n validateData,\n getMappingFieldName\n};\n\nexport default utils;\n","/**\n * Return a default definition Object\n * @return {Object} Default definition\n */\nexport function defaultDefinition () {\n return {\n dataset: {\n query: defaultQuery()\n },\n template: {}\n };\n}\n\n/**\n * Return AGO query defaults\n * @return {Object} Default query\n */\nexport function defaultQuery () {\n return {\n where: '1=1',\n returnGeometry: false,\n returnDistinctValues: false,\n returnIdsOnly: false,\n returnCountOnly: false,\n outFields: '*',\n sqlFormat: 'standard',\n f: 'json'\n };\n}\n\n/**\n * Ensure that all required inputs exist in mappings\n * @param {object} mappings Mappings object\n * @param {array} inputs Array of inputs in specification\n * @return {object} Returns mappings\n */\nexport function applyDefaultsToMappings (mappings, inputs) {\n const errs = [];\n // iterate over inputs\n for (let i = 0; i < inputs.length; i++) {\n const input = inputs[i];\n\n // If required but not there\n if (input.required && !mappings[input.name]) {\n errs.push(input.name);\n }\n\n // if it's not required, has a default and not in the mappings\n if (!input.required && !mappings[input.name] && input['default']) {\n // add the default\n mappings[input.name] = input['default'];\n }\n }\n if (errs.length > 0) {\n throw new Error(`Required Mappings Missing: ${errs.join(',')}`);\n } else {\n return mappings;\n }\n}\n\n/**\n * Convert datasets to dataset\n */\nexport function convertDatasetsToDataset (datasets, series, chartType, dataset) {\n // console.log('Datasets and dataset are:', datasets, dataset);\n if (!dataset) {\n dataset = {\n query: this.defaultQuery()\n };\n }\n // Mappings held here\n const mappings = {};\n // Queries held here\n const queries = [];\n // Urls held here\n const urls = [];\n // Data held here\n const data = [];\n\n datasets.forEach((dtst) => {\n // Push queries data and urls first\n if (dtst.query) {\n queries.push(dtst.query);\n }\n if (dtst.url) {\n urls.push(dtst.url);\n }\n if (dtst.data) {\n data.push(dtst.data);\n }\n // Construct mappings\n // Grouped bar chart here\n if (chartType === 'grouped') {\n if (!mappings.group) {\n mappings.group = series[0].category;\n }\n if (!mappings.x) {\n mappings.x = {\n field: [],\n label: series[0].value.label\n };\n }\n if (series.length > 1) {\n series.forEach((attr) => {\n mappings.x.field.push(`attributes.${attr.value.field}`);\n });\n } else {\n mappings.x.field.push(`attributes.${series[0].value.field}`);\n }\n\n // Bubble Chart starts here\n } else if (chartType === 'bubble') {\n mappings.x = series[0].category;\n mappings.y = series[0].value;\n mappings.size = series[0].size;\n\n // Scatter plot starts here\n } else if (chartType === 'scatter') {\n mappings.x = series[0].category;\n mappings.y = series[0].value;\n mappings.color = series[0].color;\n\n // Pie Chart starts here\n } else if (chartType === 'pie') {\n mappings.label = series[0].category;\n mappings.y = series[0].value;\n mappings.radius = series[0].radius;\n\n // Bar horizontal starts here\n } else if (chartType === 'bar-horizontal') {\n mappings.y = series[0].category;\n mappings.x = series[0].value;\n\n // Timeline chart starts here\n } else if (chartType === 'time') {\n mappings.time = series[0].category;\n mappings.value = series[0].value;\n\n // time-trendline chart starts here\n } else if (chartType === 'time-trendline') {\n mappings.time = series[0].category;\n mappings.value = series[0].value;\n mappings.trendline = series[0].trendline;\n\n // X Y only charts here\n } else {\n mappings.x = series[0].category;\n mappings.y = series[0].value;\n }\n });\n\n const builtDataset = {\n query: convertQueries(queries, dataset.query),\n mappings\n };\n if (data.length > 0) {\n builtDataset.data = data[0];\n }\n\n if (urls.length > 0) {\n builtDataset.url = convertUrls(urls);\n }\n\n return builtDataset;\n}\n\n/**\n * Convert over query\n */\nfunction convertQueries (queries, defaultQuery) {\n if (queries.length > 1) {\n console.warn('Warning, currently multiple queries is not supported. Reverting to default.', queries);\n return defaultQuery;\n }\n return queries[0] ? queries[0] : defaultQuery; // Might not have a query passed in so check and if it hasn't then return default query\n}\n\n/**\n * Convert over URLs\n */\nfunction convertUrls (urls) {\n if (urls.length > 1) {\n console.warn('Warning, currently multiple URLS are not supported. Using first url', urls);\n return urls[0];\n }\n return urls[0];\n}\n\nconst specUtils = {\n defaultDefinition,\n defaultQuery,\n applyDefaultsToMappings,\n convertDatasetsToDataset\n};\n\nexport default specUtils;\n","import * as d3 from 'd3';\nimport { mixin } from './utils';\nimport { defaultQuery } from './spec';\n\n/**\n * Takes in params, iterates over them, encodes and returns stringified and encoded query\n *\n * @param {object} params - merged default and user defined parameters\n *\n * @returns {string} - stringified and encoded query\n */\nfunction serializeQueryParams (params) {\n const str = [];\n for (const param in params) {\n if (params.hasOwnProperty(param)) {\n let val = params[param];\n if (typeof val !== 'string') {\n val = JSON.stringify(val);\n }\n str.push(`${encodeURIComponent(param)}=${encodeURIComponent(val)}`);\n }\n }\n const queryString = str.join('&');\n return queryString;\n}\n\n/**\n * Helper function to request JSON from a url\n * @param {string} url URL to request from\n * @param {Function} callback Callback function\n * @param {number} timeout Timeout on request\n * @return {object} Response object\n */\nexport function getJson (url, callback, timeout) {\n const cb = (err, data) => {\n // if timeout error then return a timeout error\n if (err && err.response === '') {\n callback(new Error('This service is taking too long to respond, unable to chart'));\n } else if (err) {\n // Other errors return generic error.\n callback(new Error(`Error loading ${url} with a response of: ${err.message}`));\n } else {\n callback(null, JSON.parse(data.responseText));\n }\n };\n if (url.length > 2000) {\n const uri = url.split('?');\n d3.xhr(uri[0])\n .on('beforesend', (xhr) => { xhr.timeout = timeout; xhr.ontimeout = xhr.onload; })\n .header('Content-Type', 'application/x-www-form-urlencoded')\n .post(uri[1], cb);\n } else {\n d3.xhr(url)\n .on('beforesend', (xhr) => { xhr.timeout = timeout; xhr.ontimeout = xhr.onload; })\n .get(cb);\n }\n}\n\n/**\n * Given a dataset hash create a feature service request\n * @param {object} dataset Dataset object\n * @param {object} queryFromSpec Query passed in by the user\n * @return {string} url string\n */\nexport function createFeatureServiceRequest (dataset, queryFromSpec) {\n const mergedQuery = mixin({}, defaultQuery(), queryFromSpec);\n\n // Handle bbox\n if (mergedQuery.bbox) {\n // make sure a geometry was not also passed in\n if (mergedQuery.geometry) {\n throw new Error('Dataset.query can not have both a geometry and a bbox specified');\n }\n // Get the bbox (w,s,e,n)\n const bboxArr = mergedQuery.bbox.split(',');\n\n // Remove it so it's not serialized as-is\n delete mergedQuery.bbox;\n\n // cook it into a json string\n mergedQuery.geometry = JSON.stringify({\n xmin: bboxArr[0],\n ymin: bboxArr[2],\n xmax: bboxArr[1],\n ymax: bboxArr[3]\n });\n // set spatial ref as geographic\n mergedQuery.inSR = '4326';\n }\n\n if (!mergedQuery.groupByFieldsForStatistics && !!dataset.mappings.group) {\n mergedQuery.groupByFieldsForStatistics = dataset.mappings.group.field;\n }\n if (!mergedQuery.outStatistics && !!dataset.mappings.count) {\n // TODO Why are we explicitlystating _SUM as a stats type?\n mergedQuery.orderByFields = `${dataset.mappings.count.field}_SUM`;\n mergedQuery.outStatistics = JSON.stringify([{\n statisticType: 'sum',\n onStatisticField: dataset.mappings.count.field,\n outStatisticFieldName: `${dataset.mappings.count.field}_SUM`\n }]);\n }\n\n // iterate the mappings keys to check for sort\n // -----------------------------------------------------------------\n // This approach would seem 'clean' but if there are multiple fields\n // to sort by, the order would be determined by how javascript decides to\n // iterate the mappings property hash.\n // Thus, using mappings.sort gives the developer explicit control\n // -----------------------------------------------------------------\n // var sort = [];\n // for (var property in dataset.mappings) {\n // if (dataset.mappings.hasOwnProperty(property)) {\n // if(dataset.mappings[property].sort){\n // //ok - build up the sort\n // sort.push(dataset.mappings[property].field + ' ' + dataset.mappings[property].sort);\n // }\n // }\n // }\n // if(sort.length > 0){\n // mergedQuery.orderByFields = sort.join(',');\n // }\n // -----------------------------------------------------------------\n // check for a sort passed directly in\n\n if (dataset.mappings.sort) {\n mergedQuery.orderByFields = dataset.mappings.sort;\n }\n\n let url = `${dataset.url}/query?${serializeQueryParams(mergedQuery)}`;\n\n if (dataset.token) {\n url = `${url}&token=${dataset.token}`;\n }\n\n return url;\n}\n\nconst requestUtils = {\n getJson,\n createFeatureServiceRequest\n};\n\nexport default requestUtils;\n","import { version } from '../package.json';\nimport utils from './utils/utils';\nimport requestUtils from './utils/request';\nimport specUtils from './utils/spec';\n// import specTemplates from './charts/specs';\nimport * as d3 from 'd3';\nimport * as vg from 'vega';\n\n// get cedar root URL for loading chart specs\nconst baseUrl = (function () {\n var cdnProtocol = 'http:';\n var cdnUrl = '//esri.github.io/cedar/js';\n var src;\n if (window && window.document) {\n src = (window.document.currentScript && window.document.currentScript.src);\n if (src) {\n // real browser, get base url from current script\n return src.substr(0, src.lastIndexOf('/'));\n } else {\n // ie, set base url to CDN\n // NOTE: could fallback to CDN only if can't find any scripts named cedar\n return (window.document.location ? window.document.location.protocol : cdnProtocol) + cdnUrl;\n }\n } else {\n // node, set base url to CDN\n return cdnProtocol + cdnUrl;\n }\n})();\n\nexport default class Cedar {\n /**\n * Creates a new Chart object.\n *\n * @example\n * var chart = new Cedar({\n * \"type\": \"bar\"\n * \"dataset\":\n * \"url\":\"http://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Education_WebMercator/MapServer/5\",\n * \"query\": {\n * \"groupByFieldsForStatistics\": \"FACUSE\",\n * \"outStatistics\": [{\n * \"statisticType\": \"sum\",\n * \"onStatisticField\": \"TOTAL_STUD\",\n * \"outStatisticFieldName\": \"TOTAL_STUD_SUM\"\n * }]\n * },\n * \"mappings\":{\n * \"sort\": \"TOTAL_STUD_SUM DESC\",\n * \"x\": {\"field\":\"FACUSE\",\"label\":\"Facility Use\"},\n * \"y\": {\"field\":\"TOTAL_STUD_SUM\",\"label\":\"Total Students\"}\n * }\n * }\n * });\n *\n * @param {Object} options\n * @param {String} options.type - Chart type as a chartType (\"bar\") or a URL to a Cedar specification\n * @param {Object} options.dataset - Dataset definition including Source and Style mappings\n * @param {String} options.dataset.url - GeoService Layer URL\n *\n * \"url\":\"http://.../rest/services/DATA/Education/MapServer/5\"\n * @param {Object} options.dataset.query - GeoServices Layer query parameters (where, bbox, outStatistics) [optional]\n *\n * \"query\": {\n * \"groupByFieldsForStatistics\": \"FACUSE\",\n * \"outStatistics\": [{\n * \"statisticType\": \"sum\",\n * \"onStatisticField\": \"TOTAL_STUD\",\n * \"outStatisticFieldName\": \"TOTAL_STUD_SUM\" }] }\n * @param {Object} options.dataset.data - Inline feature collection, alternative to data from a URL\n *\n * \"data\": {\"features\":[{\"attributes\":{\"ZIP_CODE\":20005,\"TOTAL_STUD_SUM\":327}}]}\n * @param {Object} options.dataset.mappings - Relates data items to the chart style definition\n * @param {Object} options.override - Changes to the \"options.type\" chart specification\n * @param {Object} options.tooltip - Optional on-hover tooltip. Element has class=\"cedar-tooltip\" for styling.\n * @param {String} options.tooltip.id - Optional HTML element to use for tooltip. (default: unique id created)\n * @param {String} options.tooltip.title - Templated tooltip heading. Uses \"{Variable} template format\"\n * @param {String} options.tooltip.content - Templated tooltip body text. Uses \"{Variable} template format\"\n * @return {Object} new Cedar chart object\n */\n constructor (options) {\n this.version = version;\n // Pull templates in\n // this.chartTypes = specTemplates;\n\n let opts = options || {};\n\n let spec;\n\n this.baseUrl = baseUrl;\n this.chartTypes = ['bar', 'bar-horizontal', 'bubble', 'grouped', 'pie', 'scatter', 'sparkline', 'time', 'time-trendline'];\n\n // Cedar configs such as size..\n this.width = undefined;\n this.height = undefined;\n this.autolabels = true;\n this.maxLabelLength = undefined;\n\n // Array to hold event handlers\n this._events = [];\n\n // initialize internal definition\n this._definition = specUtils.defaultDefinition();\n\n // initialize vega view aka chart\n this._view = undefined;\n\n // the vega tooltip\n this._tooltip = undefined;\n\n // transform function\n this._transform = undefined;\n\n // Queue to hold methods called while xhrs are in progress\n this._methodQueue = [];\n\n // Set a base timeout\n this._timeout = undefined;\n\n // override the base timeout\n if (opts.timeout) {\n this._timeout = opts.timeout;\n }\n\n // override the base url\n if (opts.baseUrl) {\n this.baseUrl = opts.baseUrl;\n }\n\n /**\n * Flag used to determine if the library is waiting for an xhr to return.\n * @access private\n */\n this._pendingXhr = false;\n\n /**\n * Definition\n */\n\n if (opts.definition) {\n if (typeof opts.definition === 'object') {\n // hold onto the definition\n this._definition = opts.definition;\n } else if (typeof opts.definition === 'string') {\n // assume it's a url (relative or absolute) and fetch the def object\n this._pendingXhr = true;\n requestUtils.getJson(opts.definition, (err, data) => {\n if (err) {\n throw new Error('Error fetching definition object', err);\n }\n this._pendingXhr = false;\n this._definition = data;\n this._purgeMethodQueue();\n }, this._timeout);\n } else {\n throw new Error('parameter definition must be an object or string (url)');\n }\n }\n\n // if there are overrides\n if (opts.override) {\n this._definition.override = opts.override;\n }\n\n /**\n * Specs\n */\n\n // first, check for pre-defined chart type passed in as 'type'\n this._chartType = opts.type;\n spec = this._getSpecificationUrl(opts.type);\n\n // If url or object passed use that...\n if (opts.specification) {\n spec = opts.specification;\n }\n\n if (spec) {\n // is it an object or string, assumed to be url\n if (typeof spec === 'object') {\n // hold onto the template\n this._definition.specification = spec;\n } else if (typeof spec === 'string') {\n // assume it's a url (rel or abs) and fetch the template object\n this._pendingXhr = true;\n this._pendingXhr = true;\n requestUtils.getJson(spec, (err, data) => {\n if (err) {\n throw new Error('Error fetching template object', err);\n }\n this._pendingXhr = false;\n this._definition.specification = data;\n this._purgeMethodQueue();\n }, this._timeout);\n } else {\n throw new Error('parameter specification must be an object or string (url)');\n }\n }\n\n // Allow a dataset to be passed in....\n if (opts.dataset && typeof opts.dataset === 'object') {\n opts.dataset.query = utils.mixin({}, specUtils.defaultQuery(), opts.dataset.query);\n // Assign it\n this._definition.dataset = opts.dataset;\n }\n\n // Allow datasets to be passed in\n if (opts.datasets && Array.isArray(opts.datasets)) {\n this._definition.datasets = opts.datasets;\n }\n\n // Allow series to be passed in\n if (opts.series && Array.isArray(opts.series)) {\n this._definition.series = opts.series;\n }\n\n /**\n * Tooltip\n */\n // allow a tooltip to be passed in...\n if (opts.tooltip && typeof opts.tooltip === 'object') {\n this.tooltip = opts.tooltip;\n } else {\n // Build a default tooltip based on first two imputs....\n const inputs = [];\n for (let input in this._definition.dataset.mappings) {\n if (this._definition.dataset.mappings.hasOwnProperty(input)) {\n const field = this._definition.dataset.mappings[input].field;\n if (field !== undefined && field !== null) {\n inputs.push(field);\n }\n }\n }\n if (inputs.length >= 2) {\n this.tooltip = {\n 'title': `{${inputs[0]}}`,\n 'content': `{${inputs[1]}}`\n };\n }\n }\n\n /**\n * tranform\n */\n // Allow a transform func to pass in\n if (opts.transform && typeof opts.transform === 'function') {\n this._transform = opts.transform;\n }\n }\n\n /**\n * Properties\n */\n // Dataset - old api\n get dataset () {\n return this._definition.dataset;\n }\n set dataset (val) {\n this._definition.dataset = val;\n }\n\n // Datasets - new api\n get datasets () {\n return this._definition.datasets;\n }\n set datasets (val) {\n this._definition.datasets = val;\n }\n\n // Series - new api\n get series () {\n return this._definition.series;\n }\n set series (val) {\n this._definition.series = val;\n }\n\n // Specification\n get specification () {\n return this._definition.specification;\n }\n set specification (val) {\n this._definition.specification = val;\n }\n\n // override\n get override () {\n return this._definition.override;\n }\n set override (val) {\n this._definition.override = val;\n // return this.update(); // TODO is this the best way?\n }\n\n // Tooltip\n get tooltip () {\n return this._definition.tooltip;\n }\n set tooltip (val) {\n this._definition.tooltip = val;\n if (this._definition.tooltip.id === undefined || this._definition.tooltip.id === null) {\n this._definition.tooltip.id = `cedar-${Date.now()}`;\n }\n }\n\n // transform\n get transform () {\n return this._transform;\n }\n set transform (val) {\n this._transform = val;\n }\n\n _getSpecificationUrl (spec) {\n if (this.chartTypes.indexOf(spec) !== -1) {\n spec = `${this.baseUrl}/charts/${this.chartTypes[this.chartTypes.indexOf(spec)]}.json`;\n }\n return spec;\n }\n\n /**\n * Inspect the current state of the Object\n * and determine if we have sufficient information\n * to render the chart\n * @return {object} Hash of the draw state + any missing requirements\n */\n canDraw () {\n // dataset?\n // dataset.url || dataset.data?\n // dataset.mappings?\n // specification?\n // specification.template?\n // specification.inputs?\n // specification.inputs ~ dataset.mappings?\n\n return {drawable: true, errs: []};\n }\n\n /**\n * Draw the chart into the DOM element\n *\n * @example\n *\n * var chart = new Cedar({\n * \"type\": \"scatter\",\n * \"dataset\":{\n * \"url\":\"http://maps2.dcgis.dc.gov/dcgis/rest/services/DCGIS_DATA/Education_WebMercator/MapServer/5\",\n * \"query\":{},\n * \"mappings\":{\n * \"x\": {\"field\":\"POPULATION_ENROLLED_2008\",\"label\":\"Enrolment 2008\"},\n * \"y\": {\"field\":\"SQUARE_FOOTAGE\",\"label\":\"Square Footage\"},\n * \"color\":{\"field\":\"FACUSE\",\"label\":\"Facility Type\"}\n * }\n * }\n * });\n *\n * chart.show({\n * elementId: \"#chart\"\n * });\n *\n * @param {object} options\n * @param {String} options.elementId [required] Id of the Dom element into which the chart will be rendered\n * @param {String} options.renderer \"canvas\" or \"svg\" (default: `svg`)\n * @param {Boolean} options.autolabels place axis labels outside any tick labels (default: false)\n * @param {String} options.token Token to be used if the data or spec are on a secured server\n */\n show (options, clb) {\n if (this._pendingXhr) {\n // TODO addToMethodQueue\n this._addToMethodQueue('show', [options, clb]);\n } else {\n let err;\n // ensure we got an elementId\n if (!options.elementId) {\n err = 'Cedar.show requires options.elementId';\n }\n // Check if element exists in the page\n if (d3.select(options.elementId)[0][0] === null) {\n err = `Element ${options.elementId} is not present in the DOM`;\n }\n\n // hold onto the id\n this._elementId = options.elementId;\n this._renderer = options.renderer || 'svg'; // default to svg\n this.width = options.width || this.height;\n this.height = options.height || this.height;\n if (options.autolabels !== undefined && options.autolabels !== null) {\n this.autolabels = options.autolabels;\n }\n\n if (options.maxLabelLength) {\n // check if truncate label length has been passed in\n this.maxLabelLength = options.maxLabelLength;\n }\n\n // hold onto the token\n if (options.token) {\n this._token = options.token;\n }\n\n if (err) {\n throw new Error(err);\n }\n\n var chk = this.canDraw();\n\n if (chk.drawable) {\n this.update(clb);\n } else {\n // report the issues\n const errs = chk.issues.join(',');\n throw new Error(`Chart can not be drawn because: ${errs}`);\n }\n }\n }\n\n /**\n * Draw the chart based on any changes to data or specifications\n * Should be called after a user modifies\n * the dataset, query, mappings, chart specification or element size\n *\n * @example\n * dataset = {\"url\": \"...\", \"mappings\": {\"x\": {\"field\": \"STATE\"}, \"y\": {\"field\": \"POPULATION\"}}};\n * chart = new Cedar({ \"type\": \"bar\", \"dataset\": dataset });\n * chart.show({elementId: \"#chart\"});\n * chart.dataset.query.where = \"POPULATION>30000\";\n * chart.update();\n */\n update (clb) {\n if (this._view) {\n this.emit('update-start');\n }\n\n if (this._pendingXhr) {\n this._addToMethodQueue('update');\n } else {\n if (this._view) {\n // remove handlers\n // TODO Remove existing handlers\n this._remove(this._view);\n }\n\n try {\n if (this._definition.datasets && this._definition.series) {\n this._definition.dataset = specUtils.convertDatasetsToDataset(this._definition.datasets, this._definition.series, this._chartType, this._definition.dataset);\n if (!this._definition.tooltip) {\n this.tooltip = {\n 'title': `{${this._definition.series[0].category.field}}`,\n 'content': `{${this._definition.series[0].value.field}}`\n };\n }\n }\n\n // Creates the HTML Div and styling if not already created\n if (this._definition.tooltip) {\n this._createTooltip(this._definition.tooltip.id);\n }\n // Ensure we have required inputs or defaults\n let compiledMappings = specUtils.applyDefaultsToMappings(this._definition.dataset.mappings, this._definition.specification.inputs);\n\n let queryFromSpec = utils.mixin({}, this._definition.specification.query, this._definition.dataset.query);\n queryFromSpec = JSON.parse(utils.supplant(JSON.stringify(queryFromSpec), compiledMappings));\n\n // allow binding to query properties\n compiledMappings.query = queryFromSpec;\n\n // compile the template + mappings --> vega spec\n let spec = JSON.parse(utils.supplant(JSON.stringify(this._definition.specification.template), compiledMappings));\n\n // merge in user specified style overrides\n spec = utils.mergeRecursive(spec, this._definition.override);\n\n // if the spec has a url in the data node, delete it TODO: need to readress this.\n if (spec.data[0].url) {\n delete spec.data[0].url;\n }\n\n if (this._definition.dataset.data) {\n // create the data node using the passed in data\n spec.data[0].values = this._definition.dataset.data; // TODO: only works on first spec, need to address for multiple datasets.\n\n // Send to vega\n this._renderSpec(spec, clb);\n } else {\n // We need to fetch the data so....\n const url = requestUtils.createFeatureServiceRequest(this._definition.dataset, queryFromSpec);\n\n // create a callback closure to carry the spec\n const cb = (err, data) => {\n // Normalize error response\n if (!err && !!data.error) {\n err = new Error(data.error.message || data.error.details[0]);\n }\n // if no errors then continue...\n if (!err) {\n if (this._transform && typeof this._transform === 'function') {\n data = this._transform(data, this._definition.dataset);\n }\n // TODO add error handlers for xhr and AGS errors.\n spec.data[0].values = data;\n // send to vega\n this._renderSpec(spec, clb);\n } else {\n // optional callback\n if (!!clb && typeof clb === 'function') {\n clb(err, data);\n }\n }\n };\n\n // fetch the data from the service\n requestUtils.getJson(url, cb, this._timeout);\n }\n } catch (ex) {\n throw (ex);\n }\n }\n }\n\n /**\n * RENDER CHART FUNCTIONS\n *\n *\n * Render a compiled Vega specification using vega runtime\n */\n\n _renderSpec (spec, clb) {\n if (this.autolabels === true) {\n spec = this._placeLabels(spec);\n spec = this._placeaAxisTicks(spec);\n }\n // Use vega to parse the spec\n // It will handle the spec as an object or url\n vg.parse.spec(spec, (err, chartCtor) => {\n // create the view\n this._view = chartCtor({\n el: this._elementId,\n renderer: this._renderer\n });\n\n const width = this.width || parseInt(d3.select(this._elementId).style('width'), 10) || 500;\n const height = this.height || parseInt(d3.select(this._elementId).style('height'), 10) || 500;\n\n // render into the element\n this._view.width(width).height(height).update();\n\n // attach event proxies\n this._attach(this._view);\n\n if (this._view) {\n this.emit('update-end');\n }\n\n // expose errors\n if (!!clb && typeof clb === 'function') {\n clb(err, spec);\n }\n });\n }\n\n /**\n * AXIS TICK FUNCTIONS START HERE\n *\n *\n * Automatically determines axis title placement\n *\n * Calculates the maximum length of a tick label and adds padding\n */\n\n _placeLabels (spec) {\n try {\n const fields = {};\n const lengths = {};\n const inputs = [];\n // Get all inputs that may be axes\n for (let input in this._definition.dataset.mappings) {\n // check also if property is not inherited from prototype\n if (this._definition.dataset.mappings.hasOwnProperty(input)) {\n const field = this._definition.dataset.mappings[input].field;\n if (field) {\n inputs.push(input);\n fields[input] = field;\n lengths[input] = 0;\n }\n }\n }\n let length = 0;\n\n // find the max length value for each axis\n spec.data[0].values.features.forEach((feature) => {\n inputs.forEach((axis) => {\n length = (feature.attributes[fields[axis]] || '').toString().length;\n if (this.maxLabelLength) {\n // Need to make sure that the gap between title and labels isn't ridiculous\n length = length < (this.maxLabelLength + 1) ? length : this.maxLabelLength;\n }\n if (length > lengths[axis]) {\n lengths[axis] = length;\n }\n });\n });\n\n // Change each axis title offset based on longest value\n inputs.forEach((axis, index) => {\n let angle = 0;\n if (!!spec.axes && !!spec.axes[index]) {\n if (spec.axes[index].properties.labels.angle) {\n angle = spec.axes[index].properties.labels.angle.value;\n }\n if (spec.axes[index].type === 'y') {\n angle = 100 - angle;\n }\n if (this.maxLabelLength) {\n // Set max length of axes titles\n spec.axes[index].properties.labels.text = {'template': `{{ datum.data | truncate:\"${this.maxLabelLength}\"}}`};\n }\n // set title offset\n spec.axes[index].titleOffset = Math.abs(lengths[axis] * angle / 100 * 8) + 35;\n }\n });\n return spec;\n } catch (ex) {\n throw (ex);\n }\n }\n\n /**\n * Automatically determines number of axis tick marks\n *\n * Calculates the maximum length of a tick label and adds padding\n * TODO: remove expectation that there are both x,y axes\n */\n\n _placeaAxisTicks (spec) {\n if (spec.axes) {\n try {\n const width = this.width || parseInt(d3.select(this._elementId).style('width'), 10) || 500;\n const height = this.height || parseInt(d3.select(this._elementId).style('height'), 10) || 500;\n\n spec.axes[0].ticks = width / 100;\n if (spec.axes[1]) {\n spec.axes[1].ticks = height / 30;\n }\n } catch (ex) {\n throw (ex);\n }\n }\n return spec;\n }\n\n /**\n * TOOLTIP LOGIC HERE\n *\n * Instantiates the tooltip element and styling\n * @access private\n */\n _createTooltip (elem) {\n let tooltipDiv = document.getElementById(elem);\n\n // Check if tooltip has been created or not...\n if (tooltipDiv) {\n return tooltipDiv;\n }\n\n // TODO: remove inline CSS\n let style = document.createElement('style');\n style.type = 'text/css';\n style.innerHTML = '.cedar-tooltip {background-color: white; padding: 3px 10px; color: #333; margin: -30px 0 0 20px; position: absolute; z-index: 2000; font-size: 10px; border: 1px solid #BBB;} .cedar-tooltip .title {font-size: 13pt; font-weight: bold; } .cedar-tooltip .content {font-size: 10pt; } ';\n document.getElementsByTagName('head')[0].appendChild(style);\n\n tooltipDiv = document.createElement('div');\n tooltipDiv.className = 'cedar-tooltip';\n tooltipDiv.id = elem;\n tooltipDiv.cssText = 'display: none';\n // We need tooltip at the top of the page\n document.body.insertBefore(tooltipDiv, document.body.firstChild);\n\n this.on('mouseout', (event, data) => {\n this._updateTooltip(event, null);\n });\n this.on('mousemove', (event, data) => {\n this._updateTooltip(event, data);\n });\n return tooltipDiv;\n }\n\n /**\n * Places the tooltipe and fills in content\n *\n * @access private\n */\n _updateTooltip (event, data) {\n let cedartip = document.getElementById(this._definition.tooltip.id);\n if (!data) {\n cedartip.style.display = 'none';\n return;\n }\n cedartip.style.top = `${event.pageY}px`;\n cedartip.style.left = `${event.pageX}px`;\n cedartip.style.display = 'block';\n\n let content = `${this._definition.tooltip.title}${this._definition.tooltip.content}
`;\n\n cedartip.innerHTML = content.replace(/\\{(\\w+)\\}/g, (match, $1) => {\n return data[$1];\n });\n }\n\n /**\n * EVENT LOGIC HERE\n *\n *\n * Add a handler for the named event.\n * Events:\n * - mouseover\n * - mouseout\n * - click\n * - update-start\n * - update-end\n *\n *\n *\n * Callback from Cedar events\n * - callback Cedar~eventCallback\n * - param {Object} event - event response such as mouse location\n * - param {Object} data - chart data object\n *\n * @example\n * var chart = new Cedar({ ... });\n * chart.on('mouseover', function(event, data) {\n * console.log(\"Mouse Location:\", [event.offsetX, event.offsetY]);\n * console.log(\"Data value:\", data[Object.keys(data)[0]]);\n * });\n *\n * @param {String} eventName name of the event that invokes callback\n * @param {Cedar~eventCallback} callback - The callback that handles the event.\n */\n on (evtName, callback) {\n this._events.push({type: evtName, callback});\n }\n /**\n * Remove a hanlder for the named event\n */\n off (evtName, callback) {\n this._events.forEach((registeredEvent, index, object) => {\n if (registeredEvent.type === evtName && registeredEvent.callback === callback) {\n object.splice(index, 1);\n }\n });\n }\n\n /**\n * Trigger a callback\n * @param {string} eventName - [\"mouseover\",\"mouseout\",\"click\",\"update-start\",\"update-end\"]\n */\n emit (eventName) {\n if (!!this._view._handler._handlers[ eventName ] && !!this._view._handler._handlers[ eventName ][0]) {\n this._view._handler._handlers[ eventName ][0].handler();\n }\n }\n\n /**\n * Attach the generic proxy hanlders to the chart view\n * @access private\n */\n _attach (view) {\n view.on('mouseover', this._handler('mouseover'));\n view.on('mouseout', this._handler('mouseout'));\n view.on('mousemove', this._handler('mousemove'));\n view.on('click', this._handler('click'));\n view.on('update-start', this._handler('update-start'));\n view.on('update-end', this._handler('update-end'));\n }\n\n /**\n * Remove all event handlers from the view\n * @access private\n */\n _remove (view) {\n view.off('mouseover');\n view.off('mouseout');\n view.off('mousemove');\n view.off('click');\n view.off('update-start');\n view.off('update-end');\n }\n\n /**\n * Creates an entry in the method queue, executed\n * once a pending xhr is completed\n * @access private\n */\n _addToMethodQueue (name, args) {\n this._methodQueue.push({ method: name, args: args });\n }\n\n /**\n * empties the method queue by calling the queued methods\n * This helps build a more syncronous api, while still\n * doing async things in the code\n * @access private\n */\n _purgeMethodQueue () {\n if (this._methodQueue.length > 0) {\n this._methodQueue.forEach((action, index) => {\n this[action.method].apply(this, action.args);\n });\n }\n }\n\n /**\n * Generic event handler proxy\n * @access private\n */\n _handler (evtName) {\n // return a handler function w/ the events hash closed over\n const handler = (evt, item) => {\n this._events.forEach((registeredHandler) => {\n if (registeredHandler.type === evtName) {\n // invoke the callback with the data\n if (item) {\n registeredHandler.callback(evt, item.datum.attributes);\n } else {\n registeredHandler.callback(evt, null);\n }\n }\n });\n };\n return handler;\n }\n\n /**\n * SELECT LOGIC STARTS HERE\n *\n * Highlight marker based on attribute value\n *\n * @example\n * chart = new Cedar({...});\n * chart.select({key: 'ZIP_CODE', value: '20002'});\n *\n * @param {object} options - Object(key, value) to match. Calls hover on work\n * @returns {Array} items - array of chart objects that match the criteria\n */\n\n select (options) {\n let view = this._view;\n let items = view.model().scene().items[0].items[0].items;\n\n items.forEach((item) => {\n if (item.datum.attributes[options.key] === options.value) {\n if (item.hasPropertySet('hover')) {\n this._view.update({props: 'hover', items: item});\n }\n }\n });\n\n return items;\n }\n\n /**\n * Removes highlighted chart items\n *\n * If \"options\" are used, only clear specific items, otherwise clears all highlights.\n * @param {Object} options - Object(key, value) to match. Calls hover on mark\n * @returns {Array} items - array of chart objects that match the criteria, or null if all items.\n */\n\n clearSelection (options) {\n let view = this._view;\n\n if (!!options && !!options.key) {\n let items = view.model().scene().items[0].items[0].items;\n items.forEach((item) => {\n if (item.datum.attributes[options.key] === options.value) {\n this._view.update({props: 'update', items: item});\n }\n });\n return items;\n } else {\n // clear all\n this._view.update();\n return null;\n }\n }\n\n static getJson (url, callback, timeout) {\n return requestUtils.getJson(url, callback, timeout);\n }\n\n /**\n * Other now exposed utils!\n */\n static _validateMappings (inputs, mappings) {\n return utils.validateMappings(inputs, mappings);\n }\n static _validateData (data, mappings) {\n return utils.validateData(data, mappings);\n }\n static _createFeatureServiceRequest (dataset, queryFromSpec) {\n return requestUtils.createFeatureServiceRequest(dataset, queryFromSpec);\n }\n static _getMappingFieldName (mappingName, fieldName) {\n return utils.getMappingFieldName(mappingName, fieldName);\n }\n // TODO: remove once we have a better way to unit test\n static _convertDatasetsToDataset (datasets, dataset, chartType) {\n return specUtils.convertDatasetsToDataset(datasets, dataset, chartType);\n }\n}\n"],"names":["mixin","source","let","args","i","length","d3.entries","forEach","p","key","value","mergeRecursive","obj1","obj2","hasOwnProperty","constructor","Object","Array","e","supplant","template","params","const","t","replace","a","b","r","getTokenValue","JSON","stringify","tokens","tokenName","tmpTokens","tokenNameParts","split","validateMappings","inputs","mappings","filter","input","required","name","validateData","data","missingInputs","features","isArray","Error","firstRow","attributes","fld","getMappingFieldName","field","push","mappingName","fieldName","defaultDefinition","dataset","query","defaultQuery","where","returnGeometry","returnDistinctValues","returnIdsOnly","returnCountOnly","outFields","sqlFormat","f","applyDefaultsToMappings","errs","join","convertDatasetsToDataset","datasets","series","chartType","this","queries","urls","dtst","url","group","category","x","label","attr","y","size","color","radius","time","trendline","builtDataset","convertQueries","convertUrls","console","warn","serializeQueryParams","str","param","val","encodeURIComponent","queryString","getJson","callback","timeout","cb","err","response","parse","responseText","uri","d3.xhr","on","xhr","ontimeout","onload","header","post","get","createFeatureServiceRequest","queryFromSpec","mergedQuery","bbox","geometry","bboxArr","xmin","ymin","xmax","ymax","inSR","groupByFieldsForStatistics","outStatistics","count","orderByFields","statisticType","onStatisticField","outStatisticFieldName","sort","token","utils","specUtils","requestUtils","baseUrl","src","cdnProtocol","cdnUrl","window","document","currentScript","substr","lastIndexOf","location","protocol","Cedar","options","version","spec","opts","chartTypes","width","undefined","height","autolabels","maxLabelLength","_events","_definition","_view","_tooltip","_transform","_methodQueue","_timeout","_pendingXhr","definition","this$1","_purgeMethodQueue","override","_chartType","type","_getSpecificationUrl","specification","tooltip","title","content","transform","prototypeAccessors","id","Date","now","indexOf","canDraw","drawable","show","clb","_addToMethodQueue","elementId","d3.select","_elementId","_renderer","renderer","_token","chk","issues","update","emit","_remove","_createTooltip","compiledMappings","values","_renderSpec","error","message","details","ex","_placeLabels","_placeaAxisTicks","vg.parse","chartCtor","el","parseInt","style","_attach","fields","lengths","feature","axis","toString","index","angle","axes","properties","labels","text","titleOffset","Math","abs","ticks","elem","tooltipDiv","getElementById","createElement","innerHTML","getElementsByTagName","appendChild","className","cssText","body","insertBefore","firstChild","event","_updateTooltip","cedartip","display","top","left","match","$1","evtName","off","registeredEvent","object","splice","eventName","_handler","_handlers","handler","view","method","action","apply","evt","item","registeredHandler","datum","select","items","model","scene","hasPropertySet","props","clearSelection","_validateMappings","_validateData","_createFeatureServiceRequest","_getMappingFieldName","_convertDatasetsToDataset"],"mappings":"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"} \ No newline at end of file diff --git a/dist/charts/bar-horizontal.json b/dist/charts/bar-horizontal.json new file mode 100644 index 00000000..44ad9cf3 --- /dev/null +++ b/dist/charts/bar-horizontal.json @@ -0,0 +1,119 @@ +{ + "inputs": [ + { "name": "x", "type": [ "numeric", "string" ], "required": true }, + { "name": "y", "type": [ "string" ], "required": true } + ], + "query": { + "orderByFields": "{x.field} DESC", + "groupByFieldsForStatistics": "{y.field}", + "outStatistics": [{ + "statisticType": "sum", + "onStatisticField": "{x.field}", + "outStatisticFieldName": "{x.field}" + }] + }, + "template":{ + "padding": "strict", + "axes": [ + { + "type": "x", + "scale": "x", + "titleOffset": 45, + "title": "{x.label}", + "tickPadding": 10, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": 0}, + "baseline": {"value": "middle"} + } + } + }, + { + "type": "y", + "scale": "y", + "titleOffset": 25, + "title": "{y.label}", + "padding": 0.25, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": 0}, + "baseline": {"value": "middle"} + } + } + } + ], + "data": [ + { + "name": "table", + "format": {"property": "features"} + } + ], + "marks": [ + { + "from": {"data": "table"}, + "properties": { + "enter": { + "height": {"band": true, "offset": -1, "scale": "y"}, + "y": {"scale": "y", "field": "attributes.{y.field}"}, + "x2": {"scale": "x", "field": "attributes.{x.field}"}, + "x": {"scale": "x", "value": 0 } + }, + "hover": { + "fill": {"value": "#29b6ea"} + }, + "update": { + "fill": {"value": "#0079c1"} + } + }, + "type": "rect" + } + ], + "scales": [ + { + "domain": { + "data": "table", + "field": "attributes.{y.field}" + }, + "name": "y", + "range": "height", + "type": "ordinal", + "padding": 0.25 + }, + { + "domain": { + "data": "table", + "field": "attributes.{x.field}" + }, + "name": "x", + "nice": true, + "range": "width" + } + ] + } +} \ No newline at end of file diff --git a/dist/charts/bar.json b/dist/charts/bar.json new file mode 100644 index 00000000..e977dcd2 --- /dev/null +++ b/dist/charts/bar.json @@ -0,0 +1,108 @@ +{ + "inputs": [ + { "name": "x", "type": [ "string" ], "required": true }, + { "name": "y", "type": [ "numeric" ], "required": true } + ], + "query": {}, + "template":{ + "padding": "strict", + "axes": [ + { + "type": "x", + "scale": "x", + "titleOffset": 45, + "title": "{x.label}", + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": -50}, + "align": {"value": "right"}, + "baseline": {"value": "middle"} + } + } + }, + { + "type": "y", + "scale": "y", + "titleOffset": 45, + "title": "{y.label}", + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"} + } + } + } + ], + "data": [ + { + "name": "table", + "format": {"property": "features"} + } + ], + "marks": [ + { + "from": {"data": "table"}, + "properties": { + "enter": { + }, + "update": { + "width": {"band": true, "offset": -1, "scale": "x"}, + "x": {"field": "attributes.{x.field}", "scale": "x"}, + "y": {"field": "attributes.{y.field}", "scale": "y"}, + "y2": {"scale": "y", "value": 0 }, + "fill": {"value": "#0079c1"} + }, + "hover": { + "fill": {"value": "#29b6ea"} + } + }, + "type": "rect" + } + ], + "scales": [ + { + "domain": { + "data": "table", + "field": "attributes.{x.field}" + }, + "name": "x", + "range": "width", + "type": "ordinal", + "padding": 0.25 + }, + { + "domain": { + "data": "table", + "field": "attributes.{y.field}" + }, + "name": "y", + "nice": true, + "range": "height" + } + ] + } +} \ No newline at end of file diff --git a/dist/charts/bubble.json b/dist/charts/bubble.json new file mode 100644 index 00000000..f799086d --- /dev/null +++ b/dist/charts/bubble.json @@ -0,0 +1,161 @@ +{ + "inputs": [ + {"name":"x","type":["numeric"], "required":true}, + {"name":"y","type":["numeric"], "required":true}, + {"name":"size","type":["numeric"], "default": 100, "required":false} + ], + "template":{ + "padding": "strict", + "data": [ + { + "name": "table", + "format": { + "property": "features" + } + } + ], + "scales": [ + { + "name": "x", + "nice": true, + "range": "width", + "domain": { + "data": "table", + "field": "attributes.{x.field}" + } + }, + { + "name": "y", + "nice": true, + "range": "height", + "domain": { + "data": "table", + "field": "attributes.{y.field}" + } + }, + { + "name": "size", + "type": "sqrt", + "domain": { + "data": "table", + "field": "attributes.{size.field}" + }, + "range": [0,2000] + } + ], + "axes": [ + { + "type": "x", + "scale": "x", + "offset": 5, + "ticks": 5, + "title": "{x.label}", + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": 0}, + "fontSize": {"value": 14}, + "align": {"value": "left"}, + "baseline": {"value": "middle"}, + "dx": {"value": 3} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + } + } + }, + { + "type": "y", + "scale": "y", + "offset": 5, + "ticks": 5, + "title": "{y.label}", + "titleOffset": 50, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": 0}, + "fontSize": {"value": 14}, + "align": {"value": "right"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + } + } + } + ], + "legends": [ + { + "title": "{size.label}", + "offset": 0, + "size": "size", + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "bold"} + }, + "symbols": { + "strokeWidth": {"value": 2}, + "stroke": {"value": "#0079c1"}, + "fill": { "value": "#fff" }, + "fillOpacity": {"value": 0.4 } + } + } + } + ], + "marks": [ + { + "type": "symbol", + "from": { + "data": "table" + }, + "properties": { + "enter": { + "x": { + "scale": "x", + "field": "attributes.{x.field}" + }, + "y": { + "scale": "y", + "field": "attributes.{y.field}" + }, + "strokeWidth": {"value": 2}, + "fillOpacity": {"value": 0.4 }, + "size": { + "scale": "size", + "field": "attributes.{size.field}" + } + }, + "update": { + "fill": { "value": "#fff" }, + "stroke": {"value": "#0079c1"} + }, + "hover": { + "fill": {"value": "#0079c1"}, + "fillOpacity": {"value": 0.6 }, + "stroke": {"value": "#0079c1"} + } + } + } + ] + } +} \ No newline at end of file diff --git a/dist/charts/grouped.json b/dist/charts/grouped.json new file mode 100644 index 00000000..4b37059f --- /dev/null +++ b/dist/charts/grouped.json @@ -0,0 +1,232 @@ +{ + "inputs": [ + { + "name": "x", + "required": true, + "type": [ + "numeric", + "string" + ] + }, + { + "name": "group", + "required": true, + "type": [ + "string" + ] + } + ], + "query": {}, + "template": { + "axes": [ + { + "properties": { + "axis": { + "stroke": { + "value": "#dbdad9" + }, + "strokeWidth": { + "value": 1.5 + } + }, + "labels": { + "align": { + "value": "right" + }, + "angle": { + "value": -50 + }, + "baseline": { + "value": "middle" + }, + "fill": { + "value": "#999" + } + }, + "ticks": { + "stroke": { + "value": "#dbdad9" + } + }, + "title": { + "fill": { + "value": "#999" + }, + "fontSize": { + "value": 15 + }, + "fontWeight": { + "value": "normal" + } + } + }, + "scale": "cat", + "tickPadding": 8, + "tickSize": 0, + "type": "x" + }, + { + "grid": true, + "layer": "back", + "properties": { + "axis": { + "stroke": { + "value": "#dbdad9" + }, + "strokeWidth": { + "value": 1.5 + } + }, + "labels": { + "fill": { + "value": "#999" + } + }, + "ticks": { + "stroke": { + "value": "#dbdad9" + } + }, + "title": { + "fill": { + "value": "#999" + }, + "fontSize": { + "value": 15 + }, + "fontWeight": { + "value": "normal" + } + } + }, + "scale": "val", + "type": "y" + } + ], + "data": [ + { + "format": { + "property": "features" + }, + "name": "table", + "transform": [ + { + "fields": "{x.field}", + "output": { + "key": "group", + "value": "count" + }, + "type": "fold" + } + ] + } + ], + "legends": [ + { + "fill": "color", + "title": "{x.label}" + } + ], + "marks": [ + { + "from": { + "data": "table", + "transform": [ + { + "groupby": [ + "attributes.{group.field}" + ], + "type": "facet" + } + ] + }, + "marks": [ + { + "name": "bars", + "properties": { + "enter": { + "fill": { + "field": "group", + "scale": "color" + }, + "width": { + "band": true, + "scale": "pos" + }, + "x": { + "field": "group", + "scale": "pos" + }, + "y": { + "field": "count", + "scale": "val" + }, + "y2": { + "scale": "val", + "value": 0 + } + } + }, + "type": "rect" + } + ], + "properties": { + "enter": { + "height": { + "band": true, + "scale": "cat" + }, + "x": { + "field": "key", + "scale": "cat" + } + } + }, + "scales": [ + { + "domain": { + "field": "group" + }, + "name": "pos", + "range": "height", + "type": "ordinal" + } + ], + "type": "group" + } + ], + "padding": "strict", + "scales": [ + { + "domain": { + "data": "table", + "field": "attributes.{group.field}" + }, + "name": "cat", + "padding": 0.2, + "range": "width", + "type": "ordinal" + }, + { + "domain": { + "data": "table", + "field": "count" + }, + "name": "val", + "nice": true, + "range": "height", + "round": true, + "type": "linear" + }, + { + "domain": { + "data": "table", + "field": "group" + }, + "name": "color", + "range": "category20", + "type": "ordinal" + } + ] + } +} diff --git a/dist/charts/pie.json b/dist/charts/pie.json new file mode 100644 index 00000000..52ae782c --- /dev/null +++ b/dist/charts/pie.json @@ -0,0 +1,80 @@ +{ + "inputs": [ + {"name": "y", "type": ["numeric","string"], "required": true}, + {"name": "label", "type": ["string"], "required": false}, + {"name": "radius", "type": ["numeric"], "default": 200, "required": false} + ], + "template":{ + "padding": "strict", + "data": [ + { + "name": "table", + "format": { + "property": "features" + }, + "transform": [ + {"type": "pie", "field": "attributes.{y.field}"}, + {"type": "formula", "field": "hyp", "expr": "{radius}"}, + {"type": "formula", "field": "theta", "expr": "datum.layout_start + 0.5 *(datum.layout_end - datum.layout_start) - 1.57079633"}, + {"type": "formula", "field": "x", "expr": "datum.hyp * cos(datum.theta)"}, + {"type": "formula", "field": "y", "expr": "datum.hyp * sin(datum.theta)"} + ] + } + ], + "scales": [ + { + "name": "r", + "type": "sqrt", + "domain": {"data": "table", "field": "attributes.{y.field}"} + }, + { + "name": "color", + "type": "ordinal", + "domain": { + "data": "table", + "field": "attributes.{label.field}" + }, + "range": "category10" + } + ], + "marks": [ + { + "type": "arc", + "from": {"data": "table"}, + "properties": { + "enter": { + "x": {"group": "width"}, + "y": {"group": "height"}, + "startAngle": {"field": "layout_start"}, + "endAngle": {"field": "layout_end"}, + "outerRadius": {"value": "{radius}"}, + "stroke": {"value": "#fff"} + }, + "update": { + "fill": {"scale": "color", "field": "attributes.{label.field}"}, + "fillOpacity": {"value": 1} + }, + "hover": { + "fillOpacity": {"value": 0.8} + } + } + }, + { + "type": "text", + "from": {"data": "table"}, + "properties": { + "enter": { + "fill": {"value": "#fff"}, + "y": {"field": "y", "mult": 0.6}, + "x": {"field": "x", "mult": 0.6}, + "fill": {"value": "#fff"}, + "align": {"value": "center"}, + "baseline": {"value": "middle"}, + "text": {"field": "attributes.{label.field}"} + } + } + } + ] + } + +} \ No newline at end of file diff --git a/dist/charts/scatter.json b/dist/charts/scatter.json new file mode 100644 index 00000000..9942207c --- /dev/null +++ b/dist/charts/scatter.json @@ -0,0 +1,165 @@ +{ + "inputs":[ + {"name":"x","type":["numeric"], "required":true}, + {"name":"y","type":["numeric"], "required":true}, + {"name":"color","type":["string"], "default": "#0079c1", "required":false} + ], + "template":{ + "padding": "strict", + "data": [ + { + "name": "table", + "format": { + "property": "features" + } + } + ], + "scales": [ + { + "name": "x", + "nice": true, + "range": "width", + "domain": { + "data": "table", + "field": "attributes.{x.field}" + } + }, + { + "name": "y", + "nice": true, + "range": "height", + "domain": { + "data": "table", + "field": "attributes.{y.field}" + } + }, + { + "name": "c", + "type": "ordinal", + "domain": { + "data": "table", + "field": "attributes.{color.field}" + }, + "range": "category10" + } + ], + "axes": [ + { + "type": "x", + "scale": "x", + "title": "{x.label}", + "tickPadding": 10, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": 0}, + "fontSize": {"value": 14}, + "align": {"value": "center"}, + "baseline": {"value": "middle"} + } + } + }, + { + "type": "y", + "scale": "y", + "offset": 5, + "ticks": 5, + "title": "{y.label}", + "titleOffset": 50, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "angle": {"value": 0}, + "fontSize": {"value": 14}, + "align": {"value": "right"} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1.5} + } + } + } + ], + "legends": [ + { + "fill": "c", + "title": "{color.label} ", + "offset": 0, + "properties": { + "symbols": { + "fillOpacity": { + "value": 0.5 + }, + "stroke": { + "value": "transparent" + } + } + } + } + ], + "marks": [ + { + "type": "symbol", + "from": { + "data": "table" + }, + "properties": { + "enter": { + "x": { + "scale": "x", + "field": "attributes.{x.field}" + }, + "y": { + "scale": "y", + "field": "attributes.{y.field}" + }, + "fill": { + "scale": "c", + "field": "attributes.{color.field}" + }, + "fillOpacity": { + "value": 0.5 + } + }, + "update": { + "size": { + "value": 100 + }, + "stroke": { + "value": "transparent" + } + }, + "hover": { + "size": { + "value": 300 + }, + "stroke": { + "value": "white" + } + } + } + } + ] + } + +} \ No newline at end of file diff --git a/dist/charts/sparkline.json b/dist/charts/sparkline.json new file mode 100644 index 00000000..cda11e2c --- /dev/null +++ b/dist/charts/sparkline.json @@ -0,0 +1,41 @@ +{ + "inputs": [ + { "name": "x", "type": [ "datetime" ], "required": true }, + { "name": "y", "type": [ "number" ], "required": true } + ], + "template":{ + "data": [{ + "name": "table", + "format": {"type": "json", "parse": {"attributes.{x.field}":"date"}} + }], + "padding": {"top": 0, "left": 0, "bottom": 0, "right": 0}, + "scales": [ + { + "name": "x", + "type": "time", + "range": "width", + "zero": false, + "domain": {"data": "table", "field": "attributes.{x.field}"} + }, + { + "name": "y", + "type": "linear", + "range": "height", + "zero": false, + "domain": {"data": "table", "field": "attributes.{y.field}"} + } + ], + "marks": [{ + "type": "line", + "from": {"data": "table"}, + "properties": { + "enter": { + "x": {"scale": "x", "field": "attributes.{x.field}"}, + "y": {"scale": "y", "field": "attributes.{y.field}"}, + "stroke": {"value": "#f00"}, + "strokeWidth": {"value": 1} + } + } + }] + } +} \ No newline at end of file diff --git a/dist/charts/time-trendline.json b/dist/charts/time-trendline.json new file mode 100644 index 00000000..2f67b981 --- /dev/null +++ b/dist/charts/time-trendline.json @@ -0,0 +1,116 @@ +{ + "inputs":[ + {"name":"time","type":["time"], "required":true}, + {"name":"value","type":["numeric"], "required":true}, + {"name":"trendline","type":["numeric"], "required":true} + ], + "template":{ + "padding": "strict", + "data": [ + { + "name": "table", + "url":"{data}&orderByFields={time.field}", + "format": {"type": "json", "property": "features", "parse": {"attributes.{time.field}":"date"}} + }, + { + "name": "exports", + "source": "table", + "transform": [ + {"type": "formula", "field": "export", "expr": "datum"} + ] + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "range": "width", + "nice": "month", + "zero": false, + "domain": {"data": "table", "field": "attributes.{time.field}"} + }, + { + "name": "y", + "type": "linear", + "range": "height", + "nice": true, + "domain": {"data": "table", "field": "attributes.{value.field}"} + } + ], + "axes": [ + { + "type": "x", + "scale": "x", + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "strokeWidth" : {"value" :0} + }, + "labels": { + "fill": {"value": "#999"}, + "fontSize": {"value": 13} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 0} + } + } + }, + { + "type": "y", + "scale": "y", + "ticks": 5, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "strokeWidth" : {"value" :0} + }, + "labels": { + "fill": {"value": "#999"}, + "fontSize": {"value": 13} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 0} + } + } + } + ], + "marks": [ + { + "type": "line", + "from": {"data": "table"}, + "properties": { + "enter": { + "x": {"scale": "x", "field": "attributes.{time.field}"}, + "y": {"scale": "y", "field": "attributes.{value.field}"}, + "stroke": {"value": "#0079c1"}, + "strokeWidth" : { "value" : 3} + } + } + }, + { + "type": "line", + "from": {"data": "table"}, + "properties": { + "enter": { + "x": {"scale": "x", "field": "attributes.{time.field}"}, + "y": {"scale": "y", "field": "attributes.{trendline.field}"}, + "stroke": {"value": "#000000"}, + "strokeWidth" : { "value" : 3}, + "strokeDash" : { "value" : [7, 2]} + } + } + } + + ] + } +} \ No newline at end of file diff --git a/dist/charts/time.json b/dist/charts/time.json new file mode 100644 index 00000000..818e7f5b --- /dev/null +++ b/dist/charts/time.json @@ -0,0 +1,122 @@ +{ + "inputs":[ + {"name":"time","type":["time"], "required":true}, + {"name":"value","type":["numeric"], "required":true} + ], + "template":{ + "padding": "strict", + "data": [ + { + "name": "table", + "url":"{data}&orderByFields={time.field}", + "format": {"type": "json", "property": "features", "parse": {"attributes.{time.field}":"date"}} + }, + { + "name": "exports", + "source": "table", + "transform": [ + {"type": "formula", "field": "export", "expr": "datum"} + ] + } + ], + "scales": [ + { + "name": "x", + "type": "time", + "range": "width", + "zero": false, + "domain": {"data": "table", "field": "attributes.{time.field}"} + }, + { + "name": "y", + "type": "linear", + "range": "height", + "nice": true, + "domain": {"data": "table", "field": "attributes.{value.field}"} + } + ], + "axes": [ + { + "type": "x", + "scale": "x", + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "fontSize": {"value": 13} + }, + "axis": { + "stroke": {"value": "#dbdad9"}, + "strokeWidth": {"value": 1} + } + } + }, + { + "type": "y", + "scale": "y", + "ticks": 5, + "properties": { + "title": { + "fontSize": {"value": 15}, + "fill": {"value": "#999"}, + "fontWeight": {"value": "normal"} + }, + "ticks": { + "stroke": {"value": "#dbdad9"} + }, + "labels": { + "fill": {"value": "#999"}, + "fontSize": {"value": 13} + }, + "axis": { + "stroke": {"value": "#dbdad9"} + } + } + } + ], + "marks": [ + { + "type": "symbol", + "from": {"data": "table"}, + "properties": { + "enter": { + "x": {"scale": "x", "field": "attributes.{time.field}"}, + "y": {"scale": "y", "field": "attributes.{value.field}"}, + "stroke": {"value": "#0079c1"}, + "fill": {"value": "#0079c1"}, + "size": {"value": 20}, + "fillOpacity": { + "value": 0.8 + }, + "hover": { + "fill": {"value": "#0079c1"}, + "size": {"value": 25} + }, + "update": { + "fill": {"value": "#f00"} + } + } + } + }, + { + "type": "line", + "from": {"data": "table"}, + "properties": { + "enter": { + "x": {"scale": "x", "field": "attributes.{time.field}"}, + "y": {"scale": "y", "field": "attributes.{value.field}"}, + "y2": {"scale": "y", "value": 0}, + "stroke": {"value": "#0079c1"} + } + } + } + ] + } +} \ No newline at end of file