126 |
126 |
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><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-Main"></div><div class="Tl-Overlay-Tip"></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}}" 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="{{#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}}'; |
137 |
137 |
138 /* Classes */ |
138 /* Classes */ |
139 |
139 |
140 Tlns.Classes.Timeline = function(_options) { |
140 Tlns.Classes.Timeline = function(_options) { |
141 |
141 |
152 this.$.html(Mustache.to_html(Tlns.Templates.Timeline, this)); |
152 this.$.html(Mustache.to_html(Tlns.Templates.Timeline, this)); |
153 |
153 |
154 this.main_height = this.height - this.$.find('.Tl-TopBar').outerHeight(); |
154 this.main_height = this.height - this.$.find('.Tl-TopBar').outerHeight(); |
155 this.$.find('.Tl-BottomPart').css("height", this.main_height + "px"); |
155 this.$.find('.Tl-BottomPart').css("height", this.main_height + "px"); |
156 this.$.find('.Tl-MainPart').css("width", this.main_width + "px"); |
156 this.$.find('.Tl-MainPart').css("width", this.main_width + "px"); |
157 this.$.find('.Tl-Overlay-Container').css("left", Math.floor(this.$.find('.Tl-BottomPart').outerWidth() - this.main_width / 2) + "px"); |
157 this.$.find('.Tl-Overlay-Container').css("left", (this.$.find('.Tl-BottomPart').outerWidth() - this.main_width) + "px"); |
|
158 this.$.find('.Tl-Canvas').attr({ |
|
159 width: this.main_width, |
|
160 height: this.main_height |
|
161 }); |
158 var _o = this.$.find('.Tl-MainPart').offset(); |
162 var _o = this.$.find('.Tl-MainPart').offset(); |
159 this.dragging_bounds = { |
163 this.dragging_bounds = { |
160 left: _o.left, |
164 left: _o.left, |
161 top: _o.top, |
165 top: _o.top, |
162 right: _o.left + this.$.find('.Tl-MainPart').outerWidth(), |
166 right: _o.left + this.$.find('.Tl-MainPart').outerWidth(), |
202 $(this).show(); |
206 $(this).show(); |
203 }).mouseout(function(_event) { |
207 }).mouseout(function(_event) { |
204 $(this).hide(); |
208 $(this).hide(); |
205 }) |
209 }) |
206 |
210 |
207 this.throttledSetTime = _.throttle(function(_time) { |
211 this.throttledDrawGrid = _.throttle(function() { |
208 _this.setTime(_time) |
212 _this.drawGrid(); |
209 }, 150); |
213 }, 150); |
210 |
214 |
211 /* Loading Univers */ |
215 /* Loading Univers */ |
212 $.getJSON(this.url_univers, function(_data) { |
216 $.getJSON(this.url_univers, function(_data) { |
213 _this.onUniversLoaded(_data); |
217 _this.onUniversLoaded(_data); |
215 } |
219 } |
216 |
220 |
217 Tlns.Classes.Timeline.prototype.onMouseDown = function(_event) { |
221 Tlns.Classes.Timeline.prototype.onMouseDown = function(_event) { |
218 this.mouse_down = true; |
222 this.mouse_down = true; |
219 this.is_dragging = false; |
223 this.is_dragging = false; |
220 this.time_at_start = this.central_time; |
|
221 this.start_pos = { |
224 this.start_pos = { |
222 x: _event.pageX, |
225 x: _event.pageX, |
223 y: _event.pageY |
226 y: _event.pageY |
224 }; |
227 }; |
225 if (typeof this.dragging_type === "undefined") { |
228 if (typeof this.dragging_type === "undefined") { |
|
229 this.time_at_start = this.central_time; |
226 this.dragging_type = "timeline"; |
230 this.dragging_type = "timeline"; |
227 } |
231 } |
228 } |
232 } |
229 |
233 |
230 Tlns.Classes.Timeline.prototype.onMouseUp = function(_event) { |
234 Tlns.Classes.Timeline.prototype.onMouseUp = function(_event) { |
|
235 if (this.is_dragging) { |
|
236 switch (this.dragging_type) { |
|
237 case "occurrence": |
|
238 this.editing_occurrence.editing = false; |
|
239 this.throttledDrawGrid(); |
|
240 break; |
|
241 } |
|
242 } |
231 this.mouse_down = false; |
243 this.mouse_down = false; |
232 this.is_dragging = false; |
244 this.is_dragging = false; |
233 this.dragging_type = undefined; |
245 this.dragging_type = undefined; |
234 } |
246 } |
235 |
247 |
240 if (_event.pageX > this.dragging_bounds.left |
252 if (_event.pageX > this.dragging_bounds.left |
241 && _event.pageX < this.dragging_bounds.right |
253 && _event.pageX < this.dragging_bounds.right |
242 && _event.pageY > this.dragging_bounds.top |
254 && _event.pageY > this.dragging_bounds.top |
243 && _event.pageY < this.dragging_bounds.bottom |
255 && _event.pageY < this.dragging_bounds.bottom |
244 ) { |
256 ) { |
245 var _newTime = Math.floor(this.time_at_start + ( this.start_pos.x - _event.pageX ) / this.current_scale); |
257 var _timeDelta = Math.floor(( this.start_pos.x - _event.pageX ) / this.current_scale); |
246 switch (this.dragging_type) { |
258 switch (this.dragging_type) { |
|
259 case "occurrence": |
|
260 this.editing_occurrence.date = this.time_at_start - _timeDelta; |
|
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))); |
|
262 this.editing_occurrence.univers = this.univers[_u]; |
|
263 this.editing_occurrence.univers_id = this.univers[_u].id; |
|
264 this.throttledDrawGrid(); |
|
265 break; |
247 case "timeline": |
266 case "timeline": |
248 this.throttledSetTime(_newTime); |
267 this.setTime(this.time_at_start + _timeDelta); |
249 break; |
268 break; |
250 } |
269 } |
251 } else { |
270 } else { |
252 this.onMouseUp(_event); |
271 this.onMouseUp(_event); |
253 } |
272 } |
270 } |
289 } |
271 |
290 |
272 Tlns.Classes.Timeline.prototype.setTime = function(_centralTime) { |
291 Tlns.Classes.Timeline.prototype.setTime = function(_centralTime) { |
273 this.sync_now = false; |
292 this.sync_now = false; |
274 this.central_time = _centralTime; |
293 this.central_time = _centralTime; |
275 this.drawGrid(); |
294 this.throttledDrawGrid(); |
276 } |
295 } |
277 |
296 |
278 Tlns.Classes.Timeline.prototype.setLevel = function(_level) { |
297 Tlns.Classes.Timeline.prototype.setLevel = function(_level) { |
279 if (_level >= 0 && _level < this.timescales.length) { |
298 if (_level >= 0 && _level < this.timescales.length) { |
280 this.$.find('.Tl-TopBar-Timescales>div').each(function() { |
299 this.$.find('.Tl-TopBar-Timescales>div').each(function() { |
306 var _grid_width = Math.floor(_timescale.grid_interval * this.current_scale), |
325 var _grid_width = Math.floor(_timescale.grid_interval * this.current_scale), |
307 _roundstart = Math.floor((this.start_time - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset, |
326 _roundstart = Math.floor((this.start_time - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset, |
308 _html = ''; |
327 _html = ''; |
309 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)); |
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)); |
310 for (var _t = _roundstart; _t < this.end_time; _t += _timescale.grid_interval) { |
329 for (var _t = _roundstart; _t < this.end_time; _t += _timescale.grid_interval) { |
311 _html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + this.current_scale * (_t - this.central_time) + 'px">' |
330 _html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + this.current_scale * (_t - this.start_time) + 'px">' |
312 + '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>'; |
331 + '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>'; |
313 } |
332 } |
314 /* |
333 /* |
315 |
334 |
316 for (var _t = _roundstart; _t < _tmax; _t += _timescale.grid_interval) { |
335 for (var _t = _roundstart; _t < _tmax; _t += _timescale.grid_interval) { |
317 var _isMajor = !(Math.floor((_t - _offset) / _timescale.grid_interval) % _timescale.major_interval); |
336 var _isMajor = !(Math.floor((_t - _offset) / _timescale.grid_interval) % _timescale.major_interval); |
318 _html += '<div class="Tl-Grid-Column' + ( _isMajor ? ' Tl-Grid-Major' : '' ) + '" style="width:' + _grid_width + 'px; left: ' + _scale * (_t - this.central_time) + 'px">' |
337 _html += '<div class="Tl-Grid-Column' + ( _isMajor ? ' Tl-Grid-Major' : '' ) + '" style="width:' + _grid_width + 'px; left: ' + _scale * (_t - this.start_time) + 'px">' |
319 + ( _isMajor ? '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.date_format) + '</div>' : '' ) + '</div>'; |
338 + ( _isMajor ? '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.date_format) + '</div>' : '' ) + '</div>'; |
320 } |
339 } |
321 */ |
340 */ |
322 if (this.start_time <= _now && this.end_time >= _now) { |
341 if (this.start_time <= _now && this.end_time >= _now) { |
323 _html += '<div class="Tl-Grid-Now" style="left: ' + this.current_scale * (_now - this.central_time) + 'px"></div>' |
342 _html += '<div class="Tl-Grid-Now" style="left: ' + this.current_scale * (_now - this.start_time) + 'px"></div>' |
324 } |
343 } |
325 this.$.find('.Tl-Grid').html(_html); |
344 this.$.find('.Tl-Grid').html(_html); |
326 this.drawOccurrences(); |
345 this.drawOccurrences(); |
327 } |
346 } |
328 |
347 |
383 var _this = this, |
402 var _this = this, |
384 _visible = _(this.occurrences).filter(function(_occ) { |
403 _visible = _(this.occurrences).filter(function(_occ) { |
385 return (_occ.date >= _this.start_time && _occ.date <= _this.end_time && _occ.published); |
404 return (_occ.date >= _this.start_time && _occ.date <= _this.end_time && _occ.published); |
386 }); |
405 }); |
387 _(_visible).each(function(_occ) { |
406 _(_visible).each(function(_occ) { |
388 _occ.x = _this.current_scale * (_occ.date - _this.central_time); |
407 _occ.x = _this.current_scale * (_occ.date - _this.start_time); |
389 _occ.in_cluster = false; |
408 _occ.in_cluster = false; |
390 }); |
409 }); |
391 |
410 |
392 var _moved = true; |
411 var _moved = true; |
393 while (_moved) { |
412 while (_moved) { |
439 break; |
458 break; |
440 } |
459 } |
441 } |
460 } |
442 }); |
461 }); |
443 |
462 |
|
463 var _links = []; |
|
464 |
|
465 _(_visible).each(function(_occurrence) { |
|
466 _(_occurrence.dependsOn).each(function(_dependance) { |
|
467 var _parent = _(_visible).find(function(_o) { |
|
468 return _o.type == "narrative" && _o.id == _dependance; |
|
469 }); |
|
470 if (typeof _parent !== "undefined") { |
|
471 _links.push({ |
|
472 from_x: _occurrence.x, |
|
473 from_y: _occurrence.univers.y + Math.floor(_this.univers_height / 2), |
|
474 to_x: _parent.x, |
|
475 to_y: _parent.univers.y + Math.floor(_this.univers_height / 2) |
|
476 }); |
|
477 } |
|
478 }); |
|
479 }); |
|
480 |
|
481 var _ctx = this.$.find('.Tl-Canvas')[0].getContext('2d'); |
|
482 _ctx.clearRect(0,0,this.main_width, this.main_height); |
|
483 _(_links).each(function(_link) { |
|
484 _ctx.beginPath(); |
|
485 _ctx.moveTo(_link.from_x,_link.from_y); |
|
486 _ctx.lineTo(_link.to_x,_link.to_y); |
|
487 _ctx.stroke(); |
|
488 }) |
|
489 |
444 var _html = Mustache.to_html(Tlns.Templates.Occurrence, { |
490 var _html = Mustache.to_html(Tlns.Templates.Occurrence, { |
445 occurrences:_(_visible).reject(function(_o) {return _o.in_cluster}), |
491 occurrences:_(_visible).reject(function(_o) {return _o.in_cluster}), |
446 clusters: _clusters |
492 clusters: _clusters |
447 }); |
493 }); |
448 this.$.find('.Tl-Occurrences').html(_html); |
494 this.$.find('.Tl-Occurrences').html(_html); |
449 this.$.find('.Tl-Occurrence').mousedown(function() { |
495 this.$.find('.Tl-Occurrence').mousedown(function() { |
450 _this.dragging_type = "occurrence" |
496 var _el = $(this); |
|
497 _this.editing_occurrence = _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
|
498 if (typeof _this.editing_occurrence !== "undefined") { |
|
499 _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; |
|
503 } |
451 }).mouseover(function() { |
504 }).mouseover(function() { |
452 var _el = $(this), |
505 var _el = $(this), |
453 _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
506 _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id")); |
454 _this.showTooltip(_occurrence.x, _occurrence.univers.y, _occurrence.title); |
507 _this.showTooltip(_occurrence.x, _occurrence.univers.y, _occurrence.title); |
455 }).mouseout(function() { |
508 }).mouseout(function() { |