/* ******************************************************************************
	INFORMATION :
	Ce fichier est la propriété de la société ELSIMPEX / TECHNICIENS-DU-NET.COM.
	Il fait partit de la suite "manuSCRIPT" qui n'est PAS libre de droits.
	Ce logiciel est protégé et sa copie, même partielle, est ILLICITE.
	Pour toute informations, contactez info@techniciens-du-net.com
   ******************************************************************************/
// Défileur manuSCRIPT


// write html scroller
function scroll_write_html(scroller) {
	document.writeln('<div id="' + scroller.id + '"' + scroll_css_html(scroller.classStop) + ' style="width: ' + scroller.width + 'px; height: ' + scroller.height + 'px;"' + (scroller.pause_mo ? ' onMouseOver="scroll_mo_freeze(\'' + scroller.id + '\');"; onMouseOut="scroll_mo_freeze(\'' + scroller.id + '\', false);"' : '') + '>');
	
	// loop through list
	var i = scroller.first;
	do {
		// write the item
		document.writeln('<div id="' + i.id + '"' + scroll_css_html(i.classPlay) + ' style="position: absolute; width: ' + scroller.width + 'px; visibility: hidden;">\n' + scroll_item_html(i) + '<\/div>');
		// next
		i = i.next;
	} while (i != scroller.first);
	document.writeln('<\/div>');
}


// do the scrolling
function scroll_pf_play(scroller) {
	if (!scroller.element) {
		scroll_pf_elements(scroller);
	}
	// set class
	if (scroller.classPlay) {
		scroller.element.className = scroller.classPlay;
	}
	// scroll
	scroll_do(scroller.id);
}


// stop scrolling
function scroll_pf_stop(scroller) {
	// set class
	if (scroller.classStop) {
		scroller.element.className = scroller.classStop;
	}
}


// perform scrolling
function scroll_do(id) {
	scroller = scroll_find(id);

	// calculate scroll increment
	var yinc = (scroller.shuttle * scroller.px);
	// will we scroll past the item?
	if (yinc > 0) {
		if (scroller.hilight.top > scroller.top && scroller.hilight.top - yinc < scroller.top) {
			yinc = scroller.hilight.top - scroller.top;
		}
	} else {
		if (scroller.hilight.top < scroller.top && scroller.hilight.top - yinc > scroller.top) {
			yinc = scroller.hilight.top - scroller.top;
		}
	}

	// calculate positions and clipping
	scroll_pf_calculate(scroller, yinc);
	// move and clip all items
	scroll_pf_position(scroller, yinc > 0);

	// pause?
	var timeout;
	if (scroller.hilight.top == scroller.top) {
		timeout = scroller.pause;
		// hilight item
		scroller.hilight.paused = true;
		scroller.hilight.element.className = scroller.hilight.classStop;
		// next item for hilight
		scroller.hilight = (yinc > 0 ? scroller.hilight.next : scroller.hilight.prev);
	} else {
		timeout = scroller.timeout;
	}

	// timeout until next scroll
	scroller.timer = setTimeout('scroll_do(\'' + scroller.id + '\')', timeout);
}


// calculate positions of items
function scroll_pf_calculate(scroller, yinc) {
	var i = scroller.first;
	var start = i;
	
	do {
		i.top -= yinc;
		if (i.top + i.height <= scroller.top) {
			scroll_hide(i);
			if (yinc > 0) {
				// going up, wrap to bottom
				scroll_wrap_to_bottom(scroller, i);
				if (i == scroller.first) {
					scroller.first = i.next;
				}
			}
		} else if (i.top >= scroller.bottom) {
			scroll_hide(i);
			if (yinc < 0) {
				// going down, wrap to top
				scroll_wrap_to_top(scroller, i);
				if (i == scroller.first) {
					scroller.first = i.prev;
				}
			}

		} else {
			// calculate clipping
			i.clip_top = (i.top < scroller.top ? scroller.top - i.top : 0);
			i.clip_bottom = (i.top + i.height > scroller.bottom ? scroller.bottom - i.top : i.height);
			i.onscreen = true;
		}
		if (i.paused) {
			i.element.className = i.classPlay;
			i.paused = false;
		}
		i = (yinc > 0 ? i.next : i.prev);
	} while (i != start);
}


// position and clip elements
function scroll_pf_position(scroller, up) {
	var i = scroller.first;
	while (i.onscreen) {
		i.element.style.top = i.top + 'px';
		i.element.style.clip = 'rect(' + i.clip_top + 'px ' + scroller.width + 'px '+ i.clip_bottom + 'px 0px)';
		if (!i.visible) {
			i.visible = true;
			i.element.style.visibility = 'visible';
		}
		i.onscreen = false;
		i = (up ? i.next : i.prev);
	}
}


