/*


         ,----------------------------------------.
        /   Fonctions pour la page vidéo 2009      )
       (            Ioan Sameli - 2009            /
        `--\   /---------------------------------´
           |  /
            \|
             `
           (")-''-(").___,.--´'"`-._
            \O_ O  )   `-.  (     ).`-.__.´)
            (_Y_.)/  ._   )  `._ `. ``-..-´
          _,.`--´_..-_/  /--'_.' ,´
         (il).-'´  (li).´  ((!.-´
*/


  /**************************************/
 /***   Initialize links and stuff   ***/
/**************************************/

	// Default channel
	var currentChannel = 'emission';

	var initialTab = null;
	var initialProgram = null;
	var initialVideo = null;
	var initialBroadcast = null;

	addToStart(initAppLinks);
	addToStart(initPlayer);

	// Launch a request to count the videos
	addToStart(countVideo);

	// Make the count request each 10 minutes (600 seconds)
	setInterval(countVideo,600*1000);

	// Load calendar script
	loadScript('/scripts/video/calendar.js', 'utf-8');

	// Delay befor eplaying the first video automatically if no video is started manually
	var autoPlayDelay = 10;
	
	// Programs to exclude from the search results
	// 150070 = Journal en Continu
	// 169967 = Café des sports webcam
	// 273626 = Mabule promo 
	// 149139 = Passe-moi les jumelles promo
	// 178742 = TTC promo
	// 437722 = Temps Présent promo
	// 140622 = Infrarouge promo
	// 149546 = Vidéo TSR vod
	// 45 = Le journal de la nuit
	var alwaysIgnorePrograms = [150070, 169967, 273626, 149139, 178742, 437722, 140622, 149546, 45];


  /**************************/
 /***   HTML templates   ***/
/**************************/

	// The HTML templates are stored here, because the <> characters are annoying in XML files.

	// Used when the playback of a video fails because no compatible files were found
	var noAvailableFile = '<div class="noFile">'
		+ '<strong>Aucun fichier compatible trouv&eacute;.</strong><br/>'
		+ 'Vous pouvez essayer l\'un des fichiers suivants:$fallback_files'
		+ '</div>';

	// The open program's playlist template
	var templateVideoListProgramWithRollover = '$broadcast_separator<li class="line2">\n'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;" '
		+ 'onmouseover="displayVideoDetail($player.videos[this.name]);">'
		+ '<span class="main">$title <em>$parsed_duration</em>\n'
		+ '</span></a></li>\n';

	// The open program's playlist template
	var playlistTemplateSearchResult = '<li class="line$line">\n'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">'
		+ '<span class="main">$title <em>$parsed_duration</em>\n'
		+ '</span></a></li>\n';

	// The week choice's playlist template
	/*var playlistTemplateWeekChoice = '<li>'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">\n'
		+ '$img'
		+ '<strong>$boxTitle</strong>\n'
		+ '<span>$boxText $parsed_duration</span>\n'
		+ '<em>$xobix_program_name</em>'
		+ '</a></li>\n';*/

	var playlistTemplateWeekChoice = '<li>'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;" class="weekchoice">'
		+ '$img'
		+ '<span class="desc">'
		+ '<em>$boxTitle</em>'
		+ '<span>$title</span>'
		+ '</span>'
		+ '<strong>$xobix_program_name</strong>'
		+ '</a></li>';

	/*var playlistTemplateWeekChoiceSport = '<li>'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">\n'
		+ '$img'
		+ '<span style="font-size:11px;">$title $parsed_duration</span>\n'
		+ '<em>$xobix_program_name, $parsed_broadcast_date</em>'
		+ '</a></li>\n';*/

	var playlistTemplateWeekChoiceSport = '<li>'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;" class="weekchoice">'
		+ '$img'
		+ '<span class="desc">'
		// + '<em>$parsed_broadcast_date</em>'
		+ '<span>$title</span>'
		+ '</span>'
		+ '<strong>$parsed_broadcast_date</strong>'
		+ '</a></li>';

	var splaylistTemplateWeekChoiceSport = '<li>'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">\n'
		+ '$img'
		+ '<span style="font-size:11px;">$title $parsed_duration</span>\n'
		+ '<em>$xobix_program_name, $parsed_broadcast_date</em>'
		+ '</a></li>\n';

	// Journal en continu playlist template
	var playlistTemplateContinu = '<li>'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">\n'
		+ '$img'
		+ '<strong><em>$broadcast_time</em> $title</strong>\n'
		+ '<span> $parsed_duration</span>\n'
		+ '</a></li>\n';

	var searchResultsTemplate = '<li class="line$line">'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;" '
		+ 'onmouseover="displayVideoDetail($player.videos[this.name]);">\n'
		+ '<span class="num">$index.</span>\n'
		+ '<span class="title"><span>$title <em>$parsed_duration</em>\n'
		+ '</span></span><span class="program"><span>$xobix_program_name, $parsed_broadcast_notime_date</span></span></a></li>\n';

	var unused_searchResultsTemplate = '<li class="line$line">'
		+ '<a href="$test_url">$img<strong>$title</strong>'
		+ '<em style="color:#999999;">$subtitle</em></a></li>';

	// The detail of a video
	var playlistTemplateOpenVideo = '<div>\n'
		+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">'
		/* On peut rajouter une condition pour afficher une image ''d'erreur'' si on a pas d'image à afficher */
									/* ICI */
		+ '<div id="videoDetailLeft">$img<span><em>$parsed_duration</em>$parsed_creation_notime_date</span></div>'
		+ '<div id="videoDetailRight"><strong>$title</strong></div></a>\n'
		// + '<a class="send2friend" href="javascript:void(window.open(\'index.html?siteSect=200004&lastUrl=http%3A%2F%2Fwww.tsr.ch%2Ftsr%2Findex.html%3FsiteSect%3D500000%26amp;channel=$channel_anchor_program=$xobix_program_id;vid=$id\',\'send2friend\',\'toolbar=no,location=no,status=no,menubar=no,width=360,height=260\'));">Envoyer à un ami</a>'
		+ '<br style="clear:both;display:block;height:1px;"/>\n';

	// template for the last videos list
	var lastVideosTemplate = '<li class="line$line">\n<a href="#" name="$id" rel="video"'
		+ ' onclick="$player.playVideo(this.name);return false;">$img<span>\n'
		+ '<strong>$xobix_program_name: </strong>$title <em>$parsed_duration</em></span></a></li>\n';

	// REDEFINED FOR ST*P*D MSIE !!1! JAVASCRIPT FIX ADDED !11!! OMG WTF NOES!!!!
	// TODO: make this code only available to MSIE, serve decent code to other browsers
	var lastVideosTemplate = '<li class="line$lastVideoLine">\n<a href="#" name="$id" rel="video"'
		+ ' onclick="$player.playVideo(this.name);return false;">'
		+ '<img src="$preview" alt="" onmouseover="this.nextSibling.style.display=\'block\';" onmouseout="this.nextSibling.style.display=\'none\';"/>'
		+ '<span>'
		+ '<strong>$xobix_program_name: </strong>$title <em>$parsed_duration</em></span></a></li>\n';

	// For the programs list
	var programsListTemplate = '<li class="line$line"><a href="#program=$programVideoSource"'
		+ ' onmouseover="$(\'previewEmission\').src=(\'$pathimg\');"'
		+ ' onclick="loadProgramVideos($programVideoSource); return false;" rel="program"><img src="$pathimg" alt=""/><span> $programName'
		+ '</span></a></li>\n';

	// Title of a video, with some details. Displayed next to the video at the top of the page.
	var titleTemplate = ''
		+ '<a title="envoyer &agrave; un ami" class="send" href="javascript:void(window.open(\'index.html?siteSect=200004&lastUrl=http%3A%2F%2Fwww.tsr.ch%2Ftsr%2Findex.html%3FsiteSect%3D500000%2523channel=$chan2;vid=$id\',\'send2friend\',\'toolbar=no,location=no,status=no,menubar=no,width=360,height=380\'));">Envoyer &agrave; un ami</a>'
		+ '<a id="dvd-shop-1" title="commander le dvd" class="dvd $showBoutiqueLink" href="http://www3.tsr.ch/tsr/index.html?siteSect=300010&date=$wysi_broadcast_date&emission=$xobix_program_id&player=1&norecharge=1" target="_blank">Commander le DVD de cette &eacute;mission</a>'
		+ '<div><strong>$xobix_program_name</strong>'
		+ '<span> - $title</span></div>';

	// Title of a video, with some details. Displayed next to the video at the top of the page.
	var detailTemplate = ''
		+ '<div class="infoblock" id="video-detail-block">'
		+ '  <div class="b2">'
		+ '    <div style="cursor:pointer;" onclick="switchRelated();return false;"><h3><a href="#">Infos pour cette vid&eacute;o</a></h3></div>'
		+ '    <div class="content">'
		+ '      <div class="txt">'
		+ '        <strong>$title</strong>'
		+ '        <em>$parsed_broadcast_date</em>'
		+ '        <span>$overview</span>'
		+ '      </div>'
		+ '      <a class="actlink send" href="javascript:void(window.open(\'index.html?siteSect=200004&lastUrl=http%3A%2F%2Fwww.tsr.ch%2Ftsr%2Findex.html%3FsiteSect%3D500000%2526channel=$channel_anchor_program=$xobix_program_id;vid=$id\',\'send2friend\',\'toolbar=no,location=no,status=no,menubar=no,width=360,height=380\'));">Envoyer &agrave; un ami</a>'
		+ '      <a id="dvd-shop-2" class="actlink dvd $showBoutiqueLink" href="http://www3.tsr.ch/tsr/index.html?siteSect=300010&date=$wysi_broadcast_date&emission=$xobix_program_id&player=1&norecharge=1" target="_blank">Commander le DVD de cette &eacute;mission</a>'
		+ '    </div>'
		+ '  </div>'
		+ '</div>';


  /************************************/
 /***   Initialization functions   ***/
