var timeline = function() {
// CONFIG VALUES
this.public_instance = '';
// THE STAGE OBJECT HOLDS REFERENCES TO THE HTML ELEMENTS USED IN THE TIMELINE
this.stage = {
'root': '',
'canvas': '',
'context': '',
'notes': '',
'years': '',
'teams': '',
'titles': ''
}
// THE TIMELINE OBJECT HOLDS THE DATA PULLED OUT OF THE HTML
this.timeline = {
'data': [],
'start_year': 1980,
'end_year': 2010
}
// INIT FUNCTION
this.init = function(el) {
this.stage.root = el;
// set a reference in the global space
if (typeof(window.timelines) == "undefined") {
window.timelines = [];
}
window.timelines.push(this);
this.public_instance = window.timelines[window.timelines.length-1];
this.stage.teams = this.stage.root.find('UL#timeline-data LI');
this.set_timeline_data();
this.stage.root.addClass('timeline-display');
this.set_timeline_width();
var t = this;
// THIS IS A BIT OF A HACK, WAIT 5ms BEFORE RUNNING BUILDING THE TIMELINE BAR AND DRAWING THE LINKS. ON SOME BROWSERS THE WIDTHS GET ALL SCREWED UP WHEN YOU TRY TO DO IT ALL AT ONCE
setTimeout(function(){
t.setup_timeline_bar();
t.setup_timeline_actions();
t.draw_all_timeline_links();
}, 50);
}
// SET THE WIDTH OF THE TEAMS LI ELEMENTS SO THEY TAKE UP 100% OF THE GRAPHIC
this.set_timeline_width = function() {
this.stage.teams.width(this.stage.root.width() / this.timeline.data.length);
}
// ATTACH ACTIONS TO THE LI ELEMENTS
this.setup_timeline_actions = function() {
public_instance = this.public_instance;
this.stage.teams.hover(function() {
public_instance.draw_timeline_links(this);
});
this.stage.years.find('LI').hover(function() {
public_instance.draw_matchup(this);
});
}
// PART OF THE INIT FUNCTION. CAPTURE THE DATA FROM THE HTML MARKUP AND STORE IT FOR FASTER ACCESS.
this.set_timeline_data = function() {
this.timeline.data = this.stage.teams.map(function() {
var timeline_item = {'el': $(this), 'wins': [], 'losses': [], 'notes':[] };
$(this).find('.timeline .win').each(function(){
var d = new Date($(this).attr('title'));
timeline_item.wins.push(d);
});
$(this).find('.timeline .lose').each(function(){
var d = new Date($(this).attr('title'));
timeline_item.losses.push(d);
});
$(this).find('.timeline .note').each(function(){
var d = new Date($(this).attr('title'));
timeline_item.notes.push({'date':d, 'note': $(this).text()});
});
return timeline_item;
});
}
// SET UP THE EXTRA HTML THAT WILL BE USED BY THE VISUALIZATION
this.setup_timeline_bar = function() {
this.stage.root.append('
');
this.stage.root.append('');
this.stage.titles = this.stage.root.find('DIV.timeline-titles H3');
this.stage.years = this.stage.root.find('UL.timeline-bar');
var current_year = this.timeline.start_year + 0;
while (current_year <= this.timeline.end_year) {
this.stage.years.append(''+ current_year.toString().substring(2,4) +'');
current_year++;
}
this.stage.canvas = this.stage.root.find('canvas').get(0);
this.stage.years.find('LI').width(this.stage.years.width()/this.stage.years.find('LI').length);
this.stage.root.append('');
this.stage.notes = this.stage.root.find('DIV.timeline-notes');
}
// GET AND RETURN THE CONTEXT OF THE CANVAS FOR THIS TIMELINE
this.ctx = function() {
if (this.stage.context == '') {
this.stage.context = this.stage.canvas.getContext('2d');
}
return this.stage.context;
}
this.draw_all_timeline_links = function() {
var t = this;
this.stage.teams.each(function() {
t.draw_timeline_links(this,false);
});
}
// DRAW A LINK BETWEEN A TEAM AND ANY YEARS THEY WERE IN THE FINALS
this.draw_timeline_links = function(el, clear) {
if (typeof(clear) == 'undefined') {
clear = true;
}
// clear the canvas and any previously selected years.
if (clear) {
this.clear_data();
}
$(el).addClass('selected');
var id = this.stage.teams.index(el);
var t = this;
jQuery.each(this.timeline.data[id].wins, function(i,d) {
var year = d.getFullYear();
t.draw_connection($(t.stage.teams[id]), t.stage.years.find('LI#y' + year), '#0000ff');
// also, highlight the years that are pointed to by the canvas.
t.stage.years.find('LI#y'+year).addClass('selected win');
});
jQuery.each(this.timeline.data[id].losses, function(i,d) {
var year = d.getFullYear();
t.draw_connection($(t.stage.teams[id]), t.stage.years.find('LI#y' + year), '#ff0000');
// also, highlight the years that are pointed to by the canvas.
t.stage.years.find('LI#y'+year).addClass('selected lose');
});
// only show notes and titles if we're not showing ALL of them
if (clear) {
var t = this;
jQuery.each(this.timeline.data[id].notes, function(i,note) {
t.draw_note(note);
});
this.stage.titles.text(this.timeline.data[id].el.find('h3').text());
}
}
// DRAW A LINK BETWEEN A YEAR AND THE TWO TEAMS THAT PLAYED IN THE FINALS THAT YEAR
this.draw_matchup = function(el) {
year = $(el).attr('id').substring(1);
// find the winner
var winner = this.stage.teams.find('SPAN.win[title*=' + year + ']').parents('LI').get(0);
var winner_id = this.stage.teams.index(winner);
var loser = this.stage.teams.find('SPAN.lose[title*=' + year + ']').parents('LI').get(0);
var loser_id = this.stage.teams.index(loser);
this.clear_data();
$(el).addClass('selected');
if (typeof(winner) != 'undefined') {
$(this.stage.teams[winner_id]).addClass('selected');
this.draw_connection($(this.stage.teams[winner_id]), this.stage.years.find('LI#y' + year), '#0000ff');
}
if (typeof(loser) != 'undefined') {
$(this.stage.teams[loser_id]).addClass('selected');
this.draw_connection($(this.stage.teams[loser_id]), this.stage.years.find('LI#y' + year), '#ff0000');
}
if (typeof(loser) != 'undefined' && typeof(winner) != 'undefined') {
this.stage.titles.html('' + $(this.stage.teams[winner_id]).find('h3').text() + ' vs. ' +$(this.stage.teams[loser_id]).find('h3').text() + '');
}
}
// DRAW A NOTE ON THE GRAPHIC
this.draw_note = function(note) {
var year = note.date.getFullYear();
if (this.stage.years.find('LI#y' + year).length == 1) {
var year_pos = this.stage.years.find('LI#y' + year).position().left;
var h = $(this.stage.canvas).height();
this.ctx().strokeStyle = '#00ff00';
this.ctx().globalAlpha = 1;
this.ctx().beginPath();
this.ctx().moveTo(year_pos, 0);
this.ctx().lineTo(year_pos,h);
this.ctx().stroke();
this.stage.notes.append(''+ note.note + '
');
}
}
// GENERIC FUNCTION TO DRAW A CONNECTION BETWEEN A SINGLE YEAR AND A SINGLE TEAM, USED BY OTHER FUNCTIONS
this.draw_connection = function(team,year,color) {
this.ctx().globalAlpha = 0.2;
this.ctx().fillStyle = color;
var l1 = team.position().left;
var l2 = year.position().left
var r1 = l1 + team.width();
var r2 = year.width() + year.position().left;
var h = $(this.stage.canvas).height();
this.ctx().beginPath();
this.ctx().moveTo(l1,0);
this.ctx().lineTo(r1,0);
this.ctx().lineTo(r2,h);
this.ctx().lineTo(l2,h);
this.ctx().fill();
}
// CLEAR THE DATA
this.clear_data = function() {
this.ctx().clearRect(0,0,$(this.stage.canvas).width(),$(this.stage.canvas).height());
this.stage.years.find('li').removeClass('selected win lose');
this.stage.teams.removeClass('selected');
this.stage.notes.html('');
this.stage.titles.html('');
}
}