Mercurial > hg > extraction-interface
comparison geotemco/js/FuzzyTimeline/FuzzyTimelineWidget.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 * FuzzyTimelineWidget.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 FuzzyTimelineWidget | |
24 * FuzzyTimelineWidget Implementation | |
25 * @author Sebastian Kruse (skruse@mpiwg-berlin.mpg.de) | |
26 * | |
27 * @param {WidgetWrapper} core wrapper for interaction to other widgets | |
28 * @param {HTML object} div parent div to append the FuzzyTimeline widget div | |
29 * @param {JSON} options user specified configuration that overwrites options in FuzzyTimelineConfig.js | |
30 */ | |
31 FuzzyTimelineWidget = function(core, div, options) { | |
32 | |
33 this.datasets; | |
34 this.selected = undefined; | |
35 this.overallMin; | |
36 this.overallMax; | |
37 | |
38 this.core = core; | |
39 this.core.setWidget(this); | |
40 | |
41 this.options = (new FuzzyTimelineConfig(options)).options; | |
42 this.gui = new FuzzyTimelineGui(this, div, this.options); | |
43 | |
44 this.viewMode; | |
45 this.density; | |
46 this.rangeSlider; | |
47 this.rangeBars; | |
48 this.rangePiechart; | |
49 this.spanHash = []; | |
50 | |
51 this.handles = []; | |
52 this.zoomFactor = 1; | |
53 | |
54 this.scaleMode = "normal"; | |
55 } | |
56 | |
57 FuzzyTimelineWidget.prototype = { | |
58 | |
59 initWidget : function(data) { | |
60 var fuzzyTimeline = this; | |
61 | |
62 delete fuzzyTimeline.overallMin; | |
63 delete fuzzyTimeline.overallMax; | |
64 | |
65 $(fuzzyTimeline.gui.plotDiv).empty(); | |
66 $(fuzzyTimeline.gui.sliderTable).empty(); | |
67 delete fuzzyTimeline.rangeSlider; | |
68 $(fuzzyTimeline.gui.rangePiechartDiv).empty(); | |
69 delete fuzzyTimeline.rangePiechart; | |
70 | |
71 fuzzyTimeline.switchViewMode("density"); | |
72 | |
73 if ( (data instanceof Array) && (data.length > 0) ) | |
74 { | |
75 fuzzyTimeline.datasets = data; | |
76 | |
77 $(fuzzyTimeline.datasets).each(function(){ | |
78 $(this.objects).each(function(){ | |
79 var datemin,datemax; | |
80 if (this.isTemporal){ | |
81 //TODO: allow more than one date | |
82 datemin = moment(this.dates[0].date); | |
83 datemax = datemin; | |
84 } else if (this.isFuzzyTemporal){ | |
85 //TODO: allow more than one date | |
86 datemin = this.TimeSpanBegin; | |
87 datemax = this.TimeSpanEnd; | |
88 } | |
89 | |
90 if (typeof fuzzyTimeline.overallMin === "undefined") | |
91 fuzzyTimeline.overallMin = datemin; | |
92 if (typeof fuzzyTimeline.overallMax === "undefined") | |
93 fuzzyTimeline.overallMax = datemax; | |
94 | |
95 if (fuzzyTimeline.overallMin > datemin) | |
96 fuzzyTimeline.overallMin = datemin; | |
97 if (fuzzyTimeline.overallMax < datemax) | |
98 fuzzyTimeline.overallMax = datemax; | |
99 }); | |
100 }); | |
101 | |
102 fuzzyTimeline.rangeSlider = new FuzzyTimelineRangeSlider(fuzzyTimeline); | |
103 fuzzyTimeline.rangeSlider.initialize(fuzzyTimeline.datasets); | |
104 | |
105 fuzzyTimeline.rangePiechart = new FuzzyTimelineRangePiechart(fuzzyTimeline, fuzzyTimeline.gui.rangePiechartDiv); | |
106 fuzzyTimeline.rangePiechart.initialize(fuzzyTimeline.datasets); | |
107 } | |
108 }, | |
109 | |
110 switchViewMode : function(viewMode){ | |
111 var fuzzyTimeline = this; | |
112 if (viewMode !== fuzzyTimeline.viewMode){ | |
113 $(fuzzyTimeline.gui.plotDiv).empty(); | |
114 if (viewMode === "density"){ | |
115 fuzzyTimeline.density = new FuzzyTimelineDensity(fuzzyTimeline,fuzzyTimeline.gui.plotDiv); | |
116 } else if (viewMode === "barchart"){ | |
117 fuzzyTimeline.rangeBars = new FuzzyTimelineRangeBars(fuzzyTimeline); | |
118 } | |
119 fuzzyTimeline.viewMode = viewMode; | |
120 } | |
121 }, | |
122 | |
123 scaleData : function(data){ | |
124 var fuzzyTimeline = this; | |
125 if (fuzzyTimeline.scaleMode == "normal"){ | |
126 return data; | |
127 } else if (fuzzyTimeline.scaleMode == "logarithm"){ | |
128 for(var index in data){ | |
129 var val = data[index]; | |
130 if (val!=0){ | |
131 var sign = 1; | |
132 if (val<0){ | |
133 sign = -1; | |
134 } | |
135 data[index] = sign*Math.log(Math.abs(data[index])+1); | |
136 } | |
137 } | |
138 return data; | |
139 } else if (fuzzyTimeline.scaleMode == "percentage"){ | |
140 var overallCnt = 0; | |
141 for(var index in data){ | |
142 var val = data[index]; | |
143 if (val > 0){ | |
144 overallCnt += val; | |
145 } | |
146 } | |
147 //make 1 = 100% | |
148 overallCnt = overallCnt/100; | |
149 if (overallCnt != 0){ | |
150 for(var index in data){ | |
151 data[index] = (data[index])/overallCnt; | |
152 } | |
153 } | |
154 return data; | |
155 } | |
156 }, | |
157 | |
158 changeScaleMode : function(scaleMode) { | |
159 var fuzzyTimeline = this; | |
160 fuzzyTimeline.scaleMode = scaleMode; | |
161 fuzzyTimeline.drawFuzzyTimeline(); | |
162 }, | |
163 | |
164 slidePositionChanged : function(spanWidth) { | |
165 var fuzzyTimeline = this; | |
166 fuzzyTimeline.spanWidth = spanWidth; | |
167 fuzzyTimeline.drawFuzzyTimeline(); | |
168 }, | |
169 | |
170 drawFuzzyTimeline : function(){ | |
171 var fuzzyTimeline = this; | |
172 var datasets = fuzzyTimeline.datasets; | |
173 if (fuzzyTimeline.viewMode === "density"){ | |
174 //redraw density plot | |
175 fuzzyTimeline.density.drawDensityPlot(datasets); | |
176 //select currently selected data (if there is any) | |
177 fuzzyTimeline.density.selectionChanged(fuzzyTimeline.selected); | |
178 } else if (fuzzyTimeline.viewMode === "barchart"){ | |
179 //redraw range plot | |
180 fuzzyTimeline.rangeBars.drawRangeBarChart(datasets,fuzzyTimeline.spanWidth); | |
181 //select currently selected data (if there is any) | |
182 fuzzyTimeline.rangeBars.selectionChanged(fuzzyTimeline.selected); | |
183 } | |
184 }, | |
185 | |
186 highlightChanged : function(objects) { | |
187 var fuzzyTimeline = this; | |
188 if( !GeoTemConfig.highlightEvents ){ | |
189 return; | |
190 } | |
191 if ( (typeof objects === "undefined") || (objects.length == 0) ){ | |
192 return; | |
193 } | |
194 if (fuzzyTimeline.viewMode === "density") | |
195 this.density.highlightChanged(objects); | |
196 else if (fuzzyTimeline.viewMode === "barchart") | |
197 this.rangeBars.highlightChanged(objects); | |
198 | |
199 fuzzyTimeline.rangePiechart.highlightChanged(objects); | |
200 }, | |
201 | |
202 selectionChanged : function(selection) { | |
203 var fuzzyTimeline = this; | |
204 if( !GeoTemConfig.selectionEvents ){ | |
205 return; | |
206 } | |
207 if ((typeof selection.objects !== "undefined")&& | |
208 (selection.objects.length == GeoTemConfig.datasets.length)) | |
209 fuzzyTimeline.selected = selection.objects; | |
210 else | |
211 delete fuzzyTimeline.selected; | |
212 if (fuzzyTimeline.viewMode === "density") | |
213 this.density.selectionChanged(fuzzyTimeline.selected); | |
214 else if (fuzzyTimeline.viewMode === "barchart") | |
215 this.rangeBars.selectionChanged(fuzzyTimeline.selected); | |
216 | |
217 if (selection.valid()) | |
218 fuzzyTimeline.rangePiechart.selectionChanged(fuzzyTimeline.selected); | |
219 else | |
220 fuzzyTimeline.rangePiechart.selectionChanged([]); | |
221 | |
222 //selections "overwrite" each other | |
223 if (selection.widget != fuzzyTimeline) | |
224 fuzzyTimeline.clearHandles(); | |
225 }, | |
226 | |
227 buildSpanArray : function(spanWidth) { | |
228 var spanArray = []; | |
229 var tickStart = moment(this.overallMin); | |
230 do{ | |
231 spanArray.push(moment(tickStart)); | |
232 tickStart.add(spanWidth); | |
233 } while (tickStart <= this.overallMax); | |
234 spanArray.push(moment(tickStart)); | |
235 | |
236 this.spanHash.push({spanWidth:spanWidth,overallMin:moment(this.overallMin),spanArray:spanArray}); | |
237 return(spanArray); | |
238 }, | |
239 | |
240 getSpanArray : function(spanWidth){ | |
241 for (var i = 0; i < this.spanHash.length; i++){ | |
242 var element = this.spanHash[i]; | |
243 if ( ((this.overallMin-element.overallMin)===0) && | |
244 ((spanWidth-element.spanWidth)===0)) | |
245 return element.spanArray; | |
246 } | |
247 return this.buildSpanArray(spanWidth); | |
248 }, | |
249 | |
250 clearSpanArray : function(){ | |
251 this.spanHash = []; | |
252 }, | |
253 | |
254 getTicks : function(dataObject, spanWidth) { | |
255 var datemin,datemax; | |
256 if (dataObject.isTemporal){ | |
257 datemin = moment(dataObject.dates[0].date); | |
258 datemax = datemin; | |
259 } else if (dataObject.isFuzzyTemporal){ | |
260 datemin = dataObject.TimeSpanBegin; | |
261 datemax = dataObject.TimeSpanEnd; | |
262 } else{ | |
263 return; | |
264 } | |
265 | |
266 if (typeof spanWidth._data === "undefined"){ | |
267 //This does only work with millisecond spans, as the length of years is (very) inaccurate. | |
268 //(e.g. 100-0 = 99, 2000-1000 = 1001, 5000-0 = 5003, and so on and even more: duration(5000a) = 4932a) | |
269 //So the time consuming loop below is needed for accurate dates, when years/months/days etc. are supplied | |
270 var firstTick = Math.floor((datemin-this.overallMin)/spanWidth); | |
271 var lastTick = Math.floor((datemax-this.overallMin)/spanWidth); | |
272 //calculate how much the first (and last) tick and the time-span overlap | |
273 var firstTickPercentage = 1; | |
274 var lastTickPercentage = 1; | |
275 if (firstTick != lastTick){ | |
276 var secondTickStart = this.overallMin+(firstTick+1)*spanWidth; | |
277 var lastTickStart = this.overallMin+lastTick*spanWidth; | |
278 firstTickPercentage = (secondTickStart-datemin)/spanWidth; | |
279 lastTickPercentage = (datemax-lastTickStart)/spanWidth; | |
280 } | |
281 if (firstTickPercentage === 0){ | |
282 firstTick++; | |
283 firstTickPercentage = 1; | |
284 } | |
285 if (lastTickPercentage === 0){ | |
286 lastTick--; | |
287 lastTickPercentage = 1; | |
288 } | |
289 } else { | |
290 var spanArray = this.getSpanArray(spanWidth); | |
291 var firstTick, lastTick; | |
292 var tickCount = 0; | |
293 var tickStart = spanArray[0]; | |
294 var lastTickStart; | |
295 do{ | |
296 lastTickStart = spanArray[tickCount]; | |
297 tickCount++; | |
298 tickStart = spanArray[tickCount]; | |
299 if ( (typeof firstTick === "undefined") && (datemin < tickStart) ){ | |
300 firstTick = tickCount-1; | |
301 firstTickPercentage = (tickStart - datemin)/spanWidth; | |
302 } | |
303 if ( (typeof lastTick === "undefined") && (datemax <= tickStart) ){ | |
304 lastTick = tickCount-1; | |
305 lastTickPercentage = (datemax - lastTickStart)/spanWidth; | |
306 } | |
307 } while (tickStart < datemax); | |
308 if (firstTick == lastTick){ | |
309 firstTickPercentage = 1; | |
310 lastTickPercentage = 1; | |
311 } | |
312 } | |
313 | |
314 return({ firstTick:firstTick, | |
315 lastTick:lastTick, | |
316 firstTickPercentage:firstTickPercentage, | |
317 lastTickPercentage:lastTickPercentage}); | |
318 }, | |
319 | |
320 getObjects : function(dateStart, dateEnd) { | |
321 var fuzzyTimeline = this; | |
322 var searchDateStart, searchDateEnd; | |
323 if (typeof dateStart !== "undefined") | |
324 searchDateStart = moment(dateStart); | |
325 if (typeof dateEnd !== "undefined") | |
326 searchDateEnd = moment(dateEnd); | |
327 | |
328 var datasets = []; | |
329 $(fuzzyTimeline.datasets).each(function(){ | |
330 var objects = []; | |
331 //check if we got "real" datasets, or just array of objects | |
332 var datasetObjects = this; | |
333 if (typeof this.objects !== "undefined") | |
334 datasetObjects = this.objects; | |
335 $(datasetObjects).each(function(){ | |
336 var datemin,datemax; | |
337 var dataObject = this; | |
338 if (dataObject.isTemporal){ | |
339 datemin = moment(dataObject.dates[0].date); | |
340 datemax = datemin; | |
341 } else if (dataObject.isFuzzyTemporal){ | |
342 datemin = dataObject.TimeSpanBegin; | |
343 datemax = dataObject.TimeSpanEnd; | |
344 } else{ | |
345 return; | |
346 } | |
347 | |
348 if (typeof searchDateEnd === 'undefined'){ | |
349 if ( (datemin <= searchDateStart) && (datemax >= searchDateStart) ) | |
350 objects.push(this); | |
351 } else { | |
352 if ((datemin < searchDateEnd) && (datemax >= searchDateStart)) | |
353 objects.push(this); | |
354 } | |
355 }); | |
356 datasets.push(objects); | |
357 }); | |
358 | |
359 return(datasets); | |
360 }, | |
361 | |
362 triggerHighlight : function(highlightedObjects){ | |
363 var fuzzyTimeline = this; | |
364 if (fuzzyTimeline.viewMode === "density") | |
365 fuzzyTimeline.density.highlightChanged(highlightedObjects); | |
366 else if (fuzzyTimeline.viewMode === "barchart") | |
367 fuzzyTimeline.rangeBars.highlightChanged(highlightedObjects); | |
368 | |
369 fuzzyTimeline.core.triggerHighlight(highlightedObjects); | |
370 }, | |
371 | |
372 triggerSelection : function(selectedObjects){ | |
373 var fuzzyTimeline = this; | |
374 fuzzyTimeline.selected = selectedObjects; | |
375 if (fuzzyTimeline.viewMode === "density") | |
376 fuzzyTimeline.density.selectionChanged(selectedObjects); | |
377 else if (fuzzyTimeline.viewMode === "barchart") | |
378 fuzzyTimeline.rangeBars.selectionChanged(selectedObjects); | |
379 | |
380 selection = new Selection(selectedObjects); | |
381 | |
382 fuzzyTimeline.core.triggerSelection(selection); | |
383 }, | |
384 | |
385 addHandle : function(x1,x2){ | |
386 var fuzzyTimeline = this; | |
387 //make sure the interval is ordered correctly | |
388 if (x2<x1){ | |
389 var temp = x1; | |
390 x1 = x2; | |
391 x2 = temp; | |
392 } | |
393 fuzzyTimeline.handles.push({x1:x1,x2:x2}); | |
394 fuzzyTimeline.drawHandles(); | |
395 //enabled "play" button | |
396 $(fuzzyTimeline.rangeSlider.startAnimation).removeClass("playDisabled").addClass("playEnabled"); | |
397 }, | |
398 | |
399 selectByX : function(x1,x2){ | |
400 var fuzzyTimeline = this; | |
401 if (fuzzyTimeline.viewMode === "density"){ | |
402 fuzzyTimeline.density.selectByX(x1,x2); | |
403 } else if (fuzzyTimeline.viewMode === "barchart"){ | |
404 fuzzyTimeline.rangeBars.selectByX(x1,x2); | |
405 } | |
406 }, | |
407 | |
408 drawHandles : function(){ | |
409 var fuzzyTimeline = this; | |
410 | |
411 $(fuzzyTimeline.gui.plotDiv).find(".plotHandle").remove(); | |
412 $(fuzzyTimeline.gui.plotDiv).find(".dragTimeRangeAlt").remove(); | |
413 $(fuzzyTimeline.gui.plotDiv).find(".plotHandleBox").remove(); | |
414 | |
415 var plotHeight = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).height(); | |
416 var plotWidth = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).width(); | |
417 //flot sends the wrong width if we extend the parent div, so scale it accordingly | |
418 plotWidth = plotWidth*fuzzyTimeline.zoomFactor; | |
419 var plotOffset = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).getPlotOffset().left; | |
420 | |
421 $(fuzzyTimeline.handles).each(function(){ | |
422 var handle = this; | |
423 | |
424 var moveLeftHandle = function(){ | |
425 leftHandle.style.left = handle.x1-$(leftHandle).width() + "px"; | |
426 }; | |
427 | |
428 var moveRightHandle = function(){ | |
429 rightHandle.style.left = handle.x2+ "px"; | |
430 }; | |
431 | |
432 var resizeHandleBox = function(){ | |
433 handleBox.style.left = handle.x1+"px"; | |
434 $(handleBox).width(handle.x2-handle.x1); | |
435 }; | |
436 | |
437 var moveDragButton = function(){ | |
438 dragButton.style.left = (handle.x1+handle.x2)/2 - $(dragButton).width()/2 + "px"; | |
439 }; | |
440 | |
441 var leftHandle = document.createElement("div"); | |
442 leftHandle.title = GeoTemConfig.getString('leftHandle'); | |
443 leftHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "leftHandle.png" + ")"; | |
444 leftHandle.setAttribute('class', 'plotHandle plotHandleIcon'); | |
445 leftHandle.style.visibility = "visible"; | |
446 $(fuzzyTimeline.gui.plotDiv).append(leftHandle); | |
447 moveLeftHandle(); | |
448 leftHandle.style.top = plotHeight/2-$(leftHandle).height()/2 + "px"; | |
449 | |
450 var rightHandle = document.createElement("div"); | |
451 rightHandle.title = GeoTemConfig.getString('leftHandle'); | |
452 rightHandle.style.backgroundImage = "url(" + GeoTemConfig.path + "rightHandle.png" + ")"; | |
453 rightHandle.setAttribute('class', 'plotHandle plotHandleIcon'); | |
454 rightHandle.style.visibility = "visible"; | |
455 moveRightHandle(); | |
456 $(fuzzyTimeline.gui.plotDiv).append(rightHandle); | |
457 | |
458 rightHandle.style.top = plotHeight/2-$(rightHandle).height()/2 + "px"; | |
459 | |
460 var handleBox = document.createElement("div"); | |
461 $(fuzzyTimeline.gui.plotDiv).append(handleBox); | |
462 $(handleBox).addClass("plotHandleBox"); | |
463 resizeHandleBox(); | |
464 $(handleBox).height(plotHeight); | |
465 | |
466 var dragButton = document.createElement("div"); | |
467 dragButton.title = GeoTemConfig.getString('dragTimeRange'); | |
468 dragButton.style.backgroundImage = "url(" + GeoTemConfig.path + "drag.png" + ")"; | |
469 dragButton.setAttribute('class', 'dragTimeRangeAlt plotHandleIcon'); | |
470 $(fuzzyTimeline.gui.plotDiv).append(dragButton); | |
471 moveDragButton(); | |
472 dragButton.style.top = plotHeight + "px"; | |
473 | |
474 $(leftHandle).mousedown(function(){ | |
475 $(fuzzyTimeline.gui.plotDiv).mousemove(function(eventObj){ | |
476 var x = eventObj.clientX; | |
477 x += $(fuzzyTimeline.gui.plotDiv).parent().scrollLeft(); | |
478 if ((x < handle.x2) && | |
479 (x >= plotOffset)){ | |
480 x = x - leftHandle.offsetWidth; | |
481 handle.x1 = x + $(leftHandle).width(); | |
482 | |
483 moveLeftHandle(); | |
484 resizeHandleBox(); | |
485 moveDragButton(); | |
486 } | |
487 }); | |
488 $(fuzzyTimeline.gui.plotDiv).mouseup(function(eventObj){ | |
489 fuzzyTimeline.selectByX(handle.x1,handle.x2); | |
490 $(fuzzyTimeline.gui.plotDiv).unbind("mouseup"); | |
491 $(fuzzyTimeline.gui.plotDiv).unbind("mousemove"); | |
492 }); | |
493 }); | |
494 | |
495 $(rightHandle).mousedown(function(){ | |
496 $(fuzzyTimeline.gui.plotDiv).mousemove(function(eventObj){ | |
497 var x = eventObj.clientX; | |
498 x += $(fuzzyTimeline.gui.plotDiv).parent().scrollLeft(); | |
499 x = x - rightHandle.offsetWidth; | |
500 if ((x > handle.x1) && | |
501 (x <= plotOffset+plotWidth)){ | |
502 handle.x2 = x; | |
503 | |
504 moveRightHandle(); | |
505 resizeHandleBox(); | |
506 moveDragButton(); | |
507 } | |
508 }); | |
509 $(fuzzyTimeline.gui.plotDiv).mouseup(function(eventObj){ | |
510 fuzzyTimeline.selectByX(handle.x1,handle.x2); | |
511 $(fuzzyTimeline.gui.plotDiv).unbind("mouseup"); | |
512 $(fuzzyTimeline.gui.plotDiv).unbind("mousemove"); | |
513 }); | |
514 }); | |
515 | |
516 $(dragButton).mousedown(function(){ | |
517 $(fuzzyTimeline.gui.plotDiv).mousemove(function(eventObj){ | |
518 var x = eventObj.clientX; | |
519 //TODO: for some reason we don't need the scoll offset here | |
520 //this should be investigated? | |
521 //x += $(fuzzyTimeline.gui.plotDiv).parent().scrollLeft(); | |
522 var xdiff = x - $(dragButton).offset().left - $(dragButton).width()/2; | |
523 handle.x1 = handle.x1+xdiff; | |
524 handle.x2 = handle.x2+xdiff; | |
525 | |
526 moveLeftHandle(); | |
527 moveRightHandle(); | |
528 resizeHandleBox(); | |
529 moveDragButton(); | |
530 }); | |
531 $(fuzzyTimeline.gui.plotDiv).mouseup(function(eventObj){ | |
532 if (handle.x1 < plotOffset) | |
533 handle.x1 = plotOffset; | |
534 if (handle.x2 > plotOffset+plotWidth) | |
535 handle.x2 = plotOffset+plotWidth; | |
536 | |
537 moveLeftHandle(); | |
538 moveRightHandle(); | |
539 resizeHandleBox(); | |
540 moveDragButton(); | |
541 | |
542 fuzzyTimeline.selectByX(handle.x1,handle.x2); | |
543 $(fuzzyTimeline.gui.plotDiv).unbind("mouseup"); | |
544 $(fuzzyTimeline.gui.plotDiv).unbind("mousemove"); | |
545 }); | |
546 }); | |
547 }); | |
548 }, | |
549 | |
550 clearHandles : function(){ | |
551 var fuzzyTimeline = this; | |
552 $(fuzzyTimeline.gui.plotDiv).find(".plotHandle").remove(); | |
553 $(fuzzyTimeline.gui.plotDiv).find(".dragTimeRangeAlt").remove(); | |
554 $(fuzzyTimeline.gui.plotDiv).find(".plotHandleBox").remove(); | |
555 fuzzyTimeline.handles = []; | |
556 //disable buttons | |
557 $(fuzzyTimeline.rangeSlider.startAnimation).removeClass("playEnabled").addClass("playDisabled"); | |
558 $(fuzzyTimeline.rangeSlider.pauseAnimation).removeClass("pauseEnabled").addClass("pauseDisabled"); | |
559 //stop the animation (if one was running) | |
560 fuzzyTimeline.pauseAnimation(); | |
561 }, | |
562 | |
563 startAnimation : function(){ | |
564 var fuzzyTimeline = this; | |
565 fuzzyTimeline.loopFunction = function(steps){ | |
566 $(fuzzyTimeline.handles).each(function(){ | |
567 if (typeof steps === "undefined") | |
568 steps = 1; | |
569 | |
570 var handle = this; | |
571 var x1 = handle.x1; | |
572 var x2 = handle.x2; | |
573 | |
574 if (typeof handle.width === "undefined") | |
575 handle.width = x2-x1; | |
576 | |
577 var plotWidth = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).width(); | |
578 var plotOffset = (fuzzyTimeline.density.plot?fuzzyTimeline.density.plot:fuzzyTimeline.rangeBars.plot).getPlotOffset().left; | |
579 | |
580 var plotMax = plotWidth+plotOffset; | |
581 | |
582 //TODO: has to be plotMin | |
583 if (!((x1 === plotOffset)&&(x2-x1 <= handle.width))){ | |
584 x1 += steps; | |
585 } | |
586 if (x2 <= plotMax){ | |
587 x2 += steps; | |
588 if (x2 > plotMax) | |
589 x2 = plotMax; | |
590 if (x2-x1 > handle.width){ | |
591 x1 = x2-handle.width; | |
592 } | |
593 } | |
594 if (x1 >= plotMax){ | |
595 //TODO: has to be plotMin | |
596 x1 = plotOffset; | |
597 x2 = plotOffset; | |
598 } | |
599 | |
600 handle.x1 = x1; | |
601 handle.x2 = x2; | |
602 | |
603 fuzzyTimeline.drawHandles(); | |
604 fuzzyTimeline.selectByX(handle.x1, handle.x2); | |
605 }); | |
606 }; | |
607 | |
608 fuzzyTimeline.loopId = setInterval(function(){ | |
609 fuzzyTimeline.loopFunction(10); | |
610 }, 100); | |
611 }, | |
612 | |
613 pauseAnimation : function(){ | |
614 var fuzzyTimeline = this; | |
615 clearInterval(fuzzyTimeline.loopId); | |
616 $(fuzzyTimeline.handles).each(function(){ | |
617 var handle = this; | |
618 delete handle.width; | |
619 }); | |
620 }, | |
621 | |
622 //This function enlargens the plot area | |
623 zoomPlot : function(zoomFactor){ | |
624 var fuzzyTimeline = this; | |
625 var oldZoomFactor = fuzzyTimeline.zoomFactor; | |
626 fuzzyTimeline.zoomFactor = zoomFactor; | |
627 if (zoomFactor > 1){ | |
628 $(fuzzyTimeline.gui.plotDiv).width(zoomFactor*100+"%"); | |
629 //leave place for the scrollbar | |
630 $(fuzzyTimeline.gui.plotDiv).height(fuzzyTimeline.gui.plotDIVHeight-20); | |
631 } else{ | |
632 $(fuzzyTimeline.gui.plotDiv).width("100%"); | |
633 $(fuzzyTimeline.gui.plotDiv).height(fuzzyTimeline.gui.plotDIVHeight); | |
634 } | |
635 | |
636 //fit handles | |
637 //this does not make much sense, as the selections are _completely_ different | |
638 //for each scale rate, as the objects may reside in different "ticks" of the graph | |
639 $(fuzzyTimeline.handles).each(function(){ | |
640 var handle = this; | |
641 handle.x1 = handle.x1 * (zoomFactor/oldZoomFactor); | |
642 handle.x2 = handle.x2 * (zoomFactor/oldZoomFactor); | |
643 }); | |
644 } | |
645 }; |