/************************************/

	function initPlayer() {

		// Load params from hash, if available
		if (n = getParam('channel'))         currentChannel   = n;
		if (n = getParamFromHash('channel')) currentChannel   = n;
		if (n = getParam('program'))         initialProgram   = n;
		if (n = getParamFromHash('program')) initialProgram   = n;
		if (n = getParam('vid'))             initialVideo     = n;
		if (n = getParamFromHash('vid'))     initialVideo     = n;
		if (n = getParam('bcid'))            initialBroadcast = n;
		if (n = getParamFromHash('bcid'))    initialBroadcast = n;

		if (initialProgram) {
			if (initialProgram == 15) initialTab = 'info_1930';
			else if (initialProgram == 26) initialTab = 'info_1900';
			else if (initialProgram == 25) initialTab = 'info_1245';
			else initialTab = 'loadprogram';
		}

		if (initialBroadcast) initialTab = 'loadbroadcast';

		if (n = getParamFromHash('tab')) initialTab = n;

		// Create tsrkit object
		mainPlayer = new tsrkit('mainPlayer');
		mainPlayer.videoContainer = 'video-container';
		mainPlayer.videoTarget = 'video_target';
		mainPlayer.videoTitleTarget = 'video-title';
		mainPlayer.videoDetailTarget = 'video-detail';

		// The player can change the title of the page
		mainPlayer.modifyPageTitle = true;

		mainPlayer.videoWidth = 800;
		mainPlayer.videoHeight = 450;

		// Load programs and display first once it's done
		mainPlayer.loadProgramsWithCallback(function(){setChannel(null,1);});

		// Play default video, if a vid is in the URL
		if (initialVideo) loadVideoAndPlay(initialVideo);

	}

	// Initialize application tabs
	// Initialize channel tabs
	function initAppLinks() {

		setActionOnClassElements('app_link', function(el){
			panels.load(getParam('tab', el.href));
		});

		setActionOnClassElements('channel_link', function(el){
			setChannel(getParam('channel', el.href));
		});
	}

	function showNavigation(channel, oldChannel) {

		var speedDown = 7;
		var speedUp = 4;

		var nav = $('subnav-' + oldChannel);
		if (!nav) {
			$('video-page').className = 'channel-'+channel;
			var nav2 = $('subnav-' + channel);
			if (!nav2) return;
			bouffe(nav2, 30, -speedUp)
			return;
		}

		if (channel == oldChannel) {
			$('video-page').className = 'channel-'+channel;
			bouffe(nav, 30, -speedUp);
		}

		else bouffe(nav, 1, speedDown, function(){
			$('video-page').className = 'channel-'+channel;
			var nav2 = $('subnav-' + channel);
			if (!nav2) return;
			bouffe(nav2, 30, -speedUp)
		});
	}

	function bouffe(nav, start, step, callBack) {

		if (!start) start = 1;
		if (!step) step = 4;

		if (start > 30 || start < 1) {
			if (typeof callBack == 'function') callBack();
			return;
		}

		nav.style.marginBottom = '-'+start+'px';
		nav.style.marginTop = start+'px';

		window.setTimeout(function(){
			bouffe(nav, start+step, step, callBack);
		},50);
	}


  /**************************/
 /***   panels gestion   ***/
/**************************/

	var defaultPagePerChannel = {
		'emission': 'weekchoice',
		'info': 'info_continu',
		'sport': 'weekchoice',
		'plus7': 'plus7'
	}

	var panels = {

		basePath:     '/interactif/video_2009_panels/',

		// Used to fight cache
		suffix:       '?d=2009-03-10',

		// All the files of the panels that we can load, in an object

		// channel emission
		programs:     'programs.xml',
		programOpen:  'program_open.xml',
		top50:        {
			'f': 'top50.xml',
			'c': loadTop50
		},
		config:       'config.xml',
		help:         'help.xml',
		lastvideos:   {
			'f':'lastvideos.xml',
			'c':loadLastVideos
		},
		search:       {
			'f':'search.xml',
			'c':populateSearchProgramList
		},
		test:         'test.xml',
		live:         {
			'f': 'continu.xml',
			'c': playLive
		},
		weekchoice:   {
			'f': 'weekchoice.xml',
			'c': loadWeekChoice
		},
		loadprogram:{
			'f':'program_open.xml',
			'c':function() {
				loadProgramVideos(initialProgram);
			}
		},
		loadbroadcast:{
			'f':'program_open.xml',
			'c':function() {
				loadBroadcast(initialBroadcast);
			}
		},

		// channel sport
		s_programs:    'programs_sport.xml',
		s_keyword:     {
			'f': 'sport_keyword.xml',
			'c': searchKeyword
		},

		// Plus7
		plus7:         {
			'f': 'plus7.xml',
			'c': loadPlus7
		},

		// channel info
		/* info_live:    'info_live.xml', */
		info_continu:    {
			'f':'continu.xml',
			'c':function() {
				loadJECvideos();
				activateLiveButton();
			}
		},
		info_1245:    {
			'f': 'program_open.xml',
			'c': function() {
				loadProgramVideos(25);
			}
		},
		info_1900:    {
			'f':'program_open.xml',
			'c':function() {
				loadProgramVideos(26);
			}
		},
		info_1930:    {
			'f':'program_open.xml',
			'c':function() {
				loadProgramVideos(15);
			}
		},
		top10:        {
			'f': 'top50.xml',
			'c': loadTop50
		},
		info_search:  'search.xml',

		// channel election
		election_programs:      'programs_election.xml',
		election_lastvideos:    'lastvideos_event.xml',
		election_classepo:      'program_open.xml',
		election_desperate:     'program_open.xml',
		election_vendredi:      'program_open.xml',
		election_search:        'search.xml',

		// easter egg!
		flickr:   'flickr_test.xml',

		// Load a panel, with really cool effects and a callback function
		// The callback function will be called after the panel is loaded.
		// the "silent" param will prevent the function to write the name of the tab in the hash (since some tabs are aliases to other tabs with callback)
		load: function(panel, callBack, silent) {

			trace('Load panel '+panel);

			// Change a class, so we can highlight the right button with CSS !
			// $('navigation').className = panel;

			if (!this[panel]) return trace('Panel '+panel+' not found.', 'error');

			if (typeof this[panel] == 'object') {

				panel_file = this[panel]['f'];
				if ((c = this[panel]['c']) && !callBack) callBack = c;
			} else panel_file = this[panel];

			// Build the full path
			var panelUrl = this.basePath + panel_file + this.suffix;

			if (!silent) {
				// Put the panel name in URL
				setHashVariable('tab', panel);

				// Remove hash variables that are not relevant
				setHashVariable('program', null);
				setHashVariable('vid', null);
				setHashVariable('live', null);
			}

			if (silent == 'tab' || !silent) {

				// To highlight current tab, set a class on current tab, remove from the other
				var appLinks = getElementsByClass('app_link');
				for (var i = 0; i < appLinks.length; i++) appLinks[i].className = 'app_link ' + ((getParam('tab', appLinks[i].href)) == panel ? 'cur' : '');
			}

			// Loading the new panel, executed after the current one is hidden
			new tsrkit_ahahLoad(panelUrl, 'video-browser-content', function() {
				if (typeof callBack == 'function') callBack(panel);
			});
		}
	}


  /********************************/
 /***   Video page functions   ***/
