Mercurial > hg > extraction-interface
comparison geotemco/js/PieChart/PieChart.js @ 0:b12c99b7c3f0
commit for previous development
author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
---|---|
date | Mon, 19 Jan 2015 17:13:49 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:b12c99b7c3f0 |
---|---|
1 /* | |
2 * PieChart.js | |
3 * | |
4 * Copyright (c) 2013, Sebastian Kruse. All rights reserved. | |
5 * | |
6 * This library is free software; you can redistribute it and/or | |
7 * modify it under the terms of the GNU Lesser General Public | |
8 * License as published by the Free Software Foundation; either | |
9 * version 3 of the License, or (at your option) any later version. | |
10 * | |
11 * This library is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
17 * License along with this library; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
19 * MA 02110-1301 USA | |
20 */ | |
21 | |
22 /** | |
23 * @class PieChart | |
24 * Implementation for a PieChart | |
25 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de) | |
26 * | |
27 * @param {HTML object} parent div to append the PieChart | |
28 */ | |
29 function PieChart(parent, watchedDataset, watchedColumn, selectionFunction) { | |
30 | |
31 if ((typeof selectionFunction !== "undefined") && | |
32 (typeof selectionFunction.type !== "undefined") && | |
33 (typeof selectionFunction.categories !== "undefined")){ | |
34 this.type = selectionFunction.type; | |
35 this.categories = selectionFunction.categories; | |
36 } | |
37 this.pieChart = this; | |
38 this.pieChartDiv; | |
39 this.preHighlightObjects; | |
40 this.highlightedLabel; | |
41 | |
42 this.informationDIV; | |
43 this.pieChartLabel; | |
44 | |
45 this.parent = parent; | |
46 this.options = parent.options; | |
47 | |
48 this.watchedDatasetObject; | |
49 this.watchedDataset = parseInt(watchedDataset); | |
50 this.watchColumn = watchedColumn; | |
51 if (typeof selectionFunction !== "undefined") | |
52 this.selectionFunction = selectionFunction; | |
53 else | |
54 //default selectionFunction returns value (creates "distinct" piechart) | |
55 this.selectionFunction = function(columnData){return columnData;}; | |
56 } | |
57 | |
58 PieChart.prototype = { | |
59 | |
60 remove : function() { | |
61 for (var i = 0; i < this.parent.pieCharts.length; i++){ | |
62 if (this.parent.pieCharts[i] === this) | |
63 this.parent.pieCharts[i] = null; | |
64 } | |
65 $(this.pieChartDiv).remove(); | |
66 $(this.informationDIV).remove(); | |
67 this.parent.redrawPieCharts(); | |
68 }, | |
69 | |
70 refreshLabel : function(){ | |
71 $(this.pieChartLabel).empty(); | |
72 $(this.pieChartLabel).append(this.watchedDatasetObject.label + " - " + this.watchColumn); | |
73 | |
74 var c = GeoTemConfig.getColor(this.watchedDataset); | |
75 $(this.pieChartLabel).css("color","rgb("+c.r1+","+c.g1+","+c.b1+")"); | |
76 }, | |
77 | |
78 initialize : function() { | |
79 var pieChart = this; | |
80 | |
81 if (typeof this.pieChartDiv === "undefined"){ | |
82 this.informationDIV = document.createElement("div"); | |
83 this.pieChartLabel = $("<span></span>"); | |
84 $(this.informationDIV).append(this.pieChartLabel); | |
85 this.refreshLabel(); | |
86 | |
87 var removeButton = document.createElement("button"); | |
88 $(this.informationDIV).append(removeButton); | |
89 $(removeButton).text("remove"); | |
90 $(removeButton).click(function(){ | |
91 pieChart.remove(); | |
92 }); | |
93 | |
94 //only allow editing if it is a "manually" created piechart | |
95 //automatic (with a selection function) ones, can lead to numerous problems, | |
96 //e.g. too many categories or numeral categories threated as text ones | |
97 if ((typeof pieChart.type !== "undefined")&& | |
98 (typeof pieChart.categories !== "undefined")){ | |
99 var editButton = document.createElement("button"); | |
100 $(this.informationDIV).append(editButton); | |
101 $(editButton).text("edit"); | |
102 $(editButton).click(function(){ | |
103 var chooser = new PieChartCategoryChooser( | |
104 pieChart.parent, | |
105 pieChart.parent.options, | |
106 pieChart.watchedDataset, | |
107 pieChart.watchColumn, | |
108 pieChart.type, | |
109 pieChart.categories); | |
110 }); | |
111 | |
112 //add save button | |
113 if (pieChart.options.allowLocalStorage){ | |
114 var saveButton = document.createElement("button"); | |
115 $(this.informationDIV).append(saveButton); | |
116 $(saveButton).text("save"); | |
117 $(saveButton).click(function(){ | |
118 $( "<div>" + | |
119 "pie chart name : " + | |
120 "<input type='text' size=30 id='saveName' class='ui-widget-content ui-corner-all'></input>" + | |
121 "</div>").dialog({ | |
122 width:'auto', | |
123 buttons: [ | |
124 { | |
125 text: "save", | |
126 click: function(){ | |
127 var saveName = $("#saveName").val(); | |
128 var saveObject = new Object(); | |
129 saveObject.type = pieChart.type; | |
130 saveObject.categories = pieChart.categories; | |
131 saveObject.columnName = pieChart.watchColumn; | |
132 //save to LocalStorage | |
133 $.remember({ | |
134 name:pieChart.options.localStoragePrefix+saveName, | |
135 value:saveObject, | |
136 json:true | |
137 }); | |
138 $(this).dialog( "close" ); | |
139 } | |
140 } | |
141 ] | |
142 }); | |
143 | |
144 //set value to default (column name) | |
145 $("#saveName").val(pieChart.watchColumn); | |
146 //TODO: z-index has to be set, as the "tool-bars" of map (.ddbToolbar in style.css) | |
147 //also have a z-index of 10000. z-index should be removed from all elements. | |
148 $(".ui-dialog").css("z-index",10005); | |
149 }); | |
150 } | |
151 } | |
152 | |
153 $(this.parent.gui.pieChartsDiv).append(this.informationDIV); | |
154 this.pieChartDiv = document.createElement("div"); | |
155 $(this.parent.gui.pieChartsDiv).append(this.pieChartDiv); | |
156 | |
157 $(this.pieChartDiv).unbind(); | |
158 $(this.pieChartDiv).bind("plothover", function (event, pos, item) { | |
159 var highlightedLabel; | |
160 | |
161 if (item) { | |
162 highlightedLabel = item.series.label; | |
163 } | |
164 if (highlightedLabel !== pieChart.highlightedLabel){ | |
165 pieChart.highlightedLabel = highlightedLabel; | |
166 pieChart.triggerHighlight(highlightedLabel); | |
167 } | |
168 }); | |
169 | |
170 $(this.pieChartDiv).bind("plotclick", function (event, pos, item) { | |
171 if (item) { | |
172 //item.series.label contains the column element | |
173 pieChart.triggerSelection(item.series.label); | |
174 } else { | |
175 pieChart.triggerSelection(); | |
176 } | |
177 }); | |
178 } | |
179 }, | |
180 | |
181 //check if dataset is still there | |
182 checkForDataSet : function() { | |
183 var datasets = this.parent.datasets; | |
184 if ((typeof datasets !== "undefined") && (typeof this.watchedDatasetObject !== "undefined")){ | |
185 //check if our data went missing | |
186 for (var i = 0; i < datasets.length; i++){ | |
187 if (datasets[i] === this.watchedDatasetObject){ | |
188 //if dataset "before" this one was removed, the index changes | |
189 if (this.watchedDataset !== i){ | |
190 //change color to the new one (changes with index!) | |
191 this.watchedDataset = i; | |
192 this.refreshLabel(); | |
193 } | |
194 return true; | |
195 } | |
196 } | |
197 } | |
198 return false; | |
199 }, | |
200 | |
201 initPieChart : function(dataSets) { | |
202 // get dataset object (could not be there on startup, e.g. piechart defined before load completes) | |
203 if (typeof this.watchedDatasetObject === "undefined") | |
204 this.watchedDatasetObject = this.parent.datasets[this.watchedDataset]; | |
205 | |
206 this.initialize(); | |
207 | |
208 // if our dataset went missing, remove this piechart | |
209 if (!this.checkForDataSet()){ | |
210 this.remove(); | |
211 return; | |
212 } | |
213 | |
214 var objects = []; | |
215 for (var i = 0; i < dataSets.length; i++) | |
216 objects.push([]); | |
217 objects[this.watchedDataset] = dataSets[this.watchedDataset].objects; | |
218 | |
219 this.preHighlightObjects = objects; | |
220 this.redrawPieChart(objects); | |
221 }, | |
222 | |
223 redrawPieChart : function(objects) { | |
224 | |
225 if (typeof objects === "undefined") | |
226 objects = this.preHighlightObjects; | |
227 | |
228 if (this.checkForDataSet(objects)){ | |
229 var pieChart = this; | |
230 if (objects[this.watchedDataset].length === 0) | |
231 objects = this.preHighlightObjects; | |
232 | |
233 var calculateSlices = function(dataObjects){ | |
234 var chartDataCounter = new Object; | |
235 | |
236 $(dataObjects).each(function(){ | |
237 var columnData = pieChart.parent.getElementData(this, pieChart.watchColumn, pieChart.selectionFunction); | |
238 | |
239 //disregard empty cells | |
240 if ( (typeof columnData === "undefined") || (columnData == "") ) | |
241 return; | |
242 | |
243 var weight = this.weight; | |
244 | |
245 if (typeof chartDataCounter[columnData] === "undefined") | |
246 chartDataCounter[columnData] = weight; | |
247 else | |
248 chartDataCounter[columnData] += weight; | |
249 }); | |
250 | |
251 var chartData = []; | |
252 $.each(chartDataCounter, function(name,val){ | |
253 //get rgb-color (24bit = 6 hex digits) from hash | |
254 var color = '#'+hex_md5(name).substr(0,6); | |
255 chartData.push({label:name,data:val,color:color}); | |
256 }); | |
257 | |
258 //sort by count (occurances of category) | |
259 var sortByVal = function(a,b){ | |
260 return (b.data-a.data); | |
261 }; | |
262 chartData.sort(sortByVal); | |
263 | |
264 return chartData; | |
265 }; | |
266 | |
267 var chartData = calculateSlices(objects[this.watchedDataset]); | |
268 | |
269 if (chartData.length>0){ | |
270 $(this.pieChartDiv).empty(); | |
271 | |
272 //calculate height (flot NEEDS a height) | |
273 var parentHeight = $(this.parent.gui.pieChartsDiv).outerHeight(true) - $(this.parent.gui.columnSelectorDiv).outerHeight(true); | |
274 var pieChartCount = 0; | |
275 $(this.parent.pieCharts).each(function(){ | |
276 if (this instanceof PieChart) | |
277 pieChartCount++; | |
278 }); | |
279 var height = (parentHeight/pieChartCount) - $(this.informationDIV).outerHeight(true); | |
280 if (pieChart.options.restrictPieChartSize !== false) | |
281 height = Math.min(height, $(window).height() * pieChart.options.restrictPieChartSize); | |
282 $(this.pieChartDiv).height(height); | |
283 | |
284 $.plot($(this.pieChartDiv), chartData, | |
285 { | |
286 series: { | |
287 // Make this a pie chart. | |
288 pie: { | |
289 show:true | |
290 } | |
291 }, | |
292 legend: { show:true, position: 'se' }, | |
293 grid: { | |
294 hoverable: true, | |
295 clickable: true | |
296 }, | |
297 tooltip: true, | |
298 tooltipOpts: { | |
299 content: "%s %p.1%" | |
300 } | |
301 } | |
302 ); | |
303 } | |
304 } | |
305 }, | |
306 | |
307 triggerHighlight : function(columnElement) { | |
308 var highlightedObjects = []; | |
309 for (var i = 0; i < GeoTemConfig.datasets.length; i++) | |
310 highlightedObjects.push([]); | |
311 | |
312 if (this.watchedDataset >= 0) | |
313 highlightedObjects[this.watchedDataset] = | |
314 this.parent.getElementsByValue(columnElement, this.watchedDataset, this.watchColumn, this.selectionFunction); | |
315 else | |
316 highlightedObjects[this.watchedDataset] = []; | |
317 | |
318 this.parent.core.triggerHighlight(highlightedObjects); | |
319 | |
320 var pieChart = this; | |
321 $(this.parent.pieCharts).each(function(){ | |
322 if (this instanceof PieChart && (this !== pieChart)){ | |
323 if (this.watchedDataset === pieChart.watchedDataset) | |
324 this.redrawPieChart(highlightedObjects); | |
325 } | |
326 }); | |
327 }, | |
328 | |
329 triggerSelection : function(columnElement) { | |
330 var selectedObjects = []; | |
331 for (var i = 0; i < GeoTemConfig.datasets.length; i++) | |
332 selectedObjects.push([]); | |
333 | |
334 var selection; | |
335 if (typeof columnElement !== "undefined"){ | |
336 selectedObjects[this.watchedDataset] = | |
337 this.parent.getElementsByValue(columnElement, this.watchedDataset, this.watchColumn, this.selectionFunction); | |
338 selection = new Selection(selectedObjects, this); | |
339 } else { | |
340 selection = new Selection(selectedObjects); | |
341 } | |
342 | |
343 this.parent.core.triggerSelection(selection); | |
344 | |
345 if (!selection.valid()){ | |
346 selection.loadAllObjects(); | |
347 //"undo" selection (click next to piechart) | |
348 //so also redraw this dataset | |
349 this.preHighlightObjects = selection.objects; | |
350 this.redrawPieChart(selection.objects); | |
351 } | |
352 | |
353 var pieChart = this; | |
354 $(this.parent.pieCharts).each(function(){ | |
355 if (this instanceof PieChart && (this !== pieChart)){ | |
356 if (this.watchedDataset === pieChart.watchedDataset){ | |
357 this.preHighlightObjects = selection.objects; | |
358 this.redrawPieChart(selection.objects); | |
359 } | |
360 } | |
361 }); | |
362 }, | |
363 | |
364 deselection : function() { | |
365 }, | |
366 | |
367 filtering : function() { | |
368 }, | |
369 | |
370 inverseFiltering : function() { | |
371 }, | |
372 | |
373 triggerRefining : function() { | |
374 }, | |
375 | |
376 reset : function() { | |
377 }, | |
378 | |
379 show : function() { | |
380 }, | |
381 | |
382 hide : function() { | |
383 } | |
384 }; |