// direction of scroller
function scroll_pf_direction(scroller) {
	if (!scroller.element) {
		scroll_pf_elements(scroller);
	}
	// find top
	var i = scroller.first;
	while (i.prev.top < i.top) {
		i = i.prev;
	}
	
	// find hilight element
	if (scroller.shuttle > 0) {
		// wrap top items
		while (i.top + i.height <= scroller.top) {
			scroll_hide(i);
			scroll_wrap_to_bottom(scroller, i);
			i = i.next;
		}
		scroller.first = i;
		scroller.hilight = (i.top <= scroller.top ? i.next : i);

	} else if (scroller.shuttle < 0) {
		do {
			i = i.prev;
		} while (i.top >= scroller.bottom);
		scroller.first = i;
		// wrap bottom items
		i = i.prev;
		while (i != scroller.first) {
			if (i.top > scroller.bottom) {
				scroll_hide(i);
				scroll_wrap_to_top(scroller, i);
			}
			i = i.prev;
		}
		// find hilight
		i = scroller.first.next;
		while (i.next.top < scroller.top) {
			i = i.next;
		}
		scroller.hilight = i;
	}
}


// wrap to bottom
function scroll_wrap_to_bottom(scroller, i) {
	i.top = i.prev.top + i.prev.height;
	if (i.top < scroller.bottom) {
		i.top = scroller.bottom;
	}
}


// wrap to top
function scroll_wrap_to_top(scroller, i) {
	i.top = (i.next.top > scroller.top ? scroller.top : i.next.top) - i.height;
}


// hide an item
function scroll_hide(i) {
	if (i.visible) {
		i.element.style.visibility = 'hidden';
		i.visible = false;
	}
}


// calculate element details
function scroll_pf_elements(scroller) {
	// get element
	scroller.element = document.getElementById(scroller.id);
	scroller.top = 0;
	// add up offsetTop of all parent elements (sometimes thrown out by borders on tables)
	var e = scroller.element;
	while (e) {
		scroller.top += e.offsetTop;
		e = e.offsetParent;
	}
	// bottom of scroller
	scroller.bottom = scroller.top + scroller.height;

	// get all item elements
	var i = scroller.first;
	var y = scroller.bottom;
	while (!i.element) {
		i.element = document.getElementById(i.id);
		i.top = y;
		i.height = i.element.offsetHeight;
		// next item (start pos)
		y += i.height;
		i = i.next;
	}
	scroller.hilight = scroller.first;
}


/*
scroll_config.js variables
- The following variables can all be user-defined in scroll_config.js
*/

// css classes
var scroll_css_control_play = '';
var scroll_css_control_stop = '';
var scroll_css_item_play = '';
var scroll_css_item_stop = '';
var scroll_css_item_title = '';
var scroll_css_item_description = '';
var scroll_css_item_links = '';
// what to link
var scroll_link_title = true;
var scroll_link_description = false;

// scroll width and height (clipping size)
var scroll_width = 100;
var scroll_height = 100;
// scroll pause - time (seconds) an item pauses when it reaches the top
var scroll_pause = 2;
// scroll fps (frames per second) - frame rate of scrolling animation
var scroll_fps = 12;
// number of pixels to scroll each frame
var scroll_pixels = 2;
// speed (shuttle) of scrolling (negative = reverse)
var scroll_shuttle = 1;

// behaviours
var onMouseOver_pause = false;

/*
 end scroll_config.js variables
*/


// scrollers
var scroll_control = new Array();
var scroll_css_cache = new Array();


// new scroller control object
function scroll_new_control(id) {
	this.id			= id.toString();
	this.width		= scroll_width;
	this.height		= scroll_height;
	this.pause		= Math.round(scroll_pause * 1000);
	this.pause_mo	= onMouseOver_pause;
	this.timeout	= Math.round(1000 / scroll_fps);
	this.px			= scroll_pixels;
	this.shuttle	= scroll_shuttle;
	this.play		= false;
	this.timer		= null;
	this.classPlay	= scroll_css_control_play;
	this.classStop	= scroll_css_control_stop;
}


// new scroller item object
function scroll_new_item(id, title, description, url, target) {
	this.id				= id.toString();
	this.title			= title;
	this.description	= description;
	this.url			= (url ? url : '');
	this.target			= target;
	this.classPlay		= (scroll_css_item_play ? scroll_find_class(scroll_css_item_play) : null);
	this.classStop		= (scroll_css_item_stop ? scroll_find_class(scroll_css_item_stop) : null);
	this.classTitle		= (scroll_css_item_title ? scroll_find_class(scroll_css_item_title) : null);
	this.classDesc		= (scroll_css_item_description ? scroll_find_class(scroll_css_item_description) : null);
	this.classLink		= (scroll_css_item_links ? scroll_find_class(scroll_css_item_links) : null);
	this.link_title		= scroll_link_title;
	this.link_desc		= scroll_link_description;
}


// scroll speed - set the speed
function scroll_speed(id, speed, increment) {
	scroll_speed_sc(scroll_find(id), speed, increment);
}


// scroll speed shuttle - increment play speed (negative to slow)
function scroll_speed_shuttle(id, shuttle) {
	scroll_speed_sc(scroll_find(id), shuttle, true);
}


// toggle play/pause
function scroll_play_stop(id) {
	var scroller = scroll_find(id);
	scroll_speed_sc(scroller, 1);
	if (scroller.play) {
		scroll_stop_sc(scroller);
	} else {
		scroll_play_sc(scroller);
	}
}