/********************************/

	// Set channel
	function setChannel(channel, silent) {

		var oldChannel = currentChannel;

		if (!channel) channel = currentChannel;
		else currentChannel = channel;

		showNavigation(channel, oldChannel);

		if (!silent) {
			setHashVariable();
			setHashVariable('channel', channel);
		}

		// Load channel jingle
		loadJingle(channel);

		// Load the default panel automatically
		panels.load(initialTab || defaultPagePerChannel[channel], null, 'tab');
		initialTab = null;
	}

	function switchRelated(){
		switchClass('video-detail-block', 'closed');
		switchClass('related-videos-block', 'closed');
	}

	// Create an argument for Solr with the list of programs to load
	function createSolrAllProgramsArgument(exclude) {

		var requestPrograms = '';

		for (var i in mainPlayer.programs) {

			if (!exclude && mainPlayer.programs[i].channel != currentChannel) continue;
			if (exclude  && mainPlayer.programs[i].channel == currentChannel) continue;

			requestPrograms += (requestPrograms ? ' ' : '') + i;
		}

		// Always exclude some programs (fix ioan 09.10.2009)
		if (exclude) for (var i in alwaysIgnorePrograms) requestPrograms += (requestPrograms ? ' ' : '') + alwaysIgnorePrograms[i];

		// When is sport channel, also search in all the items tagged "sport"
		if (currentChannel == 'sport') requestPrograms = 'tag:sport OR (' + requestPrograms + ')';

		return '(' + requestPrograms + ')';
	}

	function showProgramsList(channel) {

		if (!channel) channel = 'emission';

		mainPlayer.loadProgramsWithCallback(function() {

			// First, count how many programs are in this channel
			// Start at 3, because the logo at the top takes 3 rows
			var progCounter = 3;

			for (var i in mainPlayer.programs) {
				var program = mainPlayer.programs[i];
				if (program.channel != channel) continue;
				progCounter++;
			}

			var columnHeight = Math.ceil(progCounter/3);
			trace('There are '+(progCounter-3)+' '+channel+' programs, column height is '+columnHeight);

			// Start to create code, the first item contains an image
			var totalCode = '<ul class="programList">';
			totalCode += '<li><img style="margin-bottom:4px;height:60px;width:300px;" id="previewEmission" '
				+ 'src="/images/interactif/video_2009/banner_toute_emission.gif"></li>';

			// Create the HTML code for the list of programs
			var progCounter = 3;
			for (var i in mainPlayer.programs) {

				// The current program
				var program = mainPlayer.programs[i];
				if (program.channel != channel) continue;

				// Cut each 13 items
				if (progCounter && progCounter % columnHeight == 0) totalCode += '</ul><ul class="programList">';

				// Prepare data for the template parsing
				var programData = {
					'line':Math.floor(progCounter) % 2 + 1,
					'programVideoSource':program.programVideoSource,
					'programName':program.programName,
					'pathimg':program.programIcon,
					'index':progCounter
				};

				currentItem = parseTemplate(programsListTemplate, programData, progCounter);

				// Add to the whole code
				totalCode += currentItem;

				progCounter++;
			}

			totalCode += '</ul>';
			$('programLists').innerHTML = totalCode;
		});
	}

	function loadProgramVideos(programVideoId) {

		panels.load('programOpen', function() {

			// If this is an info page, well, display a calendar, and let it load the videos!
			if (currentChannel == 'info') createCalendar(programVideoId, true);
			else {
				loadProgramPlaylist(programVideoId);
				setHashVariable('tab', 'loadprogram');
			}
			setHashVariable('program', programVideoId);
		}, true);
	}

	function loadBroadcast(broadcastId) {
		panels.load('programOpen', function() {
			loadProgramPlaylist(broadcastId, 'xobix_broadcast_id');
		}, true);
	}

	// Standard search
	// Displays the first result's details
	// searchId can be either a string, associated with the field param, or an object containing several fields
	function loadProgramPlaylist(searchId, field) {

		if (typeof searchId == 'object') {
			var param = searchId;

			// when the search is not on the whole program, display the "back to program" link
			if (searchId.title){
				$('backToProgram').style.display = 'none';
				$('searchInProgramInput').value = searchId.title;
			}
			else $('backToProgram').style.display = 'block';

		} else {

			// by default: search by xobix_program_id
			if (!field) field = 'xobix_program_id';

			// when the search is not on the whole program, display the "back to program" link
			if (field == 'xobix_program_id') $('backToProgram').style.display = 'none';
			else $('backToProgram').style.display = 'block';

			// Build the request for Solr
			var param = {};
			param[field] = searchId;

			//K_UPDATE, 14.02.2008 load only current video in the program list if video come from video TSR other
			/*if (searchId == 74) {
				param['xobix_video_id'] = mainPlayer.currentVideoID;
				trace("special program("+searchId+"), list only currentVideo => " + mainPlayer.currentVideoID, 'info');
			}*/
		}

		// Ignore the broadcasts in the future if there's no other field than xobix_program_id
		// if (field == 'xobix_program_id') param['broadcast_date:' + createSolrDateRangePast()] = null;

		var count = (field == 'xobix_program_id') ? 20 : 50;

		var newRequest = mainPlayer.searchOnSolr(param, 'broadcast_date desc, xobix_broadcast_position asc', count);

		newRequest.rTarget = 'programPlayList';
		newRequest.rPaginationTarget = 'programPaging';
		newRequest.rTemplate = templateVideoListProgramWithRollover;

		// display the detail of the first video
		newRequest.rCallback = function(){

			var v = mainPlayer.videos[newRequest.firstVideoId];

			var progId = (field == 'xobix_program_id' ? searchId : '')

			if (v) {

				// Display the detail of the first video
				displayVideoDetail(v);

				// Save the current program ID
				currentProgramId = v.xobix_program_id;

				// Play first video if there's no video playing yet
				if (mainPlayer.currentVideoID < 2) mainPlayer.playVideo(newRequest.firstVideoId);

				progId = v.xobix_program_id;

			} else trace('The request did not return any video ?', 'warning');

			// in order to display the program info even if there's no result, the xobix_program_id is required
			// use the original search field if we can't find the first result
			var progData = mainPlayer.programs[progId];

			if (progData) {

				var programDetail = $('programDetail');
				programDetail.innerHTML = '<span>' + progData.programUrl + '</span>';
				programDetail.style.backgroundImage = 'url(' + progData.programIcon + ')';
				programDetail.href = progData.programUrl;

				$('backToProgram').innerHTML = 'Voir toutes les vid&eacute;os de ' + progData.programName;
				$('backToProgram').href = '#program=' + progData.programVideoSource;

				// Add the program name in the "searchInProgram" label
				$('searchInProgramLabel').innerHTML = progData.programName;

			} else trace('Error: no data loaded for this program', 'error');

		};

		newRequest.launch();
	}

	// Inject HTML code containing the details in the #videoDetail HTML element
	displayVideoDetail = function(vData) {
		var codeHTML = parseTemplate(playlistTemplateOpenVideo, vData);
		if (v = $('videoDetail')) {
			v.innerHTML = codeHTML;
			v.style.display = 'block';
		}
	}

	function countVideo() {

		mainPlayer.loadProgramsWithCallback(function() {

			var newRequest = mainPlayer.searchOnSolr({'role':'video'}, null, 1);

			// Callback function will use the number of results
			newRequest.rCallback = function() {
				var n = mainPlayer.requests[newRequest.id].numFound;
				$('video-count').firstChild.innerHTML = n;
				trace('On a compt&eacute; les vid&eacute;os, il y en a '+n,'info');
			};

			// Launch request and set back the old results count
			newRequest.launch();
		});
	}

	// Load a video from Solr and play it, and load the programs from the video
	function loadVideoAndPlay(vid) {

		var newRequest = mainPlayer.searchOnSolr({'role':'video','xobix_video_id':vid});
		newRequest.rCallback = function() {
		    trace('## play video ## ', 'error');
			mainPlayer.playVideo(vid);
		};
		newRequest.rTarget = '';
		newRequest.launch();
	}

	// Create a video and load the media of the default jingle.
	function loadJingle(channel) {

		var channelJingles = {
			'emission':'anim_emission.swf',
			'info':'anim_info.swf',
			'sport':'anim_sport.swf',
			'plus7':'anim_plus7.swf',
			'hq':'anim_hq.swf'
		}

		var channelTitles = {
			'emission':'Plus de 10\'000 &eacute;missions disponibles',
			'info':'Toute l\'info en vid&eacute;o',
			'sport':'Tout le sport en vid&eacute;o',
			'plus7':'TSR +7',
			'hq':'Regarder vos vid&eacute;o en Haute Qualit&eacute;'
		}

		// Sometimes, show the HQ jingle instead
		channel = maybe(4) ? 'hq' : channel;

		if (!channelJingles[channel]) return;

		// Create a video in the parent player, and save all the properties
		var newVideo = mainPlayer.addvideo(1);
		newVideo.xobix_program_name = 'tsrvideo.ch';
		newVideo.title = channelTitles[channel];
		newVideo.parsed_broadcast_date = '';
		newVideo.isMeta = 1;

		// Adding the media
		var newMedium = newVideo.addMedium();
		newMedium.bitrate = '99';
		newMedium.codec = 'swf';
		newMedium.url = '/flash/jingle_page_video/' + channelJingles[channel];
		newMedium.mWidth = '800';
		newMedium.mHeight = '450';

		if (mainPlayer.currentVideoID < 3) mainPlayer.playVideo(1);
	}

	function loadWeekChoice() {

		var p = currentChannel == 'sport' ? 'index.html?siteSect=500208' : 'index.html?siteSect=500203';
		var d = new Date();
		p += '&amp;h=' + d.getDay()+d.getHours();
		var newRequest = mainPlayer.loadFromXML(p);
		newRequest.rTarget = 'weekChoiceList';
		newRequest.rTemplate = currentChannel == 'sport' ? playlistTemplateWeekChoiceSport : playlistTemplateWeekChoice;

		newRequest.rCallback = function(){

			// Play first result after a few seconds if no other video is played
			window.clearTimeout(autoPlay);
			autoPlay = window.setTimeout(function(){
				if (mainPlayer.currentVideoID < 3) mainPlayer.playVideo(newRequest.firstVideoId);
			}, autoPlayDelay * 1000);
		};

		newRequest.launch();
	}

	function loadLastVideos() {

		mainPlayer.loadProgramsWithCallback(function() {

			var p = {};
			p.xobix_program_id = createSolrAllProgramsArgument();
			p.preview_image_url = 'h*';

			// Create request
			var newRequest = mainPlayer.searchOnSolr(p, 'broadcast_date desc', 60);
			newRequest.rTarget = 'lastVideosList';
			newRequest.rTemplate = lastVideosTemplate;

			newRequest.launch();
		});
	}

	function playLive() {

		// Empty the related videos
		$('related-videos').innerHTML = '';

		// Create a video in the parent player, and save all the properties
		var newVideo = mainPlayer.addvideo('live');

		newVideo.title = 'Les infos en direct';
		newVideo.xobix_program_id = '';
		newVideo.xobix_program_name = 'tsrvideo.ch';
		newVideo.xobix_video_id = 'live';
		newVideo.parsed_broadcast_date = '';

		// Add the live media (with fake informations, just to make it appear valid and fool tsrkit functions)
		var newMedium = newVideo.addMedium();
		newMedium.bitrate = '800000';
		newMedium.codec = 'flash';
		newMedium.url = 'CHTSR_4_2@3444';

		mainPlayer.playVideo('live');
		setHashVariable('vid', 'live')
	}


	function activateLiveButton() {

		var tb = $('tsrinfoBouton');

		// Gestion du lien sur la banière -> si le param 'live' est setté, on lance l'info en direct
		if (getParamFromHash('vid')=='live') playLive();

		addEvent($('infoContinuBannerBloc'), 'click', function(e){
			if (e.preventDefault) e.preventDefault(); else e.returnValue = false; // Kill event
			playLive();
		});

		// Would be cleaner to do this stuff in CSS, but well...
		tb.onmouseout = function () {tb.src="/images/video/banner_info2009/bouton_off.gif";}
		tb.onmousedown = function () {tb.src="/images/video/banner_info2009/bouton_active.gif";}
		tb.onmouseup = function () {tb.src="/images/video/banner_info2009/bouton_off.gif";}

		// Different image for IE and Safari
		var tb_over = '/images/video/banner_info2009/' + ((IE || safari) ? 'bouton_hover.gif' : 'bouton_hover_anim4.gif');
		tb.onmouseover = function () {tb.src = tb_over;}
	}

  /**************************/
 /***   Related Videos   ***/
