timeline/js/timeline.js
changeset 66 37492d1ce841
parent 65 03bbfd9cd3c6
child 67 5d1ac260d3ee
equal deleted inserted replaced
65:03bbfd9cd3c6 66:37492d1ce841
   102         grid_date_format : '{{0hours}}:{{0minutes}}',
   102         grid_date_format : '{{0hours}}:{{0minutes}}',
   103         start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{0hours}}:{{0minutes}}',
   103         start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{0hours}}:{{0minutes}}',
   104         end_date_format : '{{0hours}}:{{0minutes}}'
   104         end_date_format : '{{0hours}}:{{0minutes}}'
   105     }, {
   105     }, {
   106         label : "1 Heure",
   106         label : "1 Heure",
   107         span : 80 * 60 * 1000,
   107         span : 60 * 60 * 1000,
   108         grid_interval : 15 * 60 * 1000,
   108         grid_interval : 15 * 60 * 1000,
   109         grid_date_format : '{{0hours}}:{{0minutes}}',
   109         grid_date_format : '{{0hours}}:{{0minutes}}',
   110         start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{0hours}}:{{0minutes}}',
   110         start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{0hours}}:{{0minutes}}',
   111         end_date_format : '{{0hours}}:{{0minutes}}'
   111         end_date_format : '{{0hours}}:{{0minutes}}'
   112     }],
   112     }],
   113     level: 0,
   113     level: 0,
   114     central_time: 0,
   114     central_time: 0,
   115     sync_now: true,
   115     sync_now: true,
   116     url_occurrences: '',
   116     url_occurrences: '',
   117     occurrences: {}
   117     occurrences: [],
       
   118     cluster_spacing: 9
   118 }
   119 }
   119 
   120 
   120 for (var _i = 0; _i < Tlns.Defaults.Timeline.timescales.length; _i++) {
   121 for (var _i = 0; _i < Tlns.Defaults.Timeline.timescales.length; _i++) {
   121     Tlns.Defaults.Timeline.timescales[_i].level = _i;
   122     Tlns.Defaults.Timeline.timescales[_i].level = _i;
   122 }
   123 }
   125 
   126 
   126 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>'
   127     + '<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>'
   128     + '<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>'
   129     + '<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>'
   130     + '<div class="Tl-BottomPart"><ul class="Tl-UniversLabels"></ul><div class="Tl-MainPart"><div class="Tl-Grid"></div></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 
   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 Tlns.Templates.Univers = '<span class="Tl-UniversText">{{title}}</span>'
   133 
       
   134 Tlns.Templates.Univers = '<span class="Tl-UniversText">{{title}}</span>';
       
   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}}';
   133 
   137 
   134 /* Classes */
   138 /* Classes */
   135 
   139 
   136 Tlns.Classes.Timeline = function(_options) {
   140 Tlns.Classes.Timeline = function(_options) {
   137 
   141 
   148     this.$.html(Mustache.to_html(Tlns.Templates.Timeline, this));
   152     this.$.html(Mustache.to_html(Tlns.Templates.Timeline, this));
   149     
   153     
   150     this.main_height = this.height - this.$.find('.Tl-TopBar').outerHeight();
   154     this.main_height = this.height - this.$.find('.Tl-TopBar').outerHeight();
   151     this.$.find('.Tl-BottomPart').css("height", this.main_height + "px");
   155     this.$.find('.Tl-BottomPart').css("height", this.main_height + "px");
   152     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");
   153     var _o = this.$.find('.Tl-MainPart').offset();
   158     var _o = this.$.find('.Tl-MainPart').offset();
   154     this.dragging_bounds = {
   159     this.dragging_bounds = {
   155         left: _o.left,
   160         left: _o.left,
   156         top: _o.top,
   161         top: _o.top,
   157         right: _o.left + this.$.find('.Tl-MainPart').outerWidth(),
   162         right: _o.left + this.$.find('.Tl-MainPart').outerWidth(),
   191     this.$.find('.Tl-MainPart').mouseup(function(_event) {
   196     this.$.find('.Tl-MainPart').mouseup(function(_event) {
   192         _this.onMouseUp(_event);
   197         _this.onMouseUp(_event);
   193         return false;
   198         return false;
   194     });
   199     });
   195     
   200     
       
   201     this.$.find('.Tl-Overlay-Box').mouseover(function(_event) {
       
   202         $(this).show();
       
   203     }).mouseout(function(_event) {
       
   204         $(this).hide();
       
   205     })
       
   206     
   196     this.throttledSetTime = _.throttle(function(_time) {
   207     this.throttledSetTime = _.throttle(function(_time) {
   197         _this.setTime(_time)
   208         _this.setTime(_time)
   198     }, 150);
   209     }, 150);
   199     
   210     
   200     /* Loading Univers */
   211     /* Loading Univers */
   204 }
   215 }
   205 
   216 
   206 Tlns.Classes.Timeline.prototype.onMouseDown = function(_event) {
   217 Tlns.Classes.Timeline.prototype.onMouseDown = function(_event) {
   207     this.mouse_down = true;
   218     this.mouse_down = true;
   208     this.is_dragging = false;
   219     this.is_dragging = false;
       
   220     this.time_at_start = this.central_time;
   209     this.start_pos = {
   221     this.start_pos = {
   210         x: _event.pageX,
   222         x: _event.pageX,
   211         y: _event.pageY
   223         y: _event.pageY
   212     };
   224     };
   213     var _target = $(_event.target);
   225     if (typeof this.dragging_type === "undefined") {
   214     while (!_target.hasClass("Tl-Main") && _target.length) {
   226         this.dragging_type = "timeline";
   215         if (_target.hasClass("Tl-MainPart")) {
       
   216             this.dragging_type = "timeline";
       
   217             this.time_at_start = this.central_time;
       
   218             break;
       
   219         }
       
   220         _target = _target.parent();
       
   221     }
   227     }
   222 }
   228 }
   223 
   229 
   224 Tlns.Classes.Timeline.prototype.onMouseUp = function(_event) {
   230 Tlns.Classes.Timeline.prototype.onMouseUp = function(_event) {
   225     this.mouse_down = false;
   231     this.mouse_down = false;
   226     this.is_dragging = false;
   232     this.is_dragging = false;
       
   233     this.dragging_type = undefined;
   227 }
   234 }
   228 
   235 
   229 Tlns.Classes.Timeline.prototype.onMouseMove = function(_event) {
   236 Tlns.Classes.Timeline.prototype.onMouseMove = function(_event) {
   230     if (this.mouse_down) {
   237     if (this.mouse_down) {
   231         this.is_dragging = true;
   238         this.is_dragging = true;
       
   239         this.$.find('.Tl-Overlay-Box').hide();
   232         if (_event.pageX > this.dragging_bounds.left
   240         if (_event.pageX > this.dragging_bounds.left
   233             && _event.pageX < this.dragging_bounds.right
   241             && _event.pageX < this.dragging_bounds.right
   234             && _event.pageY > this.dragging_bounds.top
   242             && _event.pageY > this.dragging_bounds.top
   235             && _event.pageY < this.dragging_bounds.bottom) {
   243             && _event.pageY < this.dragging_bounds.bottom
       
   244         ) {
       
   245             var _newTime = Math.floor(this.time_at_start + ( this.start_pos.x - _event.pageX ) / this.current_scale);
   236             switch (this.dragging_type) {
   246             switch (this.dragging_type) {
   237                 case "timeline":
   247                 case "timeline":
   238                     var _newTime = Math.floor(this.time_at_start + ( this.start_pos.x - _event.pageX ) / this.current_scale);
       
   239                     this.throttledSetTime(_newTime);
   248                     this.throttledSetTime(_newTime);
   240                 break;
   249                 break;
   241             }
   250             }
   242         } else {
   251         } else {
   243             this.onMouseUp(_event);
   252             this.onMouseUp(_event);
   251         this.univers_height = Math.floor(this.main_height / _data.length);
   260         this.univers_height = Math.floor(this.main_height / _data.length);
   252     }
   261     }
   253     for(var _i = 0; _i < _data.length; _i++) {
   262     for(var _i = 0; _i < _data.length; _i++) {
   254         this.univers.push(new Tlns.Classes.Univers(_data[_i], this, _i));
   263         this.univers.push(new Tlns.Classes.Univers(_data[_i], this, _i));
   255     }
   264     }
       
   265     this.loadOccurrences();
   256 }
   266 }
   257 
   267 
   258 Tlns.Classes.Timeline.prototype.offsetTime = function(_timeOffset) {
   268 Tlns.Classes.Timeline.prototype.offsetTime = function(_timeOffset) {
   259     this.setTime(this.central_time + _timeOffset);
   269     this.setTime(this.central_time + _timeOffset);
   260 }
   270 }
   288     } else {
   298     } else {
   289         this.$.find('.Tl-TopBar-SyncButton').removeClass("active");
   299         this.$.find('.Tl-TopBar-SyncButton').removeClass("active");
   290     }
   300     }
   291     var _timescale = this.timescales[this.level],
   301     var _timescale = this.timescales[this.level],
   292         _offset = new Date().getTimezoneOffset() * 60000;
   302         _offset = new Date().getTimezoneOffset() * 60000;
   293     this.current_scale = this.main_width / (_timescale.span);
   303     this.current_scale = this.main_width / (_timescale.span)
   294     var _tmin = this.central_time - (_timescale.span / 2),
   304     this.start_time = this.central_time - (_timescale.span / 2);
   295         _tmax = this.central_time + (_timescale.span / 2),
   305     this.end_time = this.central_time + (_timescale.span / 2);
   296         _grid_width = Math.floor(_timescale.grid_interval * this.current_scale),
   306     var _grid_width = Math.floor(_timescale.grid_interval * this.current_scale),
   297         _roundstart = Math.floor((_tmin - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset,
   307         _roundstart = Math.floor((this.start_time - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset,
   298         _html = '';
   308         _html = '';
   299     this.$.find('.Tl-TopBar-TimeSpan').html(Tlns.Utils.dateFormat(_tmin, _timescale.start_date_format) + ' - ' + Tlns.Utils.dateFormat(_tmax, _timescale.end_date_format));
   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));
   300     for (var _t = _roundstart; _t < _tmax; _t += _timescale.grid_interval) {
   310     for (var _t = _roundstart; _t < this.end_time; _t += _timescale.grid_interval) {
   301         _html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + this.current_scale * (_t - this.central_time) + 'px">'
   311         _html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + this.current_scale * (_t - this.central_time) + 'px">'
   302         + '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>';
   312         + '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>';
   303     }
   313     }
   304 /*
   314 /*
   305  
   315  
   307         var _isMajor = !(Math.floor((_t - _offset) / _timescale.grid_interval) % _timescale.major_interval);
   317         var _isMajor = !(Math.floor((_t - _offset) / _timescale.grid_interval) % _timescale.major_interval);
   308         _html += '<div class="Tl-Grid-Column' + ( _isMajor ? ' Tl-Grid-Major' : '' ) + '" style="width:' + _grid_width + 'px; left: ' + _scale * (_t - this.central_time) + 'px">'
   318         _html += '<div class="Tl-Grid-Column' + ( _isMajor ? ' Tl-Grid-Major' : '' ) + '" style="width:' + _grid_width + 'px; left: ' + _scale * (_t - this.central_time) + 'px">'
   309         + ( _isMajor ? '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.date_format) + '</div>' : '' ) + '</div>';
   319         + ( _isMajor ? '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.date_format) + '</div>' : '' ) + '</div>';
   310     }
   320     }
   311 */
   321 */
   312     if (_tmin <= _now && _tmax >= _now) {
   322     if (this.start_time <= _now && this.end_time >= _now) {
   313         _html += '<div class="Tl-Grid-Now" style="left: ' + this.current_scale * (_now - this.central_time) + 'px"></div>'
   323         _html += '<div class="Tl-Grid-Now" style="left: ' + this.current_scale * (_now - this.central_time) + 'px"></div>'
   314     }
   324     }
   315     this.$.find('.Tl-Grid').html(_html);
   325     this.$.find('.Tl-Grid').html(_html);
       
   326     this.drawOccurrences();
       
   327 }
       
   328 
       
   329 Tlns.Classes.Timeline.prototype.loadOccurrences = function() {
       
   330     var _url = Mustache.to_html(this.url_occurrences, {
       
   331             from_time: this.start_time,
       
   332             to_time: this.end_time
       
   333         }),
       
   334         _this = this;
       
   335     $.getJSON(_url, function(_data) {
       
   336         _this.onOccurrencesLoaded(_data);
       
   337     });
       
   338 }
       
   339 
       
   340 Tlns.Classes.Timeline.prototype.onOccurrencesLoaded = function(_data) {
       
   341     if (typeof _data.occurrencesNarratives === "object" && _data.occurrencesNarratives !== null) {
       
   342         for (var _i = 0; _i < _data.occurrencesNarratives.length; _i++) {
       
   343             this.createOrUpdateOccurrence("narrative", _data.occurrencesNarratives[_i]);
       
   344         }
       
   345         for (var _i = 0; _i < _data.occurrencesProduction.length; _i++) {
       
   346             this.createOrUpdateOccurrence("production", _data.occurrencesProduction[_i]);
       
   347         }
       
   348     }
       
   349     if (!this.mouse_down) {
       
   350         this.drawOccurrences();
       
   351     }
       
   352 }
       
   353 
       
   354 Tlns.Classes.Timeline.prototype.getOccurrence = function(_type, _id) {
       
   355     return _(this.occurrences).find(function(_occ) {
       
   356         return (_occ.type == _type && _occ.id == _id);
       
   357     });
       
   358 }
       
   359 
       
   360 Tlns.Classes.Timeline.prototype.createOrUpdateOccurrence = function(_type, _data) {
       
   361     var _occurrence = this.getOccurrence(_type, _data.id);
       
   362     if (typeof _occurrence === "undefined") {
       
   363         _occurrence = new Tlns.Classes.Occurrence(this);
       
   364         this.occurrences.push(_occurrence);
       
   365     }
       
   366     _occurrence.update(_type, _data);
       
   367 }
       
   368 
       
   369 Tlns.Classes.Timeline.prototype.showTooltip = function(_x, _y, _html) {
       
   370     this.$.find('.Tl-Overlay-Box').show()
       
   371         .css({
       
   372             left: _x + "px",
       
   373             top: _y + "px"
       
   374         });
       
   375     this.$.find('.Tl-Overlay-Main').html(_html);
       
   376 }
       
   377 
       
   378 Tlns.Classes.Timeline.prototype.hideTooltip = function() {
       
   379     this.$.find('.Tl-Overlay-Box').hide();
   316 }
   380 }
   317 
   381 
   318 Tlns.Classes.Timeline.prototype.drawOccurrences = function() {
   382 Tlns.Classes.Timeline.prototype.drawOccurrences = function() {
   319     
   383     var _this = this,
   320 }
   384         _visible = _(this.occurrences).filter(function(_occ) {
       
   385         return (_occ.date >= _this.start_time && _occ.date <= _this.end_time && _occ.published);
       
   386     });
       
   387     _(_visible).each(function(_occ) {
       
   388         _occ.x = _this.current_scale * (_occ.date - _this.central_time);
       
   389         _occ.in_cluster = false;
       
   390     });
       
   391     
       
   392     var _moved = true;
       
   393     while (_moved) {
       
   394         _moved = false;
       
   395         for (var _i = 0; _i < _visible.length; _i++) {
       
   396             for (var _j = 0; _j < _i; _j++) {
       
   397                 if (_visible[_j].univers_id == _visible[_i].univers_id
       
   398                     && _visible[_j].x != _visible[_i].x
       
   399                     && Math.abs(_visible[_j].x-_visible[_i].x) < this.cluster_spacing
       
   400                 ) {
       
   401                     _moved = true;
       
   402                     _visible[_i].x = this.cluster_spacing * Math.round(_visible[_i].x / this.cluster_spacing);
       
   403                     _visible[_j].x = this.cluster_spacing * Math.round(_visible[_j].x / this.cluster_spacing);
       
   404                 }
       
   405             }
       
   406         }
       
   407     }
       
   408     var _clusters = [];
       
   409     for (var _i = 0; _i < _visible.length; _i++) {
       
   410         for (var _j = 0; _j < _i; _j++) {
       
   411             if (_visible[_j].univers_id == _visible[_i].univers_id && _visible[_j].x == _visible[_i].x) {
       
   412                 _visible[_j].in_cluster = true;
       
   413                 _visible[_i].in_cluster = true;
       
   414                 var _x = _visible[_j].x,
       
   415                     _y = _visible[_j].univers.y;
       
   416                     _cluster = _(_clusters).find(function(_c) { return _c.x == _x && _c.y == _y });
       
   417                 if (typeof _cluster === "undefined") {
       
   418                     _cluster = { x: _x, y: _y, occurrences: [] };
       
   419                     _clusters.push(_cluster);
       
   420                 }
       
   421                 if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) {
       
   422                     return _o.type == _visible[_j].type && _o.id == _visible[_j].id;
       
   423                 })) {
       
   424                     _cluster.occurrences.push({type: _visible[_j].type, id: _visible[_j].id});
       
   425                 }
       
   426                 if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) {
       
   427                     return _o.type == _visible[_i].type && _o.id == _visible[_i].id;
       
   428                 })) {
       
   429                     _cluster.occurrences.push({type: _visible[_i].type, id: _visible[_i].id});
       
   430                 }
       
   431             }
       
   432         }
       
   433     }
       
   434     _(_clusters).each(function(_cluster) {
       
   435         _cluster.type = _cluster.occurrences[0].type;
       
   436         for (var _i = 1; _i < _cluster.occurrences.length; _i++) {
       
   437             if (_cluster.occurrences[_i].type !== _cluster.type) {
       
   438                 _cluster.type = "both";
       
   439                 break;
       
   440             }
       
   441         }
       
   442     });
       
   443     
       
   444     var _html = Mustache.to_html(Tlns.Templates.Occurrence, {
       
   445         occurrences:_(_visible).reject(function(_o) {return _o.in_cluster}),
       
   446         clusters: _clusters
       
   447     });
       
   448     this.$.find('.Tl-Occurrences').html(_html);
       
   449     this.$.find('.Tl-Occurrence').mousedown(function() {
       
   450         _this.dragging_type = "occurrence"
       
   451     }).mouseover(function() {
       
   452         var _el = $(this),
       
   453             _occurrence = _this.getOccurrence(_el.attr("occurrence-type"),_el.attr("occurrence-id"));
       
   454         _this.showTooltip(_occurrence.x, _occurrence.univers.y, _occurrence.title);
       
   455     }).mouseout(function() {
       
   456         _this.hideTooltip();
       
   457     });
       
   458 }
       
   459 
       
   460 Tlns.Classes.Timeline.prototype.getUnivers = function(_id) {
       
   461     return _(this.univers).find(function(_univ) {
       
   462         return (_univ.id == _id);
       
   463     });
       
   464 }
       
   465 
       
   466 /*
       
   467  * Univers
       
   468  */
   321 
   469 
   322 Tlns.Classes.Univers = function(_data, _timeline, _index) {
   470 Tlns.Classes.Univers = function(_data, _timeline, _index) {
   323     this.id = _data.id;
   471     this.id = _data.id;
   324     this.index = _index;
   472     this.index = _index;
   325     this.title = _data.nom;
   473     this.title = _data.nom;
   326     this.mainCharacter = _data.personnage;
   474     this.mainCharacter = _data.personnage;
       
   475     this.y = (_timeline.univers_height * _index);
   327 
   476 
   328     this.$label = $('<li>').css({
   477     this.$label = $('<li>').css({
   329         height : _timeline.univers_height + "px"
   478         height : _timeline.univers_height + "px"
   330     }).html(Mustache.to_html(Tlns.Templates.Univers, this))
   479     }).html(Mustache.to_html(Tlns.Templates.Univers, this))
   331     .addClass((_index % 2) ? 'Tl-Line-Odd' : 'Tl-Line-Even');
   480       .addClass((_index % 2) ? 'Tl-Line-Odd' : 'Tl-Line-Even');
   332     
   481     
   333     _timeline.$.find('.Tl-UniversLabels').append(this.$label);
   482     _timeline.$.find('.Tl-UniversLabels').append(this.$label);
   334     var _txt = _data.nom,
   483     var _txt = _data.nom,
   335         _span = this.$label.find('span');
   484         _span = this.$label.find('span');
   336 
   485 
   337     while (_span.outerWidth() > (_timeline.width - _timeline.main_width) && _txt) {
   486     while (_span.outerWidth() > (_timeline.width - _timeline.main_width) && _txt) {
   338         _txt = _txt.substr(0, _txt.length - 1);
   487         _txt = _txt.substr(0, _txt.length - 1);
   339         _span.html(_txt + '&hellip;');
   488         _span.html(_txt + '&hellip;');
   340     }
   489     }
   341 }
   490 }
       
   491 
       
   492 /*
       
   493  * Occurrence
       
   494  */
       
   495 
       
   496 Tlns.Classes.Occurrence = function(_timeline) {
       
   497     this.timeline = _timeline;
       
   498 }
       
   499 
       
   500 Tlns.Classes.Occurrence.prototype.update = function(_type, _data) {
       
   501     this.type = _type;
       
   502     this.id = _data.id || _.uniqueId();
       
   503     this.date = _data.date || _data.datePublication;
       
   504     this.title = _data.titre || "<untitled>";
       
   505     this.univers_id = _data.univers;
       
   506     this.univers = this.timeline.getUnivers(this.univers_id);
       
   507     this.status = _data.statut;
       
   508     this.published = _data.publie || false;
       
   509     this.locked = _data.verrouille || false;
       
   510     this.characters = _data.personnagesSecondaires || [];
       
   511     this.dependsOn = _data.dependDe || [];
       
   512 }
       
   513 
       
   514 Tlns.Classes.Occurrence.prototype.toString = function() {
       
   515     return "Occurrence " + this.type + ': "' + this.title + '"';
       
   516 }