Mercurial > hg > mpiwg_geobrowser
comparison lib/GeoTemCo/js/PieChart/PieChartCategoryChooser.js @ 0:b57c7821382f
initial
author | Dirk Wintergruen <dwinter@mpiwg-berlin.mpg.de> |
---|---|
date | Thu, 28 May 2015 10:28:12 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:b57c7821382f |
---|---|
1 /* | |
2 * PieChartCategoryChooser.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 PieChartCategoryChooser | |
24 * PieChart dialog for category creation | |
25 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de) | |
26 * | |
27 * @param {PieChartWidget} parent PieChart widget object | |
28 * @param {JSON} options PieChart configuration | |
29 * @param {number} datasetIndex index of the dataset | |
30 * @param {String} columnName name of the column | |
31 */ | |
32 | |
33 function PieChartCategoryChooser(pieChart, options, datasetIndex, columnName, type, categories) { | |
34 | |
35 var pieChartCategoryChooser = this; | |
36 | |
37 this.parent = pieChart; | |
38 this.options = options; | |
39 this.datasetIndex = parseInt(datasetIndex); | |
40 this.columnName = columnName; | |
41 this.chartData; | |
42 | |
43 this.dialog = $("<div></div>"); | |
44 this.dialog.html("").dialog({modal: true}).dialog('open'); | |
45 | |
46 //to asure that the dialog is above (z-index of) the toolbars | |
47 $(".ui-front").css("z-index","10001"); | |
48 | |
49 var allNumeric = this.loadValues(datasetIndex, columnName); | |
50 | |
51 if (typeof allNumeric === "undefined") | |
52 return; | |
53 if (allNumeric === true){ | |
54 this.createNumeralBasedChooser(this.chartData, categories); | |
55 } else { | |
56 this.createTextBasedChooser(this.chartData, categories); | |
57 } | |
58 }; | |
59 | |
60 PieChartCategoryChooser.prototype = { | |
61 | |
62 loadValues : function(datasetIndex, columnName){ | |
63 var pieChartCategoryChooser = this; | |
64 | |
65 var allNumeric = true; | |
66 pieChartCategoryChooser.chartData = []; | |
67 var chartData = pieChartCategoryChooser.chartData; | |
68 $(GeoTemConfig.datasets[datasetIndex].objects).each(function(){ | |
69 var columnData = | |
70 pieChartCategoryChooser.parent.getElementData(this, columnName); | |
71 | |
72 if (isNaN(parseFloat(columnData))) | |
73 allNumeric = false; | |
74 | |
75 if ($.inArray(columnData, chartData) == -1) | |
76 chartData.push(columnData); | |
77 }); | |
78 | |
79 if (chartData.length === 0) | |
80 return; | |
81 else | |
82 return allNumeric; | |
83 }, | |
84 | |
85 createTextBasedChooser : function(chartData, categories){ | |
86 var pieChartCategoryChooser = this; | |
87 | |
88 var addCategory = function(name,elements){ | |
89 var newCategoryContainer = document.createElement("fieldset"); | |
90 var newCategoryLegend = document.createElement("legend"); | |
91 var newCategoryName = document.createElement("input"); | |
92 $(newCategoryName).width("80%"); | |
93 newCategoryName.type = "text"; | |
94 newCategoryName.value = name; | |
95 var newCategoryRemove = document.createElement("button"); | |
96 $(newCategoryRemove).text("X"); | |
97 $(newCategoryRemove).click(function(){ | |
98 $(newCategoryContainer).find("li").each(function(){ | |
99 //move all elements to unselected list | |
100 //("unselected" is defined below) | |
101 //prepend so the items appear on top | |
102 $(this).prependTo(unselected); | |
103 }); | |
104 //and remove this category | |
105 $(newCategoryContainer).remove(); | |
106 }); | |
107 $(newCategoryLegend).append(newCategoryName); | |
108 $(newCategoryLegend).append(newCategoryRemove); | |
109 $(newCategoryContainer).append(newCategoryLegend); | |
110 $(newCategoryContainer).width("200px"); | |
111 $(newCategoryContainer).css("float","left"); | |
112 var newCategory = document.createElement("ul"); | |
113 $(newCategory).addClass("connectedSortable"); | |
114 $(newCategory).css("background", "#eee"); | |
115 newCategoryContainer.appendChild(newCategory); | |
116 $(newCategory).append("<br/>"); | |
117 cell.appendChild(newCategoryContainer); | |
118 //if there are pre-selected elements (e.g. "edit") | |
119 //add them and remove them from unselected value list | |
120 if (typeof elements !== "undefined"){ | |
121 $(elements).each(function(){ | |
122 var value = this; | |
123 //add to category | |
124 $(newCategory).append("<li>"+value+"</li>"); | |
125 //remove from unselected list | |
126 $(unselected).find("li").filter(function(){ | |
127 return ($(this).text() === ""+value); | |
128 }).remove(); | |
129 }); | |
130 } | |
131 | |
132 $( ".connectedSortable" ).sortable({ | |
133 connectWith: ".connectedSortable" | |
134 }).disableSelection(); | |
135 }; | |
136 | |
137 var table = document.createElement("table"); | |
138 var row = document.createElement("tr"); | |
139 table.appendChild(row); | |
140 var cell = document.createElement("td"); | |
141 row.appendChild(cell); | |
142 cell = document.createElement("td"); | |
143 row.appendChild(cell); | |
144 var addCategoryButton = document.createElement("button"); | |
145 $(addCategoryButton).text("add new category"); | |
146 cell.appendChild(addCategoryButton); | |
147 var applyCategoryButton = document.createElement("button"); | |
148 $(applyCategoryButton).text("apply"); | |
149 cell.appendChild(applyCategoryButton); | |
150 | |
151 row = document.createElement("tr"); | |
152 table.appendChild(row); | |
153 cell = document.createElement("td"); | |
154 row.appendChild(cell); | |
155 var unselected = document.createElement("ul"); | |
156 $(unselected).addClass("connectedSortable"); | |
157 cell.appendChild(unselected); | |
158 cell = document.createElement("td"); | |
159 $(cell).attr("valign","top"); | |
160 $(cell).width("100%"); | |
161 row.appendChild(cell); | |
162 | |
163 this.dialog.append(table); | |
164 | |
165 $( ".connectedSortable" ).sortable({ | |
166 connectWith: ".connectedSortable" | |
167 }).disableSelection(); | |
168 | |
169 $(chartData).each(function(){ | |
170 $(unselected).append("<li class='ui-state-default'>"+this+"</li>"); | |
171 }); | |
172 | |
173 if (typeof categories !== "undefined"){ | |
174 $(categories).each(function(){ | |
175 var category = this; | |
176 addCategory(category.label, category.values); | |
177 }); | |
178 } | |
179 | |
180 $(addCategoryButton).click(function(){addCategory();}); | |
181 | |
182 $(applyCategoryButton).click(function(){ | |
183 var categories = []; | |
184 $(cell).children().each(function(){ | |
185 var label = $(this).find("legend > input").val(); | |
186 var values = []; | |
187 $(this).find("li").each(function(){ | |
188 values.push($(this).text()); | |
189 }); | |
190 | |
191 categories.push({label:label,values:values}); | |
192 }); | |
193 | |
194 var values = []; | |
195 $(unselected).find("li").each(function(){ | |
196 values.push($(this).text()); | |
197 }); | |
198 | |
199 categories.push({label:"other",values:values}); | |
200 | |
201 //create pie chart | |
202 pieChartCategoryChooser.parent.addCategorizedPieChart( | |
203 pieChartCategoryChooser.datasetIndex, pieChartCategoryChooser.columnName, | |
204 "text", categories); | |
205 | |
206 //close dialog | |
207 $(pieChartCategoryChooser.dialog).dialog("close"); | |
208 }); | |
209 | |
210 //set dialog size | |
211 var wWidth = $(window).width(); | |
212 var dWidth = wWidth * 0.9; | |
213 var wHeight = $(window).height(); | |
214 var dHeight = wHeight * 0.9; | |
215 $(this.dialog).dialog("option", "width", dWidth); | |
216 $(this.dialog).dialog("option", "height", dHeight); | |
217 }, | |
218 | |
219 createNumeralBasedChooser : function(chartData, existingCategories){ | |
220 var numericChartData = []; | |
221 for (var i = 0; i < chartData.length; i++){ | |
222 numericChartData.push(parseFloat(chartData[i])); | |
223 } | |
224 chartData = numericChartData; | |
225 chartData = chartData.sort(function sortNumber(a,b){ | |
226 return a - b; | |
227 }); | |
228 | |
229 var min = chartData[0]; | |
230 var max = chartData[chartData.length-1]; | |
231 //find minimum step width that is needed | |
232 //(otherwise there could be steps that contain more than one element) | |
233 var minStep=max-min; | |
234 for (var i = 1; i < chartData.length; i++){ | |
235 var thisStep = chartData[i]-chartData[i-1]; | |
236 if ((thisStep) < minStep) | |
237 minStep = thisStep; | |
238 } | |
239 | |
240 var pieChartCategoryChooser = this; | |
241 | |
242 var addCategoryButton = document.createElement("button"); | |
243 $(addCategoryButton).text("add new category"); | |
244 this.dialog.append(addCategoryButton); | |
245 var applyCategoryButton = document.createElement("button"); | |
246 $(applyCategoryButton).text("apply"); | |
247 this.dialog.append(applyCategoryButton); | |
248 this.dialog.append("tip: use left/right arrow key for finer adjustment"); | |
249 | |
250 var table = document.createElement("table"); | |
251 row = document.createElement("tr"); | |
252 table.appendChild(row); | |
253 cell = document.createElement("td"); | |
254 row.appendChild(cell); | |
255 cell.colSpan = 2; | |
256 var slider = document.createElement("div"); | |
257 cell.appendChild(slider); | |
258 var handles = []; | |
259 var categories = []; | |
260 | |
261 row = document.createElement("tr"); | |
262 table.appendChild(row); | |
263 cell = document.createElement("td"); | |
264 $(cell).attr("valign","top"); | |
265 row.appendChild(cell); | |
266 var unselected = document.createElement("ul"); | |
267 cell.appendChild(unselected); | |
268 | |
269 cell = document.createElement("td"); | |
270 $(cell).attr("valign","top"); | |
271 $(cell).width("100%"); | |
272 row.appendChild(cell); | |
273 | |
274 this.dialog.append(table); | |
275 | |
276 $(chartData).each(function(){ | |
277 $(unselected).append("<li class='ui-state-default'>"+this+"</li>"); | |
278 }); | |
279 | |
280 var addCategory = function(boundary){ | |
281 //check if another handle can be added | |
282 if ((handles.length>0) && (handles[handles.length-1] === max)) | |
283 return false; | |
284 //destroy old slider (has to be recreated to show the new handle) | |
285 if (handles.length>0) | |
286 $(slider).slider("destroy"); | |
287 | |
288 if (typeof boundary === "undefined") | |
289 boundary = max; | |
290 handles.push(boundary); | |
291 | |
292 $(slider).slider({ | |
293 min:min, | |
294 max:max, | |
295 step:minStep, | |
296 values: handles | |
297 }); | |
298 | |
299 var placeValues = function(){ | |
300 $(unselected).find("li").remove(); | |
301 $(cell).children().find("li").remove(); | |
302 | |
303 var j = 0, i = 0; | |
304 for (; i < chartData.length; i++){ | |
305 if (chartData[i]>handles[j]) | |
306 j++; | |
307 if (j == handles.length) | |
308 break; | |
309 $(categories[j]).append("<li class='ui-state-default'>"+chartData[i]+"</li>"); | |
310 } | |
311 for (; i < chartData.length; i++){ | |
312 $(unselected).append("<li class='ui-state-default'>"+chartData[i]+"</li>"); | |
313 } | |
314 }; | |
315 | |
316 $(slider).on( "slide", function( event, ui ){ | |
317 var last = min; | |
318 //check whether handle values are increasing | |
319 for(var i = 0; i < ui.values.length; i++){ | |
320 if (ui.values[i]<last) | |
321 return false; | |
322 last = ui.values[i]; | |
323 } | |
324 handles = ui.values; | |
325 for(var i = 0; i < handles.length; i++){ | |
326 $(categories[i]).parent().find("legend").text("<="+handles[i]); | |
327 } | |
328 | |
329 placeValues(); | |
330 }); | |
331 | |
332 var newCategoryContainer = document.createElement("fieldset"); | |
333 $(newCategoryContainer).append("<legend><="+boundary+"</legend>"); | |
334 $(newCategoryContainer).width("188px"); | |
335 $(newCategoryContainer).css("float","left"); | |
336 var newCategory = document.createElement("ul"); | |
337 $(newCategory).addClass("connectedSortable"); | |
338 $(newCategory).css("background", "#eee"); | |
339 newCategoryContainer.appendChild(newCategory); | |
340 cell.appendChild(newCategoryContainer); | |
341 categories.push(newCategory); | |
342 | |
343 placeValues(); | |
344 }; | |
345 | |
346 $(addCategoryButton).click(function(){addCategory();}); | |
347 | |
348 if (typeof existingCategories !== "undefined"){ | |
349 $(existingCategories).each(function(){ | |
350 var boundary = this; | |
351 addCategory(boundary); | |
352 }); | |
353 } | |
354 | |
355 $(applyCategoryButton).click(function(){ | |
356 var categorieBoundaries = handles; | |
357 | |
358 //create pie chart | |
359 pieChartCategoryChooser.parent.addCategorizedPieChart( | |
360 pieChartCategoryChooser.datasetIndex, pieChartCategoryChooser.columnName, | |
361 "numeral", categorieBoundaries); | |
362 | |
363 //close dialog | |
364 $(pieChartCategoryChooser.dialog).dialog("close"); | |
365 }); | |
366 | |
367 //set dialog size | |
368 var wWidth = $(window).width(); | |
369 var dWidth = wWidth * 0.9; | |
370 var wHeight = $(window).height(); | |
371 var dHeight = wHeight * 0.9; | |
372 $(this.dialog).dialog("option", "width", dWidth); | |
373 $(this.dialog).dialog("option", "height", dHeight); | |
374 } | |
375 }; |