/**************************/


	related_videos = [];

	// Loads two related videos in the same broadcast: the one after and the one before.
	function loadRelatedVideos(o_video) {

		// TODO: TRY TO GET RELATED WITH SOLR:
		// http://admin.search2.tsr.ch/solr/select?wt=xslt&tr=more-like-this-test.xsl&debugQuery=1&q=xobix_video_id%3A10353614&mlt=true&fl=solr_id%2Ctitle%2Csubtitle%2Cabstract%2Cbody%2Curl%2Crole%2Cpreview_image_url%2Cpreview_image_caption&mlt.fl=title&mlt.msd=10&mlt.mintf=1&mlt.mindf=2&mlt.minwl=4&mlt.maxwl=25&mlt.maxqt=2&mlt.maxntp=25

		var broadcast_id = o_video.xobix_broadcast_id;
		var program_id = o_video.xobix_program_id;
		var video_id = o_video.xobix_video_id;

		if (!o_video.xobix_broadcast_id || !o_video.xobix_program_id) return;

		// Show the related directly open, only if there is no abstract
		var showOpen = o_video.abstract ? 0 : 1;

		if (showOpen) switchClass('video-detail-block', 'closed');

		// Create new request
		var newRequest = mainPlayer.searchOnSolr({'xobix_broadcast_id': o_video.xobix_broadcast_id}, 'broadcast_date desc, xobix_broadcast_position asc');
		newRequest.rCallback = function(r){

			var videos = r.videoResults;
			related_videos = [];

			/*
			// Get the 3 first videos
			for (var i in videos) {
				if (videos[i].xobix_video_id != video_id && videos[i].preview_image_url) related_videos.push(videos[i]);
			}
			*/

			var catchNext = 0;
			var catchPrevious = 0;
			var firstPlaying = 0;
			var lastVideo = null;

			$('related-videos').innerHTML = '';

			// Loop to get the two videos around the current one
			for (var i in videos) {

				var video = videos[i];
				if (typeof video == 'function') continue;

				// Catch the video before the current
				if (video.xobix_video_id == video_id) {
					catchNext = 1;
					if (lastVideo) related_videos.push(lastVideo);
					if(i==0) firstPlaying = 1;
				}

				// If near the last three, get them to make sure we have at least two.
				if (i > videos.length-4 && related_videos.length < 3) catchNext = 1;

				// wat
				if (video.xobix_video_id == video_id && i==0) catchNext = 1;

				if (i==2 && firstPlaying) catchNext = 1;

				// if it's the first one, catch the next one
				if (video.xobix_video_id != video_id) {
					if (catchNext) {
						if (related_videos.length < 25)
                            related_videos.push(video);
						else
                            catchNext = 0;
					} else lastVideo = video;
				}
			}

			if (related_videos.length > 1)
                showRelatedVideos(related_videos, showOpen);
			else {

				// Create new request
				var newRequest2 = mainPlayer.searchOnSolr({'xobix_program_id': o_video.xobix_program_id}, 'broadcast_date desc, xobix_broadcast_position asc');
				newRequest2.rCallback = function(r){
					var videos = r.videoResults;
					related_videos = [];

					// Loop to get the two videos around the current one
					for (var i in videos) {
						if (videos[i].xobix_video_id != video_id && videos[i].preview_image_url)
                            related_videos.push(videos[i]);
					}
					if (related_videos.length > 1) showRelatedVideos(related_videos, showOpen);
				};
				newRequest2.launch();
			}
		};
		newRequest.launch();
	}

	function showRelatedVideos(rv, showOpen) {
        // set the global variable now
	    related_videos = rv;

		// Build video links
		var v_links = '';
		for (var i in related_videos) {
			if (i > 2) break;
			var v = related_videos[i];
			if (typeof v == 'function') continue;
			v.duration = v.media_duration_hms;

			// Classe spéciale si il n'y a pas d'image
			v_links += parseTemplate(
				'<a href="#vid=$xobix_video_id" rel="video" name="$xobix_video_id" class="rv'+(v.preview ? '' : ' noImg')+'" '
				+'onclick="return mainPlayer.playVideo(this.name);">'
				+'<span class="title">$title $parsed_duration</span>'
				+(v.preview ? '<img src="$preview" alt=""/>' : '')+'</a>', v);
		}

		var block_content = '<div class="infoblock' + (showOpen ? '' : ' closed') + '" id="related-videos-block"><div class="b2">'
			+ '<div style="cursor:pointer;" onclick="switchRelated();return false;"><h3><a href="#">Vid&eacute;os relatives</a></h3></div>'
			+ '<div class="content">'
			+ v_links
			+ '</div></div></div>';
		$('related-videos').innerHTML = block_content;

		$('related-videos').style.display = 'block';
	}

	// The flash will call this to receive the related videos.
	function get_related_videos() {
		return related_videos;
	}

	// Populate the programs dropdown list in the search panel
	function populateSearchProgramList() {

		mainPlayer.loadProgramsWithCallback(function() {

			var elmSelect = $('search_program');
			if (!elmSelect) return;
			for (var cp in mainPlayer.programs) {
				var p = mainPlayer.programs[cp];
				if (p.channel != currentChannel) continue;
				var opt = document.createElement('option');
				opt.value = cp;
				opt.innerHTML = p.programName;
				elmSelect.appendChild(opt);
			}
		});
	}


  /******************************/
 /***   Journal en Continu   ***/