// play - scroll up
function scroll_play(id) {
	scroll_play_sc(scroll_find(id));
}
function scroll_play_sc(scroller) {
	if (!scroller.play) {
		scroller.play = true;
		scroll_restore_sc(scroller);
	}
}


// stop scrolling (pause)
function scroll_stop(id) {
	scroll_stop_sc(scroll_find(id));
}
function scroll_stop_sc(scroller) {
	if (scroller.play) {
		scroller.play = false;
		scroll_freeze_sc(scroller);
		scroll_pf_stop(scroller);
	}
}


// freeze play/pause toggle
function scroll_freeze(id, pause) {
	if (pause != false) {
		scroll_freeze_sc(scroll_find(id));
	} else {
		scroll_restore_sc(scroll_find(id));
	}
}


// mouse over toggle
function scroll_mo_freeze(id, pause) {
	var scroller = scroll_find(id);
	if (pause != false) {
		if (scroller.freeze) {
			clearTimeout(scroller.freeze);
			scroller.freeze = null;
		}
		scroll_freeze_sc(scroller);
	} else {
		if (!scroller.freeze) {
			scroller.freeze = setTimeout('scroll_freeze(\'' + id + '\', false);', 1);
		}
	}
}


// freeze a scroller (pause without changing play state)
function scroll_freeze_sc(scroller) {
	clearTimeout(scroller.timer);
	scroller.timer = null;
}


// restarts a scroller that may have been frozen
function scroll_restore_sc(scroller) {
	if (scroller.play && !scroller.timer) {
		scroll_pf_play(scroller);
	}
}


// scroll speed - set play speed, negative speed reverses
function scroll_speed_sc(scroller, speed, increment) {
	var shuttle = scroller.shuttle;
	scroller.shuttle = (increment ? scroller.shuttle : 0) + speed;
	// possible direction change
	if (scroller.shuttle && shuttle * scroller.shuttle <= 0) {
		scroll_pf_direction(scroller);
	}
	// if scroller playing
	if (scroller.play) {
		if (scroller.shuttle) {
			// speed (possibly again), restore play status
			scroll_restore_sc(scroller);
		} else {
			// no speed, freeze
			scroll_freeze_sc(scroller);
		}
	}
}


// add an item
function scroll_add(title, description, url, target) {
	var scroller = scroll_control[scroll_control.length - 1];
	if (scroller.first) {
		var i = 1;
		// add item to linked list
		var item = scroller.first;
		while (item.next) {
			item = item.next;
			i++;
		}
		item.next = new scroll_new_item(scroller.id + '-' + i, title, description, url, target);
		// double-link (previous item)
		item.next.prev = item;
	} else {
		// first item
		scroller.first = new scroll_new_item(scroller.id + '-0', title, description, url, target);
	}
}


// write html for item
function scroll_item_html(i) {
	var html = '';
	if (i.title) {
		html += '<strong' + scroll_css_html(i.classTitle) + '>' + (i.link_title && i.url ? scroll_item_link_html(i, i.title) : i.title) + '<\/strong><br \/>';
	}
	if (i.description) {
		html += '<small' + scroll_css_html(i.classDesc) + '>' + (i.link_desc && i.url ? scroll_item_link_html(i, i.description) : i.description) + '<br \/><\/small><br \/>';
	}

	// clear node (free memory)
	scroll_clear_node(i);

	return html;
}


// write link for item
function scroll_item_link_html(i, text) {
	return '<a href="' + i.url + (i.target ? '" target="' + i.target : '') + '"' + scroll_css_html(i.classLink) + '>' + text + '<\/a>';
}


// class html
function scroll_css_html(css) {
	return (css ? ' class="' + scroll_css_cache[css] + '"' : '');
}

// clear node (extra variables)
function scroll_clear_node(i) {
	i.title			= null;
	i.description	= null;
	i.url			= null;
	i.target		= null;
	i.classTitle	= null;
	i.classDesc		= null;
	i.classLink		= null;
	i.link_title	= null;
	i.link_desc		= null;
}


// find a scroller
function scroll_find(id) {
	var i = 0;
	while (i < scroll_control.length) {
		if (scroll_control[i].id == id) {
			return scroll_control[i];
		}
		i++;
	}
	// no such scroller, return 1st scroller
	return scroll_control[0];
}


// find class - caches classes
function scroll_find_class(name) {
	var i = 0;
	while (i < scroll_css_cache.length) {
		if (scroll_css_cache[i] == name) {
			return i;
		}
		i++;
	}
	// cache new class name
	scroll_css_cache[i] = name;
	return i;
}


// add a new scroll control
function scroll_create(id) {
	scroll_control[scroll_control.length] = new scroll_new_control(id);
}


// end of scrolling list, create scroller
function scroll_done() {
	var scroller = scroll_control[scroll_control.length - 1];
	// finish double linked list
	var i = scroller.first;
	while (i.next) {
		i = i.next;
	}
	// tail to head
	i.next = scroller.first;
	// head to tail
	scroller.first.prev = i;
	// write html
	scroll_write_html(scroller);
}
