/*
* Main Timeline code
*/
window.Tlns = {
Utils : {},
Defaults : {},
Templates : {},
Classes : {}
};
/* Utility Functions */
Tlns.Utils.zeroPad = function(_n) {
return (_n < 10 ? "0" : "") + _n;
}
Tlns.Utils.SetDefaults = function(_object, _defaults, _options) {
var _options = _options || {};
_(_defaults).each(function(_v, _k) {
if(/^m(in|ax)_/.test(_k)) {
var _tab = _k.split('_')
if( typeof _object[_tab[1]] !== "undefined") {
var _fn = (_tab[0] === "min" ? Math.max : Math.min);
_object[_tab[1]] = _fn(_object[_tab[1]], _v);
}
} else {
if( typeof _options[_k] !== "undefined") {
_object[_k] = _options[_k];
} else {
_object[_k] = _v;
}
}
});
}
Tlns.Utils.dateFormat = function(_date, _template) {
if (typeof _date !== "object") {
_date = new Date(parseInt(_date));
}
var _params = {
hours: _date.getHours(),
"0hours": Tlns.Utils.zeroPad(_date.getHours()),
minutes: _date.getMinutes(),
"0minutes": Tlns.Utils.zeroPad(_date.getMinutes()),
seconds: _date.getSeconds(),
"0seconds": Tlns.Utils.zeroPad(_date.getSeconds()),
dayOfWeek: ["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"][_date.getDay()],
shortDayOfWeek: ["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"][_date.getDay()],
dayOfMonth: _date.getDate(),
"0dayOfMonth": Tlns.Utils.zeroPad(_date.getDate()),
monthNumber: 1+_date.getMonth(),
"0monthNumber": Tlns.Utils.zeroPad(1+_date.getMonth()),
monthName: ["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"][_date.getMonth()],
shortMonthName: ["jan","fev","mar","avr","mai","jun","jul","aou","sep","oct","nov","dec"][_date.getMonth()],
year: _date.getFullYear()
}
return Mustache.to_html(_template, _params);
}
Tlns.Utils.guid = function() {
return 'xxxx-xxxx-xxxx-xxxx'.replace(/x/g,function() {
return Math.floor(Math.random()*16).toString(16);
});
}
Tlns.Utils.timeFieldProcess = function(_val) {
var _h = 0,
_m = 0,
_matches = _val.match(/(\d+)/g);
if (_matches && _matches.length) {
_h = Math.min(23, +(_matches[0]));
if (_matches.length > 1) {
_m = Math.min(59, +(_matches[1]));
}
}
return {
hours: _h,
minutes: _m,
text: Tlns.Utils.zeroPad(_h) + ':' + Tlns.Utils.zeroPad(_m)
}
}
Tlns.Utils.dateFieldProcess = function(_val) {
var _now = new Date(),
_y = _now.getFullYear(),
_m = 1 + _now.getMonth(),
_d = _now.getDate(),
_matches = _val.match(/(\d+)/g);
if (_matches && _matches.length) {
_d = Math.min(31, +(_matches[0]));
if (_matches.length > 1) {
_m = Math.min(12, +(_matches[1]));
}
if (_matches.length > 2) {
_y = parseInt(_matches[2]);
if (_y < 2000) {
_y += 2000;
}
_y = Math.min(2020, Math.max(2000, _y));
}
}
return {
year: _y,
month: _m,
date: _d,
text: Tlns.Utils.zeroPad(_d) + '/' + Tlns.Utils.zeroPad(_m) + '/' + _y
}
}
Tlns.Utils.clickActiveProcess = function(_el) {
if (_el.hasClass("Ls-Active")) {
if (!_el.siblings(":not(.Ls-Active)").length) {
_el.siblings().removeClass("Ls-Active");
} else {
if (!_el.siblings(".Ls-Active").length) {
_el.siblings().addClass("Ls-Active");
}
_el.removeClass("Ls-Active");
}
} else {
_el.addClass("Ls-Active");
}
}
/* Defaults */
Tlns.Defaults.Timeline = {
container : "timeline",
width : 950,
height : 200,
url_univers : '',
min_width : 400,
min_height : 100,
main_width : 800,
timescales : [{
label : "Mois",
span : 32 * 86400 * 1000,
grid_interval : 5 * 86400 * 1000,
grid_date_format : '{{dayOfMonth}} {{shortMonthName}}',
start_date_format : '{{dayOfMonth}} {{shortMonthName}}',
end_date_format : '{{dayOfMonth}} {{shortMonthName}} {{year}}'
}, {
label : "Semaine",
span : 8 * 86400 * 1000,
grid_interval : 86400 * 1000,
grid_date_format : '{{shortDayOfWeek}} {{0dayOfMonth}}/{{0monthNumber}}',
start_date_format : '{{dayOfMonth}} {{shortMonthName}}',
end_date_format : '{{dayOfMonth}} {{shortMonthName}}'
}, {
label : "2 jours",
span : 2 * 86400 * 1000,
grid_interval : 8 * 3600 * 1000,
grid_date_format : '{{shortDayOfWeek}} {{0dayOfMonth}}/{{0monthNumber}} {{hours}}h',
start_date_format : '{{dayOfMonth}} {{shortMonthName}}',
end_date_format : '{{dayOfMonth}} {{shortMonthName}}'
}, {
label : "Demi-Journée",
span : 12 * 3600 * 1000,
grid_interval : 2 * 3600 * 1000,
grid_date_format : '{{hours}}h',
start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{hours}}h',
end_date_format : '{{dayOfMonth}} {{shortMonthName}} {{hours}}h'
}, {
label : "3 Heures",
span : 3 * 3600 * 1000,
grid_interval : 30 * 60 * 1000,
grid_date_format : '{{0hours}}:{{0minutes}}',
start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{0hours}}:{{0minutes}}',
end_date_format : '{{0hours}}:{{0minutes}}'
}, {
label : "1 Heure",
span : 60 * 60 * 1000,
grid_interval : 15 * 60 * 1000,
grid_date_format : '{{0hours}}:{{0minutes}}',
start_date_format : '{{dayOfMonth}} {{shortMonthName}} {{0hours}}:{{0minutes}}',
end_date_format : '{{0hours}}:{{0minutes}}'
}],
level: 0,
central_time: 0,
sync_now: true,
urls_occurrences: [],
occurrences: [],
cluster_spacing: 12,
tooltip_date_format: '{{dayOfMonth}} {{shortMonthName}} {{year}} {{0hours}}:{{0minutes}}',
statuses: {
"valide": "Validée",
"a_valider": "A valider",
"a_realiser": "A réaliser"
}
}
for (var _i = 0; _i < Tlns.Defaults.Timeline.timescales.length; _i++) {
Tlns.Defaults.Timeline.timescales[_i].level = _i;
}
/* Templates */
Tlns.Templates.Timeline = '<ul class="Onglets"><li class="Onglet-Tl active">Frise chronologique</li><li class="Onglet-Ls">Liste des occurrences</li></ul><div class="Tl-Main"><div class="Tl-TopBar">'
+ '<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>'
+ '<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>'
+ '<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>'
+ '<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>'
+ '<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></div>'
+'<div class="Ls-Main"><div class="Ls-Filtres">'
+ '<div class="Ls-Column"><h2>Filtres :</h2><h3>Univers :</h3><ul class="Ls-Univers"></ul></div>'
+ '<div class="Ls-Column"><h3>Type d\'occurrence :</h3><ul class="Ls-Occtypes"><li data="narrative" class="Ls-Critere Ls-Active Ls-CrWithIcon"><div class="Ls-OccIcon Tl-Occnarrative"></div>Narratives</li><li data="publication" class="Ls-Critere Ls-Active Ls-CrWithIcon"><div class="Ls-OccIcon Tl-Occpublication"></div>de Publication</li></ul>'
+ '<h3>Statut :</h3><ul class="Ls-Occstatuses"><li data="a_realiser" class="Ls-Critere Ls-Active Ls-CrWithIcon"><div class="Ls-OccIcon Tl-Occpublication Tl-Occa_realiser"></div>À réaliser</li><li data="a_valider" class="Ls-Critere Ls-Active Ls-CrWithIcon"><div class="Ls-OccIcon Tl-Occpublication Tl-Occa_valider"></div>À valider</li><li data="valide" class="Ls-Critere Ls-Active Ls-CrWithIcon"><div class="Ls-OccIcon Tl-Occpublication Tl-Occvalide"></div>Validé</li></ul></div>'
+ '<div class="Ls-Column"><h3>Format :</h3><ul class="Ls-Formats"></ul><h3>Est au JT :</h3><ul class="Ls-IsJt"><li class="Ls-Critere Ls-Active" data="1">Oui</li><li class="Ls-Critere Ls-Active" data="0">Non</li></ul></div>'
+ '<div class="Ls-Column"><h3>Réinitialiser filtres :</h3><ul><li class="Ls-Critere Ls-Active Ls-All">Tous les contenus</li></ul><h3>Recherche par titre :</h3><p><input class="Ls-Search" type="search" placeholder="Rechercher" /></p><h3>Date :</h3><p><label class="Ls-Label">Du </label><input class="Ls-From-Date Ls-Input" /></p><p><label class="Ls-Label">à </label><input class="Ls-From-Time Ls-Input" /></p><p><label class="Ls-Label">Au </label><input class="Ls-To-Date Ls-Input" /></p><p><label class="Ls-Label">à </label><input class="Ls-To-Time Ls-Input" /></p></div>'
+ '</div><div class="Ls-Resultats"><h2>Occurrences :</h2><ul class="Ls-Occurrences"></ul></div></div>';
Tlns.Templates.Univers = '<span class="Tl-UniversText">{{title}}</span>';
Tlns.Templates.Univers_List = '{{#univers}}<li data="{{id}}" class="Ls-Critere Ls-Active">{{title}}</li>{{/univers}}';
Tlns.Templates.Formats_List = '{{#formats}}<li class="Ls-Critere Ls-Active">{{.}}</li>{{/formats}}';
Tlns.Templates.Occurrence = '{{#clusters}}<div class="Tl-Cluster" 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}} Tl-Occ{{status}}{{#editing}} Tl-Editing{{/editing}}" occurrence-id="{{id}}" style="left: {{x}}px; top: {{y}}px;">'
// + '{{#locked}}<div class="Tl-Locked"></div>{{/locked}}'
+ '</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}} Tl-Occ{{status}}{{#editing}} Tl-Editing{{/editing}}" occurrence-id="{{id}}">'
+ '{{#locked}}<div class="Tl-Locked"></div>{{/locked}}</div>{{/occurrences}}</div>{{/open_cluster}}';
Tlns.Templates.Occurrence_List = '{{#occurrences}}<li class="Ls-Occurrence" data-id="{{id}}"><div class="Ls-OccIcon Tl-Occ{{type}} Tl-Occ{{status}}"></div><h4 class="Ls-Occurrence-Title"><a href="#">{{title}}</a></h4>'
+ '<p class="Ls-Occ-More">{{formatted_date}} — {{univers.title}} — {{translated_status}} — {{#jt}}Au JT{{/jt}}{{^jt}}Hors JT{{/jt}}{{#format}} — {{format}}{{/format}}</p><div style="clear:both;"></div></li>{{/occurrences}}';
Tlns.Templates.OccurrenceTooltip = '<h3 class="Tl-Tooltip-Title">{{title}}</h3><p class="Tl-Tooltip-Date">{{formatted_date}} — {{translated_status}} — {{#jt}}Au JT{{/jt}}{{^jt}}Hors JT{{/jt}}{{#format}} — {{format}}{{/format}}</p>'
+ '<p class="Tl-Tooltip-Description">{{description}}</p>'
// + '<p class="Tl-Tooltip-Characters">{{univers.mainCharacter}}{{#characters}}, {{.}}{{/characters}}</p>'
/* Classes */
Tlns.Classes.Timeline = function(_options) {
/* Setting Defaults */
Tlns.Utils.SetDefaults(this, Tlns.Defaults.Timeline, _options);
/* Setting container CSS */
this.$ = $('#' + this.container).html(Mustache.to_html(Tlns.Templates.Timeline, this));
this.$.find('.Tl-Main').css({
width : this.width + "px",
height : this.height + "px"
});
this.main_height = this.height - this.$.find('.Tl-TopBar').outerHeight();
//this.main_height = this.height - 27;
this.$.find('.Tl-BottomPart').css("height", this.main_height + "px");
this.$.find('.Tl-MainPart').css("width", this.main_width + "px");
this.$.find('.Tl-Overlay-Container').css("left", (this.$.find('.Tl-BottomPart').outerWidth() - this.main_width) + "px");
this.$.find('canvas.Tl-Layer').attr({
width: this.main_width,
height: this.main_height
});
var _o = this.$.find('.Tl-MainPart').offset();
this.dragging_bounds = {
left: _o.left,
top: _o.top,
right: _o.left + this.$.find('.Tl-MainPart').outerWidth(),
bottom: _o.top + this.$.find('.Tl-MainPart').outerHeight(),
};
var _this = this;
this.throttledDrawGrid = _.throttle(function() {
_this.drawGrid();
}, 150);
this.throttledDrawList = _.throttle(function() {
_this.drawList();
}, 150);
this.setLevel(this.level);
this.$.find('.Tl-TopBar-Timescales>div').click(function() {
_this.setLevel($(this).attr("data-level"));
});
this.$.find('.Tl-TopBar-SyncButton').click(function() {
_this.sync_now = !_this.sync_now;
_this.changeSpan();
})
this.$.find('.Tl-TopBar-PreviousButton').click(function() {
_this.offsetTime(-_this.timescales[_this.level].span / 4);
});
this.$.find('.Tl-TopBar-NextButton').click(function() {
_this.offsetTime(_this.timescales[_this.level].span / 4);
});
this.$.find('.Tl-MainPart').mousedown(function(_event) {
_this.onMouseDown(_event);
return false;
});
this.$.find('.Tl-MainPart').mousemove(function(_event) {
_this.onMouseMove(_event);
return false;
});
this.$.find('.Tl-MainPart').mouseup(function(_event) {
_this.onMouseUp(_event);
return false;
});
this.$.find('.Tl-MainPart').mousewheel(function(_event, _delta) {
var _newLevel = Math.max(0,Math.min(_this.timescales.length-1, (_delta < 0 ? -1 : 1) + parseInt(_this.level)));
if (_newLevel != _this.level) {
_this.hideTooltip();
var _deltaX = _event.pageX - _this.dragging_bounds.left,
_tAtMouse = _this.timeFromMouse(_event.pageX),
_newScale = _this.main_width / (_this.timescales[_newLevel].span),
_newStart = _tAtMouse - _deltaX / _newScale;
_this.central_time = _newStart + _this.timescales[_newLevel].span / 2;
_this.setLevel(_newLevel);
}
return false;
});
this.$.find('.Tl-Overlay-Box').mouseover(function(_event) {
$(this).show();
}).mouseout(function(_event) {
$(this).hide();
});
/* Loading Univers */
$.getJSON(this.url_univers, function(_data) {
_this.onUniversLoaded(_data);
});
/* LIST */
this.$.find("li.Ls-Critere").click(function() {
Tlns.Utils.clickActiveProcess($(this));
_this.throttledDrawList();
});
this.$.find(".Ls-Search").bind("keyup change click", function() {
_this.throttledDrawList();
});
this.$.find(".Ls-From-Date, .Ls-To-Date").datepicker(
{
dateFormat: "dd/mm/yy",
dayNames: [ "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" ],
dayNamesShort: [ "Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam" ],
dayNamesMin: [ "D", "L", "Ma", "Me", "J", "V", "S" ],
monthNames: [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ],
monthNamesShort: [ "Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Jul", "Aoû", "Sep", "Oct", "Nov", "Déc" ],
showOtherMonths: true,
selectOtherMonths: true
}
).change(function() {
var _val = $(this).val();
if (_val) {
$(this).val(Tlns.Utils.dateFieldProcess( _val ).text);
}
_this.drawList();
}).bind("keyup", function() {
_this.throttledDrawList();
});
this.$.find(".Ls-From-Time, .Ls-To-Time").change(function() {
var _val = $(this).val();
if (_val) {
$(this).val(Tlns.Utils.timeFieldProcess( _val ).text);
}
_this.throttledDrawList();
}).bind("keyup", function() {
_this.throttledDrawList();
});
this.$.find(".Ls-All").click(function() {
_this.$.find(".Ls-Critere").addClass("Ls-Active");
_this.throttledDrawList();
});
this.$.find(".Ls-None").click(function() {
_this.$.find(".Ls-Critere").removeClass("Ls-Active");
_this.throttledDrawList();
});
this.$.find(".Onglet-Tl").click(function() {
_this.$.find(".Tl-Main").show();
_this.$.find(".Ls-Main").hide();
_this.$.find(".Onglet-Ls").removeClass("active");
_this.$.find(".Onglet-Tl").addClass("active");
_this.throttledDrawGrid();
});
this.$.find(".Onglet-Ls").click(function() {
_this.$.find(".Ls-Main").show();
_this.$.find(".Tl-Main").hide();
_this.$.find(".Onglet-Tl").removeClass("active");
_this.$.find(".Onglet-Ls").addClass("active");
_this.throttledDrawList();
});
}
Tlns.Classes.Timeline.prototype.onMouseDown = function(_event) {
this.mouse_down = true;
this.is_dragging = false;
this.start_pos = {
x: _event.pageX,
y: _event.pageY
};
if (typeof this.dragging_type === "undefined") {
this.time_at_start = this.central_time;
this.dragging_type = "timeline";
}
}
Tlns.Classes.Timeline.prototype.onMouseUp = function(_event) {
this.mouse_down = false;
this.is_dragging = false;
this.dragging_type = undefined;
}
Tlns.Classes.Timeline.prototype.timeFromX = function(_x) {
return Math.max(this.start_time,Math.min(this.end_time, this.start_time + _x / this.current_scale));
}
Tlns.Classes.Timeline.prototype.timeFromMouse = function(_pageX) {
return this.timeFromX(_pageX - this.dragging_bounds.left);
}
Tlns.Classes.Timeline.prototype.universFromY = function(_y) {
return Math.max(0,Math.min(this.univers.length, Math.floor(_y / this.univers_height)))
}
Tlns.Classes.Timeline.prototype.universFromMouse = function(_pageY) {
return this.universFromY(_pageY - this.dragging_bounds.top);
}
Tlns.Classes.Timeline.prototype.onMouseMove = function(_event) {
if (this.mouse_down && !this.is_dragging) {
var _dx = this.start_pos.x - _event.pageX,
_dy = this.start_pos.y - _event.pageY,
_sqd = _dx * _dx + _dy * _dy;
if (_sqd > 16) {
this.is_dragging = true;
}
}
if (this.is_dragging) {
this.hideTooltip();
switch (this.dragging_type) {
case "timeline":
this.setTime(this.time_at_start + Math.floor(( this.start_pos.x - _event.pageX ) / this.current_scale));
break;
}
}
}
Tlns.Classes.Timeline.prototype.onUniversLoaded = function(_data) {
this.univers = [];
if(_data.length) {
this.univers_height = Math.floor(this.main_height / _data.length);
}
for(var _i = 0; _i < _data.length; _i++) {
this.univers.push(new Tlns.Classes.Univers(_data[_i], this, _i));
}
this.$.find(".Ls-Univers").html(
Mustache.to_html(
Tlns.Templates.Univers_List,
{
univers: _(this.univers).map(function(_u) {
return {
id: _u.id,
title: _u.title.replace(/(^.{10,20})[\s].+$/m,'$1…')
}
})
}
)
);
var _this = this;
this.$.find(".Ls-Univers li.Ls-Critere").click( function() {
Tlns.Utils.clickActiveProcess($(this));
_this.throttledDrawList();
});
this.loadOccurrences();
}
Tlns.Classes.Timeline.prototype.offsetTime = function(_timeOffset) {
this.setTime(this.central_time + _timeOffset);
}
Tlns.Classes.Timeline.prototype.setTime = function(_centralTime) {
this.sync_now = false;
this.central_time = _centralTime;
this.changeSpan();
}
Tlns.Classes.Timeline.prototype.setLevel = function(_level) {
if (_level >= 0 && _level < this.timescales.length) {
this.$.find('.Tl-TopBar-Timescales>div').each(function() {
var _el = $(this);
if (_el.attr("data-level") == _level) {
_el.addClass("active");
} else {
_el.removeClass("active");
}
});
this.level = _level;
this.changeSpan();
}
}
Tlns.Classes.Timeline.prototype.changeSpan = function() {
var _now = new Date().valueOf();
if (this.sync_now) {
this.central_time = _now;
}
var _timescale = this.timescales[this.level];
this.current_scale = this.main_width / (_timescale.span);
this.start_time = this.central_time - (_timescale.span / 2);
this.end_time = this.central_time + (_timescale.span / 2);
this.$.find(".Ls-From-Time").val(Tlns.Utils.dateFormat(this.start_time, '{{0hours}}:{{0minutes}}'));
this.$.find(".Ls-From-Date").val(Tlns.Utils.dateFormat(this.start_time, '{{0dayOfMonth}}/{{0monthNumber}}/{{year}}'));
this.$.find(".Ls-To-Time").val(Tlns.Utils.dateFormat(this.end_time, '{{0hours}}:{{0minutes}}'));
this.$.find(".Ls-To-Date").val(Tlns.Utils.dateFormat(this.end_time, '{{0dayOfMonth}}/{{0monthNumber}}/{{year}}'));
this.throttledDrawGrid();
this.throttledDrawList();
}
Tlns.Classes.Timeline.prototype.drawGrid = function() {
if (this.sync_now) {
this.$.find('.Tl-TopBar-SyncButton').addClass("active");
} else {
this.$.find('.Tl-TopBar-SyncButton').removeClass("active");
}
var _now = new Date().valueOf(),
_timescale = this.timescales[this.level],
_offset = new Date().getTimezoneOffset() * 60000,
_grid_width = Math.floor(_timescale.grid_interval * this.current_scale),
_roundstart = Math.floor((this.start_time - _offset) / _timescale.grid_interval) * _timescale.grid_interval + _offset,
_html = '';
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));
for (var _t = _roundstart; _t < this.end_time; _t += _timescale.grid_interval) {
var _x = this.current_scale * (_t - this.start_time);
if (_x > 0) {
_html += '<div class="Tl-Grid-Column" style="width:' + _grid_width + 'px; left: ' + _x + 'px">'
+ '<div class="Tl-Grid-Label">' + Tlns.Utils.dateFormat(_t, _timescale.grid_date_format) + '</div></div>';
}
}
if (this.start_time <= _now && this.end_time >= _now) {
_html += '<div class="Tl-Grid-Now" style="left: ' + this.current_scale * (_now - this.start_time) + 'px"></div>'
}
this.$.find('.Tl-Grid').html(_html);
this.drawOccurrences();
}
Tlns.Classes.Timeline.prototype.loadOccurrences = function() {
var _this = this;
_(this.urls_occurrences).each(function(_url_occ) {
$.getJSON(_url_occ.url, function(_data) {
_this.onOccurrencesLoaded(_data, _url_occ.type);
});
});
}
Tlns.Classes.Timeline.prototype.onOccurrencesLoaded = function(_data, _type) {
for (var _i = 0; _i < _data.length; _i++) {
this.createOrUpdateOccurrence(_type, _data[_i]);
}
if (!this.mouse_down) {
this.drawOccurrences();
}
this.$.find(".Ls-Formats").html(
Mustache.to_html(
Tlns.Templates.Formats_List,
{
formats: _(this.occurrences).chain().pluck('format').unique().value()
}
)
);
var _this = this;
this.$.find(".Ls-Formats li.Ls-Critere").click( function() {
Tlns.Utils.clickActiveProcess($(this));
_this.throttledDrawList();
});
this.throttledDrawList();
}
Tlns.Classes.Timeline.prototype.deleteOccurrence = function(_id) {
this.occurrences = _(this.occurrences).reject(function(_occ) {
return _occ.id == _id;
});
}
Tlns.Classes.Timeline.prototype.getOccurrence = function(_id) {
return _(this.occurrences).find(function(_occ) {
return _occ.id == _id;
});
}
Tlns.Classes.Timeline.prototype.createOrUpdateOccurrence = function(_type, _data) {
var _id = _type + "_" + _data.id,
_occurrence = this.getOccurrence(_id);
if (typeof _occurrence === "undefined") {
_occurrence = new Tlns.Classes.Occurrence(this);
this.occurrences.push(_occurrence);
}
_occurrence.update(_type, _data);
return _occurrence;
}
Tlns.Classes.Timeline.prototype.showTooltip = function(_x, _y, _html, _isUp) {
this.$.find('.Tl-Overlay-Box')
.removeClass(_isUp ? 'Tl-Overlay-Down' : 'Tl-Overlay-Up')
.addClass(_isUp ? 'Tl-Overlay-Up' : 'Tl-Overlay-Down')
.show()
.css({
left: _x + "px",
top: _y + "px"
});
this.$.find('.Tl-Overlay-Main').html(_html);
}
Tlns.Classes.Timeline.prototype.hideTooltip = function() {
this.$.find('.Tl-Overlay-Box').hide();
}
Tlns.Classes.Timeline.prototype.drawOccurrences = function() {
var _this = this;
_(this.occurrences).each(function(_occ) {
_occ.x = _this.current_scale * (_occ.date - _this.start_time);
_occ.y = _occ.univers.y;
_occ.in_cluster = false;
});
var _visible = _(this.occurrences).filter(function(_occ) {
return (_occ.date >= _this.start_time && _occ.date <= _this.end_time && _occ.status);
});
var _moved = true;
while (_moved) {
_moved = false;
for (var _i = 0; _i < _visible.length; _i++) {
for (var _j = 0; _j < _i; _j++) {
if (_visible[_j].univers_id == _visible[_i].univers_id
&& _visible[_j].x != _visible[_i].x
&& Math.abs(_visible[_j].x-_visible[_i].x) < this.cluster_spacing
) {
_moved = true;
_visible[_i].x = this.cluster_spacing * Math.round(_visible[_i].x / this.cluster_spacing);
_visible[_j].x = this.cluster_spacing * Math.round(_visible[_j].x / this.cluster_spacing);
}
}
}
}
var _clusters = [],
_openCluster = false;
for (var _i = 0; _i < _visible.length; _i++) {
for (var _j = 0; _j < _i; _j++) {
if (_visible[_j].univers_id == _visible[_i].univers_id && _visible[_j].x == _visible[_i].x) {
_visible[_j].in_cluster = true;
_visible[_i].in_cluster = true;
var _x = _visible[_j].x,
_y = _visible[_j].y;
_cluster = _(_clusters).find(function(_c) { return _c.x == _x && _c.y == _y });
if (typeof _cluster === "undefined") {
_cluster = { x: _x, y: _y, occurrences: [] };
_clusters.push(_cluster);
}
if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) {
return _o.type == _visible[_j].type && _o.id == _visible[_j].id;
})) {
_cluster.occurrences.push(_visible[_j]);
}
if ("undefined" === typeof _(_cluster.occurrences).find(function(_o) {
return _o.type == _visible[_i].type && _o.id == _visible[_i].id;
})) {
_cluster.occurrences.push(_visible[_i]);
}
}
}
}
_(_clusters).each(function(_cluster) {
_cluster.occurrences = _(_cluster.occurrences).sortBy(function(_o) {
return _o.date;
});
_cluster.contents = _cluster.occurrences.map(function(_o) {
return _o.id;
}).join("|");
if (_cluster.contents == _this.open_cluster) {
_openCluster = _cluster;
}
});
var _html = Mustache.to_html(Tlns.Templates.Occurrence, {
occurrences:_(_visible).reject(function(_o) {return _o.in_cluster}),
clusters: _clusters,
open_cluster: _openCluster
});
this.$.find('.Tl-Occurrences').html(_html);
if (_openCluster) {
var _w = this.$.find('.Tl-Occurrence').width(),
_ww = _w * _openCluster.occurrences.length;
this.$.find('.Tl-ClusterOverlay').css({
"margin-left": - Math.floor(_ww/2) + "px",
width: _ww
});
_(_openCluster.occurrences).each(function(_o, _i) {
_o.y = _o.y - 20;
_o.x = _o.x - (_ww / 2) + ((_i + .5) * _w);
});
}
this.$.find('.Tl-Occurrence').mousedown(function() {
var _el = $(this),
_id = _el.attr("occurrence-id");
if (typeof _id !== "undefined") {
_this.editing_occurrence = _this.getOccurrence(_id);
if (typeof _this.dragging_type === "undefined" && typeof _this.editing_occurrence !== "undefined" /* && !_this.editing_occurrence.locked */ ) {
_this.dragging_type = "occurrence";
}
if (!_this.editing_occurrence.editing) {
_(_this.occurrences).each(function(_occ) {
_occ.editing = false;
});
_this.editing_occurrence.editing = true;
}
_this.throttledDrawGrid();
}
}).mouseover(function(_event) {
var _el = $(this),
_id = _el.attr("occurrence-id");
if (typeof _id !== "undefined") {
var _occurrence = _this.getOccurrence(_id);
if (!_this.is_dragging) {
var _html = Mustache.to_html(Tlns.Templates.OccurrenceTooltip, _occurrence);
_this.showTooltip(_occurrence.x, _occurrence.y, _html, (_event.pageY - _this.dragging_bounds.top) >= (.4 * _this.main_height) );
}
}
}).mouseout(function() {
var _el = $(this),
_id = _el.attr("occurrence-id");
if (typeof _id !== "undefined") {
var _occurrence = _this.getOccurrence(_id);
_this.hideTooltip();
}
});
this.$.find('.Tl-Cluster').click(function() {
var _el = $(this),
_contents = _el.attr("cluster-contents");
if (_this.open_cluster == _contents) {
_this.open_cluster = false;
} else {
_this.open_cluster = _contents;
}
_this.throttledDrawGrid();
})
}
Tlns.Classes.Timeline.prototype.drawList = function() {
var _universfilter = this.$.find(".Ls-Univers li.Ls-Active").map(function(){return $(this).attr("data")}),
_occtypefilter = this.$.find(".Ls-Occtypes li.Ls-Active").map(function(){return $(this).attr("data")}),
_formatsfilter = this.$.find(".Ls-Formats li.Ls-Active").map(function(){return $(this).text()}),
_statusfilter = this.$.find(".Ls-Occstatuses li.Ls-Active").map(function(){return $(this).attr("data")}),
_jtfilter = this.$.find(".Ls-IsJt li.Ls-Active").map(function(){return !!+$(this).attr("data")}),
_title = this.$.find(".Ls-Search").val() || "",
_titleregexp = new RegExp( "(" + _title.replace(/(\W)/gm, "\\$1") + ")", "gim" ),
_startdate = false,
_enddate = false,
_fromDate = this.$.find(".Ls-From-Date").val(),
_toDate = this.$.find(".Ls-To-Date").val();
if (_fromDate) {
var _date = Tlns.Utils.dateFieldProcess(_fromDate),
_time = Tlns.Utils.timeFieldProcess(this.$.find(".Ls-From-Time").val());
_startdate = new Date(_date.year, _date.month - 1, _date.date, _time.hours, _time.minutes);
}
if (_toDate) {
var _date = Tlns.Utils.dateFieldProcess(_toDate),
_time = Tlns.Utils.timeFieldProcess(this.$.find(".Ls-To-Time").val());
_enddate = new Date(_date.year, _date.month - 1, _date.date, _time.hours, _time.minutes);
}
this.$.find(".Ls-Occurrences").html(
Mustache.to_html(
Tlns.Templates.Occurrence_List,
{
occurrences: _(this.occurrences).chain().filter(function(_occ) {
var _titletest = (!!_occ.title.match(_titleregexp)),
_keep = (
( !_title || _titletest )
&& _(_occtypefilter).include(_occ.type)
&& _(_universfilter).include(_occ.univers_id)
&& _(_statusfilter).include(_occ.status)
&& _(_formatsfilter).include(_occ.format)
&& _(_jtfilter).include(_occ.jt)
&& ( !_fromDate || _occ.date >= _startdate )
&& ( !_toDate || _occ.date <= _enddate )
);
return _keep;
}).sortBy(function(_occ) {
return _occ.date;
}).value()
}
)
);
if (_title) {
this.$.find(".Ls-Occurrence-Title").each(function() {
$(this).html($(this).text().replace(_titleregexp, "<span style='background:yellow'>$1</span>"));
});
}
this.$.find(".Ls-Occurrence").click(function() {
var _id = $(this).attr("data-id"),
_data = {
id: _id.replace(/^.*_/,''),
typeOccurrence: "Occurrence" + _id.replace(/_.*$/,'').replace(/^./,function(_l) { return _l.toUpperCase()})
}
return false;
});
}
Tlns.Classes.Timeline.prototype.getUnivers = function(_id) {
return _(this.univers).find(function(_univ) {
return (_univ.id == _id);
});
}
/*
* Univers
*/
Tlns.Classes.Univers = function(_data, _timeline, _index) {
this.id = _data.idUnivers;
this.index = _index;
this.title = _data.nomUnivers;
// this.mainCharacter = _data.personnage;
this.y = (_timeline.univers_height * _index);
this.$label = $('<li>').css({
height : _timeline.univers_height + "px"
}).html(Mustache.to_html(Tlns.Templates.Univers, this))
.addClass((_index % 2) ? 'Tl-Line-Odd' : 'Tl-Line-Even');
_timeline.$.find('.Tl-UniversLabels').append(this.$label);
var _txt = this.title,
_span = this.$label.find('span');
while (_span.outerWidth() > (_timeline.width - _timeline.main_width) && _txt) {
_txt = _txt.substr(0, _txt.length - 1);
_span.html(_txt + '…');
}
}
/*
* Occurrence
*/
Tlns.Classes.Occurrence = function(_timeline) {
this.timeline = _timeline;
}
Tlns.Classes.Occurrence.prototype.update = function(_type, _data) {
this.type = _type;
if (typeof _data.idOccurrenceNarrative !== "undefined" || typeof _data.idOccurrencePublication !== "undefined" || typeof _data.id !== "undefined" || typeof this.original_id === "undefined") {
this.original_id = _data.idOccurrenceNarrative || _data.idOccurrencePublication || _data.id || Tlns.Utils.guid();
}
this.id = _type + "_" + this.original_id;
if (typeof _data.date !== "undefined" || typeof _data.datePublication !== "undefined") {
this.date = 1000 * (_data.datePublication || _data.date);
} else {
if (typeof this.date === "undefined") {
this.date = new Date().valueOf();
}
}
this.formatted_date = Tlns.Utils.dateFormat(this.date,Tlns.Defaults.Timeline.tooltip_date_format);
if (typeof _data.titre !== "undefined" || typeof this.title === "undefined") {
this.title = _data.titre || "<untitled>";
}
if (typeof _data.idUnivers !== "undefined") {
this.univers_id = _data.idUnivers;
}
this.univers = this.timeline.getUnivers(this.univers_id);
if (typeof _data.statut !== "undefined" || typeof this.status === "undefined") {
switch(_data.statut) {
case "Validée":
case "valide":
this.status = "valide"
break;
case "A réaliser":
case "a_realiser":
this.status = "a_realiser";
break;
case "A valider":
case "a_valider":
default:
this.status = "a_valider";
}
}
if (typeof _data.typeOccurrencePublication !== "undefined" || typeof this.format === "undefined") {
this.format = _data.typeOccurrencePublication || 'Format non défini';
}
if (typeof _data.JT !== "undefined") {
this.jt = !!+_data.JT;
}
this.translated_status = Tlns.Defaults.Timeline.statuses[this.status];
// this.published = (_data.publication && _data.publication == "En ligne");
// this.locked = _data.verrouille || false;
// this.characters = _data.personnagesSecondaires || [];
this.dependsOn = [];
if (_data.dependanceNarrative) {
for (var _i = 0; _i < _data.dependanceNarrative.length; _i++) {
this.dependsOn.push("narrative_" + _data.dependanceNarrative[_i])
}
}
if (_data.dependancePublication) {
for (var _i = 0; _i < _data.dependancePublication.length; _i++) {
this.dependsOn.push("publication_" + _data.dependancePublication[_i])
}
}
var _tmp = $('<p>').html(_data.accroche || "");
this.description = _tmp.text().trim().replace(/(\n|\r|\r\n)/mg,' ').replace(/(^.{60,80})[\s].+$/m,'$1…');
}
Tlns.Classes.Occurrence.prototype.addDependency = function(_id) {
if (_(this.dependsOn).indexOf(_id) == -1) {
this.dependsOn.push(_id);
}
}
Tlns.Classes.Occurrence.prototype.removeDependency = function(_id) {
this.dependsOn = _(this.dependsOn).reject(function(_n) {
return _n == _id;
});
}
Tlns.Classes.Occurrence.prototype.toString = function() {
return "Occurrence " + this.type + ': "' + this.title + '"';
}