/******************************/

	function loadJECvideos() {

		var n = new Date();
		var feedJEC = 'index.html?siteSect=500201&time=' + n.getDate() + n.getHours() + n.getMinutes();
		//feedJEC contient les videos à afficher
		newRequest = mainPlayer.loadFromXML(feedJEC);
		newRequest.rTarget = 'infoContinuList';
		newRequest.rTemplate = playlistTemplateContinu;

		newRequest.rCallback = function() {
			// Play first result after a few seconds if no other video is played
			window.clearTimeout(autoPlay);
			autoPlay = window.setTimeout(function(){
				if (mainPlayer.currentVideoID < 3) mainPlayer.playVideo(newRequest.firstVideoId);
			}, autoPlayDelay * 1000);
		};
		newRequest.launch();
	}

	function searchInProgram(searchString, programId, dateRange) {

		// Create arguments for the search
		var p = {'xobix_program_id': programId || currentProgramId}

		// Ignore the broadcasts in the future
		var dr = dateRange;// || createSolrDateRangePast();
		if (dr) p['broadcast_date:' + dr] = null;

		// display the "see all videos" button if needed
		if (searchString){
			p.title = searchString;
			$('backToProgram').style.display = 'block';
		}
		else $('backToProgram').style.display = 'none';

		// If no searchString, empty the search field
		$('searchInProgramInput').value = searchString || '';

		// If a daterange is specified, display all results on one page
		var rc = dateRange ? 100 : null;

		// Create new request
		var newRequest = mainPlayer.searchOnSolr(p, 'broadcast_date desc', rc);
		newRequest.rTarget = 'programPlayList';
		newRequest.rPaginationTarget = 'programPaging';
		newRequest.rTemplate = templateVideoListProgramWithRollover;
		newRequest.launch();
	}

  /****************************/
 /***   Search functions   ***/
/****************************/

	function searchSomething() {

		// Get variables from form and build requests
		var searchParams = {'role':'video'};

		var searchContent = $('search_content').value;
		if (searchContent) searchParams.title = searchContent;

		// if no program is specified, search in all the approved programs
		if (n = $('search_program').value) searchParams.xobix_program_id = n;
		else {

			// For emission, exclude all the other info / sport programs (to access teh archives and shit)
			if (currentChannel == 'emission') searchParams['NOT xobix_program_id'] = createSolrAllProgramsArgument(1);
			else searchParams.xobix_program_id = createSolrAllProgramsArgument();
		}

		// Get the date argument
		var dr = createSolrDateRange();// || createSolrDateRangePast();
		if (dr) searchParams['broadcast_date:' + dr] = null;
		
		searchParams['NOT xobix_source_id'] = 'archives';

		// Create request
		var newRequest = mainPlayer.searchOnSolr(searchParams, 'broadcast_date desc');
		newRequest.rTarget = 'searchResults';
		newRequest.rPaginationTarget = 'searchResultsPaging';
		newRequest.rTemplate = searchResultsTemplate;

		// On callback, display the detail of the first video and the number of results
		newRequest.rCallback = function(){

			displayVideoDetail(mainPlayer.videos[newRequest.firstVideoId]);

			var s = (newRequest.numFound - 1 > 0) ? 's' : '';
			$('searchResultsTitle').innerHTML = newRequest.numFound + ' vid&#233;o' + s + ' trouv&#233;e' + s;
		}

		newRequest.launch();

		$('searchResultsTitle').innerHTML = '';
	}

	// Creates a Solr date range from the 3 fields in the form.
	// If at least year isn't specified, won't return anything.
	// exemple: broadcast_date:["2006-01-01T00:00:00Z" TO "2006-12-31T23:59:59Z"]
	function createSolrDateRange() {

		var templateDateSolr = '["$year-$month_start-$day_startT00:00:00Z" TO "$year-$month_end-$day_endT23:59:59Z"]';

		// Create an object that will contain all the properties, for the template parsing later.
		var dateData = {};
		dateData.year = $('search_year').value;
		dateData.f_month = $('search_month').value;
		dateData.f_day = $('search_day').value;

		// if no year specified, finish here.
		if (!dateData.year) return;

		// Pad values with 0 if there's only one character
		if (dateData.f_month.length == 1) dateData.f_month = '0' + dateData.f_month;
		if (dateData.f_day.length == 1) dateData.f_day = '0' + dateData.f_day;

		if (dateData.f_month) {
			dateData.month_start = dateData.f_month;
			dateData.month_end = dateData.f_month;
		} else {
			dateData.month_start = '01';
			dateData.month_end = '12';
		}

		if (dateData.f_day) {
			dateData.day_start = dateData.f_day;
			dateData.day_end = dateData.f_day;
		} else {
			dateData.day_start = '01';
			dateData.day_end = '31';
		}

		return parseTemplate(templateDateSolr, dateData);
	}

	// if there's a search in the url, do it !
	/*var hash = window.location.hash.substring(1,window.location.hash.length);
	var loadParams = getParam(null,hash,';');
	if (loadParams.search) {
		$('search_content').value = loadParams.search;
		searchSomething();
	}*/

  /**********************************/
 /***   Program loading module   ***/
