diff --git a/plottable.d.ts b/plottable.d.ts
index e3f5b97028..9da3cc0cd4 100644
--- a/plottable.d.ts
+++ b/plottable.d.ts
@@ -197,6 +197,7 @@ declare module Plottable {
class Scale implements IBroadcaster {
/**
* Creates a new Scale.
+ *
* @constructor
* @param {D3.Scale.Scale} scale The D3 scale backing the Scale.
*/
@@ -210,6 +211,7 @@ declare module Plottable {
public scale(value: any): any;
/**
* Retrieves the current domain, or sets the Scale's domain to the specified values.
+ *
* @param {any[]} [values] The new value for the domain.
* @returns {any[]|Scale} The current domain, or the calling Scale (if values is supplied).
*/
@@ -217,6 +219,7 @@ declare module Plottable {
public domain(values: any[]): Scale;
/**
* Retrieves the current range, or sets the Scale's range to the specified values.
+ *
* @param {any[]} [values] The new value for the range.
* @returns {any[]|Scale} The current range, or the calling Scale (if values is supplied).
*/
@@ -224,43 +227,68 @@ declare module Plottable {
public range(values: any[]): Scale;
/**
* Creates a copy of the Scale with the same domain and range but without any registered listeners.
+ *
* @returns {Scale} A copy of the calling Scale.
*/
public copy(): Scale;
/**
* Registers a callback to be called when the scale's domain is changed.
+ *
* @param {IBroadcasterCallback} callback A callback to be called when the Scale's domain changes.
* @returns {Scale} The Calling Scale.
*/
public registerListener(callback: IBroadcasterCallback): Scale;
}
+ class OrdinalScale extends Scale {
+ /**
+ * Creates a new OrdinalScale. Domain and Range are set later.
+ *
+ * @constructor
+ */
+ constructor();
+ public domain(): any[];
+ public domain(values: any[]): Scale;
+ /**
+ * Returns the range of pixels spanned by the scale, or sets the range.
+ *
+ * @param {number[]} [values] The pixel range to set on the scale.
+ * @returns {number[]|OrdinalScale} The pixel range, or the calling OrdinalScale.
+ */
+ public range(): any[];
+ public range(values: number[]): Scale;
+ }
class QuantitiveScale extends Scale {
/**
* Creates a new QuantitiveScale.
+ *
* @constructor
* @param {D3.Scale.QuantitiveScale} scale The D3 QuantitiveScale backing the QuantitiveScale.
*/
constructor(scale: D3.Scale.QuantitiveScale);
/**
* Retrieves the domain value corresponding to a supplied range value.
+ *
* @param {number} value: A value from the Scale's range.
* @returns {number} The domain value corresponding to the supplied range value.
*/
public invert(value: number): number;
/**
* Creates a copy of the QuantitiveScale with the same domain and range but without any registered listeners.
+ *
* @returns {QuantitiveScale} A copy of the calling QuantitiveScale.
*/
public copy(): QuantitiveScale;
/**
* Expands the QuantitiveScale's domain to cover the new region.
- * @param {number} newDomain The additional domain to be covered by the QuantitiveScale.
+ *
+ * @param {number[]} newDomain The additional domain to be covered by the QuantitiveScale.
* @returns {QuantitiveScale} The scale.
*/
public widenDomain(newDomain: number[]): QuantitiveScale;
/**
* Expands the QuantitiveScale's domain to cover the data given.
* Passes an accessor through to the native d3 code.
+ *
* @param data The data to operate on.
* @param [accessor] The accessor to get values out of the data
* @returns {QuantitiveScale} The scale.
@@ -296,6 +324,7 @@ declare module Plottable {
public nice(count?: number): QuantitiveScale;
/**
* Generates tick values.
+ *
* @param {number} [count] The number of ticks to generate.
* @returns {any[]} The generated ticks.
*/
@@ -319,6 +348,7 @@ declare module Plottable {
class LinearScale extends QuantitiveScale {
/**
* Creates a new LinearScale.
+ *
* @constructor
* @param {D3.Scale.LinearScale} [scale] The D3 LinearScale backing the LinearScale. If not supplied, uses a default scale.
*/
@@ -326,6 +356,7 @@ declare module Plottable {
constructor(scale: D3.Scale.LinearScale);
/**
* Creates a copy of the LinearScale with the same domain and range but without any registered listeners.
+ *
* @returns {LinearScale} A copy of the calling LinearScale.
*/
public copy(): LinearScale;
@@ -333,6 +364,7 @@ declare module Plottable {
class ColorScale extends Scale {
/**
* Creates a ColorScale.
+ *
* @constructor
* @param {string} [scaleType] the type of color scale to create (Category10/Category20/Category20b/Category20c)
*/
@@ -477,6 +509,27 @@ declare module Plottable {
public metadata(metadata: IMetadata): Renderer;
public data(data: any[]): Renderer;
public colorAccessor(a: IAccessor): Renderer;
+ public autorange(): Renderer;
+ }
+}
+declare module Plottable {
+ class CategoryRenderer extends Renderer {
+ public dataSelection: D3.UpdateSelection;
+ public xScale: OrdinalScale;
+ public yScale: QuantitiveScale;
+ public autorangeDataOnLayout: boolean;
+ /**
+ * Creates a CategoryRenderer with an Ordinal x scale and Quantitive y scale.
+ *
+ * @constructor
+ * @param {IDataset} dataset The dataset to render.
+ * @param {OrdinalScale} xScale The x scale to use.
+ * @param {QuantitiveScale} yScale The y scale to use.
+ * @param {IAccessor} [xAccessor] A function for extracting x values from the data.
+ * @param {IAccessor} [yAccessor] A function for extracting y values from the data.
+ */
+ constructor(dataset: IDataset, xScale: OrdinalScale, yScale: QuantitiveScale, xAccessor?: IAccessor, yAccessor?: IAccessor);
+ public autorange(): CategoryRenderer;
}
}
declare module Plottable {
@@ -484,8 +537,7 @@ declare module Plottable {
public dataSelection: D3.UpdateSelection;
public xScale: QuantitiveScale;
public yScale: QuantitiveScale;
- public xAccessor: IAccessor;
- public yAccessor: IAccessor;
+ public autorangeDataOnLayout: boolean;
/**
* Creates an XYRenderer.
*
@@ -497,6 +549,9 @@ declare module Plottable {
* @param {IAccessor} [yAccessor] A function for extracting y values from the data.
*/
constructor(dataset: IDataset, xScale: QuantitiveScale, yScale: QuantitiveScale, xAccessor?: IAccessor, yAccessor?: IAccessor);
+ public xAccessor(accessor: any): XYRenderer;
+ public yAccessor(accessor: any): XYRenderer;
+ public autorange(): XYRenderer;
/**
* Converts a SelectionArea with pixel ranges to one with data ranges.
*
@@ -533,7 +588,8 @@ declare module Plottable {
* @param {IAccessor} [yAccessor] A function for extracting y values from the data.
* @param {IAccessor} [rAccessor] A function for extracting radius values from the data.
*/
- constructor(dataset: IDataset, xScale: QuantitiveScale, yScale: QuantitiveScale, xAccessor?: IAccessor, yAccessor?: IAccessor, rAccessor?: IAccessor);
+ constructor(dataset: IDataset, xScale: QuantitiveScale, yScale: QuantitiveScale, xAccessor?: any, yAccessor?: any, rAccessor?: any);
+ public rAccessor(a: any): CircleRenderer;
}
}
declare module Plottable {
@@ -554,7 +610,7 @@ declare module Plottable {
declare module Plottable {
class BarRenderer extends XYRenderer {
public barPaddingPx: number;
- public dxAccessor: IAccessor;
+ public dxAccessor: any;
/**
* Creates a BarRenderer.
*
@@ -567,6 +623,7 @@ declare module Plottable {
* @param {IAccessor} [yAccessor] A function for extracting height of each bar from the data.
*/
constructor(dataset: IDataset, xScale: QuantitiveScale, yScale: QuantitiveScale, xAccessor?: IAccessor, dxAccessor?: IAccessor, yAccessor?: IAccessor);
+ public autorange(): BarRenderer;
}
}
declare module Plottable {
@@ -583,6 +640,7 @@ declare module Plottable {
* @param {IAccessor} [rAccessor] A function for extracting radius values from the data.
*/
constructor(dataset: IDataset, xScale: QuantitiveScale, yScale: QuantitiveScale, xAccessor?: IAccessor, yAccessor?: IAccessor, rAccessor?: IAccessor);
+ public rAccessor(a: any): SquareRenderer;
}
}
declare module Plottable {
@@ -669,6 +727,48 @@ declare module Plottable {
public rowMinimum(newVal: number): Legend;
}
}
+declare module Plottable {
+ class StandardChart extends Table {
+ constructor();
+ public yAxis(y: YAxis): StandardChart;
+ public yAxis(): YAxis;
+ public xAxis(x: XAxis): StandardChart;
+ public xAxis(): XAxis;
+ public yLabel(y: AxisLabel): StandardChart;
+ public yLabel(y: string): StandardChart;
+ public yLabel(): AxisLabel;
+ public xLabel(x: AxisLabel): StandardChart;
+ public xLabel(x: string): StandardChart;
+ public xLabel(): AxisLabel;
+ public titleLabel(x: TitleLabel): StandardChart;
+ public titleLabel(x: string): StandardChart;
+ public titleLabel(): TitleLabel;
+ public addCenterComponent(c: Component): StandardChart;
+ }
+}
+declare module Plottable {
+ class CategoryBarRenderer extends CategoryRenderer {
+ /**
+ * Creates a CategoryBarRenderer.
+ *
+ * @constructor
+ * @param {IDataset} dataset The dataset to render.
+ * @param {OrdinalScale} xScale The x scale to use.
+ * @param {QuantitiveScale} yScale The y scale to use.
+ * @param {IAccessor} [xAccessor] A function for extracting the start position of each bar from the data.
+ * @param {IAccessor} [widthAccessor] A function for extracting the width position of each bar, in pixels, from the data.
+ * @param {IAccessor} [yAccessor] A function for extracting height of each bar from the data.
+ */
+ constructor(dataset: IDataset, xScale: OrdinalScale, yScale: QuantitiveScale, xAccessor?: IAccessor, widthAccessor?: IAccessor, yAccessor?: IAccessor);
+ /**
+ * Sets the width accessor.
+ *
+ * @param {any} accessor The new width accessor.
+ * @returns {CategoryBarRenderer} The calling CategoryBarRenderer.
+ */
+ public widthAccessor(accessor: any): CategoryBarRenderer;
+ }
+}
declare module Plottable {
class Axis extends Component {
static yWidth: number;
diff --git a/plottable.js b/plottable.js
index 213b0f2206..61e681f706 100644
--- a/plottable.js
+++ b/plottable.js
@@ -1,5 +1,5 @@
/*!
-Plottable v0.5.1 (https://github.com/palantir/plottable)
+Plottable v0.7.0 (https://github.com/palantir/plottable)
Copyright 2014 Palantir Technologies
Licensed under MIT (https://github.com/palantir/plottable/blob/master/LICENSE)
*/
@@ -480,11 +480,12 @@ var Plottable;
var Scale = (function () {
/**
* Creates a new Scale.
+ *
* @constructor
* @param {D3.Scale.Scale} scale The D3 scale backing the Scale.
*/
function Scale(scale) {
- this.broadcasterCallbacks = [];
+ this._broadcasterCallbacks = [];
this._d3Scale = scale;
}
/**
@@ -503,7 +504,7 @@ var Plottable;
return this._d3Scale.domain();
} else {
this._d3Scale.domain(values);
- this.broadcasterCallbacks.forEach(function (b) {
+ this._broadcasterCallbacks.forEach(function (b) {
return b(_this);
});
return this;
@@ -521,6 +522,7 @@ var Plottable;
/**
* Creates a copy of the Scale with the same domain and range but without any registered listeners.
+ *
* @returns {Scale} A copy of the calling Scale.
*/
Scale.prototype.copy = function () {
@@ -529,21 +531,62 @@ var Plottable;
/**
* Registers a callback to be called when the scale's domain is changed.
+ *
* @param {IBroadcasterCallback} callback A callback to be called when the Scale's domain changes.
* @returns {Scale} The Calling Scale.
*/
Scale.prototype.registerListener = function (callback) {
- this.broadcasterCallbacks.push(callback);
+ this._broadcasterCallbacks.push(callback);
return this;
};
return Scale;
})();
Plottable.Scale = Scale;
+ var OrdinalScale = (function (_super) {
+ __extends(OrdinalScale, _super);
+ /**
+ * Creates a new OrdinalScale. Domain and Range are set later.
+ *
+ * @constructor
+ */
+ function OrdinalScale() {
+ _super.call(this, d3.scale.ordinal());
+ this.END_PADDING = 0.5;
+ this._range = [0, 1];
+ }
+ OrdinalScale.prototype.domain = function (values) {
+ var _this = this;
+ if (values == null) {
+ return this._d3Scale.domain();
+ } else {
+ this._d3Scale.domain(values);
+ this._broadcasterCallbacks.forEach(function (b) {
+ return b(_this);
+ });
+ this._d3Scale.rangePoints(this.range(), 2 * this.END_PADDING); // d3 scale takes total padding
+ return this;
+ }
+ };
+
+ OrdinalScale.prototype.range = function (values) {
+ if (values == null) {
+ return this._range;
+ } else {
+ this._range = values;
+ this._d3Scale.rangePoints(values, 2 * this.END_PADDING); // d3 scale takes total padding
+ return this;
+ }
+ };
+ return OrdinalScale;
+ })(Scale);
+ Plottable.OrdinalScale = OrdinalScale;
+
var QuantitiveScale = (function (_super) {
__extends(QuantitiveScale, _super);
/**
* Creates a new QuantitiveScale.
+ *
* @constructor
* @param {D3.Scale.QuantitiveScale} scale The D3 QuantitiveScale backing the QuantitiveScale.
*/
@@ -553,6 +596,7 @@ var Plottable;
}
/**
* Retrieves the domain value corresponding to a supplied range value.
+ *
* @param {number} value: A value from the Scale's range.
* @returns {number} The domain value corresponding to the supplied range value.
*/
@@ -562,6 +606,7 @@ var Plottable;
/**
* Creates a copy of the QuantitiveScale with the same domain and range but without any registered listeners.
+ *
* @returns {QuantitiveScale} A copy of the calling QuantitiveScale.
*/
QuantitiveScale.prototype.copy = function () {
@@ -570,7 +615,8 @@ var Plottable;
/**
* Expands the QuantitiveScale's domain to cover the new region.
- * @param {number} newDomain The additional domain to be covered by the QuantitiveScale.
+ *
+ * @param {number[]} newDomain The additional domain to be covered by the QuantitiveScale.
* @returns {QuantitiveScale} The scale.
*/
QuantitiveScale.prototype.widenDomain = function (newDomain) {
@@ -583,6 +629,7 @@ var Plottable;
/**
* Expands the QuantitiveScale's domain to cover the data given.
* Passes an accessor through to the native d3 code.
+ *
* @param data The data to operate on.
* @param [accessor] The accessor to get values out of the data
* @returns {QuantitiveScale} The scale.
@@ -632,6 +679,7 @@ var Plottable;
/**
* Generates tick values.
+ *
* @param {number} [count] The number of ticks to generate.
* @returns {any[]} The generated ticks.
*/
@@ -679,6 +727,7 @@ var Plottable;
}
/**
* Creates a copy of the LinearScale with the same domain and range but without any registered listeners.
+ *
* @returns {LinearScale} A copy of the calling LinearScale.
*/
LinearScale.prototype.copy = function () {
@@ -692,6 +741,7 @@ var Plottable;
__extends(ColorScale, _super);
/**
* Creates a ColorScale.
+ *
* @constructor
* @param {string} [scaleType] the type of color scale to create (Category10/Category20/Category20b/Category20c)
*/
@@ -1021,12 +1071,14 @@ var Plottable;
this.lasty = y;
var domainX = this.renderer.xScale.invert(x);
var data = this.renderer._data;
- var dataIndex = Plottable.OSUtils.sortedIndex(domainX, data, this.renderer.xAccessor);
+ var xA = this.renderer._getAppliedAccessor(this.renderer._xAccessor);
+ var yA = this.renderer._getAppliedAccessor(this.renderer._yAccessor);
+ var dataIndex = Plottable.OSUtils.sortedIndex(domainX, data, xA);
dataIndex = dataIndex > 0 ? dataIndex - 1 : 0;
var dataPoint = data[dataIndex];
- var dataX = this.renderer.xAccessor(dataPoint);
- var dataY = this.renderer.yAccessor(dataPoint);
+ var dataX = xA(dataPoint, dataIndex);
+ var dataY = yA(dataPoint, dataIndex);
var pixelX = this.renderer.xScale.scale(dataX);
var pixelY = this.renderer.yScale.scale(dataY);
this.circle.attr("cx", pixelX).attr("cy", pixelY);
@@ -1251,11 +1303,33 @@ var Plottable;
// no-op
};
+ Renderer.prototype.autorange = function () {
+ // no-op
+ return this;
+ };
+
Renderer.prototype._anchor = function (element) {
_super.prototype._anchor.call(this, element);
this.renderArea = this.content.append("g").classed("render-area", true);
return this;
};
+
+ Renderer.prototype._getAppliedAccessor = function (accessor) {
+ var _this = this;
+ if (typeof (accessor) === "function") {
+ return function (d, i) {
+ return accessor(d, i, _this._metadata);
+ };
+ } else if (typeof (accessor) === "string") {
+ return function (d, i) {
+ return d[accessor];
+ };
+ } else {
+ return function (d, i) {
+ return accessor;
+ };
+ }
+ };
Renderer.defaultColorAccessor = function (d) {
return "#1f77b4";
};
@@ -1266,42 +1340,99 @@ var Plottable;
///
var Plottable;
(function (Plottable) {
- var XYRenderer = (function (_super) {
- __extends(XYRenderer, _super);
+ var CategoryRenderer = (function (_super) {
+ __extends(CategoryRenderer, _super);
/**
- * Creates an XYRenderer.
+ * Creates a CategoryRenderer with an Ordinal x scale and Quantitive y scale.
*
* @constructor
* @param {IDataset} dataset The dataset to render.
- * @param {QuantitiveScale} xScale The x scale to use.
+ * @param {OrdinalScale} xScale The x scale to use.
* @param {QuantitiveScale} yScale The y scale to use.
* @param {IAccessor} [xAccessor] A function for extracting x values from the data.
* @param {IAccessor} [yAccessor] A function for extracting y values from the data.
*/
- function XYRenderer(dataset, xScale, yScale, xAccessor, yAccessor) {
+ function CategoryRenderer(dataset, xScale, yScale, xAccessor, yAccessor) {
var _this = this;
_super.call(this, dataset);
- this.classed("xy-renderer");
-
- this.xAccessor = (xAccessor != null) ? xAccessor : XYRenderer.defaultXAccessor;
- this.yAccessor = (yAccessor != null) ? yAccessor : XYRenderer.defaultYAccessor;
+ this.autorangeDataOnLayout = true;
+ this.classed("category-renderer", true);
this.xScale = xScale;
this.yScale = yScale;
- var data = dataset.data;
+ this._xAccessor = (xAccessor != null) ? xAccessor : "x"; // default
+ this._yAccessor = (yAccessor != null) ? yAccessor : "y"; // default
+
+ this.xScale.registerListener(function () {
+ return _this.rescale();
+ });
+ this.yScale.registerListener(function () {
+ return _this.rescale();
+ });
+ }
+ CategoryRenderer.prototype._computeLayout = function (xOffset, yOffset, availableWidth, availableHeight) {
+ _super.prototype._computeLayout.call(this, xOffset, yOffset, availableWidth, availableHeight);
+ this.xScale.range([0, this.availableWidth]);
+ this.yScale.range([this.availableHeight, 0]);
+ if (this.autorangeDataOnLayout) {
+ this.autorange();
+ }
+ return this;
+ };
- var appliedXAccessor = function (d) {
- return _this.xAccessor(d, null, _this._metadata);
+ CategoryRenderer.prototype.autorange = function () {
+ var _this = this;
+ _super.prototype.autorange.call(this);
+ var data = this._data;
+ var xA = function (d) {
+ return _this._getAppliedAccessor(_this._xAccessor)(d, null);
};
- var xDomain = d3.extent(data, appliedXAccessor);
- this.xScale.widenDomain(xDomain);
+ this.xScale.domain(data.map(xA));
- var appliedYAccessor = function (d) {
- return _this.yAccessor(d, null, _this._metadata);
+ var yA = function (d) {
+ return _this._getAppliedAccessor(_this._yAccessor)(d, null);
};
- var yDomain = d3.extent(data, appliedYAccessor);
+ var yDomain = d3.extent(data, yA);
this.yScale.widenDomain(yDomain);
+ return this;
+ };
+
+ CategoryRenderer.prototype.rescale = function () {
+ if (this.element != null) {
+ this._render();
+ }
+ };
+ return CategoryRenderer;
+ })(Plottable.Renderer);
+ Plottable.CategoryRenderer = CategoryRenderer;
+})(Plottable || (Plottable = {}));
+///
+var Plottable;
+(function (Plottable) {
+ var XYRenderer = (function (_super) {
+ __extends(XYRenderer, _super);
+ /**
+ * Creates an XYRenderer.
+ *
+ * @constructor
+ * @param {IDataset} dataset The dataset to render.
+ * @param {QuantitiveScale} xScale The x scale to use.
+ * @param {QuantitiveScale} yScale The y scale to use.
+ * @param {IAccessor} [xAccessor] A function for extracting x values from the data.
+ * @param {IAccessor} [yAccessor] A function for extracting y values from the data.
+ */
+ function XYRenderer(dataset, xScale, yScale, xAccessor, yAccessor) {
+ var _this = this;
+ _super.call(this, dataset);
+ this.autorangeDataOnLayout = true;
+ this.classed("xy-renderer", true);
+
+ this._xAccessor = (xAccessor != null) ? xAccessor : XYRenderer.defaultXAccessor;
+ this._yAccessor = (yAccessor != null) ? yAccessor : XYRenderer.defaultYAccessor;
+
+ this.xScale = xScale;
+ this.yScale = yScale;
this.xScale.registerListener(function () {
return _this.rescale();
@@ -1310,10 +1441,45 @@ var Plottable;
return _this.rescale();
});
}
+ XYRenderer.prototype.xAccessor = function (accessor) {
+ this._xAccessor = accessor;
+ this._requireRerender = true;
+ this._rerenderUpdateSelection = true;
+ return this;
+ };
+
+ XYRenderer.prototype.yAccessor = function (accessor) {
+ this._yAccessor = accessor;
+ this._requireRerender = true;
+ this._rerenderUpdateSelection = true;
+ return this;
+ };
+
XYRenderer.prototype._computeLayout = function (xOffset, yOffset, availableWidth, availableHeight) {
_super.prototype._computeLayout.call(this, xOffset, yOffset, availableWidth, availableHeight);
this.xScale.range([0, this.availableWidth]);
this.yScale.range([this.availableHeight, 0]);
+ if (this.autorangeDataOnLayout) {
+ this.autorange();
+ }
+ return this;
+ };
+
+ XYRenderer.prototype.autorange = function () {
+ var _this = this;
+ _super.prototype.autorange.call(this);
+ var data = this._data;
+ var xA = function (d) {
+ return _this._getAppliedAccessor(_this._xAccessor)(d, null);
+ };
+ var xDomain = d3.extent(data, xA);
+ this.xScale.widenDomain(xDomain);
+
+ var yA = function (d) {
+ return _this._getAppliedAccessor(_this._yAccessor)(d, null);
+ };
+ var yDomain = d3.extent(data, yA);
+ this.yScale.widenDomain(yDomain);
return this;
};
@@ -1333,10 +1499,11 @@ var Plottable;
};
XYRenderer.prototype.getDataFilterFunction = function (dataArea) {
- var _this = this;
+ var xA = this._getAppliedAccessor(this._xAccessor);
+ var yA = this._getAppliedAccessor(this._yAccessor);
var filterFunction = function (d, i) {
- var x = _this.xAccessor(d, i, _this._metadata);
- var y = _this.yAccessor(d, i, _this._metadata);
+ var x = xA(d, i);
+ var y = yA(d, i);
return Plottable.Utils.inRange(x, dataArea.xMin, dataArea.xMax) && Plottable.Utils.inRange(y, dataArea.yMin, dataArea.yMax);
};
return filterFunction;
@@ -1375,12 +1542,8 @@ var Plottable;
this._render();
}
};
- XYRenderer.defaultXAccessor = function (d) {
- return d.x;
- };
- XYRenderer.defaultYAccessor = function (d) {
- return d.y;
- };
+ XYRenderer.defaultXAccessor = "x";
+ XYRenderer.defaultYAccessor = "y";
return XYRenderer;
})(Plottable.Renderer);
Plottable.XYRenderer = XYRenderer;
@@ -1403,28 +1566,33 @@ var Plottable;
*/
function CircleRenderer(dataset, xScale, yScale, xAccessor, yAccessor, rAccessor) {
_super.call(this, dataset, xScale, yScale, xAccessor, yAccessor);
- this.rAccessor = (rAccessor != null) ? rAccessor : CircleRenderer.defaultRAccessor;
+ this._rAccessor = (rAccessor != null) ? rAccessor : CircleRenderer.defaultRAccessor;
this.classed("circle-renderer", true);
}
+ CircleRenderer.prototype.rAccessor = function (a) {
+ this._rAccessor = a;
+ this._requireRerender = true;
+ this._rerenderUpdateSelection = true;
+ return this;
+ };
+
CircleRenderer.prototype._paint = function () {
var _this = this;
_super.prototype._paint.call(this);
+ var cx = function (d, i) {
+ return _this.xScale.scale(_this._getAppliedAccessor(_this._xAccessor)(d, i));
+ };
+ var cy = function (d, i) {
+ return _this.yScale.scale(_this._getAppliedAccessor(_this._yAccessor)(d, i));
+ };
+ var r = this._getAppliedAccessor(this._rAccessor);
+ var color = this._getAppliedAccessor(this._colorAccessor);
this.dataSelection = this.renderArea.selectAll("circle").data(this._data);
this.dataSelection.enter().append("circle");
- this.dataSelection.attr("cx", function (d, i) {
- return _this.xScale.scale(_this.xAccessor(d, i, _this._metadata));
- }).attr("cy", function (d, i) {
- return _this.yScale.scale(_this.yAccessor(d, i, _this._metadata));
- }).attr("r", function (d, i) {
- return _this.rAccessor(d, i, _this._metadata);
- }).attr("fill", function (d, i) {
- return _this._colorAccessor(d, i, _this._metadata);
- });
+ this.dataSelection.attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", color);
this.dataSelection.exit().remove();
};
- CircleRenderer.defaultRAccessor = function (d) {
- return 3;
- };
+ CircleRenderer.defaultRAccessor = 3;
return CircleRenderer;
})(Plottable.XYRenderer);
Plottable.CircleRenderer = CircleRenderer;
@@ -1450,23 +1618,23 @@ var Plottable;
}
LineRenderer.prototype._anchor = function (element) {
_super.prototype._anchor.call(this, element);
- this.path = this.renderArea.append("path");
+ this.path = this.renderArea.append("path").classed("line", true);
return this;
};
LineRenderer.prototype._paint = function () {
var _this = this;
_super.prototype._paint.call(this);
+ var xA = this._getAppliedAccessor(this._xAccessor);
+ var yA = this._getAppliedAccessor(this._yAccessor);
+ var cA = this._getAppliedAccessor(this._colorAccessor);
this.line = d3.svg.line().x(function (d, i) {
- return _this.xScale.scale(_this.xAccessor(d, i, _this._metadata));
+ return _this.xScale.scale(xA(d, i));
}).y(function (d, i) {
- return _this.yScale.scale(_this.yAccessor(d, i, _this._metadata));
+ return _this.yScale.scale(yA(d, i));
});
- this.dataSelection = this.path.classed("line", true).datum(this._data);
- this.path.attr("d", this.line);
-
- // Since we can only set one stroke for the full line, call colorAccessor on first datum with index 0
- this.path.attr("stroke", this._colorAccessor(this._data[0], 0, this._metadata));
+ this.dataSelection = this.path.datum(this._data);
+ this.path.attr("d", this.line).attr("stroke", cA);
};
return LineRenderer;
})(Plottable.XYRenderer);
@@ -1489,19 +1657,24 @@ var Plottable;
* @param {IAccessor} [yAccessor] A function for extracting height of each bar from the data.
*/
function BarRenderer(dataset, xScale, yScale, xAccessor, dxAccessor, yAccessor) {
- var _this = this;
_super.call(this, dataset, xScale, yScale, xAccessor, yAccessor);
this.barPaddingPx = 1;
this.classed("bar-renderer", true);
this.dxAccessor = (dxAccessor != null) ? dxAccessor : BarRenderer.defaultDxAccessor;
-
+ }
+ BarRenderer.prototype.autorange = function () {
+ _super.prototype.autorange.call(this);
+ var xA = this._getAppliedAccessor(this._xAccessor);
+ var dxA = this._getAppliedAccessor(this.dxAccessor);
var x2Accessor = function (d) {
- return _this.xAccessor(d, null, _this._metadata) + _this.dxAccessor(d, null, _this._metadata);
+ return xA(d, null) + dxA(d, null);
};
- var x2Extent = d3.extent(dataset.data, x2Accessor);
+ var x2Extent = d3.extent(this._data, x2Accessor);
this.xScale.widenDomain(x2Extent);
- }
+ return this;
+ };
+
BarRenderer.prototype._paint = function () {
var _this = this;
_super.prototype._paint.call(this);
@@ -1513,41 +1686,36 @@ var Plottable;
var xrr = this.xScale.range()[1] - this.xScale.range()[0];
this.dataSelection.enter().append("rect");
+ var xA = this._getAppliedAccessor(this._xAccessor);
var xFunction = function (d, i) {
- var x = _this.xAccessor(d, i, _this._metadata);
+ var x = xA(d, i);
var scaledX = _this.xScale.scale(x);
return scaledX + _this.barPaddingPx;
};
+ var yA = this._getAppliedAccessor(this._yAccessor);
var yFunction = function (d, i) {
- var y = _this.yAccessor(d, i, _this._metadata);
+ var y = yA(d, i);
var scaledY = _this.yScale.scale(y);
return scaledY;
};
+ var dxA = this._getAppliedAccessor(this.dxAccessor);
var widthFunction = function (d, i) {
- var dx = _this.dxAccessor(d, i, _this._metadata);
+ var dx = dxA(d, i);
var scaledDx = _this.xScale.scale(dx);
var scaledOffset = _this.xScale.scale(0);
return scaledDx - scaledOffset - 2 * _this.barPaddingPx;
};
var heightFunction = function (d, i) {
- var y = _this.yAccessor(d, i, _this._metadata);
- var scaledY = _this.yScale.scale(y);
- return maxScaledY - scaledY;
+ return maxScaledY - yFunction(d, i);
};
- var colorFunction = function (d, i) {
- return _this._colorAccessor(d, i, _this._metadata);
- };
-
- this.dataSelection.attr("x", xFunction).attr("y", yFunction).attr("width", widthFunction).attr("height", heightFunction).attr("fill", colorFunction);
+ this.dataSelection.attr("x", xFunction).attr("y", yFunction).attr("width", widthFunction).attr("height", heightFunction).attr("fill", this._getAppliedAccessor(this._colorAccessor));
this.dataSelection.exit().remove();
};
- BarRenderer.defaultDxAccessor = function (d) {
- return d.dx;
- };
+ BarRenderer.defaultDxAccessor = "dx";
return BarRenderer;
})(Plottable.XYRenderer);
Plottable.BarRenderer = BarRenderer;
@@ -1570,34 +1738,37 @@ var Plottable;
*/
function SquareRenderer(dataset, xScale, yScale, xAccessor, yAccessor, rAccessor) {
_super.call(this, dataset, xScale, yScale, xAccessor, yAccessor);
- this.rAccessor = (rAccessor != null) ? rAccessor : SquareRenderer.defaultRAccessor;
+ this._rAccessor = (rAccessor != null) ? rAccessor : SquareRenderer.defaultRAccessor;
this.classed("square-renderer", true);
}
+ SquareRenderer.prototype.rAccessor = function (a) {
+ this._rAccessor = a;
+ this._requireRerender = true;
+ this._rerenderUpdateSelection = true;
+ return this;
+ };
+
SquareRenderer.prototype._paint = function () {
var _this = this;
_super.prototype._paint.call(this);
+ var xA = this._getAppliedAccessor(this._xAccessor);
+ var yA = this._getAppliedAccessor(this._yAccessor);
+ var rA = this._getAppliedAccessor(this._rAccessor);
+ var cA = this._getAppliedAccessor(this._colorAccessor);
var xFn = function (d, i) {
- return _this.xScale.scale(_this.xAccessor(d, i, _this._metadata)) - _this.rAccessor(d, i, _this._metadata);
+ return _this.xScale.scale(xA(d, i)) - rA(d, i);
};
var yFn = function (d, i) {
- return _this.yScale.scale(_this.yAccessor(d, i, _this._metadata)) - _this.rAccessor(d, i, _this._metadata);
+ return _this.yScale.scale(yA(d, i)) - rA(d, i);
};
this.dataSelection = this.renderArea.selectAll("rect").data(this._data);
this.dataSelection.enter().append("rect");
- this.dataSelection.attr("x", xFn).attr("y", yFn).attr("width", function (d, i) {
- return _this.rAccessor(d, i, _this._metadata);
- }).attr("height", function (d, i) {
- return _this.rAccessor(d, i, _this._metadata);
- }).attr("fill", function (d, i) {
- return _this._colorAccessor(d, i, _this._metadata);
- });
+ this.dataSelection.attr("x", xFn).attr("y", yFn).attr("width", rA).attr("height", rA).attr("fill", cA);
this.dataSelection.exit().remove();
};
- SquareRenderer.defaultRAccessor = function (d) {
- return 3;
- };
+ SquareRenderer.defaultRAccessor = 3;
return SquareRenderer;
})(Plottable.XYRenderer);
Plottable.SquareRenderer = SquareRenderer;
@@ -1815,7 +1986,6 @@ var Plottable;
}
for (var j = 0; j < nCols; j++) {
if (this.rows[i][j] === undefined) {
- // this.rows[i][j] = new Component();
this.rows[i][j] = null;
}
}
@@ -1991,6 +2161,188 @@ var Plottable;
})(Plottable.Component);
Plottable.Legend = Legend;
})(Plottable || (Plottable = {}));
+///
+var Plottable;
+(function (Plottable) {
+ var StandardChart = (function (_super) {
+ __extends(StandardChart, _super);
+ function StandardChart() {
+ _super.call(this);
+ this.xTable = new Plottable.Table();
+ this.yTable = new Plottable.Table();
+ this.centerComponent = new Plottable.ComponentGroup();
+ this.xyTable = new Plottable.Table().addComponent(0, 0, this.yTable).addComponent(1, 1, this.xTable).addComponent(0, 1, this.centerComponent);
+ this.addComponent(1, 0, this.xyTable);
+ }
+ StandardChart.prototype.yAxis = function (y) {
+ if (y != null) {
+ if (this._yAxis != null) {
+ throw new Error("yAxis already assigned!");
+ }
+ this._yAxis = y;
+ this.yTable.addComponent(0, 1, this._yAxis);
+ return this;
+ } else {
+ return this._yAxis;
+ }
+ };
+
+ StandardChart.prototype.xAxis = function (x) {
+ if (x != null) {
+ if (this._xAxis != null) {
+ throw new Error("xAxis already assigned!");
+ }
+ this._xAxis = x;
+ this.xTable.addComponent(0, 0, this._xAxis);
+ return this;
+ } else {
+ return this._xAxis;
+ }
+ };
+
+ StandardChart.prototype.yLabel = function (y) {
+ if (y != null) {
+ if (this._yLabel != null) {
+ if (typeof (y) === "string") {
+ this._yLabel.setText(y);
+ return this;
+ } else {
+ throw new Error("yLabel already assigned!");
+ }
+ }
+ if (typeof (y) === "string") {
+ y = new Plottable.AxisLabel(y, "vertical-left");
+ }
+ this._yLabel = y;
+ this.yTable.addComponent(0, 0, this._yLabel);
+ return this;
+ } else {
+ return this._yLabel;
+ }
+ };
+
+ StandardChart.prototype.xLabel = function (x) {
+ if (x != null) {
+ if (this._xLabel != null) {
+ if (typeof (x) === "string") {
+ this._xLabel.setText(x);
+ return this;
+ } else {
+ throw new Error("xLabel already assigned!");
+ }
+ }
+ if (typeof (x) === "string") {
+ x = new Plottable.AxisLabel(x, "horizontal");
+ }
+ this._xLabel = x;
+ this.xTable.addComponent(1, 0, this._xLabel);
+ return this;
+ } else {
+ return this._xLabel;
+ }
+ };
+
+ StandardChart.prototype.titleLabel = function (x) {
+ if (x != null) {
+ if (this._titleLabel != null) {
+ if (typeof (x) === "string") {
+ this._titleLabel.setText(x);
+ return this;
+ } else {
+ throw new Error("titleLabel already assigned!");
+ }
+ }
+ if (typeof (x) === "string") {
+ x = new Plottable.TitleLabel(x, "horizontal");
+ }
+ this._titleLabel = x;
+ this.addComponent(0, 0, this._titleLabel);
+ return this;
+ } else {
+ return this._titleLabel;
+ }
+ };
+
+ StandardChart.prototype.addCenterComponent = function (c) {
+ this.centerComponent.merge(c);
+ return this;
+ };
+ return StandardChart;
+ })(Plottable.Table);
+ Plottable.StandardChart = StandardChart;
+})(Plottable || (Plottable = {}));
+///
+var Plottable;
+(function (Plottable) {
+ var CategoryBarRenderer = (function (_super) {
+ __extends(CategoryBarRenderer, _super);
+ /**
+ * Creates a CategoryBarRenderer.
+ *
+ * @constructor
+ * @param {IDataset} dataset The dataset to render.
+ * @param {OrdinalScale} xScale The x scale to use.
+ * @param {QuantitiveScale} yScale The y scale to use.
+ * @param {IAccessor} [xAccessor] A function for extracting the start position of each bar from the data.
+ * @param {IAccessor} [widthAccessor] A function for extracting the width position of each bar, in pixels, from the data.
+ * @param {IAccessor} [yAccessor] A function for extracting height of each bar from the data.
+ */
+ function CategoryBarRenderer(dataset, xScale, yScale, xAccessor, widthAccessor, yAccessor) {
+ _super.call(this, dataset, xScale, yScale, xAccessor, yAccessor);
+ this.classed("bar-renderer", true);
+ this._widthAccessor = (widthAccessor != null) ? widthAccessor : 10; // default width is 10px
+ }
+ /**
+ * Sets the width accessor.
+ *
+ * @param {any} accessor The new width accessor.
+ * @returns {CategoryBarRenderer} The calling CategoryBarRenderer.
+ */
+ CategoryBarRenderer.prototype.widthAccessor = function (accessor) {
+ this._widthAccessor = accessor;
+ this._requireRerender = true;
+ this._rerenderUpdateSelection = true;
+ return this;
+ };
+
+ CategoryBarRenderer.prototype._paint = function () {
+ var _this = this;
+ _super.prototype._paint.call(this);
+ var yRange = this.yScale.range();
+ var maxScaledY = Math.max(yRange[0], yRange[1]);
+
+ this.dataSelection = this.renderArea.selectAll("rect").data(this._data);
+ var xdr = this.xScale.domain()[1] - this.xScale.domain()[0];
+ var xrr = this.xScale.range()[1] - this.xScale.range()[0];
+ this.dataSelection.enter().append("rect");
+
+ var widthFunction = this._getAppliedAccessor(this._widthAccessor);
+
+ var xA = this._getAppliedAccessor(this._xAccessor);
+ var xFunction = function (d, i) {
+ var x = xA(d, i);
+ var scaledX = _this.xScale.scale(x);
+ return scaledX - widthFunction(d, i) / 2;
+ };
+
+ var yA = this._getAppliedAccessor(this._yAccessor);
+ var yFunction = function (d, i) {
+ var y = yA(d, i);
+ var scaledY = _this.yScale.scale(y);
+ return scaledY;
+ };
+
+ var heightFunction = function (d, i) {
+ return maxScaledY - yFunction(d, i);
+ };
+
+ this.dataSelection.attr("x", xFunction).attr("y", yFunction).attr("width", widthFunction).attr("height", heightFunction).attr("fill", this._getAppliedAccessor(this._colorAccessor));
+ this.dataSelection.exit().remove();
+ };
+ return CategoryBarRenderer;
+ })(Plottable.CategoryRenderer);
+ Plottable.CategoryBarRenderer = CategoryBarRenderer;
+})(Plottable || (Plottable = {}));
///
///
///
@@ -2000,6 +2352,7 @@ var Plottable;
///
///
///
+///
///
///
///
@@ -2008,6 +2361,8 @@ var Plottable;
///
///
///
+///
+///
//grunt-end
///
var Plottable;
@@ -2432,13 +2787,8 @@ var Plottable;
};
ComponentGroup.prototype.merge = function (c) {
- if (ComponentGroup.prototype.isPrototypeOf(c)) {
- var cg = new ComponentGroup([this, c]);
- return cg;
- } else {
- this._addComponentToGroup(c);
- return this;
- }
+ this._addComponentToGroup(c);
+ return this;
};
ComponentGroup.prototype._anchor = function (element) {
diff --git a/test/tests.js b/test/tests.js
index 60aac0d479..0a6c70857d 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -312,12 +312,13 @@ describe("ComponentGroups", function () {
var cg1 = new Plottable.ComponentGroup([c1, c2]);
var cg2 = new Plottable.ComponentGroup([c3, c4]);
var cg = cg1.merge(cg2);
- assert.notEqual(cg, cg1, "merged != cg1");
+ assert.equal(cg, cg1, "merged == cg1");
assert.notEqual(cg, cg2, "merged != cg2");
var components = cg.components;
- assert.lengthOf(components, 2, "there are two inner components");
- assert.equal(components[0], cg1, "cg1 nested inside");
- assert.equal(components[1], cg2, "cg2 nested inside");
+ assert.lengthOf(components, 3, "there are three inner components");
+ assert.equal(components[0], c1, "components are inside");
+ assert.equal(components[1], c2, "components are inside");
+ assert.equal(components[2], cg2, "componentGroup2 inside componentGroup1");
});
});
});
@@ -1257,6 +1258,7 @@ describe("Renderers", function () {
};
var dataset = { data: data, metadata: metadata };
var renderer = new Plottable.CircleRenderer(dataset, xScale, yScale, xAccessor, yAccessor);
+ renderer.autorangeDataOnLayout = false;
xScale.domain([0, 400]);
yScale.domain([400, 0]);
renderer.renderTo(svg);
@@ -1266,21 +1268,21 @@ describe("Renderers", function () {
assert.closeTo(parseFloat(c1.attr("cx")), 0, 0.01, "first circle cx is correct");
assert.closeTo(parseFloat(c1.attr("cy")), 20, 0.01, "first circle cy is correct");
assert.closeTo(parseFloat(c2.attr("cx")), 11, 0.01, "second circle cx is correct");
- assert.closeTo(parseFloat(c1.attr("cy")), 20, 0.01, "second circle cy is correct");
+ assert.closeTo(parseFloat(c2.attr("cy")), 20, 0.01, "second circle cy is correct");
data = [{ x: 2, y: 2 }, { x: 4, y: 4 }];
renderer.data(data).renderTo(svg);
assert.closeTo(parseFloat(c1.attr("cx")), 2, 0.01, "first circle cx is correct after data change");
assert.closeTo(parseFloat(c1.attr("cy")), 20, 0.01, "first circle cy is correct after data change");
assert.closeTo(parseFloat(c2.attr("cx")), 14, 0.01, "second circle cx is correct after data change");
- assert.closeTo(parseFloat(c1.attr("cy")), 20, 0.01, "second circle cy is correct after data change");
+ assert.closeTo(parseFloat(c2.attr("cy")), 20, 0.01, "second circle cy is correct after data change");
metadata = { foo: 0, bar: 0 };
renderer.metadata(metadata).renderTo(svg);
assert.closeTo(parseFloat(c1.attr("cx")), 2, 0.01, "first circle cx is correct after metadata change");
assert.closeTo(parseFloat(c1.attr("cy")), 0, 0.01, "first circle cy is correct after metadata change");
assert.closeTo(parseFloat(c2.attr("cx")), 4, 0.01, "second circle cx is correct after metadata change");
- assert.closeTo(parseFloat(c1.attr("cy")), 0, 0.01, "second circle cy is correct after metadata change");
+ assert.closeTo(parseFloat(c2.attr("cy")), 0, 0.01, "second circle cy is correct after metadata change");
svg.remove();
});
@@ -1579,6 +1581,60 @@ describe("Renderers", function () {
;
});
});
+
+ describe("Category Bar Renderer", function () {
+ var verifier = new MultiTestVerifier();
+ var svg;
+ var dataset;
+ var xScale;
+ var yScale;
+ var renderer;
+ var SVG_WIDTH = 600;
+ var SVG_HEIGHT = 400;
+
+ before(function () {
+ svg = generateSVG(SVG_WIDTH, SVG_HEIGHT);
+ xScale = new Plottable.OrdinalScale();
+ yScale = new Plottable.LinearScale();
+ dataset = {
+ data: [
+ { x: "A", y: 1 },
+ { x: "B", y: 2 }
+ ],
+ metadata: { cssClass: "letters" }
+ };
+
+ renderer = new Plottable.CategoryBarRenderer(dataset, xScale, yScale);
+ renderer._anchor(svg);
+ renderer._computeLayout();
+ });
+
+ beforeEach(function () {
+ verifier.start();
+ });
+
+ it("renders correctly", function () {
+ yScale.domain([0, 4]);
+ var renderArea = renderer.renderArea;
+ var bars = renderArea.selectAll("rect");
+ var bar0 = d3.select(bars[0][0]);
+ var bar1 = d3.select(bars[0][1]);
+ assert.equal(bar0.attr("width"), "10", "bar0 width is correct");
+ assert.equal(bar1.attr("width"), "10", "bar1 width is correct");
+ assert.equal(bar0.attr("height"), "100", "bar0 height is correct");
+ assert.equal(bar1.attr("height"), "200", "bar1 height is correct");
+ assert.equal(bar0.attr("x"), "145", "bar0 x is correct");
+ assert.equal(bar1.attr("x"), "445", "bar1 x is correct");
+ verifier.end();
+ });
+
+ after(function () {
+ if (verifier.passed) {
+ svg.remove();
+ }
+ ;
+ });
+ });
});
});
///
@@ -1594,7 +1650,7 @@ describe("Scales", function () {
var scaleCopy = scale.copy();
assert.deepEqual(scale.domain(), scaleCopy.domain(), "Copied scale has the same domain as the original.");
assert.deepEqual(scale.range(), scaleCopy.range(), "Copied scale has the same range as the original.");
- assert.notDeepEqual(scale.broadcasterCallbacks, scaleCopy.broadcasterCallbacks, "Registered callbacks are not copied over");
+ assert.notDeepEqual(scale._broadcasterCallbacks, scaleCopy._broadcasterCallbacks, "Registered callbacks are not copied over");
});
it("Scale alerts listeners when its domain is updated", function () {