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 };