/**********************************/

	tsrkit.prototype.loadPrograms = function() {
		var programs = new tsrkit_programs();
		programs.linkToParent(this);
		return programs;
	}

	// Load the programs and then execute the callback function
	// If programs are already loaded, execute callback directly
	tsrkit.prototype.loadProgramsWithCallback = function(f) {
		if ((typeof this.programs) == 'undefined') {
			var programs = this.loadPrograms();
			programs.rCallback = f;
			programs.launch();
		} else f();
	}

	// Ioan Sameli, 21.09.2006
	// Create the program list from the XML file, using Ajax
	tsrkit_programs = function() {

		// This class will use ajax methods
		this.inheritFrom = tsrkit_ajaxRequest;
		this.inheritFrom();

		// The source will always be the program XML documents
		this.rSource = '/xml/description_emission.xml?d=06-05-2008-12-10';

		this.handleResult = function(answer) {
		// Ioan Sameli, 10.05.2006
		// Use the XML program list we got by Ajax to create the program list

			// Use the XML DOM to unpack the data
			var xml = answer.request.responseXML;
			if (!xml)trace('populate Program List: the answer is not valid', 'error');
			var programs = xml.getElementsByTagName('emission');

			// Create the programs in the parent if it doesn't exist yet
			if (typeof(answer.parent.programs) == 'undefined') answer.parent.programs = {};

			// Start at 3, because the logo at the top needs space
			var progCounter = 0;

			// Create the HTML code for the list of programs
			for (var progIndex = 0; progIndex < programs.length; progIndex++) {

				// The current program
				var pXML = programs.item(progIndex);

				// Ignore the programs that are incomplete
				if (!pXML.getElementsByTagName('canalWeb').length) continue;
				if (!pXML.getElementsByTagName('source').length) continue;
				if (!pXML.getElementsByTagName('photo300').length) continue;

				// Some programs are hidden
				if (pXML.getElementsByTagName('hideFromVideoPage').length) continue;

				// Then, if the parent has a channel set, check if it's the right channel
				var channel = pXML.getElementsByTagName('canalWeb').item(0).attributes.getNamedItem('value').value;
				if (answer.parent.channel && (channel.indexOf(answer.parent.channel) < 0)) continue;

				// Get the program code
				var programVideoSource = '';
				var programStorySource = '';

				// Source ID's
				var atts = pXML.getElementsByTagName('source').item(0).attributes;
				if (atts.getNamedItem('video')) programVideoSource = atts.getNamedItem('video').value;
				if (atts.getNamedItem('story')) programStorySource = atts.getNamedItem('story').value;

				// Boutique link
				var boutiqueLink = null;
				var promo = pXML.getElementsByTagName('promo-dvd');
				if (promo.item(0))
                    if (promo.item(0).attributes.getNamedItem('accrochePlayer'))
                        boutiqueLink = promo.item(0).attributes.getNamedItem('accrochePlayer').value;

                if (typeof boutiqueLink == 'string' && boutiqueLink.toLowerCase() == 'false')
                    boutiqueLink = null;

				// Ignore if the source is not set
				if (!programVideoSource) continue;

				// Add the current program to the parent player
				var cProg = answer.parent.programs[programVideoSource] = {};
				cProg.programName = getXmlElement(pXML, 'nom');
				cProg.programStorySource = programStorySource;
				cProg.programUrl = getXmlElement(pXML, 'url');
				cProg.programIcon = getXmlElement(pXML, 'photo300');
				cProg.boutiqueLink = boutiqueLink;
				cProg.channel = channel;
				cProg.programVideoSource = programVideoSource;

				progCounter++;
			}
			trace(progCounter + ' programs have been added');
		}
	}



  /***************************/
 /***   CALENDAR THINGS   ***/
/***************************/

	// Create a calendar
	function createCalendar(progId, displayFirstDayVideos) {

		if (! $('calendar')) return;
		else $('calendar').className = 'active';

		facetCal = new tsrCalendar;
		facetCal.cTarget = 'calendar';
		facetCal.progId = progId
		facetCal.dateClick = function(d) {
			loadVideosForDay(d);
			return false;
		}

		// Highlight some cells with different values
		facetCal.onRender = function(kill) {

			if (kill) return;

			// Display the videos if needed
			if (displayFirstDayVideos) {
				loadLastBroadcast(progId);
				displayFirstDayVideos = false;
			}
			mainPlayer.loadDateFacet(progId);
			this.removeHighlight();
		}
		facetCal.render();
	}

	function loadVideosForDay(dt) {

		// First, pad with 0
		dt.day = strpad(dt.day, 2, 0);
		dt.month = strpad(dt.month, 2, 0);

		// Create dateRange
		var templateDateSolr = '["$year-$month-$dayT00:00:00Z" TO "$year-$month-$dayT23:59:59Z"]';
		var dr = parseTemplate(templateDateSolr, dt);

		// Display all the results for that day.
		var param = {}
		param.broadcast_date = dr;
		if (facetCal.progId) param.xobix_program_id = facetCal.progId;

		var newRequest = mainPlayer.searchOnSolr(param, 'broadcast_date desc, xobix_broadcast_position asc', 50);

		newRequest.rTarget = 'programPlayList';
		newRequest.rPaginationTarget = 'programPaging';
		newRequest.rTemplate = templateVideoListProgramWithRollover;

		newRequest.launch();
	}

	tsrkit.prototype.loadDateFacet = function(programId) {

		// Create a new empty request object
		var newRequest = this.getNewSearch();

		var tmpDateM = facetCal.cYear + '-' + strpad(facetCal.cMonth,2,0);

		newRequest.rSource = 'http://search2.tsr.ch/solr/select?q=role:video%20AND%20xobix_program_id:'+programId+'%20AND%20broadcast_date:%5B%22'+tmpDateM+'-01T00:00:00Z%22%20TO%20%22'+tmpDateM+'-31T23:59:59Z%22%5D'
			+'&rows=0&facet=true&facet.field=broadcast_date&wt=json&json.wrf=' + newRequest.setJSONCallbackFunctionName();

		// The function that will finally handle the results
		newRequest.handleResult = handleSolrDateFacetResult;

		newRequest.launch();
	}

	var handleSolrDateFacetResult = function(result) {

		// First, cancel the timeout warning, this is the answer !
		this.handleRequestTimeout = function(){};

		// Get two "parallel" objects, one with the ids, one with the names
		var dateFacets = result.facet_counts.facet_fields.broadcast_date;

		// Get the max value of the facets, to draw pretty colors on the calendar
		var maxFacetCount = 0;
		for (var i in dateFacets) if (dateFacets[i] > maxFacetCount) maxFacetCount = dateFacets[i];

		for (var i in dateFacets) {

			var k = dateFacets[i];

			if (k) {

				// Get date of this facet
				var d = parseDateSolrToHuman(i, 'dateobj');

				// Create a factor between 1 an 9 according to the count of items for this date
				var highlight = Math.round(9 * (k / maxFacetCount));

				// Highlight the day, and set the title !
				var d = d.getDate() + '-' + (d.getMonth() + 1) + '-' + d.getFullYear();
				facetCal.highLightDay(d, 'tj-' + highlight);

				facetCal.setDayTitle(d, k + ' videos');
			}
		}

		// Finally, render the calendar.
		facetCal.render(1);
	}

	// Pad the "str" string until "pLength" with the "padder" character
	// for example: strpad ('ab', 5, 'c') => 'cccab'
	function strpad (str, pLength, padder) {
		str = String(str);
		while (str.length < pLength) {str = padder + str;}
		return str;
	}

	// This function get the last broadcast for a given program, and displays it.
	function loadLastBroadcast(programId) {

		// Create a new empty request object
		var newRequest = mainPlayer.getNewSearch();

		// Create the URL
		newRequest.rSource = 'http://search2.tsr.ch/solr/select?q=role:video%20AND%20xobix_program_id:'+programId
			+';broadcast_date%20desc&rows=1&wt=json&json.wrf=' + newRequest.setJSONCallbackFunctionName();

		// The function that will finally handle the results
		newRequest.handleResult = function(r) {loadProgramPlaylist(r.response.docs[0].xobix_broadcast_id, 'xobix_broadcast_id')};

		newRequest.launch();
	}



  /******************/
 /***   TOP 50   ***/
