keep cutting away
[dygraphs.git] / plotkit_v091 / PlotKit / Layout.js
CommitLineData
6a1aa64f
DV
1/*
2 PlotKit Layout
3 ==============
4
5 Handles laying out data on to a virtual canvas square canvas between 0.0
6 and 1.0. If you want to add new chart/plot types such as point plots,
7 you need to add them here.
8
9 Copyright
10 ---------
11 Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
12 For use under the BSD license. <http://www.liquidx.net/plotkit>
13
14*/
15
16try {
17 if (typeof(PlotKit.Base) == 'undefined')
18 {
19 throw ""
20 }
21}
22catch (e) {
23 throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base"
24}
25
26// --------------------------------------------------------------------
27// Start of Layout definition
28// --------------------------------------------------------------------
29
30if (typeof(PlotKit.Layout) == 'undefined') {
31 PlotKit.Layout = {};
32}
33
34PlotKit.Layout.NAME = "PlotKit.Layout";
35PlotKit.Layout.VERSION = PlotKit.VERSION;
36
37PlotKit.Layout.__repr__ = function() {
38 return "[" + this.NAME + " " + this.VERSION + "]";
39};
40
41PlotKit.Layout.toString = function() {
42 return this.__repr__();
43}
44
6a1aa64f
DV
45// --------------------------------------------------------------------
46// Start of Layout definition
47// --------------------------------------------------------------------
48
49PlotKit.Layout = function(style, options) {
50
51 this.options = {
6a1aa64f
DV
52 "xOriginIsZero": true,
53 "yOriginIsZero": true,
54 "xAxis": null, // [xmin, xmax]
55 "yAxis": null, // [ymin, ymax]
56 "xTicks": null, // [{label: "somelabel", v: value}, ..] (label opt.)
57 "yTicks": null, // [{label: "somelabel", v: value}, ..] (label opt.)
6a1aa64f
DV
58 };
59
60 // valid external options : TODO: input verification
61 this.style = style;
62 MochiKit.Base.update(this.options, options ? options : {});
63
b64a4f1a
DV
64 this.minxval = 0;
65 this.maxxval = null;
66 this.xscale = null; // val -> pos factor (eg, xval * xscale = xpos)
6a1aa64f 67
b64a4f1a
DV
68 this.minyval = 0;
69 this.maxyval = null;
70 this.yscale = null;
6a1aa64f 71
6a1aa64f 72 this.points = new Array(); // array of points to plot for line plots
6a1aa64f
DV
73
74 this.xticks = new Array();
75 this.yticks = new Array();
76
77 // internal states
78 this.datasets = new Array();
79 this.minxdelta = 0;
80 this.xrange = 1;
81 this.yrange = 1;
6a1aa64f
DV
82};
83
84// --------------------------------------------------------------------
85// Dataset Manipulation
86// --------------------------------------------------------------------
87
88
89PlotKit.Layout.prototype.addDataset = function(setname, set_xy) {
90 this.datasets[setname] = set_xy;
91};
92
6a1aa64f
DV
93// --------------------------------------------------------------------
94// Evaluates the layout for the current data and style.
95// --------------------------------------------------------------------
96
97PlotKit.Layout.prototype.evaluate = function() {
98 this._evaluateLimits();
0bece959
DV
99 this._evaluateLineCharts();
100 this._evaluateLineTicks();
6a1aa64f
DV
101};
102
103
6a1aa64f
DV
104// --------------------------------------------------------------------
105// START Internal Functions
106// --------------------------------------------------------------------
107
108PlotKit.Layout.prototype._evaluateLimits = function() {
109 // take all values from all datasets and find max and min
110 var map = PlotKit.Base.map;
111 var items = PlotKit.Base.items;
112 var itemgetter = MochiKit.Base.itemgetter;
113 var collapse = PlotKit.Base.collapse;
114 var listMin = MochiKit.Base.listMin;
115 var listMax = MochiKit.Base.listMax;
116 var isNil = MochiKit.Base.isUndefinedOrNull;
117
6a1aa64f 118 var all = collapse(map(itemgetter(1), items(this.datasets)));
0bece959
DV
119 this.minxval = listMin(map(parseFloat, map(itemgetter(0), all)));
120 this.maxxval = listMax(map(parseFloat, map(itemgetter(0), all)));
6a1aa64f 121 this.xrange = this.maxxval - this.minxval;
0bece959 122 this.xscale = (this.xrange != 0 ? 1/this.xrange : 1.0);
6a1aa64f 123
0bece959
DV
124 this.minyval = this.options.yAxis[0];
125 this.maxyval = this.options.yAxis[1];
6a1aa64f 126 this.yrange = this.maxyval - this.minyval;
0bece959 127 this.yscale = (this.yrange != 0 ? 1/this.yrange : 1.0);
6a1aa64f
DV
128};
129
6a1aa64f
DV
130// Create the line charts
131PlotKit.Layout.prototype._evaluateLineCharts = function() {
132 var items = PlotKit.Base.items;
133
134 var setCount = items(this.datasets).length;
135
136 // add all the rects
137 this.points = new Array();
138 var i = 0;
139 for (var setName in this.datasets) {
140 var dataset = this.datasets[setName];
141 if (PlotKit.Base.isFuncLike(dataset)) continue;
142 dataset.sort(function(a, b) { return compare(parseFloat(a[0]), parseFloat(b[0])); });
143 for (var j = 0; j < dataset.length; j++) {
144 var item = dataset[j];
145 var point = {
146 x: ((parseFloat(item[0]) - this.minxval) * this.xscale),
147 y: 1.0 - ((parseFloat(item[1]) - this.minyval) * this.yscale),
148 xval: parseFloat(item[0]),
149 yval: parseFloat(item[1]),
150 name: setName
151 };
152
153 // limit the x, y values so they do not overdraw
154 if (point.y <= 0.0) {
155 point.y = 0.0;
156 }
157 if (point.y >= 1.0) {
158 point.y = 1.0;
159 }
160 if ((point.x >= 0.0) && (point.x <= 1.0)) {
161 this.points.push(point);
162 }
163 }
164 i++;
165 }
166};
167
6a1aa64f
DV
168
169PlotKit.Layout.prototype._evaluateLineTicksForXAxis = function() {
170 var isNil = MochiKit.Base.isUndefinedOrNull;
171
9f5cb229
DV
172 this.xticks = new Array();
173 var makeTicks = function(tick) {
174 var label = tick.label;
175 if (isNil(label))
176 label = tick.v.toString();
177 var pos = this.xscale * (tick.v - this.minxval);
178 if ((pos >= 0.0) && (pos <= 1.0)) {
179 this.xticks.push([pos, label]);
6a1aa64f 180 }
9f5cb229
DV
181 };
182 MochiKit.Iter.forEach(this.options.xTicks, bind(makeTicks, this));
6a1aa64f
DV
183};
184
185PlotKit.Layout.prototype._evaluateLineTicksForYAxis = function() {
186 var isNil = MochiKit.Base.isUndefinedOrNull;
187
9f5cb229
DV
188 this.yticks = new Array();
189 var makeTicks = function(tick) {
190 var label = tick.label;
191 if (isNil(label))
192 label = tick.v.toString();
193 var pos = 1.0 - (this.yscale * (tick.v - this.minyval));
194 if ((pos >= 0.0) && (pos <= 1.0)) {
195 this.yticks.push([pos, label]);
196 }
197 };
198 MochiKit.Iter.forEach(this.options.yTicks, bind(makeTicks, this));
6a1aa64f
DV
199};
200
201PlotKit.Layout.prototype._evaluateLineTicks = function() {
202 this._evaluateLineTicksForXAxis();
203 this._evaluateLineTicksForYAxis();
204};
205
6a1aa64f
DV
206
207// --------------------------------------------------------------------
208// END Internal Functions
209// --------------------------------------------------------------------
210
211
212// Namespace Iniitialisation
213
214PlotKit.LayoutModule = {};
215PlotKit.LayoutModule.Layout = PlotKit.Layout;
216
217PlotKit.LayoutModule.EXPORT = [
218 "Layout"
219];
220
221PlotKit.LayoutModule.EXPORT_OK = [];
222
223PlotKit.LayoutModule.__new__ = function() {
224 var m = MochiKit.Base;
225
226 m.nameFunctions(this);
227
228 this.EXPORT_TAGS = {
229 ":common": this.EXPORT,
230 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
231 };
232};
233
234PlotKit.LayoutModule.__new__();
235MochiKit.Base._exportSymbols(this, PlotKit.LayoutModule);
236
237