Merge lp:~openerp-dev/openerp-web/trunk-new-graphview-ged into lp:openerp-web
- trunk-new-graphview-ged
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 3918 |
Proposed branch: | lp:~openerp-dev/openerp-web/trunk-new-graphview-ged |
Merge into: | lp:openerp-web |
Diff against target: |
51541 lines (+25106/-26000) 69 files modified
addons/web/static/src/js/data.js (+7/-2) addons/web/static/src/js/pyeval.js (+7/-4) addons/web/static/src/js/search.js (+1/-1) addons/web/static/test/search.js (+8/-2) addons/web_graph/__openerp__.py (+5/-31) addons/web_graph/static/lib/flotr2/LICENSE (+0/-19) addons/web_graph/static/lib/flotr2/Makefile (+0/-40) addons/web_graph/static/lib/flotr2/README.md (+0/-89) addons/web_graph/static/lib/flotr2/dev/notes.txt (+0/-86) addons/web_graph/static/lib/flotr2/flotr2.examples.min.js (+0/-2) addons/web_graph/static/lib/flotr2/flotr2.examples.types.js (+0/-1425) addons/web_graph/static/lib/flotr2/flotr2.ie.min.js (+0/-33) addons/web_graph/static/lib/flotr2/flotr2.js (+0/-6865) addons/web_graph/static/lib/flotr2/flotr2.min.js (+0/-27) addons/web_graph/static/lib/flotr2/js/Axis.js (+0/-303) addons/web_graph/static/lib/flotr2/js/Color.js (+0/-163) addons/web_graph/static/lib/flotr2/js/DOM.js (+0/-88) addons/web_graph/static/lib/flotr2/js/Date.js (+0/-207) addons/web_graph/static/lib/flotr2/js/DefaultOptions.js (+0/-98) addons/web_graph/static/lib/flotr2/js/EventAdapter.js (+0/-52) addons/web_graph/static/lib/flotr2/js/Flotr.js (+0/-250) addons/web_graph/static/lib/flotr2/js/Graph.js (+0/-745) addons/web_graph/static/lib/flotr2/js/Series.js (+0/-74) addons/web_graph/static/lib/flotr2/js/Text.js (+0/-88) addons/web_graph/static/lib/flotr2/js/plugins/crosshair.js (+0/-84) addons/web_graph/static/lib/flotr2/js/plugins/download.js (+0/-51) addons/web_graph/static/lib/flotr2/js/plugins/grid.js (+0/-208) addons/web_graph/static/lib/flotr2/js/plugins/handles.js (+0/-199) addons/web_graph/static/lib/flotr2/js/plugins/hit.js (+0/-337) addons/web_graph/static/lib/flotr2/js/plugins/labels.js (+0/-227) addons/web_graph/static/lib/flotr2/js/plugins/legend.js (+0/-179) addons/web_graph/static/lib/flotr2/js/plugins/selection.js (+0/-278) addons/web_graph/static/lib/flotr2/js/plugins/spreadsheet.js (+0/-296) addons/web_graph/static/lib/flotr2/js/plugins/titles.js (+0/-177) addons/web_graph/static/lib/flotr2/js/types/bars.js (+0/-274) addons/web_graph/static/lib/flotr2/js/types/bubbles.js (+0/-119) addons/web_graph/static/lib/flotr2/js/types/candles.js (+0/-127) addons/web_graph/static/lib/flotr2/js/types/gantt.js (+0/-229) addons/web_graph/static/lib/flotr2/js/types/lines.js (+0/-275) addons/web_graph/static/lib/flotr2/js/types/markers.js (+0/-140) addons/web_graph/static/lib/flotr2/js/types/pie.js (+0/-210) addons/web_graph/static/lib/flotr2/js/types/points.js (+0/-66) addons/web_graph/static/lib/flotr2/js/types/radar.js (+0/-60) addons/web_graph/static/lib/flotr2/js/types/timeline.js (+0/-90) addons/web_graph/static/lib/flotr2/lib/base64.js (+0/-113) addons/web_graph/static/lib/flotr2/lib/bean-min.js (+0/-10) addons/web_graph/static/lib/flotr2/lib/bean.js (+0/-501) addons/web_graph/static/lib/flotr2/lib/canvas2image.js (+0/-198) addons/web_graph/static/lib/flotr2/lib/canvastext.js (+0/-429) addons/web_graph/static/lib/flotr2/lib/excanvas.js (+0/-1425) addons/web_graph/static/lib/flotr2/lib/imagediff.js (+0/-343) addons/web_graph/static/lib/flotr2/lib/jasmine/MIT.LICENSE (+0/-20) addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine-html.js (+0/-190) addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.css (+0/-166) addons/web_graph/static/lib/flotr2/lib/jasmine/jasmine.js (+0/-2476) addons/web_graph/static/lib/flotr2/lib/prototype.js (+0/-4320) addons/web_graph/static/lib/flotr2/lib/underscore-min.js (+0/-27) addons/web_graph/static/lib/flotr2/lib/underscore.js (+0/-839) addons/web_graph/static/lib/flotr2/lib/yepnope.js (+0/-1) addons/web_graph/static/lib/nvd3/d3.v3.js (+8436/-0) addons/web_graph/static/lib/nvd3/nv.d3.js (+14303/-0) addons/web_graph/static/src/css/flotr2.css (+0/-69) addons/web_graph/static/src/css/graph.css (+89/-78) addons/web_graph/static/src/css/nv.d3.css (+769/-0) addons/web_graph/static/src/js/graph.js (+0/-434) addons/web_graph/static/src/js/graph_view.js (+199/-0) addons/web_graph/static/src/js/graph_widget.js (+711/-0) addons/web_graph/static/src/js/pivot_table.js (+462/-0) addons/web_graph/static/src/xml/web_graph.xml (+109/-41) |
To merge this branch: | bzr merge lp:~openerp-dev/openerp-web/trunk-new-graphview-ged |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Xavier (Open ERP) | Pending | ||
Review via email:
|
Commit message
Description of the change
New graph view, Pivot table and stuff.
- 4081. By Géry Debongnie
-
[FIX] fixes a typo 'widet_config' => 'widget_config' (it previously crashed the graph view) (addon web_graph)
- 4082. By Géry Debongnie
-
[IMP] change the icon and tooltip of heat map (column) in graph view (addon web_graph)
- 4083. By Géry Debongnie
-
[IMP] makes sure that the graph view does not reload data if the user removes a measure. Also, display the 'no data' screen if there are no current measure in graph view (addon web_graph)
- 4084. By Géry Debongnie
-
[IMP] adds checkmarks next to measures when they are used in graph view (addon web_graph)
- 4085. By Géry Debongnie
-
[IMP] display bar chart controls when the size is large enough and when it makes sense (dim x + dim y >= 2) in grap view (addon web_graph)
- 4086. By Géry Debongnie
-
[IMP] keeps the dropdown open when the user selects some measures in graph view (addon web_graph)
- 4087. By Géry Debongnie
-
[FIX] fixes a typo (nodata => no_data), which prevents a crash in graph_view, addon web_graph)
- 4088. By Géry Debongnie
-
[FIX] fix crash happening when user goes to graph view, switch to other view, changes groupby and goes back to graph view. (addon web_graph)
- 4089. By Géry Debongnie
-
[IMP] optimizes pivot table so that it doesn't reload data when the groupbys have been changed in such a way that it should only fold some headers (addon web_graph)
- 4090. By Géry Debongnie
-
[REF] large refactoring in graph view: changes the flow of the program to make it much simpler (addon web_graph)
- 4091. By Géry Debongnie
-
[MERGE] merge trunk into local branch
- 4092. By Géry Debongnie
-
[IMP] two small tweaks to improve the code quality in addon web_graph
- 4093. By Géry Debongnie
-
[FIX] makes the querygroup methods compatible with the 'field:interval' format of groupbys accepted by read_group
- 4094. By Géry Debongnie
-
[IMP] changes the backend code of graph view to use the new functionality of read_group (use 'field_
name:interval' in readgroup instead of context (addon web_graph) - 4095. By Géry Debongnie
-
[REF] refactoring: removes the 'interval' attributes in groupbys and improves searchbar integration (addon web_graph)
- 4096. By Géry Debongnie
-
[FIX] fixes a crash happening when in dashboards, the graph view was trying to access undefined attributes (addon web_graph)
- 4097. By Géry Debongnie
-
[FIX] fixes a problem with fields selection : the string was not correctly displayed (addon web_graph)
- 4098. By Géry Debongnie
-
[IMP] graph_view now properly honors the 'interval' attribute of field names in the xml description (addon web_graph)
- 4099. By Géry Debongnie
-
[FIX] fixes two small issues concerning the groupby dates in graph view (addon web_graph)
- 4100. By Géry Debongnie
-
[REF] lots of small tweaks to improve the code, and some small fixes, after xmo's code review (addon web_graph)
- 4101. By Géry Debongnie
-
[FIX] fixes a crash in line chart mode when the view had more than one measure (addon web_graph)
- 4102. By Géry Debongnie
-
[FIX] fixes a typo, causing crashes when selecting date fields in groupbys (addon web_graph)
- 4103. By Géry Debongnie
-
[MERGE] merge trunk into local branch
- 4104. By Géry Debongnie
-
[FIX] fixes a crash happening when the context has a groupby attributes which is an array (addon web_graph)
Preview Diff
1 | === modified file 'addons/web/static/src/js/data.js' |
2 | --- addons/web/static/src/js/data.js 2014-01-15 22:13:49 +0000 |
3 | +++ addons/web/static/src/js/data.js 2014-01-27 15:23:42 +0000 |
4 | @@ -129,11 +129,14 @@ |
5 | if (_.isEmpty(grouping) && !ctx['group_by_no_leaf']) { |
6 | return null; |
7 | } |
8 | + var raw_fields = _.map(grouping.concat(this._fields || []), function (field) { |
9 | + return (_.contains(field, ':')) ? field.split(':')[0] : field; |
10 | + }); |
11 | |
12 | var self = this; |
13 | return this._model.call('read_group', { |
14 | groupby: grouping, |
15 | - fields: _.uniq(grouping.concat(this._fields || [])), |
16 | + fields: _.uniq(raw_fields), |
17 | domain: this._model.domain(this._filter), |
18 | context: ctx, |
19 | offset: this._offset, |
20 | @@ -233,12 +236,14 @@ |
21 | |
22 | var group_size = fixed_group[grouping_field + '_count'] || fixed_group.__count || 0; |
23 | var leaf_group = fixed_group.__context.group_by.length === 0; |
24 | + var raw_field = (_.contains(grouping_field, ':')) ? grouping_field.split(':')[0] : grouping_field; |
25 | + |
26 | this.attributes = { |
27 | folded: !!(fixed_group.__fold), |
28 | grouped_on: grouping_field, |
29 | // if terminal group (or no group) and group_by_no_leaf => use group.__count |
30 | length: group_size, |
31 | - value: fixed_group[grouping_field], |
32 | + value: fixed_group[raw_field], |
33 | // A group is open-able if it's not a leaf in group_by_no_leaf mode |
34 | has_children: !(leaf_group && fixed_group.__context['group_by_no_leaf']), |
35 | |
36 | |
37 | === modified file 'addons/web/static/src/js/pyeval.js' |
38 | --- addons/web/static/src/js/pyeval.js 2013-08-06 12:50:22 +0000 |
39 | +++ addons/web/static/src/js/pyeval.js 2014-01-27 15:23:42 +0000 |
40 | @@ -845,16 +845,18 @@ |
41 | }; |
42 | instance.web.pyeval.eval_domains_and_contexts = function (source) { |
43 | return new $.Deferred(function (d) {setTimeout(function () { |
44 | + var result; |
45 | try { |
46 | var contexts = ([instance.session.user_context] || []).concat(source.contexts); |
47 | // see Session.eval_context in Python |
48 | - d.resolve({ |
49 | + result = { |
50 | context: instance.web.pyeval.eval('contexts', contexts), |
51 | domain: instance.web.pyeval.eval('domains', source.domains), |
52 | group_by: instance.web.pyeval.eval('groupbys', source.group_by_seq || []) |
53 | - }); |
54 | + }; |
55 | + |
56 | } catch (e) { |
57 | - d.resolve({ error: { |
58 | + result = { error: { |
59 | code: 400, |
60 | message: instance.web._t("Evaluation Error"), |
61 | data: { |
62 | @@ -863,8 +865,9 @@ |
63 | instance.web._t("Local evaluation failure\n%s\n\n%s"), |
64 | e.message, JSON.stringify(source)) |
65 | } |
66 | - }}); |
67 | + }}; |
68 | } |
69 | + d.resolve(result); |
70 | }, 0); }); |
71 | }; |
72 | })(); |
73 | |
74 | === modified file 'addons/web/static/src/js/search.js' |
75 | --- addons/web/static/src/js/search.js 2014-01-15 22:13:49 +0000 |
76 | +++ addons/web/static/src/js/search.js 2014-01-27 15:23:42 +0000 |
77 | @@ -85,7 +85,7 @@ |
78 | && facet.get('field') === model.get('field'); |
79 | }); |
80 | if (previous) { |
81 | - previous.values.add(model.get('values')); |
82 | + previous.values.add(model.get('values'), _.omit(options, 'at', 'merge')); |
83 | return; |
84 | } |
85 | B.Collection.prototype.add.call(this, model, options); |
86 | |
87 | === modified file 'addons/web/static/test/search.js' |
88 | --- addons/web/static/test/search.js 2013-11-07 11:12:31 +0000 |
89 | +++ addons/web/static/test/search.js 2014-01-27 15:23:42 +0000 |
90 | @@ -425,7 +425,7 @@ |
91 | "should have the right facet in the query"); |
92 | }); |
93 | }); |
94 | - test('facet selection: new value existing facet', {asserts: 3}, function (instance, $s) { |
95 | + test('facet selection: new value existing facet', {asserts: 8}, function (instance, $s) { |
96 | var field = { |
97 | get_domain: openerp.testing.noop, |
98 | get_context: openerp.testing.noop, |
99 | @@ -451,8 +451,14 @@ |
100 | {item: completion}); |
101 | equal(view.query.length, 1, "should still have only one facet"); |
102 | var facet = view.query.at(0); |
103 | + var values = facet.get('values'); |
104 | + equal(values.length, 2, 'should have two values'); |
105 | + equal(values[0].label, 'previous'); |
106 | + equal(values[0].value, 41); |
107 | + equal(values[1].label, 'dummy'); |
108 | + equal(values[1].value, 42); |
109 | deepEqual( |
110 | - facet.get('values'), |
111 | + values, |
112 | [{label: 'previous', value: 41}, {label: 'dummy', value: 42}], |
113 | "should have added selected value to old one"); |
114 | }); |
115 | |
116 | === modified file 'addons/web_graph/__openerp__.py' |
117 | --- addons/web_graph/__openerp__.py 2013-12-12 09:45:18 +0000 |
118 | +++ addons/web_graph/__openerp__.py 2014-01-27 15:23:42 +0000 |
119 | @@ -15,37 +15,11 @@ |
120 | 'version': '3.0', |
121 | 'depends': ['web'], |
122 | 'js': [ |
123 | - 'static/lib/flotr2/lib/bean.js', |
124 | - 'static/lib/flotr2/js/Flotr.js', |
125 | - 'static/lib/flotr2/js/DefaultOptions.js', |
126 | - 'static/lib/flotr2/js/Color.js', |
127 | - 'static/lib/flotr2/js/Date.js', |
128 | - 'static/lib/flotr2/js/DOM.js', |
129 | - 'static/lib/flotr2/js/EventAdapter.js', |
130 | - 'static/lib/flotr2/js/Text.js', |
131 | - 'static/lib/flotr2/js/Graph.js', |
132 | - 'static/lib/flotr2/js/Axis.js', |
133 | - 'static/lib/flotr2/js/Series.js', |
134 | - 'static/lib/flotr2/js/types/lines.js', |
135 | - 'static/lib/flotr2/js/types/bars.js', |
136 | - 'static/lib/flotr2/js/types/bubbles.js', |
137 | - 'static/lib/flotr2/js/types/candles.js', |
138 | - 'static/lib/flotr2/js/types/gantt.js', |
139 | - 'static/lib/flotr2/js/types/markers.js', |
140 | - 'static/lib/flotr2/js/types/pie.js', |
141 | - 'static/lib/flotr2/js/types/points.js', |
142 | - 'static/lib/flotr2/js/types/radar.js', |
143 | - 'static/lib/flotr2/js/types/timeline.js', |
144 | - 'static/lib/flotr2/js/plugins/crosshair.js', |
145 | - 'static/lib/flotr2/js/plugins/download.js', |
146 | - 'static/lib/flotr2/js/plugins/grid.js', |
147 | - 'static/lib/flotr2/js/plugins/hit.js', |
148 | - 'static/lib/flotr2/js/plugins/selection.js', |
149 | - 'static/lib/flotr2/js/plugins/labels.js', |
150 | - 'static/lib/flotr2/js/plugins/legend.js', |
151 | - 'static/lib/flotr2/js/plugins/spreadsheet.js', |
152 | - 'static/lib/flotr2/js/plugins/titles.js', |
153 | - 'static/src/js/graph.js' |
154 | + 'static/lib/nvd3/d3.v3.js', |
155 | + 'static/lib/nvd3/nv.d3.js', |
156 | + 'static/src/js/graph_view.js', |
157 | + 'static/src/js/pivot_table.js', |
158 | + 'static/src/js/graph_widget.js', |
159 | ], |
160 | 'css': [ |
161 | 'static/src/css/*.css', |
162 | |
163 | === removed directory 'addons/web_graph/static/lib/flotr2' |
164 | === removed file 'addons/web_graph/static/lib/flotr2/LICENSE' |
165 | --- addons/web_graph/static/lib/flotr2/LICENSE 2012-05-07 08:19:08 +0000 |
166 | +++ addons/web_graph/static/lib/flotr2/LICENSE 1970-01-01 00:00:00 +0000 |
167 | @@ -1,19 +0,0 @@ |
168 | -Copyright (c) 2012 Carl Sutherland |
169 | - |
170 | -Permission is hereby granted, free of charge, to any person obtaining a copy |
171 | -of this software and associated documentation files (the "Software"), to deal |
172 | -in the Software without restriction, including without limitation the rights |
173 | -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
174 | -copies of the Software, and to permit persons to whom the Software is |
175 | -furnished to do so, subject to the following conditions: |
176 | - |
177 | -The above copyright notice and this permission notice shall be included in |
178 | -all copies or substantial portions of the Software. |
179 | - |
180 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
181 | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
182 | -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
183 | -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
184 | -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
185 | -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
186 | -THE SOFTWARE. |
187 | |
188 | === removed file 'addons/web_graph/static/lib/flotr2/Makefile' |
189 | --- addons/web_graph/static/lib/flotr2/Makefile 2012-05-07 10:34:07 +0000 |
190 | +++ addons/web_graph/static/lib/flotr2/Makefile 1970-01-01 00:00:00 +0000 |
191 | @@ -1,40 +0,0 @@ |
192 | -all: test flotr2 |
193 | - |
194 | -test: |
195 | - cd spec; jasmine-headless-webkit -j jasmine.yml -c |
196 | - |
197 | -libraries: |
198 | - smoosh make/lib.json |
199 | - cat ./build/bean.js > build/lib.js |
200 | - cat ./build/underscore.js >> build/lib.js |
201 | - cat ./build/bean.min.js > build/lib.min.js |
202 | - echo ";" >> build/lib.min.js |
203 | - cat ./build/underscore.min.js >> build/lib.min.js |
204 | - echo ";" >> build/lib.min.js |
205 | - |
206 | -ie: |
207 | - smoosh make/ie.json |
208 | - |
209 | -flotr2: libraries ie |
210 | - smoosh make/flotr2.json |
211 | - cat build/lib.js build/flotr2.js > flotr2.js |
212 | - cat build/lib.min.js > flotr2.min.js |
213 | - cat build/flotr2.min.js >> flotr2.min.js |
214 | - echo ';' >> flotr2.min.js |
215 | - cp build/ie.min.js flotr2.ie.min.js |
216 | - |
217 | -flotr2-basic: libraries ie |
218 | - smoosh make/basic.json |
219 | - cat build/lib.min.js > flotr2-basic.min.js |
220 | - cat build/flotr2-basic.min.js >> flotr2-basic.min.js |
221 | - |
222 | -flotr2-standalone: ie |
223 | - smoosh make/flotr2.json |
224 | - cat build/flotr2.js > flotr2.js |
225 | - cp build/ie.min.js flotr2.ie.min.js |
226 | - |
227 | -flotr-examples: |
228 | - smoosh make/examples.json |
229 | - cp build/examples.min.js flotr2.examples.min.js |
230 | - cp build/examples-types.js flotr2.examples.types.js |
231 | - |
232 | |
233 | === removed file 'addons/web_graph/static/lib/flotr2/README.md' |
234 | --- addons/web_graph/static/lib/flotr2/README.md 2012-05-07 08:19:08 +0000 |
235 | +++ addons/web_graph/static/lib/flotr2/README.md 1970-01-01 00:00:00 +0000 |
236 | @@ -1,89 +0,0 @@ |
237 | -Flotr2 |
238 | -====== |
239 | - |
240 | -The Canvas graphing library. |
241 | - |
242 | -![Google Groups](http://groups.google.com/intl/en/images/logos/groups_logo_sm.gif) |
243 | - |
244 | -http://groups.google.com/group/flotr2/ |
245 | - |
246 | -Please fork http://jsfiddle.net/cesutherland/ZFBj5/ with your question or bug reproduction case. |
247 | - |
248 | - |
249 | -API |
250 | ---- |
251 | - |
252 | -The API consists of a primary draw method which accepts a configuration object, helper methods, and several microlibs. |
253 | - |
254 | -### Example |
255 | - |
256 | -```javascript |
257 | - var |
258 | - // Container div: |
259 | - container = document.getElementById("flotr-example-graph"), |
260 | - // First data series: |
261 | - d1 = [[0, 3], [4, 8], [8, 5], [9, 13]], |
262 | - // Second data series: |
263 | - d2 = [], |
264 | - // A couple flotr configuration options: |
265 | - options = { |
266 | - xaxis: { |
267 | - minorTickFreq: 4 |
268 | - }, |
269 | - grid: { |
270 | - minorVerticalLines: true |
271 | - } |
272 | - }, |
273 | - i, graph; |
274 | - |
275 | - // Generated second data set: |
276 | - for (i = 0; i < 14; i += 0.5) { |
277 | - d2.push([i, Math.sin(i)]); |
278 | - } |
279 | - |
280 | - // Draw the graph: |
281 | - graph = Flotr.draw( |
282 | - container, // Container element |
283 | - [ d1, d2 ], // Array of data series |
284 | - options // Configuration options |
285 | - ); |
286 | -``` |
287 | - |
288 | -### Microlibs |
289 | - |
290 | -* [underscore.js](http://documentcloud.github.com/underscore/) |
291 | -* [bean.js](https://github.com/fat/bean) |
292 | - |
293 | -Extending |
294 | ---------- |
295 | - |
296 | -Flotr may be extended by adding new plugins and graph types. |
297 | - |
298 | -### Graph Types |
299 | - |
300 | -Graph types define how a particular chart is rendered. Examples include line, bar, pie. |
301 | - |
302 | -Existing graph types are found in `js/types/`. |
303 | - |
304 | -### Plugins |
305 | - |
306 | -Plugins extend the core of flotr with new functionality. They can add interactions, new decorations, etc. Examples |
307 | -include titles, labels and selection. |
308 | - |
309 | -The plugins included are found in `js/plugins/`. |
310 | - |
311 | -Development |
312 | ------------ |
313 | - |
314 | -This project uses [smoosh](https://github.com/fat/smoosh) to build and [jasmine](http://pivotal.github.com/jasmine/) |
315 | -with [js-imagediff](https://github.com/HumbleSoftware/js-imagediff) to test. Tests may be executed by |
316 | -[jasmine-headless-webkit](http://johnbintz.github.com/jasmine-headless-webkit/) with |
317 | -`cd spec; jasmine-headless-webkit -j jasmine.yml -c` or by a browser by navigating to |
318 | -`flotr2/spec/SpecRunner.html`. |
319 | - |
320 | -Shoutouts |
321 | ---------- |
322 | - |
323 | -Thanks to Bas Wenneker, Fabien Ménager and others for all the work on the original Flotr. |
324 | -Thanks to Jochen Berger and Jordan Santell for their contributions to Flotr2. |
325 | - |
326 | |
327 | === removed directory 'addons/web_graph/static/lib/flotr2/dev' |
328 | === removed file 'addons/web_graph/static/lib/flotr2/dev/notes.txt' |
329 | --- addons/web_graph/static/lib/flotr2/dev/notes.txt 2012-05-07 08:19:08 +0000 |
330 | +++ addons/web_graph/static/lib/flotr2/dev/notes.txt 1970-01-01 00:00:00 +0000 |
331 | @@ -1,86 +0,0 @@ |
332 | -Flotr 2 Architecture Notes |
333 | - |
334 | - |
335 | -Global: |
336 | -====== |
337 | - |
338 | -Flotr.js - |
339 | - versioning information |
340 | - browser detection |
341 | - extension (plugins, graph types) |
342 | - draw |
343 | - clone / merge |
344 | - tick size |
345 | - tick formatter |
346 | - engineering notation |
347 | - magnitude |
348 | - rad, pixel, floor |
349 | - drawText |
350 | - measureText |
351 | - getBestTextAlign |
352 | - align map |
353 | - compatibility |
354 | - |
355 | - |
356 | -Graph Architecture: |
357 | -=================== |
358 | - |
359 | -Axis - |
360 | - all series |
361 | - orientation |
362 | - ticks (major, minor) |
363 | - scale (d2p, p2d, logarithmic) |
364 | - notion of stacks |
365 | - |
366 | -Series - |
367 | - per 'data' |
368 | - notion of range (x, y, min, max) |
369 | - |
370 | -Graph - |
371 | - DOM constructon |
372 | - event attachment |
373 | - options initialization |
374 | - data range calculations |
375 | - canvas spacing calculations |
376 | - event normalization |
377 | - draw methods |
378 | - DOM cleanup |
379 | - event cleanup |
380 | - |
381 | - |
382 | -Utilities: |
383 | -========== |
384 | - |
385 | -Color |
386 | - build colors |
387 | - parse textual color data |
388 | - convert colors |
389 | - clone colors |
390 | - |
391 | -Text |
392 | - calculate text size |
393 | - canvas size |
394 | - html size |
395 | - |
396 | -Date |
397 | - formatting |
398 | - constants |
399 | - |
400 | - |
401 | -Spacing Calculation |
402 | -=================== |
403 | - |
404 | -Flotr |
405 | - calculate data |
406 | - calculate margins |
407 | - |
408 | -Chart |
409 | - calculate Data Ranges - Explicit or auto data minimum, maximums |
410 | - calculate Data Range Extensions - By chart type, extend data range with needs of chart type (ie. stacked bars, stacked lines) |
411 | - add Chart Padding - By chart type |
412 | - |
413 | -Text |
414 | - use explicit margins |
415 | - calculate label margins |
416 | - calculate title margins |
417 | - |
418 | |
419 | === removed file 'addons/web_graph/static/lib/flotr2/flotr2.examples.min.js' |
420 | --- addons/web_graph/static/lib/flotr2/flotr2.examples.min.js 2012-05-07 08:19:08 +0000 |
421 | +++ addons/web_graph/static/lib/flotr2/flotr2.examples.min.js 1970-01-01 00:00:00 +0000 |
422 | @@ -1,2 +0,0 @@ |
423 | - |
424 | -(function(){var a=Flotr.EventAdapter,b=Flotr._,c="click",d="example",e="mouseenter",f="mouseleave",g=".",h="flotr-examples",i="flotr-examples-container",j="flotr-examples-reset",k="flotr-examples-thumbs",l="flotr-examples-thumb",m="flotr-examples-collapsed",n="flotr-examples-highlight",o="flotr-examples-large",p="flotr-examples-medium",q="flotr-examples-small",r="flotr-examples-mobile",s='<div class="'+l+'"></div>',t='<div class="'+h+'">'+'<div class="'+j+'">View All</div>'+'<div class="'+k+'"></div>'+'<div class="'+i+'"></div>'+"</div>";Examples=function(a){if(b.isUndefined(Flotr.ExampleList))throw"Flotr.ExampleList not defined.";this.options=a,this.list=Flotr.ExampleList,this.current=null,this.single=!1,this._initNodes(),this._example=new Flotr.Examples.Example({node:this._exampleNode}),this._initExamples()},Examples.prototype={examples:function(){function f(b){var c=$(b.currentTarget),e=c.data("example"),f=b.data.orientation;f^c.hasClass(n)&&(c.toggleClass(n).css(a),d._example.executeCallback(e,c))}var a={cursor:"pointer"},b=this._thumbsNode,c=this.list.get(),d=this,e=["basic","basic-axis","basic-bars","basic-bars-horizontal","basic-bar-stacked","basic-stacked-horizontal","basic-pie","basic-radar","basic-bubble","basic-candle","basic-legend","mouse-tracking","mouse-zoom","mouse-drag","basic-time","negative-values","click-example","download-image","download-data","advanced-titles","color-gradients","basic-timeline","advanced-markers"];(function h(){var a=e.shift(),f=c[a];if(f.type==="profile"||f.type==="test")return;var g=$(s);g.data("example",f),b.append(g),d._example.executeCallback(f,g),g.click(function(){d._loadExample(f)}),e.length&&setTimeout(h,20)})(),b.delegate(g+l,"mouseenter",{orientation:!0},f),b.delegate(g+l,"mouseleave",{orientation:!1},f)},_loadExample:function(a){a&&(window.location.hash="!"+(this.single?"single/":"")+a.key,u||(this._thumbsNode.css({position:"absolute",height:"0px",overflow:"hidden",width:"0px"}),this._resetNode.css({top:"16px"})),this._examplesNode.addClass(m),this._exampleNode.show(),this._example.setExample(a),this._resize(),$(document).scrollTop(0))},_reset:function(){window.location.hash="",u||this._thumbsNode.css({position:"",height:"",overflow:"",width:""}),this._examplesNode.removeClass(m),this._thumbsNode.height(""),this._exampleNode.hide()},_initNodes:function(){var a=$(this.options.node),b=this,c=$(t);b._resetNode=c.find(g+j),b._exampleNode=c.find(g+i),b._thumbsNode=c.find(g+k),b._examplesNode=c,b._resetNode.click(function(){b._reset()}),a.append(c),this._initResizer()},_initResizer:function(){function e(){var b=c.height()-(a.options.thumbPadding||0),e=c.width(),f;e>1760?(f=o,a._thumbsNode.height(b)):e>1140?(f=p,a._thumbsNode.height(b)):(f=q,a._thumbsNode.height("")),d!==f&&(d&&a._examplesNode.removeClass(d),a._examplesNode.addClass(f),d=f)}var a=this,b=a._examplesNode,c=$(window),d;$(window).resize(e),e(),this._resize=e},_initExamples:function(){var a=window.location.hash,b,c;a?(a=a.substring(2),c=a.split("/"),c.length==1?(b=this.list.get(a),this.examples()):c[0]=="single"&&(this.single=!0,b=this.list.get(c[1])),this._loadExample(b)):this.examples()}};var u=function(){var a=!!(navigator.userAgent.match(/Android/i)||navigator.userAgent.match(/webOS/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)),b=!!$.browser.mozilla;return!a||b}();Flotr.Examples=Examples})(),function(){var a=Flotr._,b=".",c="flotr-example",d="flotr-example-label",e="flotr-example-title",f="flotr-example-description",g="flotr-example-editor",h="flotr-example-graph",i='<div class="'+c+'">'+'<div class="'+d+" "+e+'"></div>'+'<div class="'+f+'"></div>'+'<div class="'+g+'"></div>'+"</div>",j=function(a){this.options=a,this.example=null,this._initNodes()};j.prototype={setExample:function(a){var b=this.getSource(a),c=this._editorNode;this.example=a,Math.seedrandom(a.key),this._exampleNode.css({display:"block"}),this._titleNode.html(a.name||""),this._markupNode.html(a.description||""),this._editor?this._editor.setExample(b):this._editor=new Flotr.Examples.Editor(c,{example:b,teardown:function(){Flotr.EventAdapter.stopObserving($(c).find(".render")[0]),$(c).find("canvas").each(function(a,b){Flotr.EventAdapter.stopObserving(b)})}})},getSource:function(a){var b=a.callback.toString();return navigator.userAgent.search(/firefox/i)!==-1&&(b=js_beautify(b)),b},executeCallback:function(b,c){a.isElement(c)||(c=c[0]);var d=b.args?[c].concat(b.args):[c];return Math.seedrandom(b.key),b.callback.apply(this,d)},_initNodes:function(){var a=this.options.node,c=$(i);this._titleNode=c.find(b+e),this._markupNode=c.find(b+f),this._editorNode=c.find(b+g),this._exampleNode=c,a.append(c)}},Flotr.Examples.Example=j}(),function(){function Editor(a,b){function o(){i.hide(),f&&f.call(),m.render({example:d,render:h})}function p(a,b,c){var d=!1,e='<span class="error">Error: </span>',f,g;e+='<span class="message">'+a+"</span>",typeof c!="undefined"&&(e+='<span class="position">',e+='Line <span class="line">'+c+"</span>",console.log(b),b&&(e+=" of ",b==window.location?(e+='<span class="url">script</span>',!d):e+='<span class="url">'+b+"</span>"),e+=".</span>"),i.show(),i.html(e)}var c=b.type||"javascript",d=b.example||"",e=b.noRun||!1,f=b.teardown||!1,g=$(T_CONTROLS),h=$(T_RENDER),i=$(T_ERRORS),j=$(T_SOURCE),k=$(T_EDITOR),l="editor-render-"+COUNT,m,h,n;m=new TYPES[c]({onerror:p});if(!m)throw"Invalid type: API not found for type `"+c+"`.";h.attr("id",l),i.hide(),k.append(h).append(g).append(j).addClass(c).addClass(e?"no-run":""),a=$(a),a.append(k),j.append(i),d=m.example({example:d,render:h}),n=CodeMirror(j[0],{value:d,readOnly:e,lineNumbers:!0,mode:m.codeMirrorType}),e||(g.delegate(".run","click",function(){d=n.getValue(),o()}),o()),window.onerror=function(a,b,c){return p(a,b,c),console.log(a),ONERROR&&$.isFunction(ONERROR)?ONERROR(a,b,c):!1},COUNT++,this.setExample=function(a){d=m.example({example:a,render:h}),n.setValue(d),n.refresh(),o()}}var ONERROR=window.onerror,COUNT=0,TYPES={},T_CONTROLS='<div class="controls"><button class="run btn large primary">Run</button></div>',T_EDITOR='<div class="editor"></div>',T_SOURCE='<div class="source"></div>',T_ERRORS='<div class="errors"></div>',T_RENDER='<div class="render"></div>',T_IFRAME="<iframe></iframe>";TYPES.javascript=function(b){this.onerror=b.onerror},TYPES.javascript.prototype={codeMirrorType:"javascript",example:function(a){var b=a.example,c=a.render,d=$(c).attr("id");return"("+b+')(document.getElementById("'+d+'"));'},render:function(o){eval(o.example)}},TYPES.html=function(b){this.onerror=b.onerror},TYPES.html.prototype={codeMirrorType:"htmlmixed",example:function(a){return $.trim(a.example)},render:function(a){var b=a.example,c=a.render,d=$(T_IFRAME),e=this,f,g;c.html(d),f=d[0].contentWindow,g=f.document,g.open(),f.onerror=d.onerror=function(){e.onerror.apply(null,arguments)},g.write(b),g.close()}},typeof Flotr.Examples=="undefined"&&(Flotr.Examples={}),Flotr.Examples.Editor=Editor}(),function(){var a=Flotr.DOM,b=Flotr.EventAdapter,c=Flotr._,d="click",e="example-profile",f="examples",g=function(a){if(c.isUndefined(Flotr.ExampleList))throw"Flotr.ExampleList not defined.";this.editMode="off",this.list=Flotr.ExampleList,this.current=null,this.single=!1,this.init()};g.prototype=c.extend({},Flotr.Examples.prototype,{examples:function(){var e=document.getElementById(f),g=a.node("<ul></ul>"),h;c.each(this.list.getType("profile"),function(e){h=a.node("<li>"+e.name+"</li>"),a.insert(g,h),b.observe(h,d,c.bind(function(){this.example(e)},this))},this),a.insert(e,g)},example:function(a){this._renderSource(a),this.profileStart(a),setTimeout(c.bind(function(){this._renderGraph(a),this.profileEnd()},this),50)},profileStart:function(a){var b=document.getElementById(e);this._startTime=new Date,b.innerHTML='<div>Profile started for "'+a.name+'"...</div>'},profileEnd:function(a){var b=document.getElementById(e);profileTime=new Date-this._startTime,this._startTime=null,b.innerHTML+="<div>Profile complete: "+profileTime+"ms<div>"}}),Flotr.Profile=g}() |
425 | \ No newline at end of file |
426 | |
427 | === removed file 'addons/web_graph/static/lib/flotr2/flotr2.examples.types.js' |
428 | --- addons/web_graph/static/lib/flotr2/flotr2.examples.types.js 2012-05-07 08:19:08 +0000 |
429 | +++ addons/web_graph/static/lib/flotr2/flotr2.examples.types.js 1970-01-01 00:00:00 +0000 |
430 | @@ -1,1425 +0,0 @@ |
431 | -(function () { |
432 | - |
433 | -var ExampleList = function () { |
434 | - |
435 | - // Map of examples. |
436 | - this.examples = {}; |
437 | - |
438 | -}; |
439 | - |
440 | -ExampleList.prototype = { |
441 | - |
442 | - add : function (example) { |
443 | - this.examples[example.key] = example; |
444 | - }, |
445 | - |
446 | - get : function (key) { |
447 | - return key ? (this.examples[key] || null) : this.examples; |
448 | - }, |
449 | - |
450 | - getType : function (type) { |
451 | - return Flotr._.select(this.examples, function (example) { |
452 | - return (example.type === type); |
453 | - }); |
454 | - } |
455 | -} |
456 | - |
457 | -Flotr.ExampleList = new ExampleList(); |
458 | - |
459 | -})(); |
460 | - |
461 | -(function () { |
462 | - |
463 | -Flotr.ExampleList.add({ |
464 | - key : 'basic', |
465 | - name : 'Basic', |
466 | - callback : basic |
467 | -}); |
468 | - |
469 | -function basic (container) { |
470 | - |
471 | - var |
472 | - d1 = [[0, 3], [4, 8], [8, 5], [9, 13]], // First data series |
473 | - d2 = [], // Second data series |
474 | - i, graph; |
475 | - |
476 | - // Generate first data set |
477 | - for (i = 0; i < 14; i += 0.5) { |
478 | - d2.push([i, Math.sin(i)]); |
479 | - } |
480 | - |
481 | - // Draw Graph |
482 | - graph = Flotr.draw(container, [ d1, d2 ], { |
483 | - xaxis: { |
484 | - minorTickFreq: 4 |
485 | - }, |
486 | - grid: { |
487 | - minorVerticalLines: true |
488 | - } |
489 | - }); |
490 | -} |
491 | - |
492 | -})(); |
493 | - |
494 | -(function () { |
495 | - |
496 | -Flotr.ExampleList.add({ |
497 | - key : 'basic-stacked', |
498 | - name : 'Basic Stacked', |
499 | - callback : basic_stacked, |
500 | - type : 'test' |
501 | -}); |
502 | - |
503 | -function basic_stacked (container) { |
504 | - |
505 | - var |
506 | - d1 = [[0, 3], [4, 8], [8, 2], [9, 3]], // First data series |
507 | - d2 = [[0, 2], [4, 3], [8, 8], [9, 4]], // Second data series |
508 | - i, graph; |
509 | - |
510 | - // Draw Graph |
511 | - graph = Flotr.draw(container, [ d1, d2 ], { |
512 | - lines: { |
513 | - show : true, |
514 | - stacked: true |
515 | - }, |
516 | - xaxis: { |
517 | - minorTickFreq: 4 |
518 | - }, |
519 | - grid: { |
520 | - minorVerticalLines: true |
521 | - } |
522 | - }); |
523 | -} |
524 | - |
525 | -})(); |
526 | - |
527 | -(function () { |
528 | - |
529 | -Flotr.ExampleList.add({ |
530 | - key : 'basic-stepped', |
531 | - name : 'Basic Stepped', |
532 | - callback : basic_stepped, |
533 | - type : 'test' |
534 | -}); |
535 | - |
536 | -function basic_stepped (container) { |
537 | - |
538 | - var |
539 | - d1 = [[0, 3], [4, 8], [8, 5], [9, 13]], // First data series |
540 | - d2 = [], // Second data series |
541 | - i, graph; |
542 | - |
543 | - // Generate first data set |
544 | - for (i = 0; i < 14; i += 0.5) { |
545 | - d2.push([i, Math.sin(i)]); |
546 | - } |
547 | - |
548 | - // Draw Graph |
549 | - graph = Flotr.draw(container, [ d1, d2 ], { |
550 | - lines: { |
551 | - steps : true, |
552 | - show : true |
553 | - }, |
554 | - xaxis: { |
555 | - minorTickFreq: 4 |
556 | - }, |
557 | - yaxis: { |
558 | - autoscale: true |
559 | - }, |
560 | - grid: { |
561 | - minorVerticalLines: true |
562 | - }, |
563 | - mouse : { |
564 | - track : true, |
565 | - relative : true |
566 | - } |
567 | - }); |
568 | -} |
569 | - |
570 | -})(); |
571 | - |
572 | -(function () { |
573 | - |
574 | -Flotr.ExampleList.add({ |
575 | - key : 'basic-axis', |
576 | - name : 'Basic Axis', |
577 | - callback : basic_axis |
578 | -}); |
579 | - |
580 | -function basic_axis (container) { |
581 | - |
582 | - var |
583 | - d1 = [], |
584 | - d2 = [], |
585 | - d3 = [], |
586 | - d4 = [], |
587 | - d5 = [], // Data |
588 | - ticks = [[ 0, "Lower"], 10, 20, 30, [40, "Upper"]], // Ticks for the Y-Axis |
589 | - graph; |
590 | - |
591 | - for(var i = 0; i <= 10; i += 0.1){ |
592 | - d1.push([i, 4 + Math.pow(i,1.5)]); |
593 | - d2.push([i, Math.pow(i,3)]); |
594 | - d3.push([i, i*5+3*Math.sin(i*4)]); |
595 | - d4.push([i, i]); |
596 | - if( i.toFixed(1)%1 == 0 ){ |
597 | - d5.push([i, 2*i]); |
598 | - } |
599 | - } |
600 | - |
601 | - d3[30][1] = null; |
602 | - d3[31][1] = null; |
603 | - |
604 | - function ticksFn (n) { return '('+n+')'; } |
605 | - |
606 | - graph = Flotr.draw(container, [ |
607 | - { data : d1, label : 'y = 4 + x^(1.5)', lines : { fill : true } }, |
608 | - { data : d2, label : 'y = x^3'}, |
609 | - { data : d3, label : 'y = 5x + 3sin(4x)'}, |
610 | - { data : d4, label : 'y = x'}, |
611 | - { data : d5, label : 'y = 2x', lines : { show : true }, points : { show : true } } |
612 | - ], { |
613 | - xaxis : { |
614 | - noTicks : 7, // Display 7 ticks. |
615 | - tickFormatter : ticksFn, // Displays tick values between brackets. |
616 | - min : 1, // Part of the series is not displayed. |
617 | - max : 7.5 // Part of the series is not displayed. |
618 | - }, |
619 | - yaxis : { |
620 | - ticks : ticks, // Set Y-Axis ticks |
621 | - max : 40 // Maximum value along Y-Axis |
622 | - }, |
623 | - grid : { |
624 | - verticalLines : false, |
625 | - backgroundColor : { |
626 | - colors : [[0,'#fff'], [1,'#ccc']], |
627 | - start : 'top', |
628 | - end : 'bottom' |
629 | - } |
630 | - }, |
631 | - legend : { |
632 | - position : 'nw' |
633 | - }, |
634 | - title : 'Basic Axis example', |
635 | - subtitle : 'This is a subtitle' |
636 | - }); |
637 | -} |
638 | - |
639 | -})(); |
640 | - |
641 | -(function () { |
642 | - |
643 | -Flotr.ExampleList.add({ |
644 | - key : 'basic-bars', |
645 | - name : 'Basic Bars', |
646 | - callback : basic_bars |
647 | -}); |
648 | - |
649 | -Flotr.ExampleList.add({ |
650 | - key : 'basic-bars-horizontal', |
651 | - name : 'Horizontal Bars', |
652 | - args : [true], |
653 | - callback : basic_bars, |
654 | - tolerance : 5 |
655 | -}); |
656 | - |
657 | -function basic_bars (container, horizontal) { |
658 | - |
659 | - var |
660 | - horizontal = (horizontal ? true : false), // Show horizontal bars |
661 | - d1 = [], // First data series |
662 | - d2 = [], // Second data series |
663 | - point, // Data point variable declaration |
664 | - i; |
665 | - |
666 | - for (i = 0; i < 4; i++) { |
667 | - |
668 | - if (horizontal) { |
669 | - point = [Math.ceil(Math.random()*10), i]; |
670 | - } else { |
671 | - point = [i, Math.ceil(Math.random()*10)]; |
672 | - } |
673 | - |
674 | - d1.push(point); |
675 | - |
676 | - if (horizontal) { |
677 | - point = [Math.ceil(Math.random()*10), i+0.5]; |
678 | - } else { |
679 | - point = [i+0.5, Math.ceil(Math.random()*10)]; |
680 | - } |
681 | - |
682 | - d2.push(point); |
683 | - }; |
684 | - |
685 | - // Draw the graph |
686 | - Flotr.draw( |
687 | - container, |
688 | - [d1, d2], |
689 | - { |
690 | - bars : { |
691 | - show : true, |
692 | - horizontal : horizontal, |
693 | - shadowSize : 0, |
694 | - barWidth : 0.5 |
695 | - }, |
696 | - mouse : { |
697 | - track : true, |
698 | - relative : true |
699 | - }, |
700 | - yaxis : { |
701 | - min : 0, |
702 | - autoscaleMargin : 1 |
703 | - } |
704 | - } |
705 | - ); |
706 | -} |
707 | - |
708 | -})(); |
709 | - |
710 | -(function () { |
711 | - |
712 | -Flotr.ExampleList.add({ |
713 | - key : 'basic-bar-stacked', |
714 | - name : 'Stacked Bars', |
715 | - callback : bars_stacked |
716 | -}); |
717 | - |
718 | -Flotr.ExampleList.add({ |
719 | - key : 'basic-stacked-horizontal', |
720 | - name : 'Stacked Horizontal Bars', |
721 | - args : [true], |
722 | - callback : bars_stacked, |
723 | - tolerance : 5 |
724 | -}); |
725 | - |
726 | -function bars_stacked (container, horizontal) { |
727 | - |
728 | - var |
729 | - d1 = [], |
730 | - d2 = [], |
731 | - d3 = [], |
732 | - graph, i; |
733 | - |
734 | - for (i = -10; i < 10; i++) { |
735 | - if (horizontal) { |
736 | - d1.push([Math.random(), i]); |
737 | - d2.push([Math.random(), i]); |
738 | - d3.push([Math.random(), i]); |
739 | - } else { |
740 | - d1.push([i, Math.random()]); |
741 | - d2.push([i, Math.random()]); |
742 | - d3.push([i, Math.random()]); |
743 | - } |
744 | - } |
745 | - |
746 | - graph = Flotr.draw(container,[ |
747 | - { data : d1, label : 'Serie 1' }, |
748 | - { data : d2, label : 'Serie 2' }, |
749 | - { data : d3, label : 'Serie 3' } |
750 | - ], { |
751 | - legend : { |
752 | - backgroundColor : '#D2E8FF' // Light blue |
753 | - }, |
754 | - bars : { |
755 | - show : true, |
756 | - stacked : true, |
757 | - horizontal : horizontal, |
758 | - barWidth : 0.6, |
759 | - lineWidth : 1, |
760 | - shadowSize : 0 |
761 | - }, |
762 | - grid : { |
763 | - verticalLines : horizontal, |
764 | - horizontalLines : !horizontal |
765 | - } |
766 | - }); |
767 | -} |
768 | - |
769 | -})(); |
770 | - |
771 | -(function () { |
772 | - |
773 | -Flotr.ExampleList.add({ |
774 | - key : 'basic-pie', |
775 | - name : 'Basic Pie', |
776 | - callback : basic_pie |
777 | -}); |
778 | - |
779 | -function basic_pie (container) { |
780 | - |
781 | - var |
782 | - d1 = [[0, 4]], |
783 | - d2 = [[0, 3]], |
784 | - d3 = [[0, 1.03]], |
785 | - d4 = [[0, 3.5]], |
786 | - graph; |
787 | - |
788 | - graph = Flotr.draw(container, [ |
789 | - { data : d1, label : 'Comedy' }, |
790 | - { data : d2, label : 'Action' }, |
791 | - { data : d3, label : 'Romance', |
792 | - pie : { |
793 | - explode : 50 |
794 | - } |
795 | - }, |
796 | - { data : d4, label : 'Drama' } |
797 | - ], { |
798 | - HtmlText : false, |
799 | - grid : { |
800 | - verticalLines : false, |
801 | - horizontalLines : false |
802 | - }, |
803 | - xaxis : { showLabels : false }, |
804 | - yaxis : { showLabels : false }, |
805 | - pie : { |
806 | - show : true, |
807 | - explode : 6 |
808 | - }, |
809 | - mouse : { track : true }, |
810 | - legend : { |
811 | - position : 'se', |
812 | - backgroundColor : '#D2E8FF' |
813 | - } |
814 | - }); |
815 | -} |
816 | - |
817 | -})(); |
818 | - |
819 | -(function () { |
820 | - |
821 | -Flotr.ExampleList.add({ |
822 | - key : 'basic-radar', |
823 | - name : 'Basic Radar', |
824 | - callback : basic_radar |
825 | -}); |
826 | - |
827 | -function basic_radar (container) { |
828 | - |
829 | - // Fill series s1 and s2. |
830 | - var |
831 | - s1 = { label : 'Actual', data : [[0, 3], [1, 8], [2, 5], [3, 5], [4, 3], [5, 9]] }, |
832 | - s2 = { label : 'Target', data : [[0, 8], [1, 7], [2, 8], [3, 2], [4, 4], [5, 7]] }, |
833 | - graph, ticks; |
834 | - |
835 | - // Radar Labels |
836 | - ticks = [ |
837 | - [0, "Statutory"], |
838 | - [1, "External"], |
839 | - [2, "Videos"], |
840 | - [3, "Yippy"], |
841 | - [4, "Management"], |
842 | - [5, "oops"] |
843 | - ]; |
844 | - |
845 | - // Draw the graph. |
846 | - graph = Flotr.draw(container, [ s1, s2 ], { |
847 | - radar : { show : true}, |
848 | - grid : { circular : true, minorHorizontalLines : true}, |
849 | - yaxis : { min : 0, max : 10, minorTickFreq : 2}, |
850 | - xaxis : { ticks : ticks} |
851 | - }); |
852 | -} |
853 | - |
854 | -})(); |
855 | - |
856 | -(function () { |
857 | - |
858 | -Flotr.ExampleList.add({ |
859 | - key : 'basic-bubble', |
860 | - name : 'Basic Bubble', |
861 | - callback : basic_bubble |
862 | -}); |
863 | - |
864 | -function basic_bubble (container) { |
865 | - |
866 | - var |
867 | - d1 = [], |
868 | - d2 = [], |
869 | - point, graph, i; |
870 | - |
871 | - for (i = 0; i < 10; i++ ){ |
872 | - point = [i, Math.ceil(Math.random()*10), Math.ceil(Math.random()*10)]; |
873 | - d1.push(point); |
874 | - |
875 | - point = [i, Math.ceil(Math.random()*10), Math.ceil(Math.random()*10)]; |
876 | - d2.push(point); |
877 | - } |
878 | - |
879 | - // Draw the graph |
880 | - graph = Flotr.draw(container, [d1, d2], { |
881 | - bubbles : { show : true, baseRadius : 5 }, |
882 | - xaxis : { min : -4, max : 14 }, |
883 | - yaxis : { min : -4, max : 14 } |
884 | - }); |
885 | -} |
886 | - |
887 | -})(); |
888 | - |
889 | -(function () { |
890 | - |
891 | -Flotr.ExampleList.add({ |
892 | - key : 'basic-candle', |
893 | - name : 'Basic Candle', |
894 | - callback : basic_candle |
895 | -}); |
896 | - |
897 | -function basic_candle (container) { |
898 | - |
899 | - var |
900 | - d1 = [], |
901 | - price = 3.206, |
902 | - graph, |
903 | - i, a, b, c; |
904 | - |
905 | - for (i = 0; i < 50; i++) { |
906 | - a = Math.random(); |
907 | - b = Math.random(); |
908 | - c = (Math.random() * (a + b)) - b; |
909 | - d1.push([i, price, price + a, price - b, price + c]); |
910 | - price = price + c; |
911 | - } |
912 | - |
913 | - // Graph |
914 | - graph = Flotr.draw(container, [ d1 ], { |
915 | - candles : { show : true, candleWidth : 0.6 }, |
916 | - xaxis : { noTicks : 10 } |
917 | - }); |
918 | -} |
919 | - |
920 | -})(); |
921 | - |
922 | - |
923 | -(function () { |
924 | - |
925 | -Flotr.ExampleList.add({ |
926 | - key : 'basic-legend', |
927 | - name : 'Basic Legend', |
928 | - callback : basic_legend |
929 | -}); |
930 | - |
931 | -function basic_legend (container) { |
932 | - |
933 | - var |
934 | - d1 = [], |
935 | - d2 = [], |
936 | - d3 = [], |
937 | - data, |
938 | - graph, i; |
939 | - |
940 | - // Data Generation |
941 | - for (i = 0; i < 15; i += 0.5) { |
942 | - d1.push([i, i + Math.sin(i+Math.PI)]); |
943 | - d2.push([i, i]); |
944 | - d3.push([i, 15-Math.cos(i)]); |
945 | - } |
946 | - |
947 | - data = [ |
948 | - { data : d1, label :'x + sin(x+π)' }, |
949 | - { data : d2, label :'x' }, |
950 | - { data : d3, label :'15 - cos(x)' } |
951 | - ]; |
952 | - |
953 | - |
954 | - // This function prepend each label with 'y = ' |
955 | - function labelFn (label) { |
956 | - return 'y = ' + label; |
957 | - } |
958 | - |
959 | - // Draw graph |
960 | - graph = Flotr.draw(container, data, { |
961 | - legend : { |
962 | - position : 'se', // Position the legend 'south-east'. |
963 | - labelFormatter : labelFn, // Format the labels. |
964 | - backgroundColor : '#D2E8FF' // A light blue background color. |
965 | - }, |
966 | - HtmlText : false |
967 | - }); |
968 | -} |
969 | - |
970 | -})(); |
971 | - |
972 | -(function () { |
973 | - |
974 | -Flotr.ExampleList.add({ |
975 | - key : 'mouse-tracking', |
976 | - name : 'Mouse Tracking', |
977 | - callback : mouse_tracking |
978 | -}); |
979 | - |
980 | -function mouse_tracking (container) { |
981 | - |
982 | - var |
983 | - d1 = [], |
984 | - d2 = [], |
985 | - d3 = [], |
986 | - graph, i; |
987 | - |
988 | - for (i = 0; i < 20; i += 0.5) { |
989 | - d1.push([i, 2*i]); |
990 | - d2.push([i, i*1.5+1.5*Math.sin(i)]); |
991 | - d3.push([i, 3*Math.cos(i)+10]); |
992 | - } |
993 | - |
994 | - graph = Flotr.draw( |
995 | - container, |
996 | - [ |
997 | - { |
998 | - data : d1, |
999 | - mouse : { track : false } // Disable mouse tracking for d1 |
1000 | - }, |
1001 | - d2, |
1002 | - d3 |
1003 | - ], |
1004 | - { |
1005 | - mouse : { |
1006 | - track : true, // Enable mouse tracking |
1007 | - lineColor : 'purple', |
1008 | - relative : true, |
1009 | - position : 'ne', |
1010 | - sensibility : 1, |
1011 | - trackDecimals : 2, |
1012 | - trackFormatter : function (o) { return 'x = ' + o.x +', y = ' + o.y; } |
1013 | - }, |
1014 | - crosshair : { |
1015 | - mode : 'xy' |
1016 | - } |
1017 | - } |
1018 | - ); |
1019 | - |
1020 | -}; |
1021 | - |
1022 | -})(); |
1023 | - |
1024 | -(function () { |
1025 | - |
1026 | -Flotr.ExampleList.add({ |
1027 | - key : 'mouse-zoom', |
1028 | - name : 'Mouse Zoom', |
1029 | - callback : mouse_zoom, |
1030 | - description : "<p>Select an area of the graph to zoom. Click to reset the chart.</p>" |
1031 | -}); |
1032 | - |
1033 | -function mouse_zoom (container) { |
1034 | - |
1035 | - var |
1036 | - d1 = [], |
1037 | - d2 = [], |
1038 | - d3 = [], |
1039 | - options, |
1040 | - graph, |
1041 | - i; |
1042 | - |
1043 | - for (i = 0; i < 40; i += 0.5) { |
1044 | - d1.push([i, Math.sin(i)+3*Math.cos(i)]); |
1045 | - d2.push([i, Math.pow(1.1, i)]); |
1046 | - d3.push([i, 40 - i+Math.random()*10]); |
1047 | - } |
1048 | - |
1049 | - options = { |
1050 | - selection : { mode : 'x', fps : 30 }, |
1051 | - title : 'Mouse Zoom' |
1052 | - }; |
1053 | - |
1054 | - // Draw graph with default options, overwriting with passed options |
1055 | - function drawGraph (opts) { |
1056 | - |
1057 | - // Clone the options, so the 'options' variable always keeps intact. |
1058 | - var o = Flotr._.extend(Flotr._.clone(options), opts || {}); |
1059 | - |
1060 | - // Return a new graph. |
1061 | - return Flotr.draw( |
1062 | - container, |
1063 | - [ d1, d2, d3 ], |
1064 | - o |
1065 | - ); |
1066 | - } |
1067 | - |
1068 | - // Actually draw the graph. |
1069 | - graph = drawGraph(); |
1070 | - |
1071 | - // Hook into the 'flotr:select' event. |
1072 | - Flotr.EventAdapter.observe(container, 'flotr:select', function (area) { |
1073 | - |
1074 | - // Draw graph with new area |
1075 | - f = drawGraph({ |
1076 | - xaxis: {min:area.x1, max:area.x2}, |
1077 | - yaxis: {min:area.y1, max:area.y2} |
1078 | - }); |
1079 | - |
1080 | - }); |
1081 | - |
1082 | - // When graph is clicked, draw the graph with default area. |
1083 | - Flotr.EventAdapter.observe(container, 'flotr:click', function () { drawGraph(); }); |
1084 | -}; |
1085 | - |
1086 | -})(); |
1087 | - |
1088 | - |
1089 | -(function () { |
1090 | - |
1091 | -Flotr.ExampleList.add({ |
1092 | - key : 'mouse-drag', |
1093 | - name : 'Mouse Drag', |
1094 | - callback : mouse_drag |
1095 | -}); |
1096 | - |
1097 | -function mouse_drag (container) { |
1098 | - |
1099 | - var |
1100 | - d1 = [], |
1101 | - d2 = [], |
1102 | - d3 = [], |
1103 | - options, |
1104 | - graph, |
1105 | - start, |
1106 | - i; |
1107 | - |
1108 | - for (i = -40; i < 40; i += 0.5) { |
1109 | - d1.push([i, Math.sin(i)+3*Math.cos(i)]); |
1110 | - d2.push([i, Math.pow(1.1, i)]); |
1111 | - d3.push([i, 40 - i+Math.random()*10]); |
1112 | - } |
1113 | - |
1114 | - options = { |
1115 | - xaxis: {min: 0, max: 20}, |
1116 | - title : 'Mouse Drag' |
1117 | - }; |
1118 | - |
1119 | - // Draw graph with default options, overwriting with passed options |
1120 | - function drawGraph (opts) { |
1121 | - |
1122 | - // Clone the options, so the 'options' variable always keeps intact. |
1123 | - var o = Flotr._.extend(Flotr._.clone(options), opts || {}); |
1124 | - |
1125 | - // Return a new graph. |
1126 | - return Flotr.draw( |
1127 | - container, |
1128 | - [ d1, d2, d3 ], |
1129 | - o |
1130 | - ); |
1131 | - } |
1132 | - |
1133 | - graph = drawGraph(); |
1134 | - |
1135 | - function initializeDrag (e) { |
1136 | - start = graph.getEventPosition(e); |
1137 | - Flotr.EventAdapter.observe(document, 'mousemove', move); |
1138 | - Flotr.EventAdapter.observe(document, 'mouseup', stopDrag); |
1139 | - } |
1140 | - |
1141 | - function move (e) { |
1142 | - var |
1143 | - end = graph.getEventPosition(e), |
1144 | - xaxis = graph.axes.x, |
1145 | - offset = start.x - end.x; |
1146 | - |
1147 | - graph = drawGraph({ |
1148 | - xaxis : { |
1149 | - min : xaxis.min + offset, |
1150 | - max : xaxis.max + offset |
1151 | - } |
1152 | - }); |
1153 | - // @todo: refector initEvents in order not to remove other observed events |
1154 | - Flotr.EventAdapter.observe(graph.overlay, 'mousedown', initializeDrag); |
1155 | - } |
1156 | - |
1157 | - function stopDrag () { |
1158 | - Flotr.EventAdapter.stopObserving(document, 'mousemove', move); |
1159 | - } |
1160 | - |
1161 | - Flotr.EventAdapter.observe(graph.overlay, 'mousedown', initializeDrag); |
1162 | - |
1163 | -}; |
1164 | - |
1165 | -})(); |
1166 | - |
1167 | -(function () { |
1168 | - |
1169 | -Flotr.ExampleList.add({ |
1170 | - key : 'basic-time', |
1171 | - name : 'Basic Time', |
1172 | - callback : basic_time, |
1173 | - description : "<p>Select an area of the graph to zoom. Click to reset the chart.</p>" |
1174 | -}); |
1175 | - |
1176 | -function basic_time (container) { |
1177 | - |
1178 | - var |
1179 | - d1 = [], |
1180 | - start = new Date("2009/01/01 01:00").getTime(), |
1181 | - options, |
1182 | - graph, |
1183 | - i, x, o; |
1184 | - |
1185 | - for (i = 0; i < 100; i++) { |
1186 | - x = start+(i*1000*3600*24*36.5); |
1187 | - d1.push([x, i+Math.random()*30+Math.sin(i/20+Math.random()*2)*20+Math.sin(i/10+Math.random())*10]); |
1188 | - } |
1189 | - |
1190 | - options = { |
1191 | - xaxis : { |
1192 | - mode : 'time', |
1193 | - labelsAngle : 45 |
1194 | - }, |
1195 | - selection : { |
1196 | - mode : 'x' |
1197 | - }, |
1198 | - HtmlText : false, |
1199 | - title : 'Time' |
1200 | - }; |
1201 | - |
1202 | - // Draw graph with default options, overwriting with passed options |
1203 | - function drawGraph (opts) { |
1204 | - |
1205 | - // Clone the options, so the 'options' variable always keeps intact. |
1206 | - o = Flotr._.extend(Flotr._.clone(options), opts || {}); |
1207 | - |
1208 | - // Return a new graph. |
1209 | - return Flotr.draw( |
1210 | - container, |
1211 | - [ d1 ], |
1212 | - o |
1213 | - ); |
1214 | - } |
1215 | - |
1216 | - graph = drawGraph(); |
1217 | - |
1218 | - Flotr.EventAdapter.observe(container, 'flotr:select', function(area){ |
1219 | - // Draw selected area |
1220 | - graph = drawGraph({ |
1221 | - xaxis : { min : area.x1, max : area.x2, mode : 'time', labelsAngle : 45 }, |
1222 | - yaxis : { min : area.y1, max : area.y2 } |
1223 | - }); |
1224 | - }); |
1225 | - |
1226 | - // When graph is clicked, draw the graph with default area. |
1227 | - Flotr.EventAdapter.observe(container, 'flotr:click', function () { graph = drawGraph(); }); |
1228 | -}; |
1229 | - |
1230 | -})(); |
1231 | - |
1232 | -(function () { |
1233 | - |
1234 | -Flotr.ExampleList.add({ |
1235 | - key : 'negative-values', |
1236 | - name : 'Negative Values', |
1237 | - callback : negative_values |
1238 | -}); |
1239 | - |
1240 | -function negative_values (container) { |
1241 | - |
1242 | - var |
1243 | - d0 = [], // Line through y = 0 |
1244 | - d1 = [], // Random data presented as a scatter plot. |
1245 | - d2 = [], // A regression line for the scatter. |
1246 | - sx = 0, |
1247 | - sy = 0, |
1248 | - sxy = 0, |
1249 | - sxsq = 0, |
1250 | - xmean, |
1251 | - ymean, |
1252 | - alpha, |
1253 | - beta, |
1254 | - n, x, y; |
1255 | - |
1256 | - for (n = 0; n < 20; n++){ |
1257 | - |
1258 | - x = n; |
1259 | - y = x + Math.random()*8 - 15; |
1260 | - |
1261 | - d0.push([x, 0]); |
1262 | - d1.push([x, y]); |
1263 | - |
1264 | - // Computations used for regression line |
1265 | - sx += x; |
1266 | - sy += y; |
1267 | - sxy += x*y; |
1268 | - sxsq += Math.pow(x,2); |
1269 | - } |
1270 | - |
1271 | - xmean = sx/n; |
1272 | - ymean = sy/n; |
1273 | - beta = ((n*sxy) - (sx*sy))/((n*sxsq)-(Math.pow(sx,2))); |
1274 | - alpha = ymean - (beta * xmean); |
1275 | - |
1276 | - // Compute the regression line. |
1277 | - for (n = 0; n < 20; n++){ |
1278 | - d2.push([n, alpha + beta*n]) |
1279 | - } |
1280 | - |
1281 | - // Draw the graph |
1282 | - graph = Flotr.draw( |
1283 | - container, [ |
1284 | - { data : d0, shadowSize : 0, color : '#545454' }, // Horizontal |
1285 | - { data : d1, label : 'y = x + (Math.random() * 8) - 15', points : { show : true } }, // Scatter |
1286 | - { data : d2, label : 'y = ' + alpha.toFixed(2) + ' + ' + beta.toFixed(2) + '*x' } // Regression |
1287 | - ], |
1288 | - { |
1289 | - legend : { position : 'se', backgroundColor : '#D2E8FF' }, |
1290 | - title : 'Negative Values' |
1291 | - } |
1292 | - ); |
1293 | -}; |
1294 | - |
1295 | -})(); |
1296 | - |
1297 | -(function () { |
1298 | - |
1299 | -Flotr.ExampleList.add({ |
1300 | - key : 'click-example', |
1301 | - name : 'Click Example', |
1302 | - callback : click_example |
1303 | -}); |
1304 | - |
1305 | -function click_example (container) { |
1306 | - |
1307 | - var |
1308 | - d1 = [[0,0]], // Point at origin |
1309 | - options, |
1310 | - graph; |
1311 | - |
1312 | - options = { |
1313 | - xaxis: {min: 0, max: 15}, |
1314 | - yaxis: {min: 0, max: 15}, |
1315 | - lines: {show: true}, |
1316 | - points: {show: true}, |
1317 | - mouse: {track:true}, |
1318 | - title: 'Click Example' |
1319 | - }; |
1320 | - |
1321 | - graph = Flotr.draw(container, [d1], options); |
1322 | - |
1323 | - // Add a point to the series and redraw the graph |
1324 | - Flotr.EventAdapter.observe(container, 'flotr:click', function(position){ |
1325 | - |
1326 | - // Add a point to the series at the location of the click |
1327 | - d1.push([position.x, position.y]); |
1328 | - |
1329 | - // Sort the series. |
1330 | - d1 = d1.sort(function (a, b) { return a[0] - b[0]; }); |
1331 | - |
1332 | - // Redraw the graph, with the new series. |
1333 | - graph = Flotr.draw(container, [d1], options); |
1334 | - }); |
1335 | -}; |
1336 | - |
1337 | -})(); |
1338 | - |
1339 | -(function () { |
1340 | - |
1341 | -Flotr.ExampleList.add({ |
1342 | - key : 'download-image', |
1343 | - name : 'Download Image', |
1344 | - callback : download_image, |
1345 | - description : '' + |
1346 | - '<form name="image-download" id="image-download" action="" onsubmit="return false">' + |
1347 | - '<label><input type="radio" name="format" value="png" checked="checked" /> PNG</label>' + |
1348 | - '<label><input type="radio" name="format" value="jpeg" /> JPEG</label>' + |
1349 | - |
1350 | - '<button name="to-image" onclick="CurrentExample(\'to-image\')">To Image</button>' + |
1351 | - '<button name="download" onclick="CurrentExample(\'download\')">Download</button>' + |
1352 | - '<button name="reset" onclick="CurrentExample(\'reset\')">Reset</button>' + |
1353 | - '</form>' |
1354 | -}); |
1355 | - |
1356 | -function download_image (container) { |
1357 | - |
1358 | - var |
1359 | - d1 = [], |
1360 | - d2 = [], |
1361 | - d3 = [], |
1362 | - d4 = [], |
1363 | - d5 = [], |
1364 | - graph, |
1365 | - i; |
1366 | - |
1367 | - for (i = 0; i <= 10; i += 0.1) { |
1368 | - d1.push([i, 4 + Math.pow(i,1.5)]); |
1369 | - d2.push([i, Math.pow(i,3)]); |
1370 | - d3.push([i, i*5+3*Math.sin(i*4)]); |
1371 | - d4.push([i, i]); |
1372 | - if( i.toFixed(1)%1 == 0 ){ |
1373 | - d5.push([i, 2*i]); |
1374 | - } |
1375 | - } |
1376 | - |
1377 | - // Draw the graph |
1378 | - graph = Flotr.draw( |
1379 | - container,[ |
1380 | - {data:d1, label:'y = 4 + x^(1.5)', lines:{fill:true}}, |
1381 | - {data:d2, label:'y = x^3', yaxis:2}, |
1382 | - {data:d3, label:'y = 5x + 3sin(4x)'}, |
1383 | - {data:d4, label:'y = x'}, |
1384 | - {data:d5, label:'y = 2x', lines: {show: true}, points: {show: true}} |
1385 | - ],{ |
1386 | - title: 'Download Image Example', |
1387 | - subtitle: 'You can save me as an image', |
1388 | - xaxis:{ |
1389 | - noTicks: 7, // Display 7 ticks. |
1390 | - tickFormatter: function(n){ return '('+n+')'; }, // => displays tick values between brackets. |
1391 | - min: 1, // => part of the series is not displayed. |
1392 | - max: 7.5, // => part of the series is not displayed. |
1393 | - labelsAngle: 45, |
1394 | - title: 'x Axis' |
1395 | - }, |
1396 | - yaxis:{ |
1397 | - ticks: [[0, "Lower"], 10, 20, 30, [40, "Upper"]], |
1398 | - max: 40, |
1399 | - title: 'y = f(x)' |
1400 | - }, |
1401 | - y2axis:{color:'#FF0000', max: 500, title: 'y = x^3'}, |
1402 | - grid:{ |
1403 | - verticalLines: false, |
1404 | - backgroundColor: 'white' |
1405 | - }, |
1406 | - HtmlText: false, |
1407 | - legend: { |
1408 | - position: 'nw' |
1409 | - } |
1410 | - }); |
1411 | - |
1412 | - this.CurrentExample = function (operation) { |
1413 | - |
1414 | - var |
1415 | - format = $('#image-download input:radio[name=format]:checked').val(); |
1416 | - if (Flotr.isIE && Flotr.isIE < 9) { |
1417 | - alert( |
1418 | - "Your browser doesn't allow you to get a bitmap image from the plot, " + |
1419 | - "you can only get a VML image that you can use in Microsoft Office.<br />" |
1420 | - ); |
1421 | - } |
1422 | - |
1423 | - if (operation == 'to-image') { |
1424 | - graph.download.saveImage(format, null, null, true) |
1425 | - } else if (operation == 'download') { |
1426 | - graph.download.saveImage(format); |
1427 | - } else if (operation == 'reset') { |
1428 | - graph.download.restoreCanvas(); |
1429 | - } |
1430 | - }; |
1431 | - |
1432 | - return graph; |
1433 | -}; |
1434 | - |
1435 | -})(); |
1436 | - |
1437 | -(function () { |
1438 | - |
1439 | -Flotr.ExampleList.add({ |
1440 | - key : 'download-data', |
1441 | - name : 'Download Data', |
1442 | - callback : download_data |
1443 | -}); |
1444 | - |
1445 | -function download_data (container) { |
1446 | - |
1447 | - var |
1448 | - d1 = [], |
1449 | - d2 = [], |
1450 | - d3 = [], |
1451 | - d4 = [], |
1452 | - d5 = [], |
1453 | - graph, |
1454 | - i,x; |
1455 | - |
1456 | - for (i = 0; i <= 100; i += 1) { |
1457 | - x = i / 10; |
1458 | - d1.push([x, 4 + Math.pow(x,1.5)]); |
1459 | - d2.push([x, Math.pow(x,3)]); |
1460 | - d3.push([x, i*5+3*Math.sin(x*4)]); |
1461 | - d4.push([x, x]); |
1462 | - if(x%1 === 0 ){ |
1463 | - d5.push([x, 2*x]); |
1464 | - } |
1465 | - } |
1466 | - |
1467 | - // Draw the graph. |
1468 | - graph = Flotr.draw( |
1469 | - container, [ |
1470 | - { data : d1, label : 'y = 4 + x^(1.5)', lines : { fill : true } }, |
1471 | - { data : d2, label : 'y = x^3' }, |
1472 | - { data : d3, label : 'y = 5x + 3sin(4x)' }, |
1473 | - { data : d4, label : 'y = x' }, |
1474 | - { data : d5, label : 'y = 2x', lines : { show : true }, points : { show : true } } |
1475 | - ],{ |
1476 | - xaxis : { |
1477 | - noTicks : 7, |
1478 | - tickFormatter : function (n) { return '('+n+')'; }, |
1479 | - min: 1, // Part of the series is not displayed. |
1480 | - max: 7.5 |
1481 | - }, |
1482 | - yaxis : { |
1483 | - ticks : [[ 0, "Lower"], 10, 20, 30, [40, "Upper"]], |
1484 | - max : 40 |
1485 | - }, |
1486 | - grid : { |
1487 | - verticalLines : false, |
1488 | - backgroundColor : 'white' |
1489 | - }, |
1490 | - legend : { |
1491 | - position : 'nw' |
1492 | - }, |
1493 | - spreadsheet : { |
1494 | - show : true, |
1495 | - tickFormatter : function (e) { return e+''; } |
1496 | - } |
1497 | - }); |
1498 | -}; |
1499 | - |
1500 | -})(); |
1501 | - |
1502 | -(function () { |
1503 | - |
1504 | -Flotr.ExampleList.add({ |
1505 | - key : 'advanced-titles', |
1506 | - name : 'Advanced Titles', |
1507 | - callback : advanced_titles |
1508 | -}); |
1509 | - |
1510 | -function advanced_titles (container) { |
1511 | - |
1512 | - var |
1513 | - d1 = [], |
1514 | - d2 = [], |
1515 | - d3 = [], |
1516 | - d4 = [], |
1517 | - d5 = [], |
1518 | - graph, |
1519 | - i; |
1520 | - |
1521 | - for (i = 0; i <= 10; i += 0.1) { |
1522 | - d1.push([i, 4 + Math.pow(i,1.5)]); |
1523 | - d2.push([i, Math.pow(i,3)]); |
1524 | - d3.push([i, i*5+3*Math.sin(i*4)]); |
1525 | - d4.push([i, i]); |
1526 | - if (i.toFixed(1)%1 == 0) { |
1527 | - d5.push([i, 2*i]); |
1528 | - } |
1529 | - } |
1530 | - |
1531 | - // Draw the graph. |
1532 | - graph = Flotr.draw( |
1533 | - container,[ |
1534 | - { data : d1, label : 'y = 4 + x^(1.5)', lines : { fill : true } }, |
1535 | - { data : d2, label : 'y = x^3', yaxis : 2 }, |
1536 | - { data : d3, label : 'y = 5x + 3sin(4x)' }, |
1537 | - { data : d4, label : 'y = x' }, |
1538 | - { data : d5, label : 'y = 2x', lines : { show : true }, points : { show : true } } |
1539 | - ], { |
1540 | - title : 'Advanced Titles Example', |
1541 | - subtitle : 'You can save me as an image', |
1542 | - xaxis : { |
1543 | - noTicks : 7, |
1544 | - tickFormatter : function (n) { return '('+n+')'; }, |
1545 | - min : 1, |
1546 | - max : 7.5, |
1547 | - labelsAngle : 45, |
1548 | - title : 'x Axis' |
1549 | - }, |
1550 | - yaxis : { |
1551 | - ticks : [[0, "Lower"], 10, 20, 30, [40, "Upper"]], |
1552 | - max : 40, |
1553 | - title : 'y = f(x)' |
1554 | - }, |
1555 | - y2axis : { color : '#FF0000', max : 500, title : 'y = x^3' }, |
1556 | - grid : { |
1557 | - verticalLines : false, |
1558 | - backgroundColor : 'white' |
1559 | - }, |
1560 | - HtmlText : false, |
1561 | - legend : { |
1562 | - position : 'nw' |
1563 | - } |
1564 | - }); |
1565 | -}; |
1566 | - |
1567 | -})(); |
1568 | - |
1569 | -(function () { |
1570 | - |
1571 | -Flotr.ExampleList.add({ |
1572 | - key : 'color-gradients', |
1573 | - name : 'Color Gradients', |
1574 | - callback : color_gradients |
1575 | -}); |
1576 | - |
1577 | -function color_gradients (container) { |
1578 | - |
1579 | - var |
1580 | - bars = { |
1581 | - data: [], |
1582 | - bars: { |
1583 | - show: true, |
1584 | - barWidth: 0.8, |
1585 | - lineWidth: 0, |
1586 | - fillColor: { |
1587 | - colors: ['#CB4B4B', '#fff'], |
1588 | - start: 'top', |
1589 | - end: 'bottom' |
1590 | - }, |
1591 | - fillOpacity: 0.8 |
1592 | - } |
1593 | - }, markers = { |
1594 | - data: [], |
1595 | - markers: { |
1596 | - show: true, |
1597 | - position: 'ct' |
1598 | - } |
1599 | - }, lines = { |
1600 | - data: [], |
1601 | - lines: { |
1602 | - show: true, |
1603 | - fillColor: ['#00A8F0', '#fff'], |
1604 | - fill: true, |
1605 | - fillOpacity: 1 |
1606 | - } |
1607 | - }, |
1608 | - point, |
1609 | - graph, |
1610 | - i; |
1611 | - |
1612 | - for (i = 0; i < 8; i++) { |
1613 | - point = [i, Math.ceil(Math.random() * 10)]; |
1614 | - bars.data.push(point); |
1615 | - markers.data.push(point); |
1616 | - } |
1617 | - |
1618 | - for (i = -1; i < 9; i += 0.01){ |
1619 | - lines.data.push([i, i*i/8+2]); |
1620 | - } |
1621 | - |
1622 | - graph = Flotr.draw( |
1623 | - container, |
1624 | - [lines, bars, markers], { |
1625 | - yaxis: { |
1626 | - min: 0, |
1627 | - max: 11 |
1628 | - }, |
1629 | - xaxis: { |
1630 | - min: -0.5, |
1631 | - max: 7.5 |
1632 | - }, |
1633 | - grid: { |
1634 | - verticalLines: false, |
1635 | - backgroundColor: ['#fff', '#ccc'] |
1636 | - } |
1637 | - } |
1638 | - ); |
1639 | -}; |
1640 | - |
1641 | -})(); |
1642 | - |
1643 | - |
1644 | -(function () { |
1645 | - |
1646 | -Flotr.ExampleList.add({ |
1647 | - key : 'profile-bars', |
1648 | - name : 'Profile Bars', |
1649 | - type : 'profile', |
1650 | - callback : profile_bars |
1651 | -}); |
1652 | - |
1653 | -/* |
1654 | -Flotr.ExampleList.add({ |
1655 | - key : 'basic-bars-horizontal', |
1656 | - name : 'Horizontal Bars', |
1657 | - args : [true], |
1658 | - callback : basic_bars |
1659 | -}); |
1660 | -*/ |
1661 | - |
1662 | -function profile_bars (container, horizontal) { |
1663 | - |
1664 | - var |
1665 | - horizontal = (horizontal ? true : false), // Show horizontal bars |
1666 | - d1 = [], // First data series |
1667 | - d2 = [], // Second data series |
1668 | - point, // Data point variable declaration |
1669 | - i; |
1670 | - |
1671 | - for (i = 0; i < 5000; i++) { |
1672 | - |
1673 | - if (horizontal) { |
1674 | - point = [Math.ceil(Math.random()*10), i]; |
1675 | - } else { |
1676 | - point = [i, Math.ceil(Math.random()*10)]; |
1677 | - } |
1678 | - |
1679 | - d1.push(point); |
1680 | - |
1681 | - if (horizontal) { |
1682 | - point = [Math.ceil(Math.random()*10), i+0.5]; |
1683 | - } else { |
1684 | - point = [i+0.5, Math.ceil(Math.random()*10)]; |
1685 | - } |
1686 | - |
1687 | - d2.push(point); |
1688 | - }; |
1689 | - |
1690 | - // Draw the graph |
1691 | - Flotr.draw( |
1692 | - container, |
1693 | - [d1, d2], |
1694 | - { |
1695 | - bars : { |
1696 | - show : true, |
1697 | - horizontal : horizontal, |
1698 | - barWidth : 0.5 |
1699 | - }, |
1700 | - mouse : { |
1701 | - track : true, |
1702 | - relative : true |
1703 | - }, |
1704 | - yaxis : { |
1705 | - min : 0, |
1706 | - autoscaleMargin : 1 |
1707 | - } |
1708 | - } |
1709 | - ); |
1710 | -} |
1711 | - |
1712 | -})(); |
1713 | - |
1714 | -(function () { |
1715 | - |
1716 | -Flotr.ExampleList.add({ |
1717 | - key : 'basic-timeline', |
1718 | - name : 'Basic Timeline', |
1719 | - callback : basic_timeline |
1720 | -}); |
1721 | - |
1722 | -function basic_timeline (container) { |
1723 | - |
1724 | - var |
1725 | - d1 = [[1, 4, 5]], |
1726 | - d2 = [[3.2, 3, 4]], |
1727 | - d3 = [[1.9, 2, 2], [5, 2, 3.3]], |
1728 | - d4 = [[1.55, 1, 9]], |
1729 | - d5 = [[5, 0, 2.3]], |
1730 | - data = [], |
1731 | - timeline = { show : true, barWidth : .5 }, |
1732 | - markers = [], |
1733 | - labels = ['Obama', 'Bush', 'Clinton', 'Palin', 'McCain'], |
1734 | - i, graph, point; |
1735 | - |
1736 | - // Timeline |
1737 | - Flotr._.each([d1, d2, d3, d4, d5], function (d) { |
1738 | - data.push({ |
1739 | - data : d, |
1740 | - timeline : Flotr._.clone(timeline) |
1741 | - }); |
1742 | - }); |
1743 | - |
1744 | - // Markers |
1745 | - Flotr._.each([d1, d2, d3, d4, d5], function (d) { |
1746 | - point = d[0]; |
1747 | - markers.push([point[0], point[1]]); |
1748 | - }); |
1749 | - data.push({ |
1750 | - data: markers, |
1751 | - markers: { |
1752 | - show: true, |
1753 | - position: 'rm', |
1754 | - fontSize: 11, |
1755 | - labelFormatter : function (o) { return labels[o.index]; } |
1756 | - } |
1757 | - }); |
1758 | - |
1759 | - // Draw Graph |
1760 | - graph = Flotr.draw(container, data, { |
1761 | - xaxis: { |
1762 | - noTicks: 3, |
1763 | - tickFormatter: function (x) { |
1764 | - var |
1765 | - x = parseInt(x), |
1766 | - months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
1767 | - return months[(x-1)%12]; |
1768 | - } |
1769 | - }, |
1770 | - yaxis: { |
1771 | - showLabels : false |
1772 | - }, |
1773 | - grid: { |
1774 | - horizontalLines : false |
1775 | - } |
1776 | - }); |
1777 | -} |
1778 | - |
1779 | -})(); |
1780 | - |
1781 | -(function () { |
1782 | - |
1783 | -Flotr.ExampleList.add({ |
1784 | - key : 'advanced-markers', |
1785 | - name : 'Advanced Markers', |
1786 | - callback : advanced_markers, |
1787 | - timeout : 150 |
1788 | -}); |
1789 | - |
1790 | -function advanced_markers (container) { |
1791 | - |
1792 | - var |
1793 | - xmark = new Image(), |
1794 | - checkmark = new Image(), |
1795 | - bars = { |
1796 | - data: [], |
1797 | - bars: { |
1798 | - show: true, |
1799 | - barWidth: 0.6, |
1800 | - lineWidth: 0, |
1801 | - fillOpacity: 0.8 |
1802 | - } |
1803 | - }, markers = { |
1804 | - data: [], |
1805 | - markers: { |
1806 | - show: true, |
1807 | - position: 'ct', |
1808 | - labelFormatter: function (o) { |
1809 | - return (o.y >= 5) ? checkmark : xmark; |
1810 | - } |
1811 | - } |
1812 | - }, |
1813 | - flotr = Flotr, |
1814 | - point, |
1815 | - graph, |
1816 | - i; |
1817 | - |
1818 | - |
1819 | - for (i = 0; i < 8; i++) { |
1820 | - point = [i, Math.ceil(Math.random() * 10)]; |
1821 | - bars.data.push(point); |
1822 | - markers.data.push(point); |
1823 | - } |
1824 | - |
1825 | - var runner = function () { |
1826 | - if (!xmark.complete || !checkmark.complete) { |
1827 | - setTimeout(runner, 50); |
1828 | - return; |
1829 | - } |
1830 | - |
1831 | - graph = flotr.draw( |
1832 | - container, |
1833 | - [bars, markers], { |
1834 | - yaxis: { |
1835 | - min: 0, |
1836 | - max: 11 |
1837 | - }, |
1838 | - xaxis: { |
1839 | - min: -0.5, |
1840 | - max: 7.5 |
1841 | - }, |
1842 | - grid: { |
1843 | - verticalLines: false |
1844 | - } |
1845 | - } |
1846 | - ); |
1847 | - } |
1848 | - |
1849 | - xmark.onload = runner; |
1850 | - xmark.src = 'images/xmark.png'; |
1851 | - checkmark.src = 'images/checkmark.png'; |
1852 | -}; |
1853 | - |
1854 | -})(); |
1855 | - |
1856 | |
1857 | === removed file 'addons/web_graph/static/lib/flotr2/flotr2.ie.min.js' |
1858 | --- addons/web_graph/static/lib/flotr2/flotr2.ie.min.js 2012-05-07 08:19:08 +0000 |
1859 | +++ addons/web_graph/static/lib/flotr2/flotr2.ie.min.js 1970-01-01 00:00:00 +0000 |
1860 | @@ -1,33 +0,0 @@ |
1861 | -// Copyright 2006 Google Inc. |
1862 | -// |
1863 | -// Licensed under the Apache License, Version 2.0 (the "License"); |
1864 | -// you may not use this file except in compliance with the License. |
1865 | -// You may obtain a copy of the License at |
1866 | -// |
1867 | -// http://www.apache.org/licenses/LICENSE-2.0 |
1868 | -// |
1869 | -// Unless required by applicable law or agreed to in writing, software |
1870 | -// distributed under the License is distributed on an "AS IS" BASIS, |
1871 | -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
1872 | -// See the License for the specific language governing permissions and |
1873 | -// limitations under the License. |
1874 | -// Known Issues: |
1875 | -// |
1876 | -// * Patterns only support repeat. |
1877 | -// * Radial gradient are not implemented. The VML version of these look very |
1878 | -// different from the canvas one. |
1879 | -// * Clipping paths are not implemented. |
1880 | -// * Coordsize. The width and height attribute have higher priority than the |
1881 | -// width and height style values which isn't correct. |
1882 | -// * Painting mode isn't implemented. |
1883 | -// * Canvas width/height should is using content-box by default. IE in |
1884 | -// Quirks mode will draw the canvas using border-box. Either change your |
1885 | -// doctype to HTML5 |
1886 | -// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) |
1887 | -// or use Box Sizing Behavior from WebFX |
1888 | -// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) |
1889 | -// * Non uniform scaling does not correctly scale strokes. |
1890 | -// * Optimize. There is always room for speed improvements. |
1891 | -// Only add this code if we do not already have a canvas implementation |
1892 | - |
1893 | -document.createElement("canvas").getContext||function(){function j(){return this.context_||(this.context_=new N(this))}function l(a,b,c){var d=k.call(arguments,2);return function(){return a.apply(b,d.concat(k.call(arguments)))}}function m(a){return String(a).replace(/&/g,"&").replace(/"/g,""")}function n(a,b,c){a.namespaces[b]||a.namespaces.add(b,c,"#default#VML")}function o(a){n(a,"g_vml_","urn:schemas-microsoft-com:vml"),n(a,"g_o_","urn:schemas-microsoft-com:office:office");if(!a.styleSheets.ex_canvas_){var b=a.createStyleSheet();b.owningElement.id="ex_canvas_",b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}function q(a){var b=a.srcElement;switch(a.propertyName){case"width":b.getContext().clearRect(),b.style.width=b.attributes.width.nodeValue+"px",b.firstChild&&(b.firstChild.style.width=b.clientWidth+"px");break;case"height":b.getContext().clearRect(),b.style.height=b.attributes.height.nodeValue+"px",b.firstChild&&(b.firstChild.style.height=b.clientHeight+"px")}}function r(a){var b=a.srcElement;b.firstChild&&(b.firstChild.style.width=b.clientWidth+"px",b.firstChild.style.height=b.clientHeight+"px")}function v(){return[[1,0,0],[0,1,0],[0,0,1]]}function w(a,b){var c=v();for(var d=0;d<3;d++)for(var e=0;e<3;e++){var f=0;for(var g=0;g<3;g++)f+=a[d][g]*b[g][e];c[d][e]=f}return c}function x(a,b){b.fillStyle=a.fillStyle,b.lineCap=a.lineCap,b.lineJoin=a.lineJoin,b.lineWidth=a.lineWidth,b.miterLimit=a.miterLimit,b.shadowBlur=a.shadowBlur,b.shadowColor=a.shadowColor,b.shadowOffsetX=a.shadowOffsetX,b.shadowOffsetY=a.shadowOffsetY,b.strokeStyle=a.strokeStyle,b.globalAlpha=a.globalAlpha,b.font=a.font,b.textAlign=a.textAlign,b.textBaseline=a.textBaseline,b.arcScaleX_=a.arcScaleX_,b.arcScaleY_=a.arcScaleY_,b.lineScale_=a.lineScale_}function z(a){var b=a.indexOf("(",3),c=a.indexOf(")",b+1),d=a.substring(b+1,c).split(",");if(d.length!=4||a.charAt(3)!="a")d[3]=1;return d}function A(a){return parseFloat(a)/100}function B(a,b,c){return Math.min(c,Math.max(b,a))}function C(a){var b,c,d,e,f,g;e=parseFloat(a[0])/360%360,e<0&&e++,f=B(A(a[1]),0,1),g=B(A(a[2]),0,1);if(f==0)b=c=d=g;else{var h=g<.5?g*(1+f):g+f-g*f,i=2*g-h;b=D(i,h,e+1/3),c=D(i,h,e),d=D(i,h,e-1/3)}return"#"+s[Math.floor(b*255)]+s[Math.floor(c*255)]+s[Math.floor(d*255)]}function D(a,b,c){return c<0&&c++,c>1&&c--,6*c<1?a+(b-a)*6*c:2*c<1?b:3*c<2?a+(b-a)*(2/3-c)*6:a}function F(a){if(a in E)return E[a];var b,c=1;a=String(a);if(a.charAt(0)=="#")b=a;else if(/^rgb/.test(a)){var d=z(a),b="#",e;for(var f=0;f<3;f++)d[f].indexOf("%")!=-1?e=Math.floor(A(d[f])*255):e=+d[f],b+=s[B(e,0,255)];c=+d[3]}else if(/^hsl/.test(a)){var d=z(a);b=C(d),c=d[3]}else b=y[a]||a;return E[a]={color:b,alpha:c}}function I(a){if(H[a])return H[a];var b=document.createElement("div"),c=b.style;try{c.font=a}catch(d){}return H[a]={style:c.fontStyle||G.style,variant:c.fontVariant||G.variant,weight:c.fontWeight||G.weight,size:c.fontSize||G.size,family:c.fontFamily||G.family}}function J(a,b){var c={};for(var d in a)c[d]=a[d];var e=parseFloat(b.currentStyle.fontSize),f=parseFloat(a.size);return typeof a.size=="number"?c.size=a.size:a.size.indexOf("px")!=-1?c.size=f:a.size.indexOf("em")!=-1?c.size=e*f:a.size.indexOf("%")!=-1?c.size=e/100*f:a.size.indexOf("pt")!=-1?c.size=f/.75:c.size=e,c}function K(a){return a.style+" "+a.variant+" "+a.weight+" "+a.size+"px "+a.family}function M(a){return L[a]||"square"}function N(a){this.m_=v(),this.mStack_=[],this.aStack_=[],this.currentPath_=[],this.strokeStyle="#000",this.fillStyle="#000",this.lineWidth=1,this.lineJoin="miter",this.lineCap="butt",this.miterLimit=g*1,this.globalAlpha=1,this.font="10px sans-serif",this.textAlign="left",this.textBaseline="alphabetic",this.canvas=a;var b="width:"+a.clientWidth+"px;height:"+a.clientHeight+"px;overflow:hidden;position:absolute",c=a.ownerDocument.createElement("div");c.style.cssText=b,a.appendChild(c);var d=c.cloneNode(!1);d.style.backgroundColor="red",d.style.filter="alpha(opacity=0)",a.appendChild(d),this.element_=c,this.arcScaleX_=1,this.arcScaleY_=1,this.lineScale_=1}function P(a,b,c,d){a.currentPath_.push({type:"bezierCurveTo",cp1x:b.x,cp1y:b.y,cp2x:c.x,cp2y:c.y,x:d.x,y:d.y}),a.currentX_=d.x,a.currentY_=d.y}function Q(a,b){var c=F(a.strokeStyle),d=c.color,e=c.alpha*a.globalAlpha,f=a.lineScale_*a.lineWidth;f<1&&(e*=f),b.push("<g_vml_:stroke",' opacity="',e,'"',' joinstyle="',a.lineJoin,'"',' miterlimit="',a.miterLimit,'"',' endcap="',M(a.lineCap),'"',' weight="',f,'px"',' color="',d,'" />')}function R(b,c,d,e){var f=b.fillStyle,h=b.arcScaleX_,i=b.arcScaleY_,j=e.x-d.x,k=e.y-d.y;if(f instanceof V){var l=0,m={x:0,y:0},n=0,o=1;if(f.type_=="gradient"){var p=f.x0_/h,q=f.y0_/i,r=f.x1_/h,s=f.y1_/i,t=S(b,p,q),u=S(b,r,s),v=u.x-t.x,w=u.y-t.y;l=Math.atan2(v,w)*180/Math.PI,l<0&&(l+=360),l<1e-6&&(l=0)}else{var t=S(b,f.x0_,f.y0_);m={x:(t.x-d.x)/j,y:(t.y-d.y)/k},j/=h*g,k/=i*g;var x=a.max(j,k);n=2*f.r0_/x,o=2*f.r1_/x-n}var y=f.colors_;y.sort(function(a,b){return a.offset-b.offset});var z=y.length,A=y[0].color,B=y[z-1].color,C=y[0].alpha*b.globalAlpha,D=y[z-1].alpha*b.globalAlpha,E=[];for(var G=0;G<z;G++){var H=y[G];E.push(H.offset*o+n+" "+H.color)}c.push('<g_vml_:fill type="',f.type_,'"',' method="none" focus="100%"',' color="',A,'"',' color2="',B,'"',' colors="',E.join(","),'"',' opacity="',D,'"',' g_o_:opacity2="',C,'"',' angle="',l,'"',' focusposition="',m.x,",",m.y,'" />')}else if(f instanceof W){if(j&&k){var I=-d.x,J=-d.y;c.push("<g_vml_:fill",' position="',I/j*h*h,",",J/k*i*i,'"',' type="tile"',' src="',f.src_,'" />')}}else{var K=F(b.fillStyle),L=K.color,M=K.alpha*b.globalAlpha;c.push('<g_vml_:fill color="',L,'" opacity="',M,'" />')}}function S(a,b,c){var d=a.m_;return{x:g*(b*d[0][0]+c*d[1][0]+d[2][0])-h,y:g*(b*d[0][1]+c*d[1][1]+d[2][1])-h}}function T(a){return isFinite(a[0][0])&&isFinite(a[0][1])&&isFinite(a[1][0])&&isFinite(a[1][1])&&isFinite(a[2][0])&&isFinite(a[2][1])}function U(a,b,c){if(!T(b))return;a.m_=b;if(c){var d=b[0][0]*b[1][1]-b[0][1]*b[1][0];a.lineScale_=f(e(d))}}function V(a){this.type_=a,this.x0_=0,this.y0_=0,this.r0_=0,this.x1_=0,this.y1_=0,this.r1_=0,this.colors_=[]}function W(a,b){Y(a);switch(b){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=b;break;default:X("SYNTAX_ERR")}this.src_=a.src,this.width_=a.width,this.height_=a.height}function X(a){throw new Z(a)}function Y(a){(!a||a.nodeType!=1||a.tagName!="IMG")&&X("TYPE_MISMATCH_ERR"),a.readyState!="complete"&&X("INVALID_STATE_ERR")}function Z(a){this.code=this[a],this.message=a+": DOM Exception "+this.code}var a=Math,b=a.round,c=a.sin,d=a.cos,e=a.abs,f=a.sqrt,g=10,h=g/2,i=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1],k=Array.prototype.slice;o(document);var p={init:function(a){var b=a||document;b.createElement("canvas"),b.attachEvent("onreadystatechange",l(this.init_,this,b))},init_:function(a){var b=a.getElementsByTagName("canvas");for(var c=0;c<b.length;c++)this.initElement(b[c])},initElement:function(a){if(!a.getContext){a.getContext=j,o(a.ownerDocument),a.innerHTML="",a.attachEvent("onpropertychange",q),a.attachEvent("onresize",r);var b=a.attributes;b.width&&b.width.specified?a.style.width=b.width.nodeValue+"px":a.width=a.clientWidth,b.height&&b.height.specified?a.style.height=b.height.nodeValue+"px":a.height=a.clientHeight}return a}};p.init();var s=[];for(var t=0;t<16;t++)for(var u=0;u<16;u++)s[t*16+u]=t.toString(16)+u.toString(16);var y={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"},E={},G={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"},H={},L={butt:"flat",round:"round"},O=N.prototype;O.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null),this.element_.innerHTML=""},O.beginPath=function(){this.currentPath_=[]},O.moveTo=function(a,b){var c=S(this,a,b);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y}),this.currentX_=c.x,this.currentY_=c.y},O.lineTo=function(a,b){var c=S(this,a,b);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y}),this.currentX_=c.x,this.currentY_=c.y},O.bezierCurveTo=function(a,b,c,d,e,f){var g=S(this,e,f),h=S(this,a,b),i=S(this,c,d);P(this,h,i,g)},O.quadraticCurveTo=function(a,b,c,d){var e=S(this,a,b),f=S(this,c,d),g={x:this.currentX_+2/3*(e.x-this.currentX_),y:this.currentY_+2/3*(e.y-this.currentY_)},h={x:g.x+(f.x-this.currentX_)/3,y:g.y+(f.y-this.currentY_)/3};P(this,g,h,f)},O.arc=function(a,b,f,i,j,k){f*=g;var l=k?"at":"wa",m=a+d(i)*f-h,n=b+c(i)*f-h,o=a+d(j)*f-h,p=b+c(j)*f-h;e(m-o)<1e-7&&!k&&(m+=.125),e(n-p)<1e-7&&k&&(n-=.125);var q=S(this,a,b),r=S(this,m,n),s=S(this,o,p);this.currentPath_.push({type:l,x:q.x,y:q.y,radius:f,xStart:r.x,yStart:r.y,xEnd:s.x,yEnd:s.y})},O.rect=function(a,b,c,d){this.moveTo(a,b),this.lineTo(a+c,b),this.lineTo(a+c,b+d),this.lineTo(a,b+d),this.closePath()},O.strokeRect=function(a,b,c,d){var e=this.currentPath_;this.beginPath(),this.moveTo(a,b),this.lineTo(a+c,b),this.lineTo(a+c,b+d),this.lineTo(a,b+d),this.closePath(),this.stroke(),this.currentPath_=e},O.fillRect=function(a,b,c,d){var e=this.currentPath_;this.beginPath(),this.moveTo(a,b),this.lineTo(a+c,b),this.lineTo(a+c,b+d),this.lineTo(a,b+d),this.closePath(),this.fill(),this.currentPath_=e},O.createLinearGradient=function(a,b,c,d){var e=new V("gradient");return e.x0_=a,e.y0_=b,e.x1_=c,e.y1_=d,e},O.createRadialGradient=function(a,b,c,d,e,f){var g=new V("gradientradial");return g.x0_=a,g.y0_=b,g.r0_=c,g.x1_=d,g.y1_=e,g.r1_=f,g},O.drawImage=function(c,d){var e,f,h,i,j,k,l,m,n=c.runtimeStyle.width,o=c.runtimeStyle.height;c.runtimeStyle.width="auto",c.runtimeStyle.height="auto";var p=c.width,q=c.height;c.runtimeStyle.width=n,c.runtimeStyle.height=o;if(arguments.length==3)e=arguments[1],f=arguments[2],j=k=0,l=h=p,m=i=q;else if(arguments.length==5)e=arguments[1],f=arguments[2],h=arguments[3],i=arguments[4],j=k=0,l=p,m=q;else if(arguments.length==9)j=arguments[1],k=arguments[2],l=arguments[3],m=arguments[4],e=arguments[5],f=arguments[6],h=arguments[7],i=arguments[8];else throw Error("Invalid number of arguments");var r=S(this,e,f),s=l/2,t=m/2,u=[],v=10,w=10;u.push(" <g_vml_:group",' coordsize="',g*v,",",g*w,'"',' coordorigin="0,0"',' style="width:',v,"px;height:",w,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var x=[];x.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",b(r.x/g),",","Dy=",b(r.y/g),"");var y=r,z=S(this,e+h,f),A=S(this,e,f+i),B=S(this,e+h,f+i);y.x=a.max(y.x,z.x,A.x,B.x),y.y=a.max(y.y,z.y,A.y,B.y),u.push("padding:0 ",b(y.x/g),"px ",b(y.y/g),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",x.join(""),", sizingmethod='clip');")}else u.push("top:",b(r.y/g),"px;left:",b(r.x/g),"px;");u.push(' ">','<g_vml_:image src="',c.src,'"',' style="width:',g*h,"px;"," height:",g*i,'px"',' cropleft="',j/p,'"',' croptop="',k/q,'"',' cropright="',(p-j-l)/p,'"',' cropbottom="',(q-k-m)/q,'"'," />","</g_vml_:group>"),this.element_.insertAdjacentHTML("BeforeEnd",u.join(""))},O.stroke=function(a){var c=[],d=!1,e=10,f=10;c.push("<g_vml_:shape",' filled="',!!a,'"',' style="position:absolute;width:',e,"px;height:",f,'px;"',' coordorigin="0,0"',' coordsize="',g*e,",",g*f,'"',' stroked="',!a,'"',' path="');var h=!1,i={x:null,y:null},j={x:null,y:null};for(var k=0;k<this.currentPath_.length;k++){var l=this.currentPath_[k],m;switch(l.type){case"moveTo":m=l,c.push(" m ",b(l.x),",",b(l.y));break;case"lineTo":c.push(" l ",b(l.x),",",b(l.y));break;case"close":c.push(" x "),l=null;break;case"bezierCurveTo":c.push(" c ",b(l.cp1x),",",b(l.cp1y),",",b(l.cp2x),",",b(l.cp2y),",",b(l.x),",",b(l.y));break;case"at":case"wa":c.push(" ",l.type," ",b(l.x-this.arcScaleX_*l.radius),",",b(l.y-this.arcScaleY_*l.radius)," ",b(l.x+this.arcScaleX_*l.radius),",",b(l.y+this.arcScaleY_*l.radius)," ",b(l.xStart),",",b(l.yStart)," ",b(l.xEnd),",",b(l.yEnd))}if(l){if(i.x==null||l.x<i.x)i.x=l.x;if(j.x==null||l.x>j.x)j.x=l.x;if(i.y==null||l.y<i.y)i.y=l.y;if(j.y==null||l.y>j.y)j.y=l.y}}c.push(' ">'),a?R(this,c,i,j):Q(this,c),c.push("</g_vml_:shape>"),this.element_.insertAdjacentHTML("beforeEnd",c.join(""))},O.fill=function(){this.stroke(!0)},O.closePath=function(){this.currentPath_.push({type:"close"})},O.save=function(){var a={};x(this,a),this.aStack_.push(a),this.mStack_.push(this.m_),this.m_=w(v(),this.m_)},O.restore=function(){this.aStack_.length&&(x(this.aStack_.pop(),this),this.m_=this.mStack_.pop())},O.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];U(this,w(c,this.m_),!1)},O.rotate=function(a){var b=d(a),e=c(a),f=[[b,e,0],[-e,b,0],[0,0,1]];U(this,w(f,this.m_),!1)},O.scale=function(a,b){this.arcScaleX_*=a,this.arcScaleY_*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];U(this,w(c,this.m_),!0)},O.transform=function(a,b,c,d,e,f){var g=[[a,b,0],[c,d,0],[e,f,1]];U(this,w(g,this.m_),!0)},O.setTransform=function(a,b,c,d,e,f){var g=[[a,b,0],[c,d,0],[e,f,1]];U(this,g,!0)},O.drawText_=function(a,c,d,e,f){var h=this.m_,i=1e3,j=0,k=i,l={x:0,y:0},n=[],o=J(I(this.font),this.element_),p=K(o),q=this.element_.currentStyle,r=this.textAlign.toLowerCase();switch(r){case"left":case"center":case"right":break;case"end":r=q.direction=="ltr"?"right":"left";break;case"start":r=q.direction=="rtl"?"right":"left";break;default:r="left"}switch(this.textBaseline){case"hanging":case"top":l.y=o.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":l.y=-o.size/2.25}switch(r){case"right":j=i,k=.05;break;case"center":j=k=i/2}var s=S(this,c+l.x,d+l.y);n.push('<g_vml_:line from="',-j,' 0" to="',k,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!f,'" stroked="',!!f,'" style="position:absolute;width:1px;height:1px;">'),f?Q(this,n):R(this,n,{x:-j,y:0},{x:k,y:o.size});var t=h[0][0].toFixed(3)+","+h[1][0].toFixed(3)+","+h[0][1].toFixed(3)+","+h[1][1].toFixed(3)+",0,0",u=b(s.x/g)+","+b(s.y/g);n.push('<g_vml_:skew on="t" matrix="',t,'" ',' offset="',u,'" origin="',j,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',m(a),'" style="v-text-align:',r,";font:",m(p),'" /></g_vml_:line>'),this.element_.insertAdjacentHTML("beforeEnd",n.join(""))},O.fillText=function(a,b,c,d){this.drawText_(a,b,c,d,!1)},O.strokeText=function(a,b,c,d){this.drawText_(a,b,c,d,!0)},O.measureText=function(a){if(!this.textMeasureEl_){var b='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",b),this.textMeasureEl_=this.element_.lastChild}var c=this.element_.ownerDocument;return this.textMeasureEl_.innerHTML="",this.textMeasureEl_.style.font=this.font,this.textMeasureEl_.appendChild(c.createTextNode(a)),{width:this.textMeasureEl_.offsetWidth}},O.clip=function(){},O.arcTo=function(){},O.createPattern=function(a,b){return new W(a,b)},V.prototype.addColorStop=function(a,b){b=F(b),this.colors_.push({offset:a,color:b.color,alpha:b.alpha})};var $=Z.prototype=new Error;$.INDEX_SIZE_ERR=1,$.DOMSTRING_SIZE_ERR=2,$.HIERARCHY_REQUEST_ERR=3,$.WRONG_DOCUMENT_ERR=4,$.INVALID_CHARACTER_ERR=5,$.NO_DATA_ALLOWED_ERR=6,$.NO_MODIFICATION_ALLOWED_ERR=7,$.NOT_FOUND_ERR=8,$.NOT_SUPPORTED_ERR=9,$.INUSE_ATTRIBUTE_ERR=10,$.INVALID_STATE_ERR=11,$.SYNTAX_ERR=12,$.INVALID_MODIFICATION_ERR=13,$.NAMESPACE_ERR=14,$.INVALID_ACCESS_ERR=15,$.VALIDATION_ERR=16,$.TYPE_MISMATCH_ERR=17,G_vmlCanvasManager=p,CanvasRenderingContext2D=N,CanvasGradient=V,CanvasPattern=W,DOMException=Z}(),function(){function c(b){var c,d,e,f,g,h;e=b.length,d=0,c="";while(d<e){f=b.charCodeAt(d++)&255;if(d==e){c+=a.charAt(f>>2),c+=a.charAt((f&3)<<4),c+="==";break}g=b.charCodeAt(d++);if(d==e){c+=a.charAt(f>>2),c+=a.charAt((f&3)<<4|(g&240)>>4),c+=a.charAt((g&15)<<2),c+="=";break}h=b.charCodeAt(d++),c+=a.charAt(f>>2),c+=a.charAt((f&3)<<4|(g&240)>>4),c+=a.charAt((g&15)<<2|(h&192)>>6),c+=a.charAt(h&63)}return c}function d(a){var c,d,e,f,g,h,i;h=a.length,g=0,i="";while(g<h){do c=b[a.charCodeAt(g++)&255];while(g<h&&c==-1);if(c==-1)break;do d=b[a.charCodeAt(g++)&255];while(g<h&&d==-1);if(d==-1)break;i+=String.fromCharCode(c<<2|(d&48)>>4);do{e=a.charCodeAt(g++)&255;if(e==61)return i;e=b[e]}while(g<h&&e==-1);if(e==-1)break;i+=String.fromCharCode((d&15)<<4|(e&60)>>2);do{f=a.charCodeAt(g++)&255;if(f==61)return i;f=b[f]}while(g<h&&f==-1);if(f==-1)break;i+=String.fromCharCode((e&3)<<6|f)}return i}var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1];window.btoa||(window.btoa=c),window.atob||(window.atob=d)}();var CanvasText={letters:{"\n":{width:-1,points:[]}," ":{width:10,points:[]},"!":{width:10,points:[[5,21],[5,7],null,[5,2],[4,1],[5,0],[6,1],[5,2]]},'"':{width:16,points:[[4,21],[4,14],null,[12,21],[12,14]]},"#":{width:21,points:[[11,25],[4,-7],null,[17,25],[10,-7],null,[4,12],[18,12],null,[3,6],[17,6]]},$:{width:20,points:[[8,25],[8,-4],null,[12,25],[12,-4],null,[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},"%":{width:24,points:[[21,21],[3,0],null,[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],null,[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]]},"&":{width:26,points:[[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]]},"'":{width:10,points:[[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]]},"(":{width:14,points:[[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]]},")":{width:14,points:[[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]]},"*":{width:16,points:[[8,21],[8,9],null,[3,18],[13,12],null,[13,18],[3,12]]},"+":{width:26,points:[[13,18],[13,0],null,[4,9],[22,9]]},",":{width:10,points:[[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"-":{width:26,points:[[4,9],[22,9]]},".":{width:10,points:[[5,2],[4,1],[5,0],[6,1],[5,2]]},"/":{width:22,points:[[20,25],[2,-7]]},0:{width:20,points:[[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]]},1:{width:20,points:[[6,17],[8,18],[11,21],[11,0]]},2:{width:20,points:[[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]]},3:{width:20,points:[[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},4:{width:20,points:[[13,21],[3,7],[18,7],null,[13,21],[13,0]]},5:{width:20,points:[[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]]},6:{width:20,points:[[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]]},7:{width:20,points:[[17,21],[7,0],null,[3,21],[17,21]]},8:{width:20,points:[[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]]},9:{width:20,points:[[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]]},":":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],null,[5,2],[4,1],[5,0],[6,1],[5,2]]},";":{width:10,points:[[5,14],[4,13],[5,12],[6,13],[5,14],null,[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]]},"<":{width:24,points:[[20,18],[4,9],[20,0]]},"=":{width:26,points:[[4,12],[22,12],null,[4,6],[22,6]]},">":{width:24,points:[[4,18],[20,9],[4,0]]},"?":{width:18,points:[[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],null,[9,2],[8,1],[9,0],[10,1],[9,2]]},"@":{width:27,points:[[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],null,[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],null,[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],null,[19,16],[18,8],[18,6],[19,5]]},A:{width:18,points:[[9,21],[1,0],null,[9,21],[17,0],null,[4,7],[14,7]]},B:{width:21,points:[[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],null,[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]]},C:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]]},D:{width:21,points:[[4,21],[4,0],null,[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]]},E:{width:19,points:[[4,21],[4,0],null,[4,21],[17,21],null,[4,11],[12,11],null,[4,0],[17,0]]},F:{width:18,points:[[4,21],[4,0],null,[4,21],[17,21],null,[4,11],[12,11]]},G:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],null,[13,8],[18,8]]},H:{width:22,points:[[4,21],[4,0],null,[18,21],[18,0],null,[4,11],[18,11]]},I:{width:8,points:[[4,21],[4,0]]},J:{width:16,points:[[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]]},K:{width:21,points:[[4,21],[4,0],null,[18,21],[4,7],null,[9,12],[18,0]]},L:{width:17,points:[[4,21],[4,0],null,[4,0],[16,0]]},M:{width:24,points:[[4,21],[4,0],null,[4,21],[12,0],null,[20,21],[12,0],null,[20,21],[20,0]]},N:{width:22,points:[[4,21],[4,0],null,[4,21],[18,0],null,[18,21],[18,0]]},O:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]]},P:{width:21,points:[[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]]},Q:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],null,[12,4],[18,-2]]},R:{width:21,points:[[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],null,[11,11],[18,0]]},S:{width:20,points:[[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},T:{width:16,points:[[8,21],[8,0],null,[1,21],[15,21]]},U:{width:22,points:[[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]]},V:{width:18,points:[[1,21],[9,0],null,[17,21],[9,0]]},W:{width:24,points:[[2,21],[7,0],null,[12,21],[7,0],null,[12,21],[17,0],null,[22,21],[17,0]]},X:{width:20,points:[[3,21],[17,0],null,[17,21],[3,0]]},Y:{width:18,points:[[1,21],[9,11],[9,0],null,[17,21],[9,11]]},Z:{width:20,points:[[17,21],[3,0],null,[3,21],[17,21],null,[3,0],[17,0]]},"[":{width:14,points:[[4,25],[4,-7],null,[5,25],[5,-7],null,[4,25],[11,25],null,[4,-7],[11,-7]]},"\\":{width:14,points:[[0,21],[14,-3]]},"]":{width:14,points:[[9,25],[9,-7],null,[10,25],[10,-7],null,[3,25],[10,25],null,[3,-7],[10,-7]]},"^":{width:14,points:[[3,10],[8,18],[13,10]]},_:{width:16,points:[[0,-2],[16,-2]]},"`":{width:10,points:[[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]]},a:{width:19,points:[[15,14],[15,0],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},b:{width:19,points:[[4,21],[4,0],null,[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},c:{width:18,points:[[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},d:{width:19,points:[[15,21],[15,0],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},e:{width:18,points:[[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},f:{width:12,points:[[10,21],[8,21],[6,20],[5,17],[5,0],null,[2,14],[9,14]]},g:{width:19,points:[[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},h:{width:19,points:[[4,21],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},i:{width:8,points:[[3,21],[4,20],[5,21],[4,22],[3,21],null,[4,14],[4,0]]},j:{width:10,points:[[5,21],[6,20],[7,21],[6,22],[5,21],null,[6,14],[6,-3],[5,-6],[3,-7],[1,-7]]},k:{width:17,points:[[4,21],[4,0],null,[14,14],[4,4],null,[8,8],[15,0]]},l:{width:8,points:[[4,21],[4,0]]},m:{width:30,points:[[4,14],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],null,[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]]},n:{width:19,points:[[4,14],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},o:{width:19,points:[[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]]},p:{width:19,points:[[4,14],[4,-7],null,[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},q:{width:19,points:[[15,14],[15,-7],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},r:{width:13,points:[[4,14],[4,0],null,[4,8],[5,11],[7,13],[9,14],[12,14]]},s:{width:17,points:[[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]]},t:{width:12,points:[[5,21],[5,4],[6,1],[8,0],[10,0],null,[2,14],[9,14]]},u:{width:19,points:[[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],null,[15,14],[15,0]]},v:{width:16,points:[[2,14],[8,0],null,[14,14],[8,0]]},w:{width:22,points:[[3,14],[7,0],null,[11,14],[7,0],null,[11,14],[15,0],null,[19,14],[15,0]]},x:{width:17,points:[[3,14],[14,0],null,[14,14],[3,0]]},y:{width:16,points:[[2,14],[8,0],null,[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]]},z:{width:17,points:[[14,14],[3,0],null,[3,14],[14,14],null,[3,0],[14,0]]},"{":{width:14,points:[[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],null,[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],null,[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]]},"|":{width:8,points:[[4,25],[4,-7]]},"}":{width:14,points:[[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],null,[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],null,[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]]},"~":{width:24,points:[[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],null,[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]]},"�":{diacritic:"`",letter:"a"},"�":{diacritic:"�",letter:"a"},"�":{diacritic:"^",letter:"a"},"�":{diacritic:"�",letter:"a"},"�":{diacritic:"~",letter:"a"},"�":{diacritic:"`",letter:"e"},"�":{diacritic:"�",letter:"e"},"�":{diacritic:"^",letter:"e"},"�":{diacritic:"�",letter:"e"},"�":{diacritic:"`",letter:"i"},"�":{diacritic:"�",letter:"i"},"�":{diacritic:"^",letter:"i"},"�":{diacritic:"�",letter:"i"},"�":{diacritic:"`",letter:"o"},"�":{diacritic:"�",letter:"o"},"�":{diacritic:"^",letter:"o"},"�":{diacritic:"�",letter:"o"},"�":{diacritic:"~",letter:"o"},"�":{diacritic:"`",letter:"u"},"�":{diacritic:"�",letter:"u"},"�":{diacritic:"^",letter:"u"},"�":{diacritic:"�",letter:"u"},"�":{diacritic:"�",letter:"y"},"�":{diacritic:"�",letter:"y"},"�":{diacritic:"�",letter:"c"},"�":{diacritic:"~",letter:"n"},"�":{diacritic:"`",letter:"A"},"�":{diacritic:"�",letter:"A"},"�":{diacritic:"^",letter:"A"},"�":{diacritic:"�",letter:"A"},"�":{diacritic:"~",letter:"A"},"�":{diacritic:"`",letter:"E"},"�":{diacritic:"�",letter:"E"},"�":{diacritic:"^",letter:"E"},"�":{diacritic:"�",letter:"E"},"�":{diacritic:"`",letter:"I"},"�":{diacritic:"�",letter:"I"},"�":{diacritic:"^",letter:"I"},"�":{diacritic:"�",letter:"I"},"�":{diacritic:"`",letter:"O"},"�":{diacritic:"�",letter:"O"},"�":{diacritic:"^",letter:"O"},"�":{diacritic:"�",letter:"O"},"�":{diacritic:"~",letter:"O"},"�":{diacritic:"`",letter:"U"},"�":{diacritic:"�",letter:"U"},"�":{diacritic:"^",letter:"U"},"�":{diacritic:"�",letter:"U"},"�":{diacritic:"�",letter:"Y"},"�":{diacritic:"�",letter:"C"},"�":{diacritic:"~",letter:"N"}},specialchars:{pi:{width:19,points:[[6,14],[6,0],null,[14,14],[14,0],null,[2,13],[6,16],[13,13],[17,16]]}},diacritics:{"�":{entity:"cedil",points:[[6,-4],[4,-6],[2,-7],[1,-7]]},"�":{entity:"acute",points:[[8,19],[13,22]]},"`":{entity:"grave",points:[[7,22],[12,19]]},"^":{entity:"circ",points:[[5.5,19],[9.5,23],[12.5,19]]},"�":{entity:"trema",points:[[5,21],[6,20],[7,21],[6,22],[5,21],null,[12,21],[13,20],[14,21],[13,22],[12,21]]},"~":{entity:"tilde",points:[[4,18],[7,22],[10,18],[13,22]]}},style:{size:8,font:null,color:"#000000",weight:1,textAlign:"left",textBaseline:"bottom",adjustAlign:!1,angle:0,tracking:1,boundingBoxColor:"#ff0000",originPointColor:"#000000"},debug:!1,_bufferLexemes:{},extend:function(a,b){for(var c in b){if(c in a)continue;a[c]=b[c]}return a},letter:function(a){return CanvasText.letters[a]},parseLexemes:function(a){if(CanvasText._bufferLexemes[a])return CanvasText._bufferLexemes[a];var b,c,d=a.match(/&[A-Za-z]{2,5};|\s|./g),e=[],f=[];for(b=0;b<d.length;b++){c=d[b];if(c.length==1)f.push(c);else{var g=c.substring(1,c.length-1);CanvasText.specialchars[g]?f.push(g):f=f.concat(c.toArray())}}for(b=0;b<f.length;b++)c=f[b],(c=CanvasText.letters[c]||CanvasText.specialchars[c])&&e.push(c);for(b=0;b<e.length;b++)(e===null||typeof e=="undefined")&&delete e[b];return CanvasText._bufferLexemes[a]=e},ascent:function(a){return a=a||CanvasText.style,a.size||CanvasText.style.size},descent:function(a){return a=a||CanvasText.style,7*(a.size||CanvasText.style.size)/25},measure:function(a,b){if(!a)return;b=b||CanvasText.style;var d,e,f=CanvasText.parseLexemes(a),g=0;for(d=f.length-1;d>-1;--d)c=f[d],e=c.diacritic?CanvasText.letter(c.letter).width:c.width,g+=e*(b.tracking||CanvasText.style.tracking)*(b.size||CanvasText.style.size)/25;return g},getDimensions:function(a,b){b=b||CanvasText.style;var c=CanvasText.measure(a,b),d=b.size||CanvasText.style.size,e=b.angle||CanvasText.style.angle;return b.angle==0?{width:c,height:d}:{width:Math.abs(Math.cos(e)*c)+Math.abs(Math.sin(e)*d),height:Math.abs(Math.sin(e)*c)+Math.abs(Math.cos(e)*d)}},drawPoints:function(a,b,c,d,e,f){var g,h,i=!0,j=0;f=f||{x:0,y:0},a.beginPath();for(g=0;g<b.length;g++){h=b[g];if(!h){i=!0;continue}i?(a.moveTo(c+h[0]*e+f.x,d-h[1]*e+f.y),i=!1):a.lineTo(c+h[0]*e+f.x,d-h[1]*e+f.y)}a.stroke(),a.closePath()},draw:function(a,b,c,d){if(!a)return;CanvasText.extend(d,CanvasText.style);var e,f,g=0,h=d.size/25,i=0,j=0,k=CanvasText.parseLexemes(a),l={x:0,y:0},m=CanvasText.measure(a,d),n;d.adjustAlign&&(n=CanvasText.getBestAlign(d.angle,d),CanvasText.extend(d,n));switch(d.textAlign){case"left":break;case"center":l.x=-m/2;break;case"right":l.x=-m}switch(d.textBaseline){case"bottom":break;case"middle":l.y=d.size/2;break;case"top":l.y=d.size}this.save(),this.translate(b,c),this.rotate(d.angle),this.lineCap="round",this.lineWidth=2*h*(d.weight||CanvasText.style.weight),this.strokeStyle=d.color||CanvasText.style.color;for(e=0;e<k.length;e++){f=k[e];if(f.width==-1){i=0,j=d.size*1.4;continue}var o=f.points,p=f.width;if(f.diacritic){var q=CanvasText.diacritics[f.diacritic],r=CanvasText.letter(f.letter);CanvasText.drawPoints(this,q.points,i,j-(f.letter.toUpperCase()==f.letter?3:0),h,l),o=r.points,p=r.width}CanvasText.drawPoints(this,o,i,j,h,l),CanvasText.debug&&(this.save(),this.lineJoin="miter",this.lineWidth=.5,this.strokeStyle=d.boundingBoxColor||CanvasText.style.boundingBoxColor,this.strokeRect(i+l.x,j+l.y,p*h,-d.size),this.fillStyle=d.originPointColor||CanvasText.style.originPointColor,this.beginPath(),this.arc(0,0,1.5,0,Math.PI*2,!0),this.fill(),this.closePath(),this.restore()),i+=p*h*(d.tracking||CanvasText.style.tracking)}return this.restore(),g}};CanvasText.proto=window.CanvasRenderingContext2D?window.CanvasRenderingContext2D.prototype:document.createElement("canvas").getContext("2d").__proto__,CanvasText.proto&&(CanvasText.proto.drawText=CanvasText.draw,CanvasText.proto.measure=CanvasText.measure,CanvasText.proto.getTextBounds=CanvasText.getDimensions,CanvasText.proto.fontAscent=CanvasText.ascent,CanvasText.proto.fontDescent=CanvasText.descent) |
1894 | \ No newline at end of file |
1895 | |
1896 | === removed file 'addons/web_graph/static/lib/flotr2/flotr2.js' |
1897 | --- addons/web_graph/static/lib/flotr2/flotr2.js 2012-05-07 08:19:08 +0000 |
1898 | +++ addons/web_graph/static/lib/flotr2/flotr2.js 1970-01-01 00:00:00 +0000 |
1899 | @@ -1,6865 +0,0 @@ |
1900 | -/*! |
1901 | - * bean.js - copyright Jacob Thornton 2011 |
1902 | - * https://github.com/fat/bean |
1903 | - * MIT License |
1904 | - * special thanks to: |
1905 | - * dean edwards: http://dean.edwards.name/ |
1906 | - * dperini: https://github.com/dperini/nwevents |
1907 | - * the entire mootools team: github.com/mootools/mootools-core |
1908 | - */ |
1909 | -/*global module:true, define:true*/ |
1910 | -!function (name, context, definition) { |
1911 | - if (typeof module !== 'undefined') module.exports = definition(name, context); |
1912 | - else if (typeof define === 'function' && typeof define.amd === 'object') define(definition); |
1913 | - else context[name] = definition(name, context); |
1914 | -}('bean', this, function (name, context) { |
1915 | - var win = window |
1916 | - , old = context[name] |
1917 | - , overOut = /over|out/ |
1918 | - , namespaceRegex = /[^\.]*(?=\..*)\.|.*/ |
1919 | - , nameRegex = /\..*/ |
1920 | - , addEvent = 'addEventListener' |
1921 | - , attachEvent = 'attachEvent' |
1922 | - , removeEvent = 'removeEventListener' |
1923 | - , detachEvent = 'detachEvent' |
1924 | - , doc = document || {} |
1925 | - , root = doc.documentElement || {} |
1926 | - , W3C_MODEL = root[addEvent] |
1927 | - , eventSupport = W3C_MODEL ? addEvent : attachEvent |
1928 | - , slice = Array.prototype.slice |
1929 | - , mouseTypeRegex = /click|mouse|menu|drag|drop/i |
1930 | - , touchTypeRegex = /^touch|^gesture/i |
1931 | - , ONE = { one: 1 } // singleton for quick matching making add() do one() |
1932 | - |
1933 | - , nativeEvents = (function (hash, events, i) { |
1934 | - for (i = 0; i < events.length; i++) |
1935 | - hash[events[i]] = 1 |
1936 | - return hash |
1937 | - })({}, ( |
1938 | - 'click dblclick mouseup mousedown contextmenu ' + // mouse buttons |
1939 | - 'mousewheel DOMMouseScroll ' + // mouse wheel |
1940 | - 'mouseover mouseout mousemove selectstart selectend ' + // mouse movement |
1941 | - 'keydown keypress keyup ' + // keyboard |
1942 | - 'orientationchange ' + // mobile |
1943 | - 'focus blur change reset select submit ' + // form elements |
1944 | - 'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window |
1945 | - 'error abort scroll ' + // misc |
1946 | - (W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event |
1947 | - // that doesn't actually exist, so make sure we only do these on newer browsers |
1948 | - 'show ' + // mouse buttons |
1949 | - 'input invalid ' + // form elements |
1950 | - 'touchstart touchmove touchend touchcancel ' + // touch |
1951 | - 'gesturestart gesturechange gestureend ' + // gesture |
1952 | - 'message readystatechange pageshow pagehide popstate ' + // window |
1953 | - 'hashchange offline online ' + // window |
1954 | - 'afterprint beforeprint ' + // printing |
1955 | - 'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd |
1956 | - 'loadstart progress suspend emptied stalled loadmetadata ' + // media |
1957 | - 'loadeddata canplay canplaythrough playing waiting seeking ' + // media |
1958 | - 'seeked ended durationchange timeupdate play pause ratechange ' + // media |
1959 | - 'volumechange cuechange ' + // media |
1960 | - 'checking noupdate downloading cached updateready obsolete ' + // appcache |
1961 | - '' : '') |
1962 | - ).split(' ') |
1963 | - ) |
1964 | - |
1965 | - , customEvents = (function () { |
1966 | - function isDescendant(parent, node) { |
1967 | - while ((node = node.parentNode) !== null) { |
1968 | - if (node === parent) return true |
1969 | - } |
1970 | - return false |
1971 | - } |
1972 | - |
1973 | - function check(event) { |
1974 | - var related = event.relatedTarget |
1975 | - if (!related) return related === null |
1976 | - return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isDescendant(this, related)) |
1977 | - } |
1978 | - |
1979 | - return { |
1980 | - mouseenter: { base: 'mouseover', condition: check } |
1981 | - , mouseleave: { base: 'mouseout', condition: check } |
1982 | - , mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' } |
1983 | - } |
1984 | - })() |
1985 | - |
1986 | - , fixEvent = (function () { |
1987 | - var commonProps = 'altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which'.split(' ') |
1988 | - , mouseProps = commonProps.concat('button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' ')) |
1989 | - , keyProps = commonProps.concat('char charCode key keyCode'.split(' ')) |
1990 | - , touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' ')) |
1991 | - , preventDefault = 'preventDefault' |
1992 | - , createPreventDefault = function (event) { |
1993 | - return function () { |
1994 | - if (event[preventDefault]) |
1995 | - event[preventDefault]() |
1996 | - else |
1997 | - event.returnValue = false |
1998 | - } |
1999 | - } |
2000 | - , stopPropagation = 'stopPropagation' |
2001 | - , createStopPropagation = function (event) { |
2002 | - return function () { |
2003 | - if (event[stopPropagation]) |
2004 | - event[stopPropagation]() |
2005 | - else |
2006 | - event.cancelBubble = true |
2007 | - } |
2008 | - } |
2009 | - , createStop = function (synEvent) { |
2010 | - return function () { |
2011 | - synEvent[preventDefault]() |
2012 | - synEvent[stopPropagation]() |
2013 | - synEvent.stopped = true |
2014 | - } |
2015 | - } |
2016 | - , copyProps = function (event, result, props) { |
2017 | - var i, p |
2018 | - for (i = props.length; i--;) { |
2019 | - p = props[i] |
2020 | - if (!(p in result) && p in event) result[p] = event[p] |
2021 | - } |
2022 | - } |
2023 | - |
2024 | - return function (event, isNative) { |
2025 | - var result = { originalEvent: event, isNative: isNative } |
2026 | - if (!event) |
2027 | - return result |
2028 | - |
2029 | - var props |
2030 | - , type = event.type |
2031 | - , target = event.target || event.srcElement |
2032 | - |
2033 | - result[preventDefault] = createPreventDefault(event) |
2034 | - result[stopPropagation] = createStopPropagation(event) |
2035 | - result.stop = createStop(result) |
2036 | - result.target = target && target.nodeType === 3 ? target.parentNode : target |
2037 | - |
2038 | - if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive |
2039 | - if (type.indexOf('key') !== -1) { |
2040 | - props = keyProps |
2041 | - result.keyCode = event.which || event.keyCode |
2042 | - } else if (mouseTypeRegex.test(type)) { |
2043 | - props = mouseProps |
2044 | - result.rightClick = event.which === 3 || event.button === 2 |
2045 | - result.pos = { x: 0, y: 0 } |
2046 | - if (event.pageX || event.pageY) { |
2047 | - result.clientX = event.pageX |
2048 | - result.clientY = event.pageY |
2049 | - } else if (event.clientX || event.clientY) { |
2050 | - result.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft |
2051 | - result.clientY = event.clientY + doc.body.scrollTop + root.scrollTop |
2052 | - } |
2053 | - if (overOut.test(type)) |
2054 | - result.relatedTarget = event.relatedTarget || event[(type === 'mouseover' ? 'from' : 'to') + 'Element'] |
2055 | - } else if (touchTypeRegex.test(type)) { |
2056 | - props = touchProps |
2057 | - } |
2058 | - copyProps(event, result, props || commonProps) |
2059 | - } |
2060 | - return result |
2061 | - } |
2062 | - })() |
2063 | - |
2064 | - // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both |
2065 | - , targetElement = function (element, isNative) { |
2066 | - return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element |
2067 | - } |
2068 | - |
2069 | - // we use one of these per listener, of any type |
2070 | - , RegEntry = (function () { |
2071 | - function entry(element, type, handler, original, namespaces) { |
2072 | - this.element = element |
2073 | - this.type = type |
2074 | - this.handler = handler |
2075 | - this.original = original |
2076 | - this.namespaces = namespaces |
2077 | - this.custom = customEvents[type] |
2078 | - this.isNative = nativeEvents[type] && element[eventSupport] |
2079 | - this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange' |
2080 | - this.customType = !W3C_MODEL && !this.isNative && type |
2081 | - this.target = targetElement(element, this.isNative) |
2082 | - this.eventSupport = this.target[eventSupport] |
2083 | - } |
2084 | - |
2085 | - entry.prototype = { |
2086 | - // given a list of namespaces, is our entry in any of them? |
2087 | - inNamespaces: function (checkNamespaces) { |
2088 | - var i, j |
2089 | - if (!checkNamespaces) |
2090 | - return true |
2091 | - if (!this.namespaces) |
2092 | - return false |
2093 | - for (i = checkNamespaces.length; i--;) { |
2094 | - for (j = this.namespaces.length; j--;) { |
2095 | - if (checkNamespaces[i] === this.namespaces[j]) |
2096 | - return true |
2097 | - } |
2098 | - } |
2099 | - return false |
2100 | - } |
2101 | - |
2102 | - // match by element, original fn (opt), handler fn (opt) |
2103 | - , matches: function (checkElement, checkOriginal, checkHandler) { |
2104 | - return this.element === checkElement && |
2105 | - (!checkOriginal || this.original === checkOriginal) && |
2106 | - (!checkHandler || this.handler === checkHandler) |
2107 | - } |
2108 | - } |
2109 | - |
2110 | - return entry |
2111 | - })() |
2112 | - |
2113 | - , registry = (function () { |
2114 | - // our map stores arrays by event type, just because it's better than storing |
2115 | - // everything in a single array. uses '$' as a prefix for the keys for safety |
2116 | - var map = {} |
2117 | - |
2118 | - // generic functional search of our registry for matching listeners, |
2119 | - // `fn` returns false to break out of the loop |
2120 | - , forAll = function (element, type, original, handler, fn) { |
2121 | - if (!type || type === '*') { |
2122 | - // search the whole registry |
2123 | - for (var t in map) { |
2124 | - if (t.charAt(0) === '$') |
2125 | - forAll(element, t.substr(1), original, handler, fn) |
2126 | - } |
2127 | - } else { |
2128 | - var i = 0, l, list = map['$' + type], all = element === '*' |
2129 | - if (!list) |
2130 | - return |
2131 | - for (l = list.length; i < l; i++) { |
2132 | - if (all || list[i].matches(element, original, handler)) |
2133 | - if (!fn(list[i], list, i, type)) |
2134 | - return |
2135 | - } |
2136 | - } |
2137 | - } |
2138 | - |
2139 | - , has = function (element, type, original) { |
2140 | - // we're not using forAll here simply because it's a bit slower and this |
2141 | - // needs to be fast |
2142 | - var i, list = map['$' + type] |
2143 | - if (list) { |
2144 | - for (i = list.length; i--;) { |
2145 | - if (list[i].matches(element, original, null)) |
2146 | - return true |
2147 | - } |
2148 | - } |
2149 | - return false |
2150 | - } |
2151 | - |
2152 | - , get = function (element, type, original) { |
2153 | - var entries = [] |
2154 | - forAll(element, type, original, null, function (entry) { return entries.push(entry) }) |
2155 | - return entries |
2156 | - } |
2157 | - |
2158 | - , put = function (entry) { |
2159 | - (map['$' + entry.type] || (map['$' + entry.type] = [])).push(entry) |
2160 | - return entry |
2161 | - } |
2162 | - |
2163 | - , del = function (entry) { |
2164 | - forAll(entry.element, entry.type, null, entry.handler, function (entry, list, i) { |
2165 | - list.splice(i, 1) |
2166 | - if (list.length === 0) |
2167 | - delete map['$' + entry.type] |
2168 | - return false |
2169 | - }) |
2170 | - } |
2171 | - |
2172 | - // dump all entries, used for onunload |
2173 | - , entries = function () { |
2174 | - var t, entries = [] |
2175 | - for (t in map) { |
2176 | - if (t.charAt(0) === '$') |
2177 | - entries = entries.concat(map[t]) |
2178 | - } |
2179 | - return entries |
2180 | - } |
2181 | - |
2182 | - return { has: has, get: get, put: put, del: del, entries: entries } |
2183 | - })() |
2184 | - |
2185 | - // add and remove listeners to DOM elements |
2186 | - , listener = W3C_MODEL ? function (element, type, fn, add) { |
2187 | - element[add ? addEvent : removeEvent](type, fn, false) |
2188 | - } : function (element, type, fn, add, custom) { |
2189 | - if (custom && add && element['_on' + custom] === null) |
2190 | - element['_on' + custom] = 0 |
2191 | - element[add ? attachEvent : detachEvent]('on' + type, fn) |
2192 | - } |
2193 | - |
2194 | - , nativeHandler = function (element, fn, args) { |
2195 | - return function (event) { |
2196 | - event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true) |
2197 | - return fn.apply(element, [event].concat(args)) |
2198 | - } |
2199 | - } |
2200 | - |
2201 | - , customHandler = function (element, fn, type, condition, args, isNative) { |
2202 | - return function (event) { |
2203 | - if (condition ? condition.apply(this, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) { |
2204 | - if (event) |
2205 | - event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative) |
2206 | - fn.apply(element, event && (!args || args.length === 0) ? arguments : slice.call(arguments, event ? 0 : 1).concat(args)) |
2207 | - } |
2208 | - } |
2209 | - } |
2210 | - |
2211 | - , once = function (rm, element, type, fn, originalFn) { |
2212 | - // wrap the handler in a handler that does a remove as well |
2213 | - return function () { |
2214 | - rm(element, type, originalFn) |
2215 | - fn.apply(this, arguments) |
2216 | - } |
2217 | - } |
2218 | - |
2219 | - , removeListener = function (element, orgType, handler, namespaces) { |
2220 | - var i, l, entry |
2221 | - , type = (orgType && orgType.replace(nameRegex, '')) |
2222 | - , handlers = registry.get(element, type, handler) |
2223 | - |
2224 | - for (i = 0, l = handlers.length; i < l; i++) { |
2225 | - if (handlers[i].inNamespaces(namespaces)) { |
2226 | - if ((entry = handlers[i]).eventSupport) |
2227 | - listener(entry.target, entry.eventType, entry.handler, false, entry.type) |
2228 | - // TODO: this is problematic, we have a registry.get() and registry.del() that |
2229 | - // both do registry searches so we waste cycles doing this. Needs to be rolled into |
2230 | - // a single registry.forAll(fn) that removes while finding, but the catch is that |
2231 | - // we'll be splicing the arrays that we're iterating over. Needs extra tests to |
2232 | - // make sure we don't screw it up. @rvagg |
2233 | - registry.del(entry) |
2234 | - } |
2235 | - } |
2236 | - } |
2237 | - |
2238 | - , addListener = function (element, orgType, fn, originalFn, args) { |
2239 | - var entry |
2240 | - , type = orgType.replace(nameRegex, '') |
2241 | - , namespaces = orgType.replace(namespaceRegex, '').split('.') |
2242 | - |
2243 | - if (registry.has(element, type, fn)) |
2244 | - return element // no dupe |
2245 | - if (type === 'unload') |
2246 | - fn = once(removeListener, element, type, fn, originalFn) // self clean-up |
2247 | - if (customEvents[type]) { |
2248 | - if (customEvents[type].condition) |
2249 | - fn = customHandler(element, fn, type, customEvents[type].condition, true) |
2250 | - type = customEvents[type].base || type |
2251 | - } |
2252 | - entry = registry.put(new RegEntry(element, type, fn, originalFn, namespaces[0] && namespaces)) |
2253 | - entry.handler = entry.isNative ? |
2254 | - nativeHandler(element, entry.handler, args) : |
2255 | - customHandler(element, entry.handler, type, false, args, false) |
2256 | - if (entry.eventSupport) |
2257 | - listener(entry.target, entry.eventType, entry.handler, true, entry.customType) |
2258 | - } |
2259 | - |
2260 | - , del = function (selector, fn, $) { |
2261 | - return function (e) { |
2262 | - var target, i, array = typeof selector === 'string' ? $(selector, this) : selector |
2263 | - for (target = e.target; target && target !== this; target = target.parentNode) { |
2264 | - for (i = array.length; i--;) { |
2265 | - if (array[i] === target) { |
2266 | - return fn.apply(target, arguments) |
2267 | - } |
2268 | - } |
2269 | - } |
2270 | - } |
2271 | - } |
2272 | - |
2273 | - , remove = function (element, typeSpec, fn) { |
2274 | - var k, m, type, namespaces, i |
2275 | - , rm = removeListener |
2276 | - , isString = typeSpec && typeof typeSpec === 'string' |
2277 | - |
2278 | - if (isString && typeSpec.indexOf(' ') > 0) { |
2279 | - // remove(el, 't1 t2 t3', fn) or remove(el, 't1 t2 t3') |
2280 | - typeSpec = typeSpec.split(' ') |
2281 | - for (i = typeSpec.length; i--;) |
2282 | - remove(element, typeSpec[i], fn) |
2283 | - return element |
2284 | - } |
2285 | - type = isString && typeSpec.replace(nameRegex, '') |
2286 | - if (type && customEvents[type]) |
2287 | - type = customEvents[type].type |
2288 | - if (!typeSpec || isString) { |
2289 | - // remove(el) or remove(el, t1.ns) or remove(el, .ns) or remove(el, .ns1.ns2.ns3) |
2290 | - if (namespaces = isString && typeSpec.replace(namespaceRegex, '')) |
2291 | - namespaces = namespaces.split('.') |
2292 | - rm(element, type, fn, namespaces) |
2293 | - } else if (typeof typeSpec === 'function') { |
2294 | - // remove(el, fn) |
2295 | - rm(element, null, typeSpec) |
2296 | - } else { |
2297 | - // remove(el, { t1: fn1, t2, fn2 }) |
2298 | - for (k in typeSpec) { |
2299 | - if (typeSpec.hasOwnProperty(k)) |
2300 | - remove(element, k, typeSpec[k]) |
2301 | - } |
2302 | - } |
2303 | - return element |
2304 | - } |
2305 | - |
2306 | - , add = function (element, events, fn, delfn, $) { |
2307 | - var type, types, i, args |
2308 | - , originalFn = fn |
2309 | - , isDel = fn && typeof fn === 'string' |
2310 | - |
2311 | - if (events && !fn && typeof events === 'object') { |
2312 | - for (type in events) { |
2313 | - if (events.hasOwnProperty(type)) |
2314 | - add.apply(this, [ element, type, events[type] ]) |
2315 | - } |
2316 | - } else { |
2317 | - args = arguments.length > 3 ? slice.call(arguments, 3) : [] |
2318 | - types = (isDel ? fn : events).split(' ') |
2319 | - isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1)) |
2320 | - // special case for one() |
2321 | - this === ONE && (fn = once(remove, element, events, fn, originalFn)) |
2322 | - for (i = types.length; i--;) addListener(element, types[i], fn, originalFn, args) |
2323 | - } |
2324 | - return element |
2325 | - } |
2326 | - |
2327 | - , one = function () { |
2328 | - return add.apply(ONE, arguments) |
2329 | - } |
2330 | - |
2331 | - , fireListener = W3C_MODEL ? function (isNative, type, element) { |
2332 | - var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents') |
2333 | - evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1) |
2334 | - element.dispatchEvent(evt) |
2335 | - } : function (isNative, type, element) { |
2336 | - element = targetElement(element, isNative) |
2337 | - // if not-native then we're using onpropertychange so we just increment a custom property |
2338 | - isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++ |
2339 | - } |
2340 | - |
2341 | - , fire = function (element, type, args) { |
2342 | - var i, j, l, names, handlers |
2343 | - , types = type.split(' ') |
2344 | - |
2345 | - for (i = types.length; i--;) { |
2346 | - type = types[i].replace(nameRegex, '') |
2347 | - if (names = types[i].replace(namespaceRegex, '')) |
2348 | - names = names.split('.') |
2349 | - if (!names && !args && element[eventSupport]) { |
2350 | - fireListener(nativeEvents[type], type, element) |
2351 | - } else { |
2352 | - // non-native event, either because of a namespace, arguments or a non DOM element |
2353 | - // iterate over all listeners and manually 'fire' |
2354 | - handlers = registry.get(element, type) |
2355 | - args = [false].concat(args) |
2356 | - for (j = 0, l = handlers.length; j < l; j++) { |
2357 | - if (handlers[j].inNamespaces(names)) |
2358 | - handlers[j].handler.apply(element, args) |
2359 | - } |
2360 | - } |
2361 | - } |
2362 | - return element |
2363 | - } |
2364 | - |
2365 | - , clone = function (element, from, type) { |
2366 | - var i = 0 |
2367 | - , handlers = registry.get(from, type) |
2368 | - , l = handlers.length |
2369 | - |
2370 | - for (;i < l; i++) |
2371 | - handlers[i].original && add(element, handlers[i].type, handlers[i].original) |
2372 | - return element |
2373 | - } |
2374 | - |
2375 | - , bean = { |
2376 | - add: add |
2377 | - , one: one |
2378 | - , remove: remove |
2379 | - , clone: clone |
2380 | - , fire: fire |
2381 | - , noConflict: function () { |
2382 | - context[name] = old |
2383 | - return this |
2384 | - } |
2385 | - } |
2386 | - |
2387 | - if (win[attachEvent]) { |
2388 | - // for IE, clean up on unload to avoid leaks |
2389 | - var cleanup = function () { |
2390 | - var i, entries = registry.entries() |
2391 | - for (i in entries) { |
2392 | - if (entries[i].type && entries[i].type !== 'unload') |
2393 | - remove(entries[i].element, entries[i].type) |
2394 | - } |
2395 | - win[detachEvent]('onunload', cleanup) |
2396 | - win.CollectGarbage && win.CollectGarbage() |
2397 | - } |
2398 | - win[attachEvent]('onunload', cleanup) |
2399 | - } |
2400 | - |
2401 | - return bean |
2402 | -}); |
2403 | -// Underscore.js 1.1.7 |
2404 | -// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. |
2405 | -// Underscore is freely distributable under the MIT license. |
2406 | -// Portions of Underscore are inspired or borrowed from Prototype, |
2407 | -// Oliver Steele's Functional, and John Resig's Micro-Templating. |
2408 | -// For all details and documentation: |
2409 | -// http://documentcloud.github.com/underscore |
2410 | - |
2411 | -(function() { |
2412 | - |
2413 | - // Baseline setup |
2414 | - // -------------- |
2415 | - |
2416 | - // Establish the root object, `window` in the browser, or `global` on the server. |
2417 | - var root = this; |
2418 | - |
2419 | - // Save the previous value of the `_` variable. |
2420 | - var previousUnderscore = root._; |
2421 | - |
2422 | - // Establish the object that gets returned to break out of a loop iteration. |
2423 | - var breaker = {}; |
2424 | - |
2425 | - // Save bytes in the minified (but not gzipped) version: |
2426 | - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; |
2427 | - |
2428 | - // Create quick reference variables for speed access to core prototypes. |
2429 | - var slice = ArrayProto.slice, |
2430 | - unshift = ArrayProto.unshift, |
2431 | - toString = ObjProto.toString, |
2432 | - hasOwnProperty = ObjProto.hasOwnProperty; |
2433 | - |
2434 | - // All **ECMAScript 5** native function implementations that we hope to use |
2435 | - // are declared here. |
2436 | - var |
2437 | - nativeForEach = ArrayProto.forEach, |
2438 | - nativeMap = ArrayProto.map, |
2439 | - nativeReduce = ArrayProto.reduce, |
2440 | - nativeReduceRight = ArrayProto.reduceRight, |
2441 | - nativeFilter = ArrayProto.filter, |
2442 | - nativeEvery = ArrayProto.every, |
2443 | - nativeSome = ArrayProto.some, |
2444 | - nativeIndexOf = ArrayProto.indexOf, |
2445 | - nativeLastIndexOf = ArrayProto.lastIndexOf, |
2446 | - nativeIsArray = Array.isArray, |
2447 | - nativeKeys = Object.keys, |
2448 | - nativeBind = FuncProto.bind; |
2449 | - |
2450 | - // Create a safe reference to the Underscore object for use below. |
2451 | - var _ = function(obj) { return new wrapper(obj); }; |
2452 | - |
2453 | - // Export the Underscore object for **CommonJS**, with backwards-compatibility |
2454 | - // for the old `require()` API. If we're not in CommonJS, add `_` to the |
2455 | - // global object. |
2456 | - if (typeof module !== 'undefined' && module.exports) { |
2457 | - module.exports = _; |
2458 | - _._ = _; |
2459 | - } else { |
2460 | - // Exported as a string, for Closure Compiler "advanced" mode. |
2461 | - root['_'] = _; |
2462 | - } |
2463 | - |
2464 | - // Current version. |
2465 | - _.VERSION = '1.1.7'; |
2466 | - |
2467 | - // Collection Functions |
2468 | - // -------------------- |
2469 | - |
2470 | - // The cornerstone, an `each` implementation, aka `forEach`. |
2471 | - // Handles objects with the built-in `forEach`, arrays, and raw objects. |
2472 | - // Delegates to **ECMAScript 5**'s native `forEach` if available. |
2473 | - var each = _.each = _.forEach = function(obj, iterator, context) { |
2474 | - if (obj == null) return; |
2475 | - if (nativeForEach && obj.forEach === nativeForEach) { |
2476 | - obj.forEach(iterator, context); |
2477 | - } else if (obj.length === +obj.length) { |
2478 | - for (var i = 0, l = obj.length; i < l; i++) { |
2479 | - if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; |
2480 | - } |
2481 | - } else { |
2482 | - for (var key in obj) { |
2483 | - if (hasOwnProperty.call(obj, key)) { |
2484 | - if (iterator.call(context, obj[key], key, obj) === breaker) return; |
2485 | - } |
2486 | - } |
2487 | - } |
2488 | - }; |
2489 | - |
2490 | - // Return the results of applying the iterator to each element. |
2491 | - // Delegates to **ECMAScript 5**'s native `map` if available. |
2492 | - _.map = function(obj, iterator, context) { |
2493 | - var results = []; |
2494 | - if (obj == null) return results; |
2495 | - if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); |
2496 | - each(obj, function(value, index, list) { |
2497 | - results[results.length] = iterator.call(context, value, index, list); |
2498 | - }); |
2499 | - return results; |
2500 | - }; |
2501 | - |
2502 | - // **Reduce** builds up a single result from a list of values, aka `inject`, |
2503 | - // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. |
2504 | - _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { |
2505 | - var initial = memo !== void 0; |
2506 | - if (obj == null) obj = []; |
2507 | - if (nativeReduce && obj.reduce === nativeReduce) { |
2508 | - if (context) iterator = _.bind(iterator, context); |
2509 | - return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); |
2510 | - } |
2511 | - each(obj, function(value, index, list) { |
2512 | - if (!initial) { |
2513 | - memo = value; |
2514 | - initial = true; |
2515 | - } else { |
2516 | - memo = iterator.call(context, memo, value, index, list); |
2517 | - } |
2518 | - }); |
2519 | - if (!initial) throw new TypeError("Reduce of empty array with no initial value"); |
2520 | - return memo; |
2521 | - }; |
2522 | - |
2523 | - // The right-associative version of reduce, also known as `foldr`. |
2524 | - // Delegates to **ECMAScript 5**'s native `reduceRight` if available. |
2525 | - _.reduceRight = _.foldr = function(obj, iterator, memo, context) { |
2526 | - if (obj == null) obj = []; |
2527 | - if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { |
2528 | - if (context) iterator = _.bind(iterator, context); |
2529 | - return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); |
2530 | - } |
2531 | - var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse(); |
2532 | - return _.reduce(reversed, iterator, memo, context); |
2533 | - }; |
2534 | - |
2535 | - // Return the first value which passes a truth test. Aliased as `detect`. |
2536 | - _.find = _.detect = function(obj, iterator, context) { |
2537 | - var result; |
2538 | - any(obj, function(value, index, list) { |
2539 | - if (iterator.call(context, value, index, list)) { |
2540 | - result = value; |
2541 | - return true; |
2542 | - } |
2543 | - }); |
2544 | - return result; |
2545 | - }; |
2546 | - |
2547 | - // Return all the elements that pass a truth test. |
2548 | - // Delegates to **ECMAScript 5**'s native `filter` if available. |
2549 | - // Aliased as `select`. |
2550 | - _.filter = _.select = function(obj, iterator, context) { |
2551 | - var results = []; |
2552 | - if (obj == null) return results; |
2553 | - if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); |
2554 | - each(obj, function(value, index, list) { |
2555 | - if (iterator.call(context, value, index, list)) results[results.length] = value; |
2556 | - }); |
2557 | - return results; |
2558 | - }; |
2559 | - |
2560 | - // Return all the elements for which a truth test fails. |
2561 | - _.reject = function(obj, iterator, context) { |
2562 | - var results = []; |
2563 | - if (obj == null) return results; |
2564 | - each(obj, function(value, index, list) { |
2565 | - if (!iterator.call(context, value, index, list)) results[results.length] = value; |
2566 | - }); |
2567 | - return results; |
2568 | - }; |
2569 | - |
2570 | - // Determine whether all of the elements match a truth test. |
2571 | - // Delegates to **ECMAScript 5**'s native `every` if available. |
2572 | - // Aliased as `all`. |
2573 | - _.every = _.all = function(obj, iterator, context) { |
2574 | - var result = true; |
2575 | - if (obj == null) return result; |
2576 | - if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); |
2577 | - each(obj, function(value, index, list) { |
2578 | - if (!(result = result && iterator.call(context, value, index, list))) return breaker; |
2579 | - }); |
2580 | - return result; |
2581 | - }; |
2582 | - |
2583 | - // Determine if at least one element in the object matches a truth test. |
2584 | - // Delegates to **ECMAScript 5**'s native `some` if available. |
2585 | - // Aliased as `any`. |
2586 | - var any = _.some = _.any = function(obj, iterator, context) { |
2587 | - iterator = iterator || _.identity; |
2588 | - var result = false; |
2589 | - if (obj == null) return result; |
2590 | - if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); |
2591 | - each(obj, function(value, index, list) { |
2592 | - if (result |= iterator.call(context, value, index, list)) return breaker; |
2593 | - }); |
2594 | - return !!result; |
2595 | - }; |
2596 | - |
2597 | - // Determine if a given value is included in the array or object using `===`. |
2598 | - // Aliased as `contains`. |
2599 | - _.include = _.contains = function(obj, target) { |
2600 | - var found = false; |
2601 | - if (obj == null) return found; |
2602 | - if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; |
2603 | - any(obj, function(value) { |
2604 | - if (found = value === target) return true; |
2605 | - }); |
2606 | - return found; |
2607 | - }; |
2608 | - |
2609 | - // Invoke a method (with arguments) on every item in a collection. |
2610 | - _.invoke = function(obj, method) { |
2611 | - var args = slice.call(arguments, 2); |
2612 | - return _.map(obj, function(value) { |
2613 | - return (method.call ? method || value : value[method]).apply(value, args); |
2614 | - }); |
2615 | - }; |
2616 | - |
2617 | - // Convenience version of a common use case of `map`: fetching a property. |
2618 | - _.pluck = function(obj, key) { |
2619 | - return _.map(obj, function(value){ return value[key]; }); |
2620 | - }; |
2621 | - |
2622 | - // Return the maximum element or (element-based computation). |
2623 | - _.max = function(obj, iterator, context) { |
2624 | - if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); |
2625 | - var result = {computed : -Infinity}; |
2626 | - each(obj, function(value, index, list) { |
2627 | - var computed = iterator ? iterator.call(context, value, index, list) : value; |
2628 | - computed >= result.computed && (result = {value : value, computed : computed}); |
2629 | - }); |
2630 | - return result.value; |
2631 | - }; |
2632 | - |
2633 | - // Return the minimum element (or element-based computation). |
2634 | - _.min = function(obj, iterator, context) { |
2635 | - if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); |
2636 | - var result = {computed : Infinity}; |
2637 | - each(obj, function(value, index, list) { |
2638 | - var computed = iterator ? iterator.call(context, value, index, list) : value; |
2639 | - computed < result.computed && (result = {value : value, computed : computed}); |
2640 | - }); |
2641 | - return result.value; |
2642 | - }; |
2643 | - |
2644 | - // Sort the object's values by a criterion produced by an iterator. |
2645 | - _.sortBy = function(obj, iterator, context) { |
2646 | - return _.pluck(_.map(obj, function(value, index, list) { |
2647 | - return { |
2648 | - value : value, |
2649 | - criteria : iterator.call(context, value, index, list) |
2650 | - }; |
2651 | - }).sort(function(left, right) { |
2652 | - var a = left.criteria, b = right.criteria; |
2653 | - return a < b ? -1 : a > b ? 1 : 0; |
2654 | - }), 'value'); |
2655 | - }; |
2656 | - |
2657 | - // Groups the object's values by a criterion produced by an iterator |
2658 | - _.groupBy = function(obj, iterator) { |
2659 | - var result = {}; |
2660 | - each(obj, function(value, index) { |
2661 | - var key = iterator(value, index); |
2662 | - (result[key] || (result[key] = [])).push(value); |
2663 | - }); |
2664 | - return result; |
2665 | - }; |
2666 | - |
2667 | - // Use a comparator function to figure out at what index an object should |
2668 | - // be inserted so as to maintain order. Uses binary search. |
2669 | - _.sortedIndex = function(array, obj, iterator) { |
2670 | - iterator || (iterator = _.identity); |
2671 | - var low = 0, high = array.length; |
2672 | - while (low < high) { |
2673 | - var mid = (low + high) >> 1; |
2674 | - iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; |
2675 | - } |
2676 | - return low; |
2677 | - }; |
2678 | - |
2679 | - // Safely convert anything iterable into a real, live array. |
2680 | - _.toArray = function(iterable) { |
2681 | - if (!iterable) return []; |
2682 | - if (iterable.toArray) return iterable.toArray(); |
2683 | - if (_.isArray(iterable)) return slice.call(iterable); |
2684 | - if (_.isArguments(iterable)) return slice.call(iterable); |
2685 | - return _.values(iterable); |
2686 | - }; |
2687 | - |
2688 | - // Return the number of elements in an object. |
2689 | - _.size = function(obj) { |
2690 | - return _.toArray(obj).length; |
2691 | - }; |
2692 | - |
2693 | - // Array Functions |
2694 | - // --------------- |
2695 | - |
2696 | - // Get the first element of an array. Passing **n** will return the first N |
2697 | - // values in the array. Aliased as `head`. The **guard** check allows it to work |
2698 | - // with `_.map`. |
2699 | - _.first = _.head = function(array, n, guard) { |
2700 | - return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; |
2701 | - }; |
2702 | - |
2703 | - // Returns everything but the first entry of the array. Aliased as `tail`. |
2704 | - // Especially useful on the arguments object. Passing an **index** will return |
2705 | - // the rest of the values in the array from that index onward. The **guard** |
2706 | - // check allows it to work with `_.map`. |
2707 | - _.rest = _.tail = function(array, index, guard) { |
2708 | - return slice.call(array, (index == null) || guard ? 1 : index); |
2709 | - }; |
2710 | - |
2711 | - // Get the last element of an array. |
2712 | - _.last = function(array) { |
2713 | - return array[array.length - 1]; |
2714 | - }; |
2715 | - |
2716 | - // Trim out all falsy values from an array. |
2717 | - _.compact = function(array) { |
2718 | - return _.filter(array, function(value){ return !!value; }); |
2719 | - }; |
2720 | - |
2721 | - // Return a completely flattened version of an array. |
2722 | - _.flatten = function(array) { |
2723 | - return _.reduce(array, function(memo, value) { |
2724 | - if (_.isArray(value)) return memo.concat(_.flatten(value)); |
2725 | - memo[memo.length] = value; |
2726 | - return memo; |
2727 | - }, []); |
2728 | - }; |
2729 | - |
2730 | - // Return a version of the array that does not contain the specified value(s). |
2731 | - _.without = function(array) { |
2732 | - return _.difference(array, slice.call(arguments, 1)); |
2733 | - }; |
2734 | - |
2735 | - // Produce a duplicate-free version of the array. If the array has already |
2736 | - // been sorted, you have the option of using a faster algorithm. |
2737 | - // Aliased as `unique`. |
2738 | - _.uniq = _.unique = function(array, isSorted) { |
2739 | - return _.reduce(array, function(memo, el, i) { |
2740 | - if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el; |
2741 | - return memo; |
2742 | - }, []); |
2743 | - }; |
2744 | - |
2745 | - // Produce an array that contains the union: each distinct element from all of |
2746 | - // the passed-in arrays. |
2747 | - _.union = function() { |
2748 | - return _.uniq(_.flatten(arguments)); |
2749 | - }; |
2750 | - |
2751 | - // Produce an array that contains every item shared between all the |
2752 | - // passed-in arrays. (Aliased as "intersect" for back-compat.) |
2753 | - _.intersection = _.intersect = function(array) { |
2754 | - var rest = slice.call(arguments, 1); |
2755 | - return _.filter(_.uniq(array), function(item) { |
2756 | - return _.every(rest, function(other) { |
2757 | - return _.indexOf(other, item) >= 0; |
2758 | - }); |
2759 | - }); |
2760 | - }; |
2761 | - |
2762 | - // Take the difference between one array and another. |
2763 | - // Only the elements present in just the first array will remain. |
2764 | - _.difference = function(array, other) { |
2765 | - return _.filter(array, function(value){ return !_.include(other, value); }); |
2766 | - }; |
2767 | - |
2768 | - // Zip together multiple lists into a single array -- elements that share |
2769 | - // an index go together. |
2770 | - _.zip = function() { |
2771 | - var args = slice.call(arguments); |
2772 | - var length = _.max(_.pluck(args, 'length')); |
2773 | - var results = new Array(length); |
2774 | - for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); |
2775 | - return results; |
2776 | - }; |
2777 | - |
2778 | - // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), |
2779 | - // we need this function. Return the position of the first occurrence of an |
2780 | - // item in an array, or -1 if the item is not included in the array. |
2781 | - // Delegates to **ECMAScript 5**'s native `indexOf` if available. |
2782 | - // If the array is large and already in sort order, pass `true` |
2783 | - // for **isSorted** to use binary search. |
2784 | - _.indexOf = function(array, item, isSorted) { |
2785 | - if (array == null) return -1; |
2786 | - var i, l; |
2787 | - if (isSorted) { |
2788 | - i = _.sortedIndex(array, item); |
2789 | - return array[i] === item ? i : -1; |
2790 | - } |
2791 | - if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); |
2792 | - for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i; |
2793 | - return -1; |
2794 | - }; |
2795 | - |
2796 | - |
2797 | - // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. |
2798 | - _.lastIndexOf = function(array, item) { |
2799 | - if (array == null) return -1; |
2800 | - if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); |
2801 | - var i = array.length; |
2802 | - while (i--) if (array[i] === item) return i; |
2803 | - return -1; |
2804 | - }; |
2805 | - |
2806 | - // Generate an integer Array containing an arithmetic progression. A port of |
2807 | - // the native Python `range()` function. See |
2808 | - // [the Python documentation](http://docs.python.org/library/functions.html#range). |
2809 | - _.range = function(start, stop, step) { |
2810 | - if (arguments.length <= 1) { |
2811 | - stop = start || 0; |
2812 | - start = 0; |
2813 | - } |
2814 | - step = arguments[2] || 1; |
2815 | - |
2816 | - var len = Math.max(Math.ceil((stop - start) / step), 0); |
2817 | - var idx = 0; |
2818 | - var range = new Array(len); |
2819 | - |
2820 | - while(idx < len) { |
2821 | - range[idx++] = start; |
2822 | - start += step; |
2823 | - } |
2824 | - |
2825 | - return range; |
2826 | - }; |
2827 | - |
2828 | - // Function (ahem) Functions |
2829 | - // ------------------ |
2830 | - |
2831 | - // Create a function bound to a given object (assigning `this`, and arguments, |
2832 | - // optionally). Binding with arguments is also known as `curry`. |
2833 | - // Delegates to **ECMAScript 5**'s native `Function.bind` if available. |
2834 | - // We check for `func.bind` first, to fail fast when `func` is undefined. |
2835 | - _.bind = function(func, obj) { |
2836 | - if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); |
2837 | - var args = slice.call(arguments, 2); |
2838 | - return function() { |
2839 | - return func.apply(obj, args.concat(slice.call(arguments))); |
2840 | - }; |
2841 | - }; |
2842 | - |
2843 | - // Bind all of an object's methods to that object. Useful for ensuring that |
2844 | - // all callbacks defined on an object belong to it. |
2845 | - _.bindAll = function(obj) { |
2846 | - var funcs = slice.call(arguments, 1); |
2847 | - if (funcs.length == 0) funcs = _.functions(obj); |
2848 | - each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); |
2849 | - return obj; |
2850 | - }; |
2851 | - |
2852 | - // Memoize an expensive function by storing its results. |
2853 | - _.memoize = function(func, hasher) { |
2854 | - var memo = {}; |
2855 | - hasher || (hasher = _.identity); |
2856 | - return function() { |
2857 | - var key = hasher.apply(this, arguments); |
2858 | - return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); |
2859 | - }; |
2860 | - }; |
2861 | - |
2862 | - // Delays a function for the given number of milliseconds, and then calls |
2863 | - // it with the arguments supplied. |
2864 | - _.delay = function(func, wait) { |
2865 | - var args = slice.call(arguments, 2); |
2866 | - return setTimeout(function(){ return func.apply(func, args); }, wait); |
2867 | - }; |
2868 | - |
2869 | - // Defers a function, scheduling it to run after the current call stack has |
2870 | - // cleared. |
2871 | - _.defer = function(func) { |
2872 | - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); |
2873 | - }; |
2874 | - |
2875 | - // Internal function used to implement `_.throttle` and `_.debounce`. |
2876 | - var limit = function(func, wait, debounce) { |
2877 | - var timeout; |
2878 | - return function() { |
2879 | - var context = this, args = arguments; |
2880 | - var throttler = function() { |
2881 | - timeout = null; |
2882 | - func.apply(context, args); |
2883 | - }; |
2884 | - if (debounce) clearTimeout(timeout); |
2885 | - if (debounce || !timeout) timeout = setTimeout(throttler, wait); |
2886 | - }; |
2887 | - }; |
2888 | - |
2889 | - // Returns a function, that, when invoked, will only be triggered at most once |
2890 | - // during a given window of time. |
2891 | - _.throttle = function(func, wait) { |
2892 | - return limit(func, wait, false); |
2893 | - }; |
2894 | - |
2895 | - // Returns a function, that, as long as it continues to be invoked, will not |
2896 | - // be triggered. The function will be called after it stops being called for |
2897 | - // N milliseconds. |
2898 | - _.debounce = function(func, wait) { |
2899 | - return limit(func, wait, true); |
2900 | - }; |
2901 | - |
2902 | - // Returns a function that will be executed at most one time, no matter how |
2903 | - // often you call it. Useful for lazy initialization. |
2904 | - _.once = function(func) { |
2905 | - var ran = false, memo; |
2906 | - return function() { |
2907 | - if (ran) return memo; |
2908 | - ran = true; |
2909 | - return memo = func.apply(this, arguments); |
2910 | - }; |
2911 | - }; |
2912 | - |
2913 | - // Returns the first function passed as an argument to the second, |
2914 | - // allowing you to adjust arguments, run code before and after, and |
2915 | - // conditionally execute the original function. |
2916 | - _.wrap = function(func, wrapper) { |
2917 | - return function() { |
2918 | - var args = [func].concat(slice.call(arguments)); |
2919 | - return wrapper.apply(this, args); |
2920 | - }; |
2921 | - }; |
2922 | - |
2923 | - // Returns a function that is the composition of a list of functions, each |
2924 | - // consuming the return value of the function that follows. |
2925 | - _.compose = function() { |
2926 | - var funcs = slice.call(arguments); |
2927 | - return function() { |
2928 | - var args = slice.call(arguments); |
2929 | - for (var i = funcs.length - 1; i >= 0; i--) { |
2930 | - args = [funcs[i].apply(this, args)]; |
2931 | - } |
2932 | - return args[0]; |
2933 | - }; |
2934 | - }; |
2935 | - |
2936 | - // Returns a function that will only be executed after being called N times. |
2937 | - _.after = function(times, func) { |
2938 | - return function() { |
2939 | - if (--times < 1) { return func.apply(this, arguments); } |
2940 | - }; |
2941 | - }; |
2942 | - |
2943 | - |
2944 | - // Object Functions |
2945 | - // ---------------- |
2946 | - |
2947 | - // Retrieve the names of an object's properties. |
2948 | - // Delegates to **ECMAScript 5**'s native `Object.keys` |
2949 | - _.keys = nativeKeys || function(obj) { |
2950 | - if (obj !== Object(obj)) throw new TypeError('Invalid object'); |
2951 | - var keys = []; |
2952 | - for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key; |
2953 | - return keys; |
2954 | - }; |
2955 | - |
2956 | - // Retrieve the values of an object's properties. |
2957 | - _.values = function(obj) { |
2958 | - return _.map(obj, _.identity); |
2959 | - }; |
2960 | - |
2961 | - // Return a sorted list of the function names available on the object. |
2962 | - // Aliased as `methods` |
2963 | - _.functions = _.methods = function(obj) { |
2964 | - var names = []; |
2965 | - for (var key in obj) { |
2966 | - if (_.isFunction(obj[key])) names.push(key); |
2967 | - } |
2968 | - return names.sort(); |
2969 | - }; |
2970 | - |
2971 | - // Extend a given object with all the properties in passed-in object(s). |
2972 | - _.extend = function(obj) { |
2973 | - each(slice.call(arguments, 1), function(source) { |
2974 | - for (var prop in source) { |
2975 | - if (source[prop] !== void 0) obj[prop] = source[prop]; |
2976 | - } |
2977 | - }); |
2978 | - return obj; |
2979 | - }; |
2980 | - |
2981 | - // Fill in a given object with default properties. |
2982 | - _.defaults = function(obj) { |
2983 | - each(slice.call(arguments, 1), function(source) { |
2984 | - for (var prop in source) { |
2985 | - if (obj[prop] == null) obj[prop] = source[prop]; |
2986 | - } |
2987 | - }); |
2988 | - return obj; |
2989 | - }; |
2990 | - |
2991 | - // Create a (shallow-cloned) duplicate of an object. |
2992 | - _.clone = function(obj) { |
2993 | - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); |
2994 | - }; |
2995 | - |
2996 | - // Invokes interceptor with the obj, and then returns obj. |
2997 | - // The primary purpose of this method is to "tap into" a method chain, in |
2998 | - // order to perform operations on intermediate results within the chain. |
2999 | - _.tap = function(obj, interceptor) { |
3000 | - interceptor(obj); |
3001 | - return obj; |
3002 | - }; |
3003 | - |
3004 | - // Perform a deep comparison to check if two objects are equal. |
3005 | - _.isEqual = function(a, b) { |
3006 | - // Check object identity. |
3007 | - if (a === b) return true; |
3008 | - // Different types? |
3009 | - var atype = typeof(a), btype = typeof(b); |
3010 | - if (atype != btype) return false; |
3011 | - // Basic equality test (watch out for coercions). |
3012 | - if (a == b) return true; |
3013 | - // One is falsy and the other truthy. |
3014 | - if ((!a && b) || (a && !b)) return false; |
3015 | - // Unwrap any wrapped objects. |
3016 | - if (a._chain) a = a._wrapped; |
3017 | - if (b._chain) b = b._wrapped; |
3018 | - // One of them implements an isEqual()? |
3019 | - if (a.isEqual) return a.isEqual(b); |
3020 | - if (b.isEqual) return b.isEqual(a); |
3021 | - // Check dates' integer values. |
3022 | - if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime(); |
3023 | - // Both are NaN? |
3024 | - if (_.isNaN(a) && _.isNaN(b)) return false; |
3025 | - // Compare regular expressions. |
3026 | - if (_.isRegExp(a) && _.isRegExp(b)) |
3027 | - return a.source === b.source && |
3028 | - a.global === b.global && |
3029 | - a.ignoreCase === b.ignoreCase && |
3030 | - a.multiline === b.multiline; |
3031 | - // If a is not an object by this point, we can't handle it. |
3032 | - if (atype !== 'object') return false; |
3033 | - // Check for different array lengths before comparing contents. |
3034 | - if (a.length && (a.length !== b.length)) return false; |
3035 | - // Nothing else worked, deep compare the contents. |
3036 | - var aKeys = _.keys(a), bKeys = _.keys(b); |
3037 | - // Different object sizes? |
3038 | - if (aKeys.length != bKeys.length) return false; |
3039 | - // Recursive comparison of contents. |
3040 | - for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false; |
3041 | - return true; |
3042 | - }; |
3043 | - |
3044 | - // Is a given array or object empty? |
3045 | - _.isEmpty = function(obj) { |
3046 | - if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; |
3047 | - for (var key in obj) if (hasOwnProperty.call(obj, key)) return false; |
3048 | - return true; |
3049 | - }; |
3050 | - |
3051 | - // Is a given value a DOM element? |
3052 | - _.isElement = function(obj) { |
3053 | - return !!(obj && obj.nodeType == 1); |
3054 | - }; |
3055 | - |
3056 | - // Is a given value an array? |
3057 | - // Delegates to ECMA5's native Array.isArray |
3058 | - _.isArray = nativeIsArray || function(obj) { |
3059 | - return toString.call(obj) === '[object Array]'; |
3060 | - }; |
3061 | - |
3062 | - // Is a given variable an object? |
3063 | - _.isObject = function(obj) { |
3064 | - return obj === Object(obj); |
3065 | - }; |
3066 | - |
3067 | - // Is a given variable an arguments object? |
3068 | - _.isArguments = function(obj) { |
3069 | - return !!(obj && hasOwnProperty.call(obj, 'callee')); |
3070 | - }; |
3071 | - |
3072 | - // Is a given value a function? |
3073 | - _.isFunction = function(obj) { |
3074 | - return !!(obj && obj.constructor && obj.call && obj.apply); |
3075 | - }; |
3076 | - |
3077 | - // Is a given value a string? |
3078 | - _.isString = function(obj) { |
3079 | - return !!(obj === '' || (obj && obj.charCodeAt && obj.substr)); |
3080 | - }; |
3081 | - |
3082 | - // Is a given value a number? |
3083 | - _.isNumber = function(obj) { |
3084 | - return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed)); |
3085 | - }; |
3086 | - |
3087 | - // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript |
3088 | - // that does not equal itself. |
3089 | - _.isNaN = function(obj) { |
3090 | - return obj !== obj; |
3091 | - }; |
3092 | - |
3093 | - // Is a given value a boolean? |
3094 | - _.isBoolean = function(obj) { |
3095 | - return obj === true || obj === false; |
3096 | - }; |
3097 | - |
3098 | - // Is a given value a date? |
3099 | - _.isDate = function(obj) { |
3100 | - return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear); |
3101 | - }; |
3102 | - |
3103 | - // Is the given value a regular expression? |
3104 | - _.isRegExp = function(obj) { |
3105 | - return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false)); |
3106 | - }; |
3107 | - |
3108 | - // Is a given value equal to null? |
3109 | - _.isNull = function(obj) { |
3110 | - return obj === null; |
3111 | - }; |
3112 | - |
3113 | - // Is a given variable undefined? |
3114 | - _.isUndefined = function(obj) { |
3115 | - return obj === void 0; |
3116 | - }; |
3117 | - |
3118 | - // Utility Functions |
3119 | - // ----------------- |
3120 | - |
3121 | - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its |
3122 | - // previous owner. Returns a reference to the Underscore object. |
3123 | - _.noConflict = function() { |
3124 | - root._ = previousUnderscore; |
3125 | - return this; |
3126 | - }; |
3127 | - |
3128 | - // Keep the identity function around for default iterators. |
3129 | - _.identity = function(value) { |
3130 | - return value; |
3131 | - }; |
3132 | - |
3133 | - // Run a function **n** times. |
3134 | - _.times = function (n, iterator, context) { |
3135 | - for (var i = 0; i < n; i++) iterator.call(context, i); |
3136 | - }; |
3137 | - |
3138 | - // Add your own custom functions to the Underscore object, ensuring that |
3139 | - // they're correctly added to the OOP wrapper as well. |
3140 | - _.mixin = function(obj) { |
3141 | - each(_.functions(obj), function(name){ |
3142 | - addToWrapper(name, _[name] = obj[name]); |
3143 | - }); |
3144 | - }; |
3145 | - |
3146 | - // Generate a unique integer id (unique within the entire client session). |
3147 | - // Useful for temporary DOM ids. |
3148 | - var idCounter = 0; |
3149 | - _.uniqueId = function(prefix) { |
3150 | - var id = idCounter++; |
3151 | - return prefix ? prefix + id : id; |
3152 | - }; |
3153 | - |
3154 | - // By default, Underscore uses ERB-style template delimiters, change the |
3155 | - // following template settings to use alternative delimiters. |
3156 | - _.templateSettings = { |
3157 | - evaluate : /<%([\s\S]+?)%>/g, |
3158 | - interpolate : /<%=([\s\S]+?)%>/g |
3159 | - }; |
3160 | - |
3161 | - // JavaScript micro-templating, similar to John Resig's implementation. |
3162 | - // Underscore templating handles arbitrary delimiters, preserves whitespace, |
3163 | - // and correctly escapes quotes within interpolated code. |
3164 | - _.template = function(str, data) { |
3165 | - var c = _.templateSettings; |
3166 | - var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + |
3167 | - 'with(obj||{}){__p.push(\'' + |
3168 | - str.replace(/\\/g, '\\\\') |
3169 | - .replace(/'/g, "\\'") |
3170 | - .replace(c.interpolate, function(match, code) { |
3171 | - return "'," + code.replace(/\\'/g, "'") + ",'"; |
3172 | - }) |
3173 | - .replace(c.evaluate || null, function(match, code) { |
3174 | - return "');" + code.replace(/\\'/g, "'") |
3175 | - .replace(/[\r\n\t]/g, ' ') + "__p.push('"; |
3176 | - }) |
3177 | - .replace(/\r/g, '\\r') |
3178 | - .replace(/\n/g, '\\n') |
3179 | - .replace(/\t/g, '\\t') |
3180 | - + "');}return __p.join('');"; |
3181 | - var func = new Function('obj', tmpl); |
3182 | - return data ? func(data) : func; |
3183 | - }; |
3184 | - |
3185 | - // The OOP Wrapper |
3186 | - // --------------- |
3187 | - |
3188 | - // If Underscore is called as a function, it returns a wrapped object that |
3189 | - // can be used OO-style. This wrapper holds altered versions of all the |
3190 | - // underscore functions. Wrapped objects may be chained. |
3191 | - var wrapper = function(obj) { this._wrapped = obj; }; |
3192 | - |
3193 | - // Expose `wrapper.prototype` as `_.prototype` |
3194 | - _.prototype = wrapper.prototype; |
3195 | - |
3196 | - // Helper function to continue chaining intermediate results. |
3197 | - var result = function(obj, chain) { |
3198 | - return chain ? _(obj).chain() : obj; |
3199 | - }; |
3200 | - |
3201 | - // A method to easily add functions to the OOP wrapper. |
3202 | - var addToWrapper = function(name, func) { |
3203 | - wrapper.prototype[name] = function() { |
3204 | - var args = slice.call(arguments); |
3205 | - unshift.call(args, this._wrapped); |
3206 | - return result(func.apply(_, args), this._chain); |
3207 | - }; |
3208 | - }; |
3209 | - |
3210 | - // Add all of the Underscore functions to the wrapper object. |
3211 | - _.mixin(_); |
3212 | - |
3213 | - // Add all mutator Array functions to the wrapper. |
3214 | - each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { |
3215 | - var method = ArrayProto[name]; |
3216 | - wrapper.prototype[name] = function() { |
3217 | - method.apply(this._wrapped, arguments); |
3218 | - return result(this._wrapped, this._chain); |
3219 | - }; |
3220 | - }); |
3221 | - |
3222 | - // Add all accessor Array functions to the wrapper. |
3223 | - each(['concat', 'join', 'slice'], function(name) { |
3224 | - var method = ArrayProto[name]; |
3225 | - wrapper.prototype[name] = function() { |
3226 | - return result(method.apply(this._wrapped, arguments), this._chain); |
3227 | - }; |
3228 | - }); |
3229 | - |
3230 | - // Start chaining a wrapped Underscore object. |
3231 | - wrapper.prototype.chain = function() { |
3232 | - this._chain = true; |
3233 | - return this; |
3234 | - }; |
3235 | - |
3236 | - // Extracts the result from a wrapped and chained object. |
3237 | - wrapper.prototype.value = function() { |
3238 | - return this._wrapped; |
3239 | - }; |
3240 | - |
3241 | -})(); |
3242 | -/** |
3243 | - * Flotr2 (c) 2012 Carl Sutherland |
3244 | - * MIT License |
3245 | - * Special thanks to: |
3246 | - * Flotr: http://code.google.com/p/flotr/ (fork) |
3247 | - * Flot: https://github.com/flot/flot (original fork) |
3248 | - */ |
3249 | -(function () { |
3250 | - |
3251 | -var |
3252 | - global = this, |
3253 | - previousFlotr = this.Flotr, |
3254 | - Flotr; |
3255 | - |
3256 | -Flotr = { |
3257 | - _: _, |
3258 | - bean: bean, |
3259 | - isIphone: /iphone/i.test(navigator.userAgent), |
3260 | - isIE: (navigator.appVersion.indexOf("MSIE") != -1 ? parseFloat(navigator.appVersion.split("MSIE")[1]) : false), |
3261 | - |
3262 | - /** |
3263 | - * An object of the registered graph types. Use Flotr.addType(type, object) |
3264 | - * to add your own type. |
3265 | - */ |
3266 | - graphTypes: {}, |
3267 | - |
3268 | - /** |
3269 | - * The list of the registered plugins |
3270 | - */ |
3271 | - plugins: {}, |
3272 | - |
3273 | - /** |
3274 | - * Can be used to add your own chart type. |
3275 | - * @param {String} name - Type of chart, like 'pies', 'bars' etc. |
3276 | - * @param {String} graphType - The object containing the basic drawing functions (draw, etc) |
3277 | - */ |
3278 | - addType: function(name, graphType){ |
3279 | - Flotr.graphTypes[name] = graphType; |
3280 | - Flotr.defaultOptions[name] = graphType.options || {}; |
3281 | - Flotr.defaultOptions.defaultType = Flotr.defaultOptions.defaultType || name; |
3282 | - }, |
3283 | - |
3284 | - /** |
3285 | - * Can be used to add a plugin |
3286 | - * @param {String} name - The name of the plugin |
3287 | - * @param {String} plugin - The object containing the plugin's data (callbacks, options, function1, function2, ...) |
3288 | - */ |
3289 | - addPlugin: function(name, plugin){ |
3290 | - Flotr.plugins[name] = plugin; |
3291 | - Flotr.defaultOptions[name] = plugin.options || {}; |
3292 | - }, |
3293 | - |
3294 | - /** |
3295 | - * Draws the graph. This function is here for backwards compatibility with Flotr version 0.1.0alpha. |
3296 | - * You could also draw graphs by directly calling Flotr.Graph(element, data, options). |
3297 | - * @param {Element} el - element to insert the graph into |
3298 | - * @param {Object} data - an array or object of dataseries |
3299 | - * @param {Object} options - an object containing options |
3300 | - * @param {Class} _GraphKlass_ - (optional) Class to pass the arguments to, defaults to Flotr.Graph |
3301 | - * @return {Object} returns a new graph object and of course draws the graph. |
3302 | - */ |
3303 | - draw: function(el, data, options, GraphKlass){ |
3304 | - GraphKlass = GraphKlass || Flotr.Graph; |
3305 | - return new GraphKlass(el, data, options); |
3306 | - }, |
3307 | - |
3308 | - /** |
3309 | - * Recursively merges two objects. |
3310 | - * @param {Object} src - source object (likely the object with the least properties) |
3311 | - * @param {Object} dest - destination object (optional, object with the most properties) |
3312 | - * @return {Object} recursively merged Object |
3313 | - * @TODO See if we can't remove this. |
3314 | - */ |
3315 | - merge: function(src, dest){ |
3316 | - var i, v, result = dest || {}; |
3317 | - |
3318 | - for (i in src) { |
3319 | - v = src[i]; |
3320 | - if (v && typeof(v) === 'object') { |
3321 | - if (v.constructor === Array) { |
3322 | - result[i] = this._.clone(v); |
3323 | - } else if (v.constructor !== RegExp && !this._.isElement(v)) { |
3324 | - result[i] = Flotr.merge(v, (dest ? dest[i] : undefined)); |
3325 | - } else { |
3326 | - result[i] = v; |
3327 | - } |
3328 | - } else { |
3329 | - result[i] = v; |
3330 | - } |
3331 | - } |
3332 | - |
3333 | - return result; |
3334 | - }, |
3335 | - |
3336 | - /** |
3337 | - * Recursively clones an object. |
3338 | - * @param {Object} object - The object to clone |
3339 | - * @return {Object} the clone |
3340 | - * @TODO See if we can't remove this. |
3341 | - */ |
3342 | - clone: function(object){ |
3343 | - return Flotr.merge(object, {}); |
3344 | - }, |
3345 | - |
3346 | - /** |
3347 | - * Function calculates the ticksize and returns it. |
3348 | - * @param {Integer} noTicks - number of ticks |
3349 | - * @param {Integer} min - lower bound integer value for the current axis |
3350 | - * @param {Integer} max - upper bound integer value for the current axis |
3351 | - * @param {Integer} decimals - number of decimals for the ticks |
3352 | - * @return {Integer} returns the ticksize in pixels |
3353 | - */ |
3354 | - getTickSize: function(noTicks, min, max, decimals){ |
3355 | - var delta = (max - min) / noTicks, |
3356 | - magn = Flotr.getMagnitude(delta), |
3357 | - tickSize = 10, |
3358 | - norm = delta / magn; // Norm is between 1.0 and 10.0. |
3359 | - |
3360 | - if(norm < 1.5) tickSize = 1; |
3361 | - else if(norm < 2.25) tickSize = 2; |
3362 | - else if(norm < 3) tickSize = ((decimals === 0) ? 2 : 2.5); |
3363 | - else if(norm < 7.5) tickSize = 5; |
3364 | - |
3365 | - return tickSize * magn; |
3366 | - }, |
3367 | - |
3368 | - /** |
3369 | - * Default tick formatter. |
3370 | - * @param {String, Integer} val - tick value integer |
3371 | - * @param {Object} axisOpts - the axis' options |
3372 | - * @return {String} formatted tick string |
3373 | - */ |
3374 | - defaultTickFormatter: function(val, axisOpts){ |
3375 | - return val+''; |
3376 | - }, |
3377 | - |
3378 | - /** |
3379 | - * Formats the mouse tracker values. |
3380 | - * @param {Object} obj - Track value Object {x:..,y:..} |
3381 | - * @return {String} Formatted track string |
3382 | - */ |
3383 | - defaultTrackFormatter: function(obj){ |
3384 | - return '('+obj.x+', '+obj.y+')'; |
3385 | - }, |
3386 | - |
3387 | - /** |
3388 | - * Utility function to convert file size values in bytes to kB, MB, ... |
3389 | - * @param value {Number} - The value to convert |
3390 | - * @param precision {Number} - The number of digits after the comma (default: 2) |
3391 | - * @param base {Number} - The base (default: 1000) |
3392 | - */ |
3393 | - engineeringNotation: function(value, precision, base){ |
3394 | - var sizes = ['Y','Z','E','P','T','G','M','k',''], |
3395 | - fractionSizes = ['y','z','a','f','p','n','µ','m',''], |
3396 | - total = sizes.length; |
3397 | - |
3398 | - base = base || 1000; |
3399 | - precision = Math.pow(10, precision || 2); |
3400 | - |
3401 | - if (value === 0) return 0; |
3402 | - |
3403 | - if (value > 1) { |
3404 | - while (total-- && (value >= base)) value /= base; |
3405 | - } |
3406 | - else { |
3407 | - sizes = fractionSizes; |
3408 | - total = sizes.length; |
3409 | - while (total-- && (value < 1)) value *= base; |
3410 | - } |
3411 | - |
3412 | - return (Math.round(value * precision) / precision) + sizes[total]; |
3413 | - }, |
3414 | - |
3415 | - /** |
3416 | - * Returns the magnitude of the input value. |
3417 | - * @param {Integer, Float} x - integer or float value |
3418 | - * @return {Integer, Float} returns the magnitude of the input value |
3419 | - */ |
3420 | - getMagnitude: function(x){ |
3421 | - return Math.pow(10, Math.floor(Math.log(x) / Math.LN10)); |
3422 | - }, |
3423 | - toPixel: function(val){ |
3424 | - return Math.floor(val)+0.5;//((val-Math.round(val) < 0.4) ? (Math.floor(val)-0.5) : val); |
3425 | - }, |
3426 | - toRad: function(angle){ |
3427 | - return -angle * (Math.PI/180); |
3428 | - }, |
3429 | - floorInBase: function(n, base) { |
3430 | - return base * Math.floor(n / base); |
3431 | - }, |
3432 | - drawText: function(ctx, text, x, y, style) { |
3433 | - if (!ctx.fillText) { |
3434 | - ctx.drawText(text, x, y, style); |
3435 | - return; |
3436 | - } |
3437 | - |
3438 | - style = this._.extend({ |
3439 | - size: Flotr.defaultOptions.fontSize, |
3440 | - color: '#000000', |
3441 | - textAlign: 'left', |
3442 | - textBaseline: 'bottom', |
3443 | - weight: 1, |
3444 | - angle: 0 |
3445 | - }, style); |
3446 | - |
3447 | - ctx.save(); |
3448 | - ctx.translate(x, y); |
3449 | - ctx.rotate(style.angle); |
3450 | - ctx.fillStyle = style.color; |
3451 | - ctx.font = (style.weight > 1 ? "bold " : "") + (style.size*1.3) + "px sans-serif"; |
3452 | - ctx.textAlign = style.textAlign; |
3453 | - ctx.textBaseline = style.textBaseline; |
3454 | - ctx.fillText(text, 0, 0); |
3455 | - ctx.restore(); |
3456 | - }, |
3457 | - getBestTextAlign: function(angle, style) { |
3458 | - style = style || {textAlign: 'center', textBaseline: 'middle'}; |
3459 | - angle += Flotr.getTextAngleFromAlign(style); |
3460 | - |
3461 | - if (Math.abs(Math.cos(angle)) > 10e-3) |
3462 | - style.textAlign = (Math.cos(angle) > 0 ? 'right' : 'left'); |
3463 | - |
3464 | - if (Math.abs(Math.sin(angle)) > 10e-3) |
3465 | - style.textBaseline = (Math.sin(angle) > 0 ? 'top' : 'bottom'); |
3466 | - |
3467 | - return style; |
3468 | - }, |
3469 | - alignTable: { |
3470 | - 'right middle' : 0, |
3471 | - 'right top' : Math.PI/4, |
3472 | - 'center top' : Math.PI/2, |
3473 | - 'left top' : 3*(Math.PI/4), |
3474 | - 'left middle' : Math.PI, |
3475 | - 'left bottom' : -3*(Math.PI/4), |
3476 | - 'center bottom': -Math.PI/2, |
3477 | - 'right bottom' : -Math.PI/4, |
3478 | - 'center middle': 0 |
3479 | - }, |
3480 | - getTextAngleFromAlign: function(style) { |
3481 | - return Flotr.alignTable[style.textAlign+' '+style.textBaseline] || 0; |
3482 | - }, |
3483 | - noConflict : function () { |
3484 | - global.Flotr = previousFlotr; |
3485 | - return this; |
3486 | - } |
3487 | -}; |
3488 | - |
3489 | -global.Flotr = Flotr; |
3490 | - |
3491 | -})(); |
3492 | - |
3493 | -/** |
3494 | - * Flotr Defaults |
3495 | - */ |
3496 | -Flotr.defaultOptions = { |
3497 | - colors: ['#00A8F0', '#C0D800', '#CB4B4B', '#4DA74D', '#9440ED'], //=> The default colorscheme. When there are > 5 series, additional colors are generated. |
3498 | - ieBackgroundColor: '#FFFFFF', // Background color for excanvas clipping |
3499 | - title: null, // => The graph's title |
3500 | - subtitle: null, // => The graph's subtitle |
3501 | - shadowSize: 4, // => size of the 'fake' shadow |
3502 | - defaultType: null, // => default series type |
3503 | - HtmlText: true, // => wether to draw the text using HTML or on the canvas |
3504 | - fontColor: '#545454', // => default font color |
3505 | - fontSize: 7.5, // => canvas' text font size |
3506 | - resolution: 1, // => resolution of the graph, to have printer-friendly graphs ! |
3507 | - parseFloat: true, // => whether to preprocess data for floats (ie. if input is string) |
3508 | - xaxis: { |
3509 | - ticks: null, // => format: either [1, 3] or [[1, 'a'], 3] |
3510 | - minorTicks: null, // => format: either [1, 3] or [[1, 'a'], 3] |
3511 | - showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise |
3512 | - showMinorLabels: false,// => true to show the axis minor ticks labels, false to hide |
3513 | - labelsAngle: 0, // => labels' angle, in degrees |
3514 | - title: null, // => axis title |
3515 | - titleAngle: 0, // => axis title's angle, in degrees |
3516 | - noTicks: 5, // => number of ticks for automagically generated ticks |
3517 | - minorTickFreq: null, // => number of minor ticks between major ticks for autogenerated ticks |
3518 | - tickFormatter: Flotr.defaultTickFormatter, // => fn: number, Object -> string |
3519 | - tickDecimals: null, // => no. of decimals, null means auto |
3520 | - min: null, // => min. value to show, null means set automatically |
3521 | - max: null, // => max. value to show, null means set automatically |
3522 | - autoscale: false, // => Turns autoscaling on with true |
3523 | - autoscaleMargin: 0, // => margin in % to add if auto-setting min/max |
3524 | - color: null, // => color of the ticks |
3525 | - mode: 'normal', // => can be 'time' or 'normal' |
3526 | - timeFormat: null, |
3527 | - timeMode:'UTC', // => For UTC time ('local' for local time). |
3528 | - timeUnit:'millisecond',// => Unit for time (millisecond, second, minute, hour, day, month, year) |
3529 | - scaling: 'linear', // => Scaling, can be 'linear' or 'logarithmic' |
3530 | - base: Math.E, |
3531 | - titleAlign: 'center', |
3532 | - margin: true // => Turn off margins with false |
3533 | - }, |
3534 | - x2axis: {}, |
3535 | - yaxis: { |
3536 | - ticks: null, // => format: either [1, 3] or [[1, 'a'], 3] |
3537 | - minorTicks: null, // => format: either [1, 3] or [[1, 'a'], 3] |
3538 | - showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise |
3539 | - showMinorLabels: false,// => true to show the axis minor ticks labels, false to hide |
3540 | - labelsAngle: 0, // => labels' angle, in degrees |
3541 | - title: null, // => axis title |
3542 | - titleAngle: 90, // => axis title's angle, in degrees |
3543 | - noTicks: 5, // => number of ticks for automagically generated ticks |
3544 | - minorTickFreq: null, // => number of minor ticks between major ticks for autogenerated ticks |
3545 | - tickFormatter: Flotr.defaultTickFormatter, // => fn: number, Object -> string |
3546 | - tickDecimals: null, // => no. of decimals, null means auto |
3547 | - min: null, // => min. value to show, null means set automatically |
3548 | - max: null, // => max. value to show, null means set automatically |
3549 | - autoscale: false, // => Turns autoscaling on with true |
3550 | - autoscaleMargin: 0, // => margin in % to add if auto-setting min/max |
3551 | - color: null, // => The color of the ticks |
3552 | - scaling: 'linear', // => Scaling, can be 'linear' or 'logarithmic' |
3553 | - base: Math.E, |
3554 | - titleAlign: 'center', |
3555 | - margin: true // => Turn off margins with false |
3556 | - }, |
3557 | - y2axis: { |
3558 | - titleAngle: 270 |
3559 | - }, |
3560 | - grid: { |
3561 | - color: '#545454', // => primary color used for outline and labels |
3562 | - backgroundColor: null, // => null for transparent, else color |
3563 | - backgroundImage: null, // => background image. String or object with src, left and top |
3564 | - watermarkAlpha: 0.4, // => |
3565 | - tickColor: '#DDDDDD', // => color used for the ticks |
3566 | - labelMargin: 3, // => margin in pixels |
3567 | - verticalLines: true, // => whether to show gridlines in vertical direction |
3568 | - minorVerticalLines: null, // => whether to show gridlines for minor ticks in vertical dir. |
3569 | - horizontalLines: true, // => whether to show gridlines in horizontal direction |
3570 | - minorHorizontalLines: null, // => whether to show gridlines for minor ticks in horizontal dir. |
3571 | - outlineWidth: 1, // => width of the grid outline/border in pixels |
3572 | - outline : 'nsew', // => walls of the outline to display |
3573 | - circular: false // => if set to true, the grid will be circular, must be used when radars are drawn |
3574 | - }, |
3575 | - mouse: { |
3576 | - track: false, // => true to track the mouse, no tracking otherwise |
3577 | - trackAll: false, |
3578 | - position: 'se', // => position of the value box (default south-east) |
3579 | - relative: false, // => next to the mouse cursor |
3580 | - trackFormatter: Flotr.defaultTrackFormatter, // => formats the values in the value box |
3581 | - margin: 5, // => margin in pixels of the valuebox |
3582 | - lineColor: '#FF3F19', // => line color of points that are drawn when mouse comes near a value of a series |
3583 | - trackDecimals: 1, // => decimals for the track values |
3584 | - sensibility: 2, // => the lower this number, the more precise you have to aim to show a value |
3585 | - trackY: true, // => whether or not to track the mouse in the y axis |
3586 | - radius: 3, // => radius of the track point |
3587 | - fillColor: null, // => color to fill our select bar with only applies to bar and similar graphs (only bars for now) |
3588 | - fillOpacity: 0.4 // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill |
3589 | - } |
3590 | -}; |
3591 | - |
3592 | -/** |
3593 | - * Flotr Color |
3594 | - */ |
3595 | - |
3596 | -(function () { |
3597 | - |
3598 | -var |
3599 | - _ = Flotr._; |
3600 | - |
3601 | -// Constructor |
3602 | -function Color (r, g, b, a) { |
3603 | - this.rgba = ['r','g','b','a']; |
3604 | - var x = 4; |
3605 | - while(-1<--x){ |
3606 | - this[this.rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0); |
3607 | - } |
3608 | - this.normalize(); |
3609 | -} |
3610 | - |
3611 | -// Constants |
3612 | -var COLOR_NAMES = { |
3613 | - aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255], |
3614 | - brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169], |
3615 | - darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47], |
3616 | - darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122], |
3617 | - darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130], |
3618 | - khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144], |
3619 | - lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255], |
3620 | - maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128], |
3621 | - violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0] |
3622 | -}; |
3623 | - |
3624 | -Color.prototype = { |
3625 | - scale: function(rf, gf, bf, af){ |
3626 | - var x = 4; |
3627 | - while (-1 < --x) { |
3628 | - if (!_.isUndefined(arguments[x])) this[this.rgba[x]] *= arguments[x]; |
3629 | - } |
3630 | - return this.normalize(); |
3631 | - }, |
3632 | - alpha: function(alpha) { |
3633 | - if (!_.isUndefined(alpha) && !_.isNull(alpha)) { |
3634 | - this.a = alpha; |
3635 | - } |
3636 | - return this.normalize(); |
3637 | - }, |
3638 | - clone: function(){ |
3639 | - return new Color(this.r, this.b, this.g, this.a); |
3640 | - }, |
3641 | - limit: function(val,minVal,maxVal){ |
3642 | - return Math.max(Math.min(val, maxVal), minVal); |
3643 | - }, |
3644 | - normalize: function(){ |
3645 | - var limit = this.limit; |
3646 | - this.r = limit(parseInt(this.r, 10), 0, 255); |
3647 | - this.g = limit(parseInt(this.g, 10), 0, 255); |
3648 | - this.b = limit(parseInt(this.b, 10), 0, 255); |
3649 | - this.a = limit(this.a, 0, 1); |
3650 | - return this; |
3651 | - }, |
3652 | - distance: function(color){ |
3653 | - if (!color) return; |
3654 | - color = new Color.parse(color); |
3655 | - var dist = 0, x = 3; |
3656 | - while(-1<--x){ |
3657 | - dist += Math.abs(this[this.rgba[x]] - color[this.rgba[x]]); |
3658 | - } |
3659 | - return dist; |
3660 | - }, |
3661 | - toString: function(){ |
3662 | - return (this.a >= 1.0) ? 'rgb('+[this.r,this.g,this.b].join(',')+')' : 'rgba('+[this.r,this.g,this.b,this.a].join(',')+')'; |
3663 | - }, |
3664 | - contrast: function () { |
3665 | - var |
3666 | - test = 1 - ( 0.299 * this.r + 0.587 * this.g + 0.114 * this.b) / 255; |
3667 | - return (test < 0.5 ? '#000000' : '#ffffff'); |
3668 | - } |
3669 | -}; |
3670 | - |
3671 | -_.extend(Color, { |
3672 | - /** |
3673 | - * Parses a color string and returns a corresponding Color. |
3674 | - * The different tests are in order of probability to improve speed. |
3675 | - * @param {String, Color} str - string thats representing a color |
3676 | - * @return {Color} returns a Color object or false |
3677 | - */ |
3678 | - parse: function(color){ |
3679 | - if (color instanceof Color) return color; |
3680 | - |
3681 | - var result; |
3682 | - |
3683 | - // #a0b1c2 |
3684 | - if((result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))) |
3685 | - return new Color(parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)); |
3686 | - |
3687 | - // rgb(num,num,num) |
3688 | - if((result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))) |
3689 | - return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)); |
3690 | - |
3691 | - // #fff |
3692 | - if((result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))) |
3693 | - return new Color(parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)); |
3694 | - |
3695 | - // rgba(num,num,num,num) |
3696 | - if((result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(color))) |
3697 | - return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10), parseFloat(result[4])); |
3698 | - |
3699 | - // rgb(num%,num%,num%) |
3700 | - if((result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))) |
3701 | - return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55); |
3702 | - |
3703 | - // rgba(num%,num%,num%,num) |
3704 | - if((result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(color))) |
3705 | - return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4])); |
3706 | - |
3707 | - // Otherwise, we're most likely dealing with a named color. |
3708 | - var name = (color+'').replace(/^\s*([\S\s]*?)\s*$/, '$1').toLowerCase(); |
3709 | - if(name == 'transparent'){ |
3710 | - return new Color(255, 255, 255, 0); |
3711 | - } |
3712 | - return (result = COLOR_NAMES[name]) ? new Color(result[0], result[1], result[2]) : new Color(0, 0, 0, 0); |
3713 | - }, |
3714 | - |
3715 | - /** |
3716 | - * Process color and options into color style. |
3717 | - */ |
3718 | - processColor: function(color, options) { |
3719 | - |
3720 | - var opacity = options.opacity; |
3721 | - if (!color) return 'rgba(0, 0, 0, 0)'; |
3722 | - if (color instanceof Color) return color.alpha(opacity).toString(); |
3723 | - if (_.isString(color)) return Color.parse(color).alpha(opacity).toString(); |
3724 | - |
3725 | - var grad = color.colors ? color : {colors: color}; |
3726 | - |
3727 | - if (!options.ctx) { |
3728 | - if (!_.isArray(grad.colors)) return 'rgba(0, 0, 0, 0)'; |
3729 | - return Color.parse(_.isArray(grad.colors[0]) ? grad.colors[0][1] : grad.colors[0]).alpha(opacity).toString(); |
3730 | - } |
3731 | - grad = _.extend({start: 'top', end: 'bottom'}, grad); |
3732 | - |
3733 | - if (/top/i.test(grad.start)) options.x1 = 0; |
3734 | - if (/left/i.test(grad.start)) options.y1 = 0; |
3735 | - if (/bottom/i.test(grad.end)) options.x2 = 0; |
3736 | - if (/right/i.test(grad.end)) options.y2 = 0; |
3737 | - |
3738 | - var i, c, stop, gradient = options.ctx.createLinearGradient(options.x1, options.y1, options.x2, options.y2); |
3739 | - for (i = 0; i < grad.colors.length; i++) { |
3740 | - c = grad.colors[i]; |
3741 | - if (_.isArray(c)) { |
3742 | - stop = c[0]; |
3743 | - c = c[1]; |
3744 | - } |
3745 | - else stop = i / (grad.colors.length-1); |
3746 | - gradient.addColorStop(stop, Color.parse(c).alpha(opacity)); |
3747 | - } |
3748 | - return gradient; |
3749 | - } |
3750 | -}); |
3751 | - |
3752 | -Flotr.Color = Color; |
3753 | - |
3754 | -})(); |
3755 | - |
3756 | -/** |
3757 | - * Flotr Date |
3758 | - */ |
3759 | -Flotr.Date = { |
3760 | - |
3761 | - set : function (date, name, mode, value) { |
3762 | - mode = mode || 'UTC'; |
3763 | - name = 'set' + (mode === 'UTC' ? 'UTC' : '') + name; |
3764 | - date[name](value); |
3765 | - }, |
3766 | - |
3767 | - get : function (date, name, mode) { |
3768 | - mode = mode || 'UTC'; |
3769 | - name = 'get' + (mode === 'UTC' ? 'UTC' : '') + name; |
3770 | - return date[name](); |
3771 | - }, |
3772 | - |
3773 | - format: function(d, format, mode) { |
3774 | - if (!d) return; |
3775 | - |
3776 | - // We should maybe use an "official" date format spec, like PHP date() or ColdFusion |
3777 | - // http://fr.php.net/manual/en/function.date.php |
3778 | - // http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_c-d_29.html |
3779 | - var |
3780 | - get = this.get, |
3781 | - tokens = { |
3782 | - h: get(d, 'Hours', mode).toString(), |
3783 | - H: leftPad(get(d, 'Hours', mode)), |
3784 | - M: leftPad(get(d, 'Minutes', mode)), |
3785 | - S: leftPad(get(d, 'Seconds', mode)), |
3786 | - s: get(d, 'Milliseconds', mode), |
3787 | - d: get(d, 'Date', mode).toString(), |
3788 | - m: (get(d, 'Month') + 1).toString(), |
3789 | - y: get(d, 'FullYear').toString(), |
3790 | - b: Flotr.Date.monthNames[get(d, 'Month', mode)] |
3791 | - }; |
3792 | - |
3793 | - function leftPad(n){ |
3794 | - n += ''; |
3795 | - return n.length == 1 ? "0" + n : n; |
3796 | - } |
3797 | - |
3798 | - var r = [], c, |
3799 | - escape = false; |
3800 | - |
3801 | - for (var i = 0; i < format.length; ++i) { |
3802 | - c = format.charAt(i); |
3803 | - |
3804 | - if (escape) { |
3805 | - r.push(tokens[c] || c); |
3806 | - escape = false; |
3807 | - } |
3808 | - else if (c == "%") |
3809 | - escape = true; |
3810 | - else |
3811 | - r.push(c); |
3812 | - } |
3813 | - return r.join(''); |
3814 | - }, |
3815 | - getFormat: function(time, span) { |
3816 | - var tu = Flotr.Date.timeUnits; |
3817 | - if (time < tu.second) return "%h:%M:%S.%s"; |
3818 | - else if (time < tu.minute) return "%h:%M:%S"; |
3819 | - else if (time < tu.day) return (span < 2 * tu.day) ? "%h:%M" : "%b %d %h:%M"; |
3820 | - else if (time < tu.month) return "%b %d"; |
3821 | - else if (time < tu.year) return (span < tu.year) ? "%b" : "%b %y"; |
3822 | - else return "%y"; |
3823 | - }, |
3824 | - formatter: function (v, axis) { |
3825 | - var |
3826 | - options = axis.options, |
3827 | - scale = Flotr.Date.timeUnits[options.timeUnit], |
3828 | - d = new Date(v * scale); |
3829 | - |
3830 | - // first check global format |
3831 | - if (axis.options.timeFormat) |
3832 | - return Flotr.Date.format(d, options.timeFormat, options.timeMode); |
3833 | - |
3834 | - var span = (axis.max - axis.min) * scale, |
3835 | - t = axis.tickSize * Flotr.Date.timeUnits[axis.tickUnit]; |
3836 | - |
3837 | - return Flotr.Date.format(d, Flotr.Date.getFormat(t, span), options.timeMode); |
3838 | - }, |
3839 | - generator: function(axis) { |
3840 | - |
3841 | - var |
3842 | - set = this.set, |
3843 | - get = this.get, |
3844 | - timeUnits = this.timeUnits, |
3845 | - spec = this.spec, |
3846 | - options = axis.options, |
3847 | - mode = options.timeMode, |
3848 | - scale = timeUnits[options.timeUnit], |
3849 | - min = axis.min * scale, |
3850 | - max = axis.max * scale, |
3851 | - delta = (max - min) / options.noTicks, |
3852 | - ticks = [], |
3853 | - tickSize = axis.tickSize, |
3854 | - tickUnit, |
3855 | - formatter, i; |
3856 | - |
3857 | - // Use custom formatter or time tick formatter |
3858 | - formatter = (options.tickFormatter === Flotr.defaultTickFormatter ? |
3859 | - this.formatter : options.tickFormatter |
3860 | - ); |
3861 | - |
3862 | - for (i = 0; i < spec.length - 1; ++i) { |
3863 | - var d = spec[i][0] * timeUnits[spec[i][1]]; |
3864 | - if (delta < (d + spec[i+1][0] * timeUnits[spec[i+1][1]]) / 2 && d >= tickSize) |
3865 | - break; |
3866 | - } |
3867 | - tickSize = spec[i][0]; |
3868 | - tickUnit = spec[i][1]; |
3869 | - |
3870 | - // special-case the possibility of several years |
3871 | - if (tickUnit == "year") { |
3872 | - tickSize = Flotr.getTickSize(options.noTicks*timeUnits.year, min, max, 0); |
3873 | - |
3874 | - // Fix for 0.5 year case |
3875 | - if (tickSize == 0.5) { |
3876 | - tickUnit = "month"; |
3877 | - tickSize = 6; |
3878 | - } |
3879 | - } |
3880 | - |
3881 | - axis.tickUnit = tickUnit; |
3882 | - axis.tickSize = tickSize; |
3883 | - |
3884 | - var |
3885 | - d = new Date(min); |
3886 | - |
3887 | - var step = tickSize * timeUnits[tickUnit]; |
3888 | - |
3889 | - function setTick (name) { |
3890 | - set(d, name, mode, Flotr.floorInBase( |
3891 | - get(d, name, mode), tickSize |
3892 | - )); |
3893 | - } |
3894 | - |
3895 | - switch (tickUnit) { |
3896 | - case "millisecond": setTick('Milliseconds'); break; |
3897 | - case "second": setTick('Seconds'); break; |
3898 | - case "minute": setTick('Minutes'); break; |
3899 | - case "hour": setTick('Hours'); break; |
3900 | - case "month": setTick('Month'); break; |
3901 | - case "year": setTick('FullYear'); break; |
3902 | - } |
3903 | - |
3904 | - // reset smaller components |
3905 | - if (step >= timeUnits.second) set(d, 'Milliseconds', mode, 0); |
3906 | - if (step >= timeUnits.minute) set(d, 'Seconds', mode, 0); |
3907 | - if (step >= timeUnits.hour) set(d, 'Minutes', mode, 0); |
3908 | - if (step >= timeUnits.day) set(d, 'Hours', mode, 0); |
3909 | - if (step >= timeUnits.day * 4) set(d, 'Date', mode, 1); |
3910 | - if (step >= timeUnits.year) set(d, 'Month', mode, 0); |
3911 | - |
3912 | - var carry = 0, v = NaN, prev; |
3913 | - do { |
3914 | - prev = v; |
3915 | - v = d.getTime(); |
3916 | - ticks.push({ v: v / scale, label: formatter(v / scale, axis) }); |
3917 | - if (tickUnit == "month") { |
3918 | - if (tickSize < 1) { |
3919 | - /* a bit complicated - we'll divide the month up but we need to take care of fractions |
3920 | - so we don't end up in the middle of a day */ |
3921 | - set(d, 'Date', mode, 1); |
3922 | - var start = d.getTime(); |
3923 | - set(d, 'Month', mode, get(d, 'Month', mode) + 1) |
3924 | - var end = d.getTime(); |
3925 | - d.setTime(v + carry * timeUnits.hour + (end - start) * tickSize); |
3926 | - carry = get(d, 'Hours', mode) |
3927 | - set(d, 'Hours', mode, 0); |
3928 | - } |
3929 | - else |
3930 | - set(d, 'Month', mode, get(d, 'Month', mode) + tickSize); |
3931 | - } |
3932 | - else if (tickUnit == "year") { |
3933 | - set(d, 'FullYear', mode, get(d, 'FullYear', mode) + tickSize); |
3934 | - } |
3935 | - else |
3936 | - d.setTime(v + step); |
3937 | - |
3938 | - } while (v < max && v != prev); |
3939 | - |
3940 | - return ticks; |
3941 | - }, |
3942 | - timeUnits: { |
3943 | - millisecond: 1, |
3944 | - second: 1000, |
3945 | - minute: 1000 * 60, |
3946 | - hour: 1000 * 60 * 60, |
3947 | - day: 1000 * 60 * 60 * 24, |
3948 | - month: 1000 * 60 * 60 * 24 * 30, |
3949 | - year: 1000 * 60 * 60 * 24 * 365.2425 |
3950 | - }, |
3951 | - // the allowed tick sizes, after 1 year we use an integer algorithm |
3952 | - spec: [ |
3953 | - [1, "millisecond"], [20, "millisecond"], [50, "millisecond"], [100, "millisecond"], [200, "millisecond"], [500, "millisecond"], |
3954 | - [1, "second"], [2, "second"], [5, "second"], [10, "second"], [30, "second"], |
3955 | - [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], [30, "minute"], |
3956 | - [1, "hour"], [2, "hour"], [4, "hour"], [8, "hour"], [12, "hour"], |
3957 | - [1, "day"], [2, "day"], [3, "day"], |
3958 | - [0.25, "month"], [0.5, "month"], [1, "month"], [2, "month"], [3, "month"], [6, "month"], |
3959 | - [1, "year"] |
3960 | - ], |
3961 | - monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] |
3962 | -}; |
3963 | - |
3964 | -(function () { |
3965 | - |
3966 | -var _ = Flotr._; |
3967 | - |
3968 | -Flotr.DOM = { |
3969 | - addClass: function(element, name){ |
3970 | - var classList = (element.className ? element.className : ''); |
3971 | - if (_.include(classList.split(/\s+/g), name)) return; |
3972 | - element.className = (classList ? classList + ' ' : '') + name; |
3973 | - }, |
3974 | - /** |
3975 | - * Create an element. |
3976 | - */ |
3977 | - create: function(tag){ |
3978 | - return document.createElement(tag); |
3979 | - }, |
3980 | - node: function(html) { |
3981 | - var div = Flotr.DOM.create('div'), n; |
3982 | - div.innerHTML = html; |
3983 | - n = div.children[0]; |
3984 | - div.innerHTML = ''; |
3985 | - return n; |
3986 | - }, |
3987 | - /** |
3988 | - * Remove all children. |
3989 | - */ |
3990 | - empty: function(element){ |
3991 | - element.innerHTML = ''; |
3992 | - /* |
3993 | - if (!element) return; |
3994 | - _.each(element.childNodes, function (e) { |
3995 | - Flotr.DOM.empty(e); |
3996 | - element.removeChild(e); |
3997 | - }); |
3998 | - */ |
3999 | - }, |
4000 | - hide: function(element){ |
4001 | - Flotr.DOM.setStyles(element, {display:'none'}); |
4002 | - }, |
4003 | - /** |
4004 | - * Insert a child. |
4005 | - * @param {Element} element |
4006 | - * @param {Element|String} Element or string to be appended. |
4007 | - */ |
4008 | - insert: function(element, child){ |
4009 | - if(_.isString(child)) |
4010 | - element.innerHTML += child; |
4011 | - else if (_.isElement(child)) |
4012 | - element.appendChild(child); |
4013 | - }, |
4014 | - // @TODO find xbrowser implementation |
4015 | - opacity: function(element, opacity) { |
4016 | - element.style.opacity = opacity; |
4017 | - }, |
4018 | - position: function(element, p){ |
4019 | - if (!element.offsetParent) |
4020 | - return {left: (element.offsetLeft || 0), top: (element.offsetTop || 0)}; |
4021 | - |
4022 | - p = this.position(element.offsetParent); |
4023 | - p.left += element.offsetLeft; |
4024 | - p.top += element.offsetTop; |
4025 | - return p; |
4026 | - }, |
4027 | - removeClass: function(element, name) { |
4028 | - var classList = (element.className ? element.className : ''); |
4029 | - element.className = _.filter(classList.split(/\s+/g), function (c) { |
4030 | - if (c != name) return true; } |
4031 | - ).join(' '); |
4032 | - }, |
4033 | - setStyles: function(element, o) { |
4034 | - _.each(o, function (value, key) { |
4035 | - element.style[key] = value; |
4036 | - }); |
4037 | - }, |
4038 | - show: function(element){ |
4039 | - Flotr.DOM.setStyles(element, {display:''}); |
4040 | - }, |
4041 | - /** |
4042 | - * Return element size. |
4043 | - */ |
4044 | - size: function(element){ |
4045 | - return { |
4046 | - height : element.offsetHeight, |
4047 | - width : element.offsetWidth }; |
4048 | - } |
4049 | -}; |
4050 | - |
4051 | -})(); |
4052 | - |
4053 | -/** |
4054 | - * Flotr Event Adapter |
4055 | - */ |
4056 | -(function () { |
4057 | -var |
4058 | - F = Flotr, |
4059 | - bean = F.bean; |
4060 | -F.EventAdapter = { |
4061 | - observe: function(object, name, callback) { |
4062 | - bean.add(object, name, callback); |
4063 | - return this; |
4064 | - }, |
4065 | - fire: function(object, name, args) { |
4066 | - bean.fire(object, name, args); |
4067 | - if (typeof(Prototype) != 'undefined') |
4068 | - Event.fire(object, name, args); |
4069 | - // @TODO Someone who uses mootools, add mootools adapter for existing applciations. |
4070 | - return this; |
4071 | - }, |
4072 | - stopObserving: function(object, name, callback) { |
4073 | - bean.remove(object, name, callback); |
4074 | - return this; |
4075 | - }, |
4076 | - eventPointer: function(e) { |
4077 | - if (!F._.isUndefined(e.touches) && e.touches.length > 0) { |
4078 | - return { |
4079 | - x : e.touches[0].pageX, |
4080 | - y : e.touches[0].pageY |
4081 | - }; |
4082 | - } else if (!F._.isUndefined(e.changedTouches) && e.changedTouches.length > 0) { |
4083 | - return { |
4084 | - x : e.changedTouches[0].pageX, |
4085 | - y : e.changedTouches[0].pageY |
4086 | - }; |
4087 | - } else if (e.pageX || e.pageY) { |
4088 | - return { |
4089 | - x : e.pageX, |
4090 | - y : e.pageY |
4091 | - }; |
4092 | - } else if (e.clientX || e.clientY) { |
4093 | - var |
4094 | - d = document, |
4095 | - b = d.body, |
4096 | - de = d.documentElement; |
4097 | - return { |
4098 | - x: e.clientX + b.scrollLeft + de.scrollLeft, |
4099 | - y: e.clientY + b.scrollTop + de.scrollTop |
4100 | - }; |
4101 | - } |
4102 | - } |
4103 | -}; |
4104 | -})(); |
4105 | - |
4106 | -/** |
4107 | - * Text Utilities |
4108 | - */ |
4109 | -(function () { |
4110 | - |
4111 | -var |
4112 | - F = Flotr, |
4113 | - D = F.DOM, |
4114 | - _ = F._, |
4115 | - |
4116 | -Text = function (o) { |
4117 | - this.o = o; |
4118 | -}; |
4119 | - |
4120 | -Text.prototype = { |
4121 | - |
4122 | - dimensions : function (text, canvasStyle, htmlStyle, className) { |
4123 | - |
4124 | - if (!text) return { width : 0, height : 0 }; |
4125 | - |
4126 | - return (this.o.html) ? |
4127 | - this.html(text, this.o.element, htmlStyle, className) : |
4128 | - this.canvas(text, canvasStyle); |
4129 | - }, |
4130 | - |
4131 | - canvas : function (text, style) { |
4132 | - |
4133 | - if (!this.o.textEnabled) return; |
4134 | - style = style || {}; |
4135 | - |
4136 | - var |
4137 | - metrics = this.measureText(text, style), |
4138 | - width = metrics.width, |
4139 | - height = style.size || F.defaultOptions.fontSize, |
4140 | - angle = style.angle || 0, |
4141 | - cosAngle = Math.cos(angle), |
4142 | - sinAngle = Math.sin(angle), |
4143 | - widthPadding = 2, |
4144 | - heightPadding = 6, |
4145 | - bounds; |
4146 | - |
4147 | - bounds = { |
4148 | - width: Math.abs(cosAngle * width) + Math.abs(sinAngle * height) + widthPadding, |
4149 | - height: Math.abs(sinAngle * width) + Math.abs(cosAngle * height) + heightPadding |
4150 | - }; |
4151 | - |
4152 | - return bounds; |
4153 | - }, |
4154 | - |
4155 | - html : function (text, element, style, className) { |
4156 | - |
4157 | - var div = D.create('div'); |
4158 | - |
4159 | - D.setStyles(div, { 'position' : 'absolute', 'top' : '-10000px' }); |
4160 | - D.insert(div, '<div style="'+style+'" class="'+className+' flotr-dummy-div">' + text + '</div>'); |
4161 | - D.insert(this.o.element, div); |
4162 | - |
4163 | - return D.size(div); |
4164 | - }, |
4165 | - |
4166 | - measureText : function (text, style) { |
4167 | - |
4168 | - var |
4169 | - context = this.o.ctx, |
4170 | - metrics; |
4171 | - |
4172 | - if (!context.fillText || (F.isIphone && context.measure)) { |
4173 | - return { width : context.measure(text, style)}; |
4174 | - } |
4175 | - |
4176 | - style = _.extend({ |
4177 | - size: F.defaultOptions.fontSize, |
4178 | - weight: 1, |
4179 | - angle: 0 |
4180 | - }, style); |
4181 | - |
4182 | - context.save(); |
4183 | - context.font = (style.weight > 1 ? "bold " : "") + (style.size*1.3) + "px sans-serif"; |
4184 | - metrics = context.measureText(text); |
4185 | - context.restore(); |
4186 | - |
4187 | - return metrics; |
4188 | - } |
4189 | -}; |
4190 | - |
4191 | -Flotr.Text = Text; |
4192 | - |
4193 | -})(); |
4194 | - |
4195 | -/** |
4196 | - * Flotr Graph class that plots a graph on creation. |
4197 | - */ |
4198 | -(function () { |
4199 | - |
4200 | -var |
4201 | - D = Flotr.DOM, |
4202 | - E = Flotr.EventAdapter, |
4203 | - _ = Flotr._, |
4204 | - flotr = Flotr; |
4205 | -/** |
4206 | - * Flotr Graph constructor. |
4207 | - * @param {Element} el - element to insert the graph into |
4208 | - * @param {Object} data - an array or object of dataseries |
4209 | - * @param {Object} options - an object containing options |
4210 | - */ |
4211 | -Graph = function(el, data, options){ |
4212 | -// Let's see if we can get away with out this [JS] |
4213 | -// try { |
4214 | - this._setEl(el); |
4215 | - this._initMembers(); |
4216 | - this._initPlugins(); |
4217 | - |
4218 | - E.fire(this.el, 'flotr:beforeinit', [this]); |
4219 | - |
4220 | - this.data = data; |
4221 | - this.series = flotr.Series.getSeries(data); |
4222 | - this._initOptions(options); |
4223 | - this._initGraphTypes(); |
4224 | - this._initCanvas(); |
4225 | - this._text = new flotr.Text({ |
4226 | - element : this.el, |
4227 | - ctx : this.ctx, |
4228 | - html : this.options.HtmlText, |
4229 | - textEnabled : this.textEnabled |
4230 | - }); |
4231 | - E.fire(this.el, 'flotr:afterconstruct', [this]); |
4232 | - this._initEvents(); |
4233 | - |
4234 | - this.findDataRanges(); |
4235 | - this.calculateSpacing(); |
4236 | - |
4237 | - this.draw(_.bind(function() { |
4238 | - E.fire(this.el, 'flotr:afterinit', [this]); |
4239 | - }, this)); |
4240 | -/* |
4241 | - try { |
4242 | - } catch (e) { |
4243 | - try { |
4244 | - console.error(e); |
4245 | - } catch (e2) {} |
4246 | - }*/ |
4247 | -}; |
4248 | - |
4249 | -function observe (object, name, callback) { |
4250 | - E.observe.apply(this, arguments); |
4251 | - this._handles.push(arguments); |
4252 | - return this; |
4253 | -} |
4254 | - |
4255 | -Graph.prototype = { |
4256 | - |
4257 | - destroy: function () { |
4258 | - E.fire(this.el, 'flotr:destroy'); |
4259 | - _.each(this._handles, function (handle) { |
4260 | - E.stopObserving.apply(this, handle); |
4261 | - }); |
4262 | - this._handles = []; |
4263 | - this.el.graph = null; |
4264 | - }, |
4265 | - |
4266 | - observe : observe, |
4267 | - |
4268 | - /** |
4269 | - * @deprecated |
4270 | - */ |
4271 | - _observe : observe, |
4272 | - |
4273 | - processColor: function(color, options){ |
4274 | - var o = { x1: 0, y1: 0, x2: this.plotWidth, y2: this.plotHeight, opacity: 1, ctx: this.ctx }; |
4275 | - _.extend(o, options); |
4276 | - return flotr.Color.processColor(color, o); |
4277 | - }, |
4278 | - /** |
4279 | - * Function determines the min and max values for the xaxis and yaxis. |
4280 | - * |
4281 | - * TODO logarithmic range validation (consideration of 0) |
4282 | - */ |
4283 | - findDataRanges: function(){ |
4284 | - var a = this.axes, |
4285 | - xaxis, yaxis, range; |
4286 | - |
4287 | - _.each(this.series, function (series) { |
4288 | - range = series.getRange(); |
4289 | - if (range) { |
4290 | - xaxis = series.xaxis; |
4291 | - yaxis = series.yaxis; |
4292 | - xaxis.datamin = Math.min(range.xmin, xaxis.datamin); |
4293 | - xaxis.datamax = Math.max(range.xmax, xaxis.datamax); |
4294 | - yaxis.datamin = Math.min(range.ymin, yaxis.datamin); |
4295 | - yaxis.datamax = Math.max(range.ymax, yaxis.datamax); |
4296 | - xaxis.used = (xaxis.used || range.xused); |
4297 | - yaxis.used = (yaxis.used || range.yused); |
4298 | - } |
4299 | - }, this); |
4300 | - |
4301 | - // Check for empty data, no data case (none used) |
4302 | - if (!a.x.used && !a.x2.used) a.x.used = true; |
4303 | - if (!a.y.used && !a.y2.used) a.y.used = true; |
4304 | - |
4305 | - _.each(a, function (axis) { |
4306 | - axis.calculateRange(); |
4307 | - }); |
4308 | - |
4309 | - var |
4310 | - types = _.keys(flotr.graphTypes), |
4311 | - drawn = false; |
4312 | - |
4313 | - _.each(this.series, function (series) { |
4314 | - if (series.hide) return; |
4315 | - _.each(types, function (type) { |
4316 | - if (series[type] && series[type].show) { |
4317 | - this.extendRange(type, series); |
4318 | - drawn = true; |
4319 | - } |
4320 | - }, this); |
4321 | - if (!drawn) { |
4322 | - this.extendRange(this.options.defaultType, series); |
4323 | - } |
4324 | - }, this); |
4325 | - }, |
4326 | - |
4327 | - extendRange : function (type, series) { |
4328 | - if (this[type].extendRange) this[type].extendRange(series, series.data, series[type], this[type]); |
4329 | - if (this[type].extendYRange) this[type].extendYRange(series.yaxis, series.data, series[type], this[type]); |
4330 | - if (this[type].extendXRange) this[type].extendXRange(series.xaxis, series.data, series[type], this[type]); |
4331 | - }, |
4332 | - |
4333 | - /** |
4334 | - * Calculates axis label sizes. |
4335 | - */ |
4336 | - calculateSpacing: function(){ |
4337 | - |
4338 | - var a = this.axes, |
4339 | - options = this.options, |
4340 | - series = this.series, |
4341 | - margin = options.grid.labelMargin, |
4342 | - T = this._text, |
4343 | - x = a.x, |
4344 | - x2 = a.x2, |
4345 | - y = a.y, |
4346 | - y2 = a.y2, |
4347 | - maxOutset = options.grid.outlineWidth, |
4348 | - i, j, l, dim; |
4349 | - |
4350 | - // TODO post refactor, fix this |
4351 | - _.each(a, function (axis) { |
4352 | - axis.calculateTicks(); |
4353 | - axis.calculateTextDimensions(T, options); |
4354 | - }); |
4355 | - |
4356 | - // Title height |
4357 | - dim = T.dimensions( |
4358 | - options.title, |
4359 | - {size: options.fontSize*1.5}, |
4360 | - 'font-size:1em;font-weight:bold;', |
4361 | - 'flotr-title' |
4362 | - ); |
4363 | - this.titleHeight = dim.height; |
4364 | - |
4365 | - // Subtitle height |
4366 | - dim = T.dimensions( |
4367 | - options.subtitle, |
4368 | - {size: options.fontSize}, |
4369 | - 'font-size:smaller;', |
4370 | - 'flotr-subtitle' |
4371 | - ); |
4372 | - this.subtitleHeight = dim.height; |
4373 | - |
4374 | - for(j = 0; j < options.length; ++j){ |
4375 | - if (series[j].points.show){ |
4376 | - maxOutset = Math.max(maxOutset, series[j].points.radius + series[j].points.lineWidth/2); |
4377 | - } |
4378 | - } |
4379 | - |
4380 | - var p = this.plotOffset; |
4381 | - if (x.options.margin === false) { |
4382 | - p.bottom = 0; |
4383 | - p.top = 0; |
4384 | - } else { |
4385 | - p.bottom += (options.grid.circular ? 0 : (x.used && x.options.showLabels ? (x.maxLabel.height + margin) : 0)) + |
4386 | - (x.used && x.options.title ? (x.titleSize.height + margin) : 0) + maxOutset; |
4387 | - |
4388 | - p.top += (options.grid.circular ? 0 : (x2.used && x2.options.showLabels ? (x2.maxLabel.height + margin) : 0)) + |
4389 | - (x2.used && x2.options.title ? (x2.titleSize.height + margin) : 0) + this.subtitleHeight + this.titleHeight + maxOutset; |
4390 | - } |
4391 | - if (y.options.margin === false) { |
4392 | - p.left = 0; |
4393 | - p.right = 0; |
4394 | - } else { |
4395 | - p.left += (options.grid.circular ? 0 : (y.used && y.options.showLabels ? (y.maxLabel.width + margin) : 0)) + |
4396 | - (y.used && y.options.title ? (y.titleSize.width + margin) : 0) + maxOutset; |
4397 | - |
4398 | - p.right += (options.grid.circular ? 0 : (y2.used && y2.options.showLabels ? (y2.maxLabel.width + margin) : 0)) + |
4399 | - (y2.used && y2.options.title ? (y2.titleSize.width + margin) : 0) + maxOutset; |
4400 | - } |
4401 | - |
4402 | - p.top = Math.floor(p.top); // In order the outline not to be blured |
4403 | - |
4404 | - this.plotWidth = this.canvasWidth - p.left - p.right; |
4405 | - this.plotHeight = this.canvasHeight - p.bottom - p.top; |
4406 | - |
4407 | - // TODO post refactor, fix this |
4408 | - x.length = x2.length = this.plotWidth; |
4409 | - y.length = y2.length = this.plotHeight; |
4410 | - y.offset = y2.offset = this.plotHeight; |
4411 | - x.setScale(); |
4412 | - x2.setScale(); |
4413 | - y.setScale(); |
4414 | - y2.setScale(); |
4415 | - }, |
4416 | - /** |
4417 | - * Draws grid, labels, series and outline. |
4418 | - */ |
4419 | - draw: function(after) { |
4420 | - |
4421 | - var |
4422 | - context = this.ctx, |
4423 | - i; |
4424 | - |
4425 | - E.fire(this.el, 'flotr:beforedraw', [this.series, this]); |
4426 | - |
4427 | - if (this.series.length) { |
4428 | - |
4429 | - context.save(); |
4430 | - context.translate(this.plotOffset.left, this.plotOffset.top); |
4431 | - |
4432 | - for (i = 0; i < this.series.length; i++) { |
4433 | - if (!this.series[i].hide) this.drawSeries(this.series[i]); |
4434 | - } |
4435 | - |
4436 | - context.restore(); |
4437 | - this.clip(); |
4438 | - } |
4439 | - |
4440 | - E.fire(this.el, 'flotr:afterdraw', [this.series, this]); |
4441 | - if (after) after(); |
4442 | - }, |
4443 | - /** |
4444 | - * Actually draws the graph. |
4445 | - * @param {Object} series - series to draw |
4446 | - */ |
4447 | - drawSeries: function(series){ |
4448 | - |
4449 | - function drawChart (series, typeKey) { |
4450 | - var options = this.getOptions(series, typeKey); |
4451 | - this[typeKey].draw(options); |
4452 | - } |
4453 | - |
4454 | - var drawn = false; |
4455 | - series = series || this.series; |
4456 | - |
4457 | - _.each(flotr.graphTypes, function (type, typeKey) { |
4458 | - if (series[typeKey] && series[typeKey].show && this[typeKey]) { |
4459 | - drawn = true; |
4460 | - drawChart.call(this, series, typeKey); |
4461 | - } |
4462 | - }, this); |
4463 | - |
4464 | - if (!drawn) drawChart.call(this, series, this.options.defaultType); |
4465 | - }, |
4466 | - |
4467 | - getOptions : function (series, typeKey) { |
4468 | - var |
4469 | - type = series[typeKey], |
4470 | - graphType = this[typeKey], |
4471 | - options = { |
4472 | - context : this.ctx, |
4473 | - width : this.plotWidth, |
4474 | - height : this.plotHeight, |
4475 | - fontSize : this.options.fontSize, |
4476 | - fontColor : this.options.fontColor, |
4477 | - textEnabled : this.textEnabled, |
4478 | - htmlText : this.options.HtmlText, |
4479 | - text : this._text, // TODO Is this necessary? |
4480 | - element : this.el, |
4481 | - data : series.data, |
4482 | - color : series.color, |
4483 | - shadowSize : series.shadowSize, |
4484 | - xScale : _.bind(series.xaxis.d2p, series.xaxis), |
4485 | - yScale : _.bind(series.yaxis.d2p, series.yaxis) |
4486 | - }; |
4487 | - |
4488 | - options = flotr.merge(type, options); |
4489 | - |
4490 | - // Fill |
4491 | - options.fillStyle = this.processColor( |
4492 | - type.fillColor || series.color, |
4493 | - {opacity: type.fillOpacity} |
4494 | - ); |
4495 | - |
4496 | - return options; |
4497 | - }, |
4498 | - /** |
4499 | - * Calculates the coordinates from a mouse event object. |
4500 | - * @param {Event} event - Mouse Event object. |
4501 | - * @return {Object} Object with coordinates of the mouse. |
4502 | - */ |
4503 | - getEventPosition: function (e){ |
4504 | - |
4505 | - var |
4506 | - d = document, |
4507 | - b = d.body, |
4508 | - de = d.documentElement, |
4509 | - axes = this.axes, |
4510 | - plotOffset = this.plotOffset, |
4511 | - lastMousePos = this.lastMousePos, |
4512 | - pointer = E.eventPointer(e), |
4513 | - dx = pointer.x - lastMousePos.pageX, |
4514 | - dy = pointer.y - lastMousePos.pageY, |
4515 | - r, rx, ry; |
4516 | - |
4517 | - if ('ontouchstart' in this.el) { |
4518 | - r = D.position(this.overlay); |
4519 | - rx = pointer.x - r.left - plotOffset.left; |
4520 | - ry = pointer.y - r.top - plotOffset.top; |
4521 | - } else { |
4522 | - r = this.overlay.getBoundingClientRect(); |
4523 | - rx = e.clientX - r.left - plotOffset.left - b.scrollLeft - de.scrollLeft; |
4524 | - ry = e.clientY - r.top - plotOffset.top - b.scrollTop - de.scrollTop; |
4525 | - } |
4526 | - |
4527 | - return { |
4528 | - x: axes.x.p2d(rx), |
4529 | - x2: axes.x2.p2d(rx), |
4530 | - y: axes.y.p2d(ry), |
4531 | - y2: axes.y2.p2d(ry), |
4532 | - relX: rx, |
4533 | - relY: ry, |
4534 | - dX: dx, |
4535 | - dY: dy, |
4536 | - absX: pointer.x, |
4537 | - absY: pointer.y, |
4538 | - pageX: pointer.x, |
4539 | - pageY: pointer.y |
4540 | - }; |
4541 | - }, |
4542 | - /** |
4543 | - * Observes the 'click' event and fires the 'flotr:click' event. |
4544 | - * @param {Event} event - 'click' Event object. |
4545 | - */ |
4546 | - clickHandler: function(event){ |
4547 | - if(this.ignoreClick){ |
4548 | - this.ignoreClick = false; |
4549 | - return this.ignoreClick; |
4550 | - } |
4551 | - E.fire(this.el, 'flotr:click', [this.getEventPosition(event), this]); |
4552 | - }, |
4553 | - /** |
4554 | - * Observes mouse movement over the graph area. Fires the 'flotr:mousemove' event. |
4555 | - * @param {Event} event - 'mousemove' Event object. |
4556 | - */ |
4557 | - mouseMoveHandler: function(event){ |
4558 | - if (this.mouseDownMoveHandler) return; |
4559 | - var pos = this.getEventPosition(event); |
4560 | - E.fire(this.el, 'flotr:mousemove', [event, pos, this]); |
4561 | - this.lastMousePos = pos; |
4562 | - }, |
4563 | - /** |
4564 | - * Observes the 'mousedown' event. |
4565 | - * @param {Event} event - 'mousedown' Event object. |
4566 | - */ |
4567 | - mouseDownHandler: function (event){ |
4568 | - |
4569 | - /* |
4570 | - // @TODO Context menu? |
4571 | - if(event.isRightClick()) { |
4572 | - event.stop(); |
4573 | - |
4574 | - var overlay = this.overlay; |
4575 | - overlay.hide(); |
4576 | - |
4577 | - function cancelContextMenu () { |
4578 | - overlay.show(); |
4579 | - E.stopObserving(document, 'mousemove', cancelContextMenu); |
4580 | - } |
4581 | - E.observe(document, 'mousemove', cancelContextMenu); |
4582 | - return; |
4583 | - } |
4584 | - */ |
4585 | - |
4586 | - if (this.mouseUpHandler) return; |
4587 | - this.mouseUpHandler = _.bind(function (e) { |
4588 | - E.stopObserving(document, 'mouseup', this.mouseUpHandler); |
4589 | - E.stopObserving(document, 'mousemove', this.mouseDownMoveHandler); |
4590 | - this.mouseDownMoveHandler = null; |
4591 | - this.mouseUpHandler = null; |
4592 | - // @TODO why? |
4593 | - //e.stop(); |
4594 | - E.fire(this.el, 'flotr:mouseup', [e, this]); |
4595 | - }, this); |
4596 | - this.mouseDownMoveHandler = _.bind(function (e) { |
4597 | - var pos = this.getEventPosition(e); |
4598 | - E.fire(this.el, 'flotr:mousemove', [event, pos, this]); |
4599 | - this.lastMousePos = pos; |
4600 | - }, this); |
4601 | - E.observe(document, 'mouseup', this.mouseUpHandler); |
4602 | - E.observe(document, 'mousemove', this.mouseDownMoveHandler); |
4603 | - E.fire(this.el, 'flotr:mousedown', [event, this]); |
4604 | - this.ignoreClick = false; |
4605 | - }, |
4606 | - drawTooltip: function(content, x, y, options) { |
4607 | - var mt = this.getMouseTrack(), |
4608 | - style = 'opacity:0.7;background-color:#000;color:#fff;display:none;position:absolute;padding:2px 8px;-moz-border-radius:4px;border-radius:4px;white-space:nowrap;', |
4609 | - p = options.position, |
4610 | - m = options.margin, |
4611 | - plotOffset = this.plotOffset; |
4612 | - |
4613 | - if(x !== null && y !== null){ |
4614 | - if (!options.relative) { // absolute to the canvas |
4615 | - if(p.charAt(0) == 'n') style += 'top:' + (m + plotOffset.top) + 'px;bottom:auto;'; |
4616 | - else if(p.charAt(0) == 's') style += 'bottom:' + (m + plotOffset.bottom) + 'px;top:auto;'; |
4617 | - if(p.charAt(1) == 'e') style += 'right:' + (m + plotOffset.right) + 'px;left:auto;'; |
4618 | - else if(p.charAt(1) == 'w') style += 'left:' + (m + plotOffset.left) + 'px;right:auto;'; |
4619 | - } |
4620 | - else { // relative to the mouse |
4621 | - if(p.charAt(0) == 'n') style += 'bottom:' + (m - plotOffset.top - y + this.canvasHeight) + 'px;top:auto;'; |
4622 | - else if(p.charAt(0) == 's') style += 'top:' + (m + plotOffset.top + y) + 'px;bottom:auto;'; |
4623 | - if(p.charAt(1) == 'e') style += 'left:' + (m + plotOffset.left + x) + 'px;right:auto;'; |
4624 | - else if(p.charAt(1) == 'w') style += 'right:' + (m - plotOffset.left - x + this.canvasWidth) + 'px;left:auto;'; |
4625 | - } |
4626 | - |
4627 | - mt.style.cssText = style; |
4628 | - D.empty(mt); |
4629 | - D.insert(mt, content); |
4630 | - D.show(mt); |
4631 | - } |
4632 | - else { |
4633 | - D.hide(mt); |
4634 | - } |
4635 | - }, |
4636 | - |
4637 | - clip: function () { |
4638 | - |
4639 | - var |
4640 | - ctx = this.ctx, |
4641 | - o = this.plotOffset, |
4642 | - w = this.canvasWidth, |
4643 | - h = this.canvasHeight; |
4644 | - |
4645 | - if (flotr.isIE && flotr.isIE < 9) { |
4646 | - // Clipping for excanvas :-( |
4647 | - ctx.save(); |
4648 | - ctx.fillStyle = this.processColor(this.options.ieBackgroundColor); |
4649 | - ctx.fillRect(0, 0, w, o.top); |
4650 | - ctx.fillRect(0, 0, o.left, h); |
4651 | - ctx.fillRect(0, h - o.bottom, w, o.bottom); |
4652 | - ctx.fillRect(w - o.right, 0, o.right,h); |
4653 | - ctx.restore(); |
4654 | - } else { |
4655 | - ctx.clearRect(0, 0, w, o.top); |
4656 | - ctx.clearRect(0, 0, o.left, h); |
4657 | - ctx.clearRect(0, h - o.bottom, w, o.bottom); |
4658 | - ctx.clearRect(w - o.right, 0, o.right,h); |
4659 | - } |
4660 | - }, |
4661 | - |
4662 | - _initMembers: function() { |
4663 | - this._handles = []; |
4664 | - this.lastMousePos = {pageX: null, pageY: null }; |
4665 | - this.plotOffset = {left: 0, right: 0, top: 0, bottom: 0}; |
4666 | - this.ignoreClick = true; |
4667 | - this.prevHit = null; |
4668 | - }, |
4669 | - |
4670 | - _initGraphTypes: function() { |
4671 | - _.each(flotr.graphTypes, function(handler, graphType){ |
4672 | - this[graphType] = flotr.clone(handler); |
4673 | - }, this); |
4674 | - }, |
4675 | - |
4676 | - _initEvents: function () { |
4677 | - |
4678 | - var |
4679 | - el = this.el, |
4680 | - touchendHandler, movement, touchend; |
4681 | - |
4682 | - if ('ontouchstart' in el) { |
4683 | - |
4684 | - touchendHandler = _.bind(function (e) { |
4685 | - touchend = true; |
4686 | - E.stopObserving(document, 'touchend', touchendHandler); |
4687 | - E.fire(el, 'flotr:mouseup', [event, this]); |
4688 | - this.multitouches = null; |
4689 | - |
4690 | - if (!movement) { |
4691 | - this.clickHandler(e); |
4692 | - } |
4693 | - }, this); |
4694 | - |
4695 | - this.observe(this.overlay, 'touchstart', _.bind(function (e) { |
4696 | - movement = false; |
4697 | - touchend = false; |
4698 | - this.ignoreClick = false; |
4699 | - |
4700 | - if (e.touches && e.touches.length > 1) { |
4701 | - this.multitouches = e.touches; |
4702 | - } |
4703 | - |
4704 | - E.fire(el, 'flotr:mousedown', [event, this]); |
4705 | - this.observe(document, 'touchend', touchendHandler); |
4706 | - }, this)); |
4707 | - |
4708 | - this.observe(this.overlay, 'touchmove', _.bind(function (e) { |
4709 | - |
4710 | - var pos = this.getEventPosition(e); |
4711 | - |
4712 | - e.preventDefault(); |
4713 | - |
4714 | - movement = true; |
4715 | - |
4716 | - if (this.multitouches || (e.touches && e.touches.length > 1)) { |
4717 | - this.multitouches = e.touches; |
4718 | - } else { |
4719 | - if (!touchend) { |
4720 | - E.fire(el, 'flotr:mousemove', [event, pos, this]); |
4721 | - } |
4722 | - } |
4723 | - this.lastMousePos = pos; |
4724 | - }, this)); |
4725 | - |
4726 | - } else { |
4727 | - this. |
4728 | - observe(this.overlay, 'mousedown', _.bind(this.mouseDownHandler, this)). |
4729 | - observe(el, 'mousemove', _.bind(this.mouseMoveHandler, this)). |
4730 | - observe(this.overlay, 'click', _.bind(this.clickHandler, this)). |
4731 | - observe(el, 'mouseout', function () { |
4732 | - E.fire(el, 'flotr:mouseout'); |
4733 | - }); |
4734 | - } |
4735 | - }, |
4736 | - |
4737 | - /** |
4738 | - * Initializes the canvas and it's overlay canvas element. When the browser is IE, this makes use |
4739 | - * of excanvas. The overlay canvas is inserted for displaying interactions. After the canvas elements |
4740 | - * are created, the elements are inserted into the container element. |
4741 | - */ |
4742 | - _initCanvas: function(){ |
4743 | - var el = this.el, |
4744 | - o = this.options, |
4745 | - children = el.children, |
4746 | - removedChildren = [], |
4747 | - child, i, |
4748 | - size, style; |
4749 | - |
4750 | - // Empty the el |
4751 | - for (i = children.length; i--;) { |
4752 | - child = children[i]; |
4753 | - if (!this.canvas && child.className === 'flotr-canvas') { |
4754 | - this.canvas = child; |
4755 | - } else if (!this.overlay && child.className === 'flotr-overlay') { |
4756 | - this.overlay = child; |
4757 | - } else { |
4758 | - removedChildren.push(child); |
4759 | - } |
4760 | - } |
4761 | - for (i = removedChildren.length; i--;) { |
4762 | - el.removeChild(removedChildren[i]); |
4763 | - } |
4764 | - |
4765 | - D.setStyles(el, {position: 'relative'}); // For positioning labels and overlay. |
4766 | - size = {}; |
4767 | - size.width = el.clientWidth; |
4768 | - size.height = el.clientHeight; |
4769 | - |
4770 | - if(size.width <= 0 || size.height <= 0 || o.resolution <= 0){ |
4771 | - throw 'Invalid dimensions for plot, width = ' + size.width + ', height = ' + size.height + ', resolution = ' + o.resolution; |
4772 | - } |
4773 | - |
4774 | - // Main canvas for drawing graph types |
4775 | - this.canvas = getCanvas(this.canvas, 'canvas'); |
4776 | - // Overlay canvas for interactive features |
4777 | - this.overlay = getCanvas(this.overlay, 'overlay'); |
4778 | - this.ctx = getContext(this.canvas); |
4779 | - this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); |
4780 | - this.octx = getContext(this.overlay); |
4781 | - this.octx.clearRect(0, 0, this.overlay.width, this.overlay.height); |
4782 | - this.canvasHeight = size.height; |
4783 | - this.canvasWidth = size.width; |
4784 | - this.textEnabled = !!this.ctx.drawText || !!this.ctx.fillText; // Enable text functions |
4785 | - |
4786 | - function getCanvas(canvas, name){ |
4787 | - if(!canvas){ |
4788 | - canvas = D.create('canvas'); |
4789 | - if (typeof FlashCanvas != "undefined" && typeof canvas.getContext === 'function') { |
4790 | - FlashCanvas.initElement(canvas); |
4791 | - } |
4792 | - canvas.className = 'flotr-'+name; |
4793 | - canvas.style.cssText = 'position:absolute;left:0px;top:0px;'; |
4794 | - D.insert(el, canvas); |
4795 | - } |
4796 | - _.each(size, function(size, attribute){ |
4797 | - D.show(canvas); |
4798 | - if (name == 'canvas' && canvas.getAttribute(attribute) === size) { |
4799 | - return; |
4800 | - } |
4801 | - canvas.setAttribute(attribute, size * o.resolution); |
4802 | - canvas.style[attribute] = size + 'px'; |
4803 | - }); |
4804 | - canvas.context_ = null; // Reset the ExCanvas context |
4805 | - return canvas; |
4806 | - } |
4807 | - |
4808 | - function getContext(canvas){ |
4809 | - if(window.G_vmlCanvasManager) window.G_vmlCanvasManager.initElement(canvas); // For ExCanvas |
4810 | - var context = canvas.getContext('2d'); |
4811 | - if(!window.G_vmlCanvasManager) context.scale(o.resolution, o.resolution); |
4812 | - return context; |
4813 | - } |
4814 | - }, |
4815 | - |
4816 | - _initPlugins: function(){ |
4817 | - // TODO Should be moved to flotr and mixed in. |
4818 | - _.each(flotr.plugins, function(plugin, name){ |
4819 | - _.each(plugin.callbacks, function(fn, c){ |
4820 | - this.observe(this.el, c, _.bind(fn, this)); |
4821 | - }, this); |
4822 | - this[name] = flotr.clone(plugin); |
4823 | - _.each(this[name], function(fn, p){ |
4824 | - if (_.isFunction(fn)) |
4825 | - this[name][p] = _.bind(fn, this); |
4826 | - }, this); |
4827 | - }, this); |
4828 | - }, |
4829 | - |
4830 | - /** |
4831 | - * Sets options and initializes some variables and color specific values, used by the constructor. |
4832 | - * @param {Object} opts - options object |
4833 | - */ |
4834 | - _initOptions: function(opts){ |
4835 | - var options = flotr.clone(flotr.defaultOptions); |
4836 | - options.x2axis = _.extend(_.clone(options.xaxis), options.x2axis); |
4837 | - options.y2axis = _.extend(_.clone(options.yaxis), options.y2axis); |
4838 | - this.options = flotr.merge(opts || {}, options); |
4839 | - |
4840 | - if (this.options.grid.minorVerticalLines === null && |
4841 | - this.options.xaxis.scaling === 'logarithmic') { |
4842 | - this.options.grid.minorVerticalLines = true; |
4843 | - } |
4844 | - if (this.options.grid.minorHorizontalLines === null && |
4845 | - this.options.yaxis.scaling === 'logarithmic') { |
4846 | - this.options.grid.minorHorizontalLines = true; |
4847 | - } |
4848 | - |
4849 | - E.fire(this.el, 'flotr:afterinitoptions', [this]); |
4850 | - |
4851 | - this.axes = flotr.Axis.getAxes(this.options); |
4852 | - |
4853 | - // Initialize some variables used throughout this function. |
4854 | - var assignedColors = [], |
4855 | - colors = [], |
4856 | - ln = this.series.length, |
4857 | - neededColors = this.series.length, |
4858 | - oc = this.options.colors, |
4859 | - usedColors = [], |
4860 | - variation = 0, |
4861 | - c, i, j, s; |
4862 | - |
4863 | - // Collect user-defined colors from series. |
4864 | - for(i = neededColors - 1; i > -1; --i){ |
4865 | - c = this.series[i].color; |
4866 | - if(c){ |
4867 | - --neededColors; |
4868 | - if(_.isNumber(c)) assignedColors.push(c); |
4869 | - else usedColors.push(flotr.Color.parse(c)); |
4870 | - } |
4871 | - } |
4872 | - |
4873 | - // Calculate the number of colors that need to be generated. |
4874 | - for(i = assignedColors.length - 1; i > -1; --i) |
4875 | - neededColors = Math.max(neededColors, assignedColors[i] + 1); |
4876 | - |
4877 | - // Generate needed number of colors. |
4878 | - for(i = 0; colors.length < neededColors;){ |
4879 | - c = (oc.length == i) ? new flotr.Color(100, 100, 100) : flotr.Color.parse(oc[i]); |
4880 | - |
4881 | - // Make sure each serie gets a different color. |
4882 | - var sign = variation % 2 == 1 ? -1 : 1, |
4883 | - factor = 1 + sign * Math.ceil(variation / 2) * 0.2; |
4884 | - c.scale(factor, factor, factor); |
4885 | - |
4886 | - /** |
4887 | - * @todo if we're getting too close to something else, we should probably skip this one |
4888 | - */ |
4889 | - colors.push(c); |
4890 | - |
4891 | - if(++i >= oc.length){ |
4892 | - i = 0; |
4893 | - ++variation; |
4894 | - } |
4895 | - } |
4896 | - |
4897 | - // Fill the options with the generated colors. |
4898 | - for(i = 0, j = 0; i < ln; ++i){ |
4899 | - s = this.series[i]; |
4900 | - |
4901 | - // Assign the color. |
4902 | - if (!s.color){ |
4903 | - s.color = colors[j++].toString(); |
4904 | - }else if(_.isNumber(s.color)){ |
4905 | - s.color = colors[s.color].toString(); |
4906 | - } |
4907 | - |
4908 | - // Every series needs an axis |
4909 | - if (!s.xaxis) s.xaxis = this.axes.x; |
4910 | - if (s.xaxis == 1) s.xaxis = this.axes.x; |
4911 | - else if (s.xaxis == 2) s.xaxis = this.axes.x2; |
4912 | - |
4913 | - if (!s.yaxis) s.yaxis = this.axes.y; |
4914 | - if (s.yaxis == 1) s.yaxis = this.axes.y; |
4915 | - else if (s.yaxis == 2) s.yaxis = this.axes.y2; |
4916 | - |
4917 | - // Apply missing options to the series. |
4918 | - for (var t in flotr.graphTypes){ |
4919 | - s[t] = _.extend(_.clone(this.options[t]), s[t]); |
4920 | - } |
4921 | - s.mouse = _.extend(_.clone(this.options.mouse), s.mouse); |
4922 | - |
4923 | - if (_.isUndefined(s.shadowSize)) s.shadowSize = this.options.shadowSize; |
4924 | - } |
4925 | - }, |
4926 | - |
4927 | - _setEl: function(el) { |
4928 | - if (!el) throw 'The target container doesn\'t exist'; |
4929 | - else if (el.graph instanceof Graph) el.graph.destroy(); |
4930 | - else if (!el.clientWidth) throw 'The target container must be visible'; |
4931 | - |
4932 | - el.graph = this; |
4933 | - this.el = el; |
4934 | - } |
4935 | -}; |
4936 | - |
4937 | -Flotr.Graph = Graph; |
4938 | - |
4939 | -})(); |
4940 | - |
4941 | -/** |
4942 | - * Flotr Axis Library |
4943 | - */ |
4944 | - |
4945 | -(function () { |
4946 | - |
4947 | -var |
4948 | - _ = Flotr._, |
4949 | - LOGARITHMIC = 'logarithmic'; |
4950 | - |
4951 | -function Axis (o) { |
4952 | - |
4953 | - this.orientation = 1; |
4954 | - this.offset = 0; |
4955 | - this.datamin = Number.MAX_VALUE; |
4956 | - this.datamax = -Number.MAX_VALUE; |
4957 | - |
4958 | - _.extend(this, o); |
4959 | - |
4960 | - this._setTranslations(); |
4961 | -} |
4962 | - |
4963 | - |
4964 | -// Prototype |
4965 | -Axis.prototype = { |
4966 | - |
4967 | - setScale : function () { |
4968 | - var length = this.length; |
4969 | - if (this.options.scaling == LOGARITHMIC) { |
4970 | - this.scale = length / (log(this.max, this.options.base) - log(this.min, this.options.base)); |
4971 | - } else { |
4972 | - this.scale = length / (this.max - this.min); |
4973 | - } |
4974 | - }, |
4975 | - |
4976 | - calculateTicks : function () { |
4977 | - var options = this.options; |
4978 | - |
4979 | - this.ticks = []; |
4980 | - this.minorTicks = []; |
4981 | - |
4982 | - // User Ticks |
4983 | - if(options.ticks){ |
4984 | - this._cleanUserTicks(options.ticks, this.ticks); |
4985 | - this._cleanUserTicks(options.minorTicks || [], this.minorTicks); |
4986 | - } |
4987 | - else { |
4988 | - if (options.mode == 'time') { |
4989 | - this._calculateTimeTicks(); |
4990 | - } else if (options.scaling === 'logarithmic') { |
4991 | - this._calculateLogTicks(); |
4992 | - } else { |
4993 | - this._calculateTicks(); |
4994 | - } |
4995 | - } |
4996 | - }, |
4997 | - |
4998 | - /** |
4999 | - * Calculates the range of an axis to apply autoscaling. |
5000 | - */ |