/******************/

	function loadTop50() {
	    trace('loadTop50:'+currentChannel);
		// Load the cached XML data from wysistat
		var r = new tsrkit_ajaxRequest;
		// r.rSource = 'index.html?siteSect=500204&isSnippet=true&channel='+currentChannel;
		r.rSource = '/xml/extern/chat/topvideo/'+currentChannel+'.xml';
		r.rTarget = 'top50List';
		r.handleResult = handleTop50;
		r.launch();
	}


	// Handle the xml result with the top50, and merge it with a request from Solr
	var handleTop50 = function(answer){

		var xml = answer.request.responseXML;

		if (!xml)trace('Wysistat top50: the answer is not valid', 'error');

		var videos = xml.getElementsByTagName('video');

		// Loop trough all the videos to build the request that will load all the videos from Solr

		// Global variable here... Not the cleanest way, but i can't give argument to a callback later.
		requestVideos = '';

		var allVids = [];

		// for (var i in videos) {
		for (var i = 0; i < videos.length; i++) {

			var currentVideo = videos[i];

			// dirty HACK: filter the items with "le journal" in them
			if (currentVideo.firstChild.data.indexOf('le journal') > 0) continue;

			// Somehow i got some numbers sometimes instead of objects... (prototype library ?)
			if (!currentVideo.attributes) continue;

			var rank = currentVideo.attributes[0].value;
			var bcidAndVid = currentVideo.attributes[1].value;
			var hits = currentVideo.attributes[2].value;

			// Get the vid without bcid
			var vid = bcidAndVid.split('-').pop();

			// To skip the videos that are twice in the file
			if(allVids[vid]) continue;
			else allVids[vid] = 1;

			requestVideos += (requestVideos ? ' ' : '') + vid + '^' + hits;
		}

		// This is the final argument to get all the videos.
		requestVideos = '(' + requestVideos + ')';

		// Call the loadLast function, but load the programs first if needed.
		mainPlayer.loadProgramsWithCallback(mergeTop50WithSolr);
	}

	// Launch a request on Solr to get all the videos from the top50 that are part of a program displayed in this application
	function mergeTop50WithSolr() {

		// Create the argument to get the programs
		//var requestPrograms = createSolrAllProgramsArgument();

		// Create the JSON request
		var p = {};
		//p.xobix_program_id = requestPrograms;
		p.xobix_video_id = requestVideos;

		// This is top50, so load only 50 results ! Or 10 for info and sport.
		var maxResultCount = (currentChannel == 'emission' ? 50 : 10);

		// Create request
		var newRequest = mainPlayer.searchOnSolr(p, null, maxResultCount);
		newRequest.rTarget = 'top50List';
		newRequest.rTemplate = searchResultsTemplate;

		// display the detail of the first video
		newRequest.rCallback = function(){
			var v = mainPlayer.videos[newRequest.firstVideoId];
			displayVideoDetail(v);

			// Set the number of result found
			if (n = $('top50Count')) n .innerHTML = newRequest.numLoaded;

		}

		// Launch request and set back the old results count
		newRequest.launch();
	}


  /**************************/
 /***   SPORT KEYWORDS   ***/
/**************************/

	function loadSportKeywordPanel(kw) {
		setHashVariable('kw', kw);
		panels.load('s_keyword', function() {searchKeyword(kw);});
	}

	function searchKeyword(kw) {

		if (kw == 's_keyword' || !kw) kw = getParam('kw',window.location.hash.substring(1,window.location.hash.length),';');

		$('kwTitle').innerHTML = kw;

		// Get variables from form and build requests
		var searchParams = {
			'title':kw,
			'xobix_program_id': createSolrAllProgramsArgument(),
			'role':'video'
		};

		// Create date argument
		// searchParams['broadcast_date:' + createSolrDateRangePast()] = null;

		// Create request
		var newRequest = mainPlayer.searchOnSolr(searchParams, 'broadcast_date desc');
		newRequest.rTarget = 'searchResults';
		newRequest.rPaginationTarget = 'searchResultsPaging';
		newRequest.rTemplate = searchResultsTemplate;

		// On callback, display the detail of the first video and the number of results
		newRequest.rCallback = function(){
			var v = mainPlayer.videos[newRequest.firstVideoId];
			displayVideoDetail(v);

			var s = (newRequest.numFound - 1 > 0) ? 's' : '';
			$('searchResultsTitle').innerHTML = newRequest.numFound + ' vid&#233;o' + s + ' trouv&#233;e' + s;
		}
		newRequest.launch();
		$('searchResultsTitle').innerHTML = '';
	}

  /******************/
 /***   TSR +7   ***/
