127 Tlns.Templates.Timeline = '<div class="Tl-TopBar"><div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-AddButton"></div></div><div class="Tl-TopBar-Spacer Tl-Border-Right"></div>' |
127 Tlns.Templates.Timeline = '<div class="Tl-TopBar"><div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-AddButton"></div></div><div class="Tl-TopBar-Spacer Tl-Border-Right"></div>' |
128 + '<div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-PreviousButton"></div></div><div class="Tl-TopBar-TimeSpan Tl-TopBar-TextBtn Tl-Border-Right">--/--</div>' |
128 + '<div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-PreviousButton"></div></div><div class="Tl-TopBar-TimeSpan Tl-TopBar-TextBtn Tl-Border-Right">--/--</div>' |
129 + '<div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-SyncButton"></div></div><div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-NextButton"></div></div><div class="Tl-TopBar-Spacer Tl-Border-Right"></div>' |
129 + '<div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-SyncButton"></div></div><div class="Tl-TopBar-Button Tl-Border-Right"><div class="Tl-TopBar-NextButton"></div></div><div class="Tl-TopBar-Spacer Tl-Border-Right"></div>' |
130 + '<div class="Tl-TopBar-Timescales">{{#timescales}}<div class="Tl-TopBar-Button Tl-TopBar-TextBtn Tl-Border-Right" data-level="{{level}}">{{label}}</div>{{/timescales}}</div></div>' |
130 + '<div class="Tl-TopBar-Timescales">{{#timescales}}<div class="Tl-TopBar-Button Tl-TopBar-TextBtn Tl-Border-Right" data-level="{{level}}">{{label}}</div>{{/timescales}}</div></div>' |
131 + '<div class="Tl-BottomPart"><ul class="Tl-UniversLabels"></ul><div class="Tl-MainPart"><div class="Tl-Layer Tl-Grid"></div><canvas class="Tl-Layer Tl-Canvas"></canvas><div class="Tl-Layer Tl-Occurrences"></div></div>' |
131 + '<div class="Tl-BottomPart"><ul class="Tl-UniversLabels"></ul><div class="Tl-MainPart"><div class="Tl-Layer Tl-Grid"></div><canvas class="Tl-Layer Tl-Canvas"></canvas><div class="Tl-Layer Tl-Occurrences"></div></div>' |
132 + '<div class="Tl-Overlay-Container"><div class="Tl-Overlay-Box"><div class="Tl-Overlay"><div class="Tl-Overlay-Main"></div><div class="Tl-Overlay-Tip"></div></div></div></div></div>'; |
132 + '<div class="Tl-Overlay-Container"><div class="Tl-Overlay-Box"><div class="Tl-Overlay"><div class="Tl-Overlay-Tip-Top"></div><div class="Tl-Overlay-Main"></div><div class="Tl-Overlay-Tip-Bottom"></div></div></div></div></div>'; |
133 |
133 |
134 Tlns.Templates.Univers = '<span class="Tl-UniversText">{{title}}</span>'; |
134 Tlns.Templates.Univers = '<span class="Tl-UniversText">{{title}}</span>'; |
135 |
135 |
136 Tlns.Templates.Occurrence = '{{#clusters}}<div class="Tl-Cluster Tl-Occ{{type}}" style="left: {{x}}px; top: {{y}}px;" cluster-contents="{{#occurrences}}{{type}}|{{id}},{{/occurrences}}"><div class="Tl-ClusterCount">{{occurrences.length}}</div></div>{{/clusters}}{{#occurrences}}<div class="Tl-Occurrence Tl-Occ{{type}}{{#editing}} Tl-Editing{{/editing}}" occurrence-type="{{type}}" occurrence-id="{{id}}" style="left: {{x}}px; top: {{univers.y}}px;"></div>{{/occurrences}}'; |
136 Tlns.Templates.Occurrence = '{{#clusters}}<div class="Tl-Cluster Tl-Occ{{type}}" style="left: {{x}}px; top: {{y}}px;" cluster-contents="{{contents}}"><div class="Tl-ClusterCount">{{occurrences.length}}</div></div>{{/clusters}}{{#occurrences}}<div class="Tl-Occurrence Tl-OccOnGrid Tl-Occ{{type}}{{#editing}} Tl-Editing{{/editing}}" occurrence-type="{{type}}" occurrence-id="{{id}}" style="left: {{x}}px; top: {{y}}px;"></div>{{/occurrences}}{{#open_cluster}}<div class="Tl-ClusterOverlay" style="left: {{x}}px; top: {{y}}px;">{{#occurrences}}<div class="Tl-Occurrence Tl-OccInCluster Tl-Occ{{type}}{{#editing}} Tl-Editing{{/editing}}" occurrence-type="{{type}}" occurrence-id="{{id}}"></div>{{/occurrences}}</div>{{/open_cluster}}'; |
137 |
137 |
138 /* Classes */ |
138 /* Classes */ |
139 |
139 |
140 Tlns.Classes.Timeline = function(_options) { |
140 Tlns.Classes.Timeline = function(_options) { |
141 |
141 |
165 top: _o.top, |
165 top: _o.top, |
166 right: _o.left + this.$.find('.Tl-MainPart').outerWidth(), |
166 right: _o.left + this.$.find('.Tl-MainPart').outerWidth(), |
167 bottom: _o.top + this.$.find('.Tl-MainPart').outerHeight(), |
167 bottom: _o.top + this.$.find('.Tl-MainPart').outerHeight(), |
168 }; |
168 }; |
169 |
169 |
|
170 var _this = this; |
|
171 |
|
172 this.throttledDrawGrid = _.throttle(function() { |
|
173 _this.drawGrid(); |
|
174 }, 150); |
|
175 |
170 this.setLevel(this.level); |
176 this.setLevel(this.level); |
171 |
177 |
172 var _this = this; |
|
173 this.$.find('.Tl-TopBar-Timescales>div').click(function() { |
178 this.$.find('.Tl-TopBar-Timescales>div').click(function() { |
174 _this.setLevel($(this).attr("data-level")); |
179 _this.setLevel($(this).attr("data-level")); |
175 }); |
180 }); |
176 |
181 |
177 this.$.find('.Tl-TopBar-SyncButton').click(function() { |
182 this.$.find('.Tl-TopBar-SyncButton').click(function() { |
200 this.$.find('.Tl-MainPart').mouseup(function(_event) { |
205 this.$.find('.Tl-MainPart').mouseup(function(_event) { |
201 _this.onMouseUp(_event); |
206 _this.onMouseUp(_event); |
202 return false; |
207 return false; |
203 }); |
208 }); |
204 |
209 |
|
210 this.$.find('.Tl-MainPart').mousewheel(function(_event, _delta) { |
|
211 var _newLevel = Math.max(0,Math.min(_this.timescales.length-1, (_delta < 0 ? -1 : 1) + parseInt(_this.level))); |
|
212 if (_newLevel != _this.level) { |
|
213 _this.hideTooltip(); |
|
214 var _deltaX = _event.pageX - _this.dragging_bounds.left, |
|
215 _tAtMouse = _this.timeFromMouse(_event.pageX), |
|
216 _newScale = _this.main_width / (_this.timescales[_newLevel].span), |
|
217 _newStart = _tAtMouse - _deltaX / _newScale; |
|
218 _this.central_time = _newStart + _this.timescales[_newLevel].span / 2; |
|
219 _this.setLevel(_newLevel); |
|
220 } |
|
221 return false; |
|
222 }); |
|
223 |
205 this.$.find('.Tl-Overlay-Box').mouseover(function(_event) { |
224 this.$.find('.Tl-Overlay-Box').mouseover(function(_event) { |
206 $(this).show(); |
225 $(this).show(); |
207 }).mouseout(function(_event) { |
226 }).mouseout(function(_event) { |
208 $(this).hide(); |
227 $(this).hide(); |
209 }) |
228 }); |
210 |
|
211 this.throttledDrawGrid = _.throttle(function() { |
|
212 _this.drawGrid(); |
|
213 }, 150); |
|
214 |
229 |
215 /* Loading Univers */ |
230 /* Loading Univers */ |
216 $.getJSON(this.url_univers, function(_data) { |
231 $.getJSON(this.url_univers, function(_data) { |
217 _this.onUniversLoaded(_data); |
232 _this.onUniversLoaded(_data); |
218 }); |
233 }); |
243 this.mouse_down = false; |
258 this.mouse_down = false; |
244 this.is_dragging = false; |
259 this.is_dragging = false; |
245 this.dragging_type = undefined; |
260 this.dragging_type = undefined; |
246 } |
261 } |
247 |
262 |
|
263 Tlns.Classes.Timeline.prototype.timeFromX = function(_x) { |
|
264 return Math.max(this.start_time,Math.min(this.end_time, this.start_time + _x / this.current_scale)); |
|
265 } |
|
266 |
|
267 Tlns.Classes.Timeline.prototype.timeFromMouse = function(_pageX) { |
|
268 return this.timeFromX(_pageX - this.dragging_bounds.left); |
|
269 } |
|
270 |
248 Tlns.Classes.Timeline.prototype.onMouseMove = function(_event) { |
271 Tlns.Classes.Timeline.prototype.onMouseMove = function(_event) { |
249 if (this.mouse_down) { |
272 if (this.mouse_down) { |
250 this.is_dragging = true; |
273 this.is_dragging = true; |
251 this.$.find('.Tl-Overlay-Box').hide(); |
274 this.hideTooltip(); |
252 if (_event.pageX > this.dragging_bounds.left |
275 if (_event.pageX > this.dragging_bounds.left |
253 && _event.pageX < this.dragging_bounds.right |
276 && _event.pageX < this.dragging_bounds.right |
254 && _event.pageY > this.dragging_bounds.top |
277 && _event.pageY > this.dragging_bounds.top |
255 && _event.pageY < this.dragging_bounds.bottom |
278 && _event.pageY < this.dragging_bounds.bottom |
256 ) { |
279 ) { |
257 var _timeDelta = Math.floor(( this.start_pos.x - _event.pageX ) / this.current_scale); |
|
258 switch (this.dragging_type) { |
280 switch (this.dragging_type) { |
259 case "occurrence": |
281 case "occurrence": |
260 this.editing_occurrence.date = this.time_at_start - _timeDelta; |
282 var _d = this.timeFromMouse(_event.pageX); |
261 var _u = Math.max(0,Math.min(this.univers.length, Math.floor(this.u_at_start - (this.start_pos.y - _event.pageY) / this.univers_height))); |
283 this.editing_occurrence.date = _d; |
|
284 var _u = Math.max(0,Math.min(this.univers.length, Math.floor((_event.pageY - this.dragging_bounds.top) / this.univers_height))); |
262 this.editing_occurrence.univers = this.univers[_u]; |
285 this.editing_occurrence.univers = this.univers[_u]; |
263 this.editing_occurrence.univers_id = this.univers[_u].id; |
286 this.editing_occurrence.univers_id = this.univers[_u].id; |
264 this.throttledDrawGrid(); |
287 this.throttledDrawGrid(); |
265 break; |
288 break; |
266 case "timeline": |
289 case "timeline": |
267 this.setTime(this.time_at_start + _timeDelta); |
290 this.setTime(this.time_at_start + Math.floor(( this.start_pos.x - _event.pageX ) / this.current_scale)); |
268 break; |
291 break; |
269 } |
292 } |
270 } else { |
293 } else { |
271 this.onMouseUp(_event); |
294 this.onMouseUp(_event); |
272 } |
295 } |
325 var _grid_width = Math.floor(_timescale.grid_interval * this.current_scale), |
348 var _grid_width = Math.floor(_timescale.grid_interval * this.current_scale), |
326 _roundstart = Math.floor((this.start_time - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset, |
349 _roundstart = Math.floor((this.start_time - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset, |
327 _html = ''; |
350 _html = ''; |
328 this.$.find('.Tl-TopBar-TimeSpan').html(Tlns.Utils.dateFormat(this.start_time, _timescale.start_date_format) + ' - ' + Tlns.Utils.dateFormat(this.end_time, _timescale.end_date_format)); |
351 this.$.find('.Tl-TopBar-TimeSpan').html(Tlns.Utils.dateFormat(this.start_time, _timescale.start_date_format) + ' - ' + Tlns.Utils.dateFormat(this.end_time, _timescale.end_date_format)); |
329 for (var _t = _roundstart; _t < this.end_time; _t += _timescale.grid_interval) { |
352 for (var _t = _roundstart; _t < this.end_time; _t += _timescale.grid_interval) { |
330 _html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + this.current_scale * (_t - this.start_time) + 'px">' |
353 var _x = this.current_scale * (_t - this.start_time); |
331 + '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>'; |
354 if (_x > 0) { |
|
355 _html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + _x + 'px">' |
|
356 + '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>'; |
|
357 } |
332 } |
358 } |
333 /* |
359 /* |
334 |
360 |
335 for (var _t = _roundstart; _t < _tmax; _t += _timescale.grid_interval) { |
361 for (var _t = _roundstart; _t < _tmax; _t += _timescale.grid_interval) { |
336 var _isMajor = !(Math.floor((_t - _offset) / _timescale.grid_interval) % _timescale.major_interval); |
362 var _isMajor = !(Math.floor((_t - _offset) / _timescale.grid_interval) % _timescale.major_interval); |
383 this.occurrences.push(_occurrence); |
409 this.occurrences.push(_occurrence); |
384 } |
410 } |
385 _occurrence.update(_type, _data); |
411 _occurrence.update(_type, _data); |
386 } |
412 } |
387 |
413 |
388 Tlns.Classes.Timeline.prototype.showTooltip = function(_x, _y, _html) { |
414 Tlns.Classes.Timeline.prototype.showTooltip = function(_x, _y, _html, _isUp) { |
389 this.$.find('.Tl-Overlay-Box').show() |
415 this.$.find('.Tl-Overlay-Box') |
|
416 .removeClass(_isUp ? 'Tl-Overlay-Down' : 'Tl-Overlay-Up') |
|
417 .addClass(_isUp ? 'Tl-Overlay-Up' : 'Tl-Overlay-Down') |
|
418 .show() |
390 .css({ |
419 .css({ |
391 left: _x + "px", |
420 left: _x + "px", |
392 top: _y + "px" |
421 top: _y + "px" |
393 }); |
422 }); |
394 this.$.find('.Tl-Overlay-Main').html(_html); |
423 this.$.find('.Tl-Overlay-Main').html(_html); |
422 _visible[_j].x = this.cluster_spacing * Math.round(_visible[_j].x / this.cluster_spacing); |
452 _visible[_j].x = this.cluster_spacing * Math.round(_visible[_j].x / this.cluster_spacing); |
423 } |
453 } |
424 } |
454 } |
425 } |
455 } |
426 } |
456 } |
427 var _clusters = []; |
457 var _clusters = [], |
|
458 _openCluster = false; |
428 for (var _i = 0; _i < _visible.length; _i++) { |
459 for (var _i = 0; _i < _visible.length; _i++) { |
429 for (var _j = 0; _j < _i; _j++) { |
460 for (var _j = 0; _j < _i; _j++) { |
430 if (_visible[_j].univers_id == _visible[_i].univers_id && _visible[_j].x == _visible[_i].x) { |
461 if (_visible[_j].univers_id == _visible[_i].univers_id && _visible[_j].x == _visible[_i].x) { |
431 _visible[_j].in_cluster = true; |
462 _visible[_j].in_cluster = true; |
432 _visible[_i].in_cluster = true; |
463 _visible[_i].in_cluster = true; |
433 var _x = _visible[_j].x, |
464 var _x = _visible[_j].x, |
434 _y = _visible[_j].univers.y; |
465 _y = _visible[_j].y; |
435 _cluster = _(_clusters).find(function(_c) { return _c.x == _x && _c.y == _y }); |
466 _cluster = _(_clusters).find(function(_c) { return _c.x == _x && _c.y == _y }); |
436 if (typeof _cluster === "undefined") { |
467 if (typeof _cluster === "undefined") { |
437 _cluster = { x: _x, y: _y, occurrences: [] }; |
468 _cluster = { x: _x, y: _y, occurrences: [] }; |
438 _clusters.push(_cluster); |
469 _clusters.push(_cluster); |
439 } |
470 } |
440 if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) { |
471 if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) { |
441 return _o.type == _visible[_j].type && _o.id == _visible[_j].id; |
472 return _o.type == _visible[_j].type && _o.id == _visible[_j].id; |
442 })) { |
473 })) { |
443 _cluster.occurrences.push({type: _visible[_j].type, id: _visible[_j].id}); |
474 _cluster.occurrences.push(_visible[_j]); |
444 } |
475 } |
445 if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) { |
476 if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) { |
446 return _o.type == _visible[_i].type && _o.id == _visible[_i].id; |
477 return _o.type == _visible[_i].type && _o.id == _visible[_i].id; |
447 })) { |
478 })) { |
448 _cluster.occurrences.push({type: _visible[_i].type, id: _visible[_i].id}); |
479 _cluster.occurrences.push(_visible[_i]); |
449 } |
480 } |
450 } |
481 } |
451 } |
482 } |
452 } |
483 } |
453 _(_clusters).each(function(_cluster) { |
484 _(_clusters).each(function(_cluster) { |
454 _cluster.type = _cluster.occurrences[0].type; |
485 _cluster.type = _cluster.occurrences[0].type; |
|
486 _cluster.contents = _cluster.occurrences.map(function(_o) { |
|
487 return _o.type + ":" + _o.id; |
|
488 }).join("|"); |
|
489 if (_cluster.contents == _this.open_cluster) { |
|
490 _openCluster = _cluster; |
|
491 } |
455 for (var _i = 1; _i < _cluster.occurrences.length; _i++) { |
492 for (var _i = 1; _i < _cluster.occurrences.length; _i++) { |
456 if (_cluster.occurrences[_i].type !== _cluster.type) { |
493 if (_cluster.occurrences[_i].type !== _cluster.type) { |
457 _cluster.type = "both"; |
494 _cluster.type = "both"; |
458 break; |
495 break; |
459 } |
496 } |
460 } |
497 } |
461 }); |
498 }); |
|
499 |
462 |
500 |
463 var _links = []; |
501 var _links = []; |
464 |
502 |
465 _(_visible).each(function(_occurrence) { |
503 _(_visible).each(function(_occurrence) { |
466 _(_occurrence.dependsOn).each(function(_dependance) { |
504 _(_occurrence.dependsOn).each(function(_dependance) { |
485 _ctx.moveTo(_link.from_x,_link.from_y); |
523 _ctx.moveTo(_link.from_x,_link.from_y); |
486 _ctx.lineTo(_link.to_x,_link.to_y); |
524 _ctx.lineTo(_link.to_x,_link.to_y); |
487 _ctx.stroke(); |
525 _ctx.stroke(); |
488 }) |
526 }) |
489 |
527 |
|
528 console.log(_openCluster); |
|
529 |
490 var _html = Mustache.to_html(Tlns.Templates.Occurrence, { |
530 var _html = Mustache.to_html(Tlns.Templates.Occurrence, { |
491 occurrences:_(_visible).reject(function(_o) {return _o.in_cluster}), |
531 occurrences:_(_visible).reject(function(_o) {return _o.in_cluster}), |
492 clusters: _clusters |
532 clusters: _clusters, |
|
533 open_cluster: _openCluster |
493 }); |
534 }); |
494 this.$.find('.Tl-Occurrences').html(_html); |
535 this.$.find('.Tl-Occurrences').html(_html); |
|
536 |
|
537 |
|
538 if (_openCluster) { |
|
539 var _w = this.$.find('.Tl-Occurrence').width(), |
|
540 _ww = _w * _openCluster.occurrences.length; |
|
541 this.$.find('.Tl-ClusterOverlay').css({ |
|
542 "margin-left": - Math.floor(_ww/2) + "px", |
|
543 width: _ww |
|
544 }); |
|
545 _(_openCluster.occurrences).each(function(_o, _i) { |
|
546 _o.y = _o.y - 20; |
|
547 _o.x = _o.x - (_ww / 2) + ((_i + .5) * _w); |
|
548 }); |
|
549 } |
|
550 |
495 this.$.find('.Tl-Occurrence').mousedown(function() { |
551 this.$.find('.Tl-Occurrence').mousedown(function() { |
496 var _el = $(this); |
552 var _el = $(this); |
497 _this.editing_occurrence = _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
553 _this.editing_occurrence = _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
498 if (typeof _this.editing_occurrence !== "undefined") { |
554 if (typeof _this.editing_occurrence !== "undefined") { |
499 _this.dragging_type = "occurrence"; |
555 _this.dragging_type = "occurrence"; |
500 _this.time_at_start = _this.editing_occurrence.date; |
|
501 _this.u_at_start = _this.editing_occurrence.univers.index; |
|
502 _this.editing_occurrence.editing = true; |
556 _this.editing_occurrence.editing = true; |
503 } |
557 } |
504 }).mouseover(function() { |
558 }).mouseover(function(_event) { |
505 var _el = $(this), |
559 var _el = $(this), |
506 _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
560 _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
507 _this.showTooltip(_occurrence.x, _occurrence.univers.y, _occurrence.title); |
561 _this.showTooltip(_occurrence.x, _occurrence.y, _occurrence.title, (_event.pageY - _this.dragging_bounds.top) > (_this.main_height / 2) ); |
508 }).mouseout(function() { |
562 }).mouseout(function() { |
509 _this.hideTooltip(); |
563 _this.hideTooltip(); |
510 }); |
564 }); |
|
565 this.$.find('.Tl-Cluster').click(function() { |
|
566 var _el = $(this), |
|
567 _contents = _el.attr("cluster-contents"); |
|
568 if (_this.open_cluster == _contents) { |
|
569 _this.open_cluster = false; |
|
570 } else { |
|
571 _this.open_cluster = _contents; |
|
572 } |
|
573 console.log(_this.open_cluster); |
|
574 _this.throttledDrawGrid(); |
|
575 }) |
511 } |
576 } |
512 |
577 |
513 Tlns.Classes.Timeline.prototype.getUnivers = function(_id) { |
578 Tlns.Classes.Timeline.prototype.getUnivers = function(_id) { |
514 return _(this.univers).find(function(_univ) { |
579 return _(this.univers).find(function(_univ) { |
515 return (_univ.id == _id); |
580 return (_univ.id == _id); |