/******************/

	function loadPlus7() {

		var n = new Date();

		// Remove 7 days
		n.setTime(n.getTime() - (7*24*3600*1000));

		// Build the solr timestamp
		var m = (n.getMonth()+1)+'';
		m = m.length > 1 ? m : '0' + m;
		var d = n.getDate()+'';
		d = d.length > 1 ? d : '0' + d;

		var t = n.getFullYear()+'-' + m +'-' + d + 'T00:00:00Z';

		// Search parameters: take  broadcasts tagged +7, from the last 7 days
		var p = {category:'TSRplusSept'};
		p['broadcast_date:["' + t + '" TO *]'] = null;

		var newRequest = mainPlayer.searchOnSolr(p , 'broadcast_date desc', 100);

		newRequest.rTarget = 'plus7List';
		newRequest.rTemplate = '<li>'
			+ '<a href="#" name="$id" rel="video" onclick="$player.playVideo(this.name);return false;">'
			+ '$img'
			+ '<span>$parsed_broadcast_notime_date</span>'
			+ '<strong>$xobix_program_name</strong>'
			+ '<em>$title</em>'
			+ '</a></li>';

		// Initialize the scrollbar with a delay (apparently the HTML code takes some time to build, or whatever)
		// newRequest.rCallback = window.setTimeout(initscrollZone, 300);
		// originalScrollWidth = $('scrollZone').scrollWidth;

		newRequest.rCallback = function(){

			// Start scrolling automatically
			autoScrollPlus7(8)

			// Play first result after a few seconds if no other video is played
			window.clearTimeout(autoPlay);
			autoPlay = window.setTimeout(function(){
				if (mainPlayer.currentVideoID < 3) mainPlayer.playVideo(newRequest.firstVideoId);
			}, autoPlayDelay * 1000);
		};

		newRequest.launch();
	}

	// Recursive autoscroll function, will work as long as the plus7 panel is displayed
	function autoScrollPlus7(s) {
		window.setTimeout(function(){
			if (!$('plus7List')) return;
			tsrScroll('plus7List');
			// autoScrollPlus7(20); // Recall itself to scroll again
		}, s*1000);
	}

	// UNFINISHED scrollbar: it roughly works but still needs lot of tuning.
	/*originalScrollWidth = 0;
	function initscrollZone() {

		var widthRatio = (Math.round(originalScrollWidth / $('plus7List').scrollWidth * 100));

		var scrollZonecontainer = $('scrollZonecontainer');

		var scrollbar = document.createElement('div');
		scrollbar.id = 'scrollZonebar';
		scrollZonecontainer.appendChild(scrollbar);


		var scrollact = document.createElement('div');
		scrollact.id = 'scrollZoneact';
		scrollact.style.width = widthRatio+'%';
		scrollbar.appendChild(scrollact);

		$('scrollZonedebug').innerHTML = ' ('+scrollbar.scrollWidth+') ' + $('plus7List').scrollWidth + ' / '+ originalScrollWidth +' = ' + (widthRatio) + '% => ' + scrollact.scrollWidth+'px';

		// Scrolling events
		scrollact.onmousedown = function(e) {

			// Kill event
			if (e.preventDefault) e.preventDefault();
			else e.returnValue = false;

			var loffseto = scrollact.style.marginLeft.substr(0, scrollact.style.marginLeft.length-2);

			var loffset = e.clientX - loffseto;

			document.onmousemove = function(e){

				var l = e.clientX - loffset;
				if (l < 0) l = 0;
				if ((l + scrollact.scrollWidth) > scrollbar.scrollWidth) l = scrollbar.scrollWidth - scrollact.scrollWidth;
				$('scrollZonedebug').innerHTML = l+' / '+(100/widthRatio);
				scrollact.style.marginLeft = l+'px';
				$('plus7List').style.marginLeft = '-' +  + 'px'
			};
		}
		document.onmouseup = function() {document.onmousemove = null;}
	}*/


  /************************/
 /*****   SCROLLER   *****/
/************************/

	// Scroller function!
	tsrScroll_on = 0;
	function tsrScroll(id, backwards) {

		if (tsrScroll_on) return;
		tsrScroll_on = 1;

		// Calculate element width to scroll (get first element that has a width)
		var container = $(id);
		if (!container) return;
		for (var i = 0; i < container.childNodes.length; i++) {
			el = container.childNodes[i];
			if (el.nodeType == 1) break;
		}
		var item_width = el.scrollWidth;   // Width of one element, in pixel

		var startPosition = 0;
		var targetPosition = -item_width;

		if (backwards) {
			moveElementStack(id, 1);
			targetPosition = 0;
			var startPosition = -item_width;
		}
		container.style.marginLeft = startPosition + 'px';

		tsrScroll_anim(container, startPosition, targetPosition, function(){
			container.style.marginLeft = 0;
			if (!backwards) moveElementStack(id);
			tsrScroll_on = 0;
		});
		return;
	}

	function tsrScroll_anim(obj, startPosition, targetPosition, callBack) {

		var step = (startPosition - targetPosition) / 4;
		step = -((step > 0) ? Math.ceil(step) : Math.floor(step));

		if (!step) {
			obj.style.marginLeft = targetPosition+'px';
			if (typeof callBack == 'function') callBack();
			return;
		}

		// nav.style.marginBottom = '-'+start+'px';
		obj.style.marginLeft = startPosition+'px';

		window.setTimeout(function(){
			tsrScroll_anim(obj, startPosition+step, targetPosition, callBack);
		},21);
	}

	// Take the first DOM child element and put it at the end, or the other way around if second argument is given
	function moveElementStack(id, backwards) {

		// remove all children from element
		var element = $(id);

		if (!backwards) {
			for (var i = 0; i < element.childNodes.length; i++) {
				el = element.childNodes[i];
				if (el.nodeType == 1) {
					element.removeChild(el);
					element.appendChild(el);
					break;
				}
			}
		}
		else {
			for (var i = element.childNodes.length-1; i > 0; i--) {
				el = element.childNodes[i];
				if (el.nodeType == 1) {
					element.removeChild(el);
					element.insertBefore(el, element.firstChild);
					break;
				}
			}
		}
	}

  /*****************************/
 /***   Library functions   ***/
/*****************************/

	// Standard functions

	function getElementsByClass(searchClass, domNode, tagName) {
		if (domNode == null) domNode = document;
		if (tagName == null) tagName = '*';
		var el = new Array();
		var tags = domNode.getElementsByTagName(tagName);
		var tcl = " "+searchClass+" ";
		for(i=0,j=0; i<tags.length; i++) {
			var test = " " + tags[i].className + " ";
			if (test.indexOf(tcl) != -1) el[j++] = tags[i];
		}
		return el;
	}

	function addEvent(obj, type, fn) {
		if (obj.addEventListener) obj.addEventListener( type, fn, false );
		else if (obj.attachEvent) {
			obj["e"+type+fn] = fn;
			obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
			obj.attachEvent( "on"+type, obj[type+fn] );
		}
	}

	// Set the given function onclick event of the elements with given class
	function setActionOnClassElements(searchClass, callback) {
		var els = getElementsByClass(searchClass);
		for (var i in els) {
			var el = els[i];
			addEvent(el, 'click', function(e){

				// Kill event
				if (e.preventDefault) e.preventDefault();
				else e.returnValue = false;
				callback(this);
			});
		}
	}

	// Add (or remove if no value) a variable in the URL's hash
	function setHashVariable(varname, val) {
		var hash = 'default';
		if (varname) hash = addParam(varname, val, window.location.hash.substring(1,window.location.hash.length), ';');
		window.location.hash = hash;
	}

	function getParamFromHash(pName) {
		var hash = window.location.hash.substring(1,window.location.hash.length);
		return getParam(pName, hash, ';');
	}

	// Add or remove a class to an element, according to whether or not the element has the class already.
	// Will keep other classes the element has
	function switchClass(el_id, class_to_switch) {

		// Get the element
		var el = $(el_id)
		if (!el) return;

		// Get an array with all the classes
		var el_classes = el.className.split(' ');
		var new_classes = [];
		var class_found = 0;

		// Remove the class from the array
		for (var i in el_classes) {
			var el_class = el_classes[i];
			if (el_class == class_to_switch) class_found = 1;
			else new_classes.push(el_class);
		}

		// Id the class has not been found, add it.
		if (!class_found) new_classes.push(class_to_switch);

		// Assich the modified class array to the element
		el.className = new_classes.join(' ');
	}

	// Will return true or false, randomly
	// By default, it's around 50/50, but with higher arguments, will occur more seldom
	function maybe(divider) {
		return Math.floor(Math.random()*100) % (divider || 2) ? 0 : 1;
	}

	// Gently scroll to an element in the page
	function scrollToTop(y) {
		var distanceToTop = 56;
		var currentPos = 0;
		if (window.pageYOffset) currentPos = window.pageYOffset;
		else if (document.body && document.body.scrollTop) currentPos = document.body.scrollTop;
		if (!y) y = currentPos;
		var y2 = y
		y = Math.floor((y - distanceToTop) / 4) - 1;
		if(y < 1) return;
		window.scrollBy(0,-y);
		window.setTimeout(function(){scrollToTop(y2-y)},50);
	}