<!--

/** CORE CONSTRUCTOR */
function core(){

	// Class variables
	this.base_url = '';
	this.url = document.location.href;
	if(this.url.charAt(this.url.length-1) != '/'){ this.url += '/'; }
	this.image_url = '';
	this.url_clean = '';
	
	// Browser detection
	this.browser = '';
	this.browser_version = '';
	this.os = '';
	
	// Language detection
	this.language_id = '';

	// Constructor
	this.construct = function(base_url_load, image_url_load, core_time, language_id_load){
		
		// URL handling
		this.base_url = base_url_load;
		this.image_url = image_url_load;
		this.url_clean = 'var/load/'+core_time+'/';
		
		// Browser detection
		this.browser = BrowserDetect.browser;
		this.browser_version = BrowserDetect.version;
		this.os = BrowserDetect.OS;
		
		// Language detection
		this.language_id = language_id_load;
	}
}
var core = new core();

// Set var for fade in/out messages
var site_fade = true;




/** DOCUMENT READY */
$(document).ready(function(sh){

	// Append alpha layer for layovers
	$('body').append('<div id="alpha_screen"></div>');
	
	// Append mouse msg
	$('body').append('<table border="0" cellspacing="0" cellpadding="0" id="msg_mouse"><tr><td class="msgm_lefttop"></td><td class="msgm_centertop"></td><td class="msgm_rightttop"></td></tr><tr><td class="msgm_leftmiddle"></td><td class="msgm_centermiddle"><div id="msg_mouse_pos"></div></td><td class="msgm_righttmiddle"></td></tr><tr><td class="msgm_leftbottom"></td><td class="msgm_centerbottom"></td><td class="msgm_righttbottom"></td></tr></table>');

	// Execute page function
	if(typeof load_index_func == "function"){ load_index_func(); }
	
	
	// Window scroll
	$(window).scroll(function(sh){
	
		// Scroll function messages
		msg_pos();
	
		// Scroll function layovers
		layover_pos();
		
		// Execute page function
		if(typeof scroll_index_func == "function"){ scroll_index_func(); }
		
	});
	
	// Window resize
	$(window).resize(function(sh){
	
		// Resize function messages
		msg_pos();
	
		// Resize function layovers
		layover_pos();
	
		// Execute page function
		if(typeof resize_index_func == "function"){ resize_index_func(); }
	});
	
	
	
	
	// Initiate app document ready function for loading image handlers
	app_doc_ready_images();
	
	// Initiate app document ready function for loading static image handlers
	app_doc_ready_images_static();
	
});
	




/** SCREEN HANDLING */
var set_freeze = false;

// Freeze screen
function freeze(){ set_freeze = true; }
function unfreeze(){ set_freeze = false; }

// Animate a screen to a position
function pos_screen_animate(SCREEN_ID, NO_TOP){

	// Set div for animation
	var $scroll_div = $("#"+SCREEN_ID);
	
	// Get the new screen position for element
	var screen_position = calc_pos_screen(SCREEN_ID);
	
	// Check if top must be modified
	var run_top = true;
	if(NO_TOP != null){ run_top = false; }
	
	// Animate to
	if(run_top){ $scroll_div.stop().animate({"top": screen_position[0]}, 400 ); }
	$('#'+SCREEN_ID).css({left: screen_position[1]});

}

// Position a screen
function pos_screen(SCREEN_ID){

	// Set div for animation
	var $scroll_div = $("#"+SCREEN_ID);

	// Get the new screen position for element
	var screen_position = calc_pos_screen(SCREEN_ID);
	
	// Place at
	$scroll_div.stop().animate({"top": screen_position[0]}, 0 );
	$('#'+SCREEN_ID).css({left: screen_position[1]});
}

// Calculate correct center x/y for element
function calc_pos_screen(SCREEN_ID){
	var scroll_top_return = 0;
	var scroll_left_return = 0;
	if($('#'+SCREEN_ID).height() < window_height()){
		if($('#'+SCREEN_ID).height() < (window_height()/2)){ scroll_top_return = (((scroll_top()+((window_height()/2)-($('#'+SCREEN_ID).height()/2))))-(window_height()/5))+'px'; }else{ scroll_top_return = ((scroll_top()+((window_height()/2)-($('#'+SCREEN_ID).height()/2))))+'px'; }
	}else if($('#'+SCREEN_ID).height() > window_height()){
		scroll_top_return = $('#'+SCREEN_ID).position().top+'px';
	}else{
		scroll_top_return = (scroll_top())+'px';
	}
	if($('#'+SCREEN_ID).width() < $(window).width()){
		scroll_left_return = (scroll_left()+(($(window).width()/2)-($('#'+SCREEN_ID).width()/2)))+'px';
	}else{
		scroll_left_return = scroll_left()+'px';
	}
	return new Array(scroll_top_return, scroll_left_return);
}

// Get window height
function window_height(){
	if(core.browser == 'saf'){
		return window.innerHeight;
	}else{
		return $(window).height();
	}
}






/** MESSAGE HANDLING */
var msg_title_hold = '';
var msg_count = 0;
var msg_z_index = 4000;
var msg_image_firstshow = false;

// Set title
function msg_title(MSG_TITLE){
	if(MSG_TITLE != '' && MSG_TITLE != null){ msg_title_hold = MSG_TITLE; }else{ msg_title_hold = ''; }
}

// Set image show on single item
function msg_image(FIRST_SHOW){
	msg_image_firstshow = FIRST_SHOW;
}

// Get/set msg count
function get_msg_count(){
	return msg_count;
}
function set_msg_count(SET_COUNT){
	msg_count = SET_COUNT;
	if(msg_count < 0){ msg_count = 0; }
}

// Get/set msg z-index
function get_msg_index(){
	return msg_z_index;
}
function set_msg_index(SET_COUNT){
	msg_z_index = SET_COUNT;
	if(msg_z_index < 4000){ msg_z_index = 4000; }
}

// Create message box
// Tag [br] => <br />
function msg(MSG, MSG_CLOSE){

	// Update message ID
	msg_count++;
	
	// Create alpha ID
	var msg_alpha_use_id = 'msg_alpha_box_'+msg_count;
	
	// Create message ID
	var msg_use_id = 'msg_box_'+msg_count;
	
	// Define message content
	var msg_content = '';
	
	// Build message title
	if(msg_title_hold != ''){ msg_content += '<div class="msg_title">'+msg_title_hold+'</div><div class="msg_line1"></div><div class="msg_line2"></div>'; }

	// Build message content
	var msg_add = '';
	if(typeof MSG == "string"){
		if(msg_image_firstshow == false){ msg_add = str_html(MSG); }
		if(msg_image_firstshow == true){ msg_add = '<div class="msg_content_multiple'+add_start_css+'"><div class="msg_content_multiple_image"></div><div class="msg_content_multiple_item">'+str_html(MSG)+'</div><div class="clear"></div></div>'; }
	}else if(MSG.length > 0){
	
		// Build as array
		for(count_msg = 0; count_msg <= MSG.length-1; count_msg++){ if(MSG[count_msg] != ''){
			var add_start_css = ''; if(count_msg == 0){ add_start_css = '_start'; }else{ add_start_css = ''; }
			msg_add += '<div class="msg_content_multiple'+add_start_css+'"><div class="msg_content_multiple_image"></div><div class="msg_content_multiple_item">'+str_html(MSG[count_msg])+'</div><div class="clear"></div></div>';
		} }
		
	}
	
	// Create XHTML for message content
	msg_content += '<div class="msg_content">'+msg_add+'</div>';
	
	// Append the alpha box and position it
	msg_z_index++;
	$('body').append('<div id="'+msg_alpha_use_id+'" class="alpha_msg" style="z-index:'+msg_z_index+';"></div>');
	
	// Position the alpha screen
	pos_screen(msg_alpha_use_id);
	
	// Append the message box and position it
	msg_z_index++;
	$('body').append('<table border="0" cellspacing="0" cellpadding="0" id="'+msg_use_id+'" class="msg" style="z-index:'+msg_z_index+'"><tr><td class="msg_lefttop"></td><td class="msg_centertop"></td><td class="msg_rightttop"></td></tr><tr><td class="msg_leftmiddle"></td><td class="msg_centermiddle"><div class="msg_pos">'+msg_content+'</div></td><td class="msg_righttmiddle"></td></tr><tr><td class="msg_leftbottom"></td><td class="msg_centerbottom"></td><td class="msg_righttbottom"></td></tr></table>');

	// Position the message screen
	pos_screen(msg_use_id);
	
	// Bind close handler to alpha screen
	$('#'+msg_alpha_use_id).mouseup(function(event){ msg_hide(this.id); });
	
	// Bind close function to message screen
	if(MSG_CLOSE != null){ if(MSG_CLOSE == true){ $('#'+msg_use_id).css({cursor: 'pointer'}); $('#'+msg_use_id).mouseup(function(event){ msg_hide(this.id); }); } }
	
	// Fade in
	if(site_fade){ $('#'+msg_use_id).fadeIn('fast'); }else{ $('#'+msg_use_id).css({display: 'block'}); }
	
	// Return the ID for external control
	return msg_count;
}

// Close message box, either the matching numeric ID or a full id="" tag is required
function msg_hide(MSG_LOAD_ID){
	
	// Continue on unfreeze and found tag
	if(set_freeze == false && MSG_LOAD_ID != null){
		
		// Get the ID if var is tag
		if(!is_numeric(MSG_LOAD_ID)){ MSG_LOAD_ID = get_id_tag(MSG_LOAD_ID); }
		
		// Fadeout element
		if(site_fade){
			$('#msg_box_'+MSG_LOAD_ID).fadeOut('fast', function(){
				
				// Remove msg element
				$('#msg_box_'+MSG_LOAD_ID).remove();
				
				// Remove alpha element
				$('#msg_alpha_box_'+MSG_LOAD_ID).remove();
			});
		
		// Remove normal
		}else{
			// Remove msg element
			$('#msg_box_'+MSG_LOAD_ID).remove();
			
			// Remove alpha element
			$('#msg_alpha_box_'+MSG_LOAD_ID).remove();
		}
	}
	
	// Reset msg count
	var msg_count = get_msg_count();
	msg_count--;
	set_msg_count(msg_count);
	
	// Reset msg index
	var msg_index = get_msg_index();
	msg_index = msg_index-2;
	set_msg_index(msg_index);
	
}

// Message positioning
function msg_pos(){
	for(c_msg = 1; c_msg <= msg_count; c_msg++){ pos_screen('msg_alpha_box_'+c_msg); }
	for(c_msg = 1; c_msg <= msg_count; c_msg++){ pos_screen_animate('msg_box_'+c_msg); }
}




/** LAYOVERS */
var layover_count = 0;
var layover_zindex = 1000;
var layover_id = new Array();

// Get/set layover count
function get_layover_count(){
	return layover_count;
}
function set_layover_count(SET_COUNT){
	layover_count = SET_COUNT;
	if(layover_count < 0){ layover_count = 0; }
}

// Get/set layover index
function get_layover_index(){
	return layover_zindex;
}
function set_layover_index(SET_COUNT){
	layover_zindex = SET_COUNT;
	if(layover_zindex < 1000){ layover_zindex = 1000; }
}

// Get/set layover id
function get_layover_id(){
	return layover_id;
}
function set_layover_id(NEW_LAYOVER_ID){
	layover_id = NEW_LAYOVER_ID;
}

// Show the layover
function layover(LAYER_ID, ALPHA_CLOSE, LAYER_CONTENT){

	// Continue if layer_id is found
	if(LAYER_ID != null){

		// If layer_content not empty then append new layer
		if(LAYER_CONTENT != null){
			$('#layover_'+LAYER_ID).remove();
			$('body').append(LAYER_CONTENT);
			app_doc_ready_images();
		}
	
		// If layover isn't shown yet
		if($('#layover_'+LAYER_ID).css("display") == 'none'){
		
			// Set close type
			var alpha_close_type = false;
			if(ALPHA_CLOSE != null){ if(ALPHA_CLOSE == true){ alpha_close_type = true; } }

			// Add to layover count
			layover_count++;
			
			// Determine z-index for layover
			layover_zindex++;
			
			// Grant z-index to layover
			$('#layover_'+LAYER_ID).css({zIndex: layover_zindex});
		
			// Add layer to ID array
			layover_id[layover_id.length] = new Array(LAYER_ID, alpha_close_type, layover_zindex);

			// Position the layover
			pos_screen('layover_'+LAYER_ID);
			
			// Show the alpha layer
			layover_alpha_show(alpha_close_type);
			
			 // Bind/unbind close function for alpha layer
			if(alpha_close_type){  $('#alpha_screen').mouseup(function(event){ layover_hide(LAYER_ID); }); $('#alpha_screen').css({cursor: 'pointer'}); }else{ $('#alpha_screen').unbind('mouseup'); $('#alpha_screen').css({cursor: 'default'}); }

			// Fade in
			if(site_fade){ $('#layover_'+LAYER_ID).fadeIn('fast'); }else{ $('#layover_'+LAYER_ID).css({display: 'block'}); }

		
		// If shown upgrade z-index
		}else{
			
			// Determine z-index for layover
			layover_zindex++;
			
			// Update z-index in array and bind/unbind alpha
			var current_layover_id = get_layover_id();
			for(count_id = 0; count_id <= current_layover_id.length-1; count_id++){
				if(LAYER_ID == current_layover_id[count_id][0]){ current_layover_id[count_id][2] = layover_zindex; }
				if(LAYER_ID == current_layover_id[count_id][0]){ if(current_layover_id[count_id][1] == true){ $('#alpha_screen').mouseup(function(event){ layover_hide(LAYER_ID); $('#alpha_screen').css({cursor: 'pointer'}); }); }else{ $('#alpha_screen').unbind('mouseup'); $('#alpha_screen').css({cursor: 'default'}); } }
			}
			set_layover_id(current_layover_id);
			
			// Grant z-index to layover
			$('#layover_'+LAYER_ID).css({zIndex: layover_zindex});
		}
	}
}

// Hide the layover
function layover_hide(LAYER_ID){

	// Continue on unfreeze and found tag
	if(set_freeze == false && LAYER_ID != null){
		
		// Fadeout element
		if(site_fade){
			$('#layover_'+LAYER_ID).fadeOut('fast', function(){
				
				// Hide layer element
				$('#layover_'+LAYER_ID).css({display: 'none'});

			});
		
		// Hide normal
		}else{
				
			// Hide layer element
			$('#layover_'+LAYER_ID).css({display: 'none'});
		}
	
		// Hide alpha screen
		layover_alpha_hide();
	}
	
	// Remove from array
	var local_layover_id = new Array();
	var current_layover_id = get_layover_id();
	var alpha_layover_bind = '';
	for(count_id = 0; count_id <= current_layover_id.length-1; count_id++){
		if(LAYER_ID != current_layover_id[count_id][0]){
		
			// Add to new array
			local_layover_id[local_layover_id.length] = current_layover_id[count_id];
		}
	}
	set_layover_id(local_layover_id);
	
	
	// Determine layover with highest z-index
	var highest_zindex = 0;
	for(count_id = 0; count_id <= local_layover_id.length-1; count_id++){ if(local_layover_id[count_id][2] > highest_zindex){ alpha_layover_bind = count_id; highest_zindex = local_layover_id[count_id][2]; } }
	
	// Handle bind/unbind alpha screen
	if(is_numeric(alpha_layover_bind)){
		current_layover_id = get_layover_id();
		if(current_layover_id.length > 0){ if(current_layover_id[alpha_layover_bind] != null){ if(current_layover_id[alpha_layover_bind][1] == true){ $('#alpha_screen').css({cursor: 'pointer'}); $('#alpha_screen').mouseup(function(event){ layover_hide(current_layover_id[alpha_layover_bind][0]); }); }else{ $('#alpha_screen').unbind('mouseup'); $('#alpha_screen').css({cursor: 'default'}); } }else{ $('#alpha_screen').unbind('mouseup'); $('#alpha_screen').css({cursor: 'default'}); } }else{ $('#alpha_screen').unbind('mouseup'); $('#alpha_screen').css({cursor: 'default'}); }
	}
	
	// Downgrade layover count
	var layover_countl = get_layover_count(); layover_countl--;
	set_layover_count(layover_countl);
	
	// Reset layover
	var layover_countl = get_layover_count();
	if(layover_countl == 0){
		local_layover_id = new Array();
		set_layover_id(local_layover_id);
		set_layover_index(1000);
	}
}

// Remove a layover
function layover_destroy(LAYER_ID){
	$('#layover_'+LAYER_ID).remove();
}

// Show the alpha layover
var layover_alpha_vis = false;
var layover_alpha_count = 0;
function layover_alpha_show(){
	
	// Position alpha layer
	pos_screen('alpha_screen');
	
	// Raise count
	layover_alpha_count++;

	// Show alpha layer or add count
	if(layover_alpha_vis == false){ $('#alpha_screen').css({display: 'block'}); layover_alpha_vis = true; }
}

// Hide the alpha layover
function layover_alpha_hide(){

	// Lower count
	layover_alpha_count--;
	
	// If count not yet 0 then lower count
	if(layover_alpha_count <= 0){ $('#alpha_screen').css({display: 'none'}); layover_alpha_vis = false; layover_alpha_count = 0; }
}

// Layover positioning
function layover_pos(NO_TOP){
	var current_layover_id = get_layover_id();
	if(layover_alpha_vis == true){ pos_screen('alpha_screen'); }
	for(c_layer = 0; c_layer <= current_layover_id.length-1; c_layer++){ pos_screen_animate('layover_'+current_layover_id[c_layer], NO_TOP); }
}







/** MOUSEOVER MSG */
var hover_timer = '';
var hover_start_timer = '';
if(msg_hover == null){ var msg_hover = new Array(); }

// Show mouse hover
function mouse_msg(e, HOVER_ID, MSG_DELAY, MSG_SIDE){

	// Clear hover timeout
	clearTimeout(hover_timer);
	clearTimeout(hover_start_timer);
	
	// Get ID from tag
	var tag_id = get_id_tag(HOVER_ID);
	
	// Get message content
	var msg_content = msg_hover[tag_id-1];
	
	// Continue if content found
	if(msg_content != ''){

		// Add content to message
		$('#msg_mouse_pos').html(str_html(msg_content));
		
		// Position message
		if(MSG_SIDE != null){
			
			// Set css for positioning
			$('#msg_mouse').css({top: (e.pageY-20)+'px'});
			$('#msg_mouse').css({left: (e.pageX-($('#msg_mouse').width()+10))+'px'});
		}else{
			
			// Check for available width on right side
			var msg_width = $('#msg_mouse').width();
			if(msg_width > ($(window).width()-e.pageX)){
			
				// Set css for positioning
				$('#msg_mouse').css({top: (e.pageY-20)+'px'});
				$('#msg_mouse').css({left: (e.pageX-($('#msg_mouse').width()+10))+'px'});
			}else{
			
				// Set css for positioning
				$('#msg_mouse').css({top: (e.pageY-20)+'px'});
				$('#msg_mouse').css({left: (e.pageX+10)+'px'});
			}
		}
		
		// Show the message
		if(MSG_DELAY != null){ hover_start_timer = setTimeout("mouse_msg_show();", MSG_DELAY); }else{ mouse_msg_show(); }
	}
}

// Show the message
function mouse_msg_show(){
	
	// Show the message
	if(site_fade){ $('#msg_mouse').fadeIn(100); }else{ $('#msg_mouse').css({display: 'block'}); }
}

// Hide mouse hover
function mouse_msg_hide(){

	// Clear hover timeout
	clearTimeout(hover_timer);
	clearTimeout(hover_start_timer);
	
	// Set timeout for close function
	hover_timer = setTimeout(mouse_msg_timer, 100);
}

// Finish hide timer
function mouse_msg_timer(){

	// Clear hover timeout
	clearTimeout(hover_timer);
	clearTimeout(hover_start_timer);
	
	// Hide the message
	$('#msg_mouse').css({display: 'none'});
}





/** RANDOM STUFF */

// Function for retrieving id tag (must be on end with _)
function get_id_tag(ID_RETURN){
	var id_tag = ID_RETURN.split('_');
	id_tag = id_tag[id_tag.length-1];
	return id_tag;
}

// Function for handling HTML tags in messages
function str_html(HTML_STR){
	var check_string = '';
	
	check_string = HTML_STR.split('[br]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[br]', '<br />'); }
	check_string = HTML_STR.split('[b]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[b]', '<b>'); }
	check_string = HTML_STR.split('[/b]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[/b]', '</b>'); }
	check_string = HTML_STR.split('[u]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[u]', '<u>'); }
	check_string = HTML_STR.split('[/u]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[/u]', '</u>'); }
	check_string = HTML_STR.split('[i]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[i]', '<i>'); }
	check_string = HTML_STR.split('[/i]'); for(count_check = 0; count_check <= check_string.length-1; count_check++){ HTML_STR = HTML_STR.replace('[/i]', '</i>'); }
	return HTML_STR;
}

// Function for returning form handle for XMLhttp POST request
function form_handle(FORM_NAME){ return formData2QueryString(document.getElementById(FORM_NAME)); }



/** BROWSER DETECTION */


var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "saf",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "moz"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "ie",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			   string: navigator.userAgent,
			   subString: "iPhone",
			   identity: "iPhone/iPod"
	    },
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();








/** JQUERY

 */

/*
---
name: ExpandableText
description: jQuery plugin for an expandable text block with shortening facility

authors:
  - Magic Web Solutions (http://www.magicwebsolutions.co.uk)

license:
  - MIT-style license

*/

(function($) {
	// jQuery plugin definition
	$.fn.expandableText = function(params) {
		// merge default and user parameters
		params = $.extend( {
			width: 300, 
			height: 45,
			more: '[more...]',
			less: '[less]'
		}, params);
		// traverse all nodes
		this.each(function() {
			// express a single node as a jQuery object
			el = $(this);
			var self = this;
			self.params = params;
			self.longText = el.html();
			self.shortText = '';
			var splitText = self.longText.split(' ');

			el.width(params.width).html('').height('');
			var i = 0;
			var text = '';
			$.each(splitText, function(index, value){
				text += value + ' ';
				el.html(text + params.more);
				++i;
				if (el.height() > params.height) {
					return false;
				} else {
					self.shortText = text;
				}
			});
			if (i < splitText.length)
				lessClick(self, el);
			else
				el.html(self.longText);
		});
		// allow jQuery chaining
		return this;
	};
	
	function moreClick($this, elem) {
		var less = $('<a></a>').html($this.params.less).attr('href','javascript:;').click(function(){
			lessClick($this, elem);
		});
		elem.empty().html($this.longText).append(less);
	}
	
	function lessClick($this, elem) {
		var more = $('<a></a>').html($this.params.more).attr('href','javascript:;').click(function(){
			moreClick($this, elem);
		});			
		elem.empty().html($this.shortText).append(more);
	}
	
})(jQuery);












/** FUNCTIONS

 */



/** WINDOW HANDLERS
*/

/** Return the scrollTop */
function scroll_top(){
	if(document.documentElement.scrollTop > 0){
		return document.documentElement.scrollTop;
	}else if(document.body.scrollTop > 0){
		return document.body.scrollTop;
	}else{
		return 0;
	}
}

/** Return the scrollLeft */
function scroll_left(){
	if(document.documentElement.scrollLeft > 0){
		return document.documentElement.scrollLeft;
	}else if(document.body.scrollLeft > 0){
		return document.body.scrollLeft;
	}else{
		return 0;
	}
}



/** STRING HANDLERS 
*/

/** Check if a variable contains a numeric value */
function is_numeric(strString)

   //  check for valid numeric strings	
   {
   var strValidChars = "0123456789.-";
   var strChar;
   var blnResult = true;

   if (strString.length == 0) return false;

   //  test strString consists of valid characters listed above
   for (i = 0; i < strString.length && blnResult == true; i++)
      {
      strChar = strString.charAt(i);
      if (strValidChars.indexOf(strChar) == -1)
         {
         blnResult = false;
         }
      }
   return blnResult;
}



/** ARRAY HANDLERS
*/

/** Return the position of needle in haystack */
Array.prototype.position = function (s) {
var i = 0;
while (i < this.length && this [i] != s) {i++};
return i < this.length ? i : undefined;
}


/** DOCUMENT HANDLERS
*/
function __getIEVersion() {
    var rv = -1; // Return value assumes failure.
    if (navigator.appName == 'Microsoft Internet Explorer') {
        var ua = navigator.userAgent;
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null)
            rv = parseFloat(RegExp.$1);
    }
    return rv;
}

function __getOperaVersion() {
    var rv = 0; // Default value
    if (window.opera) {
        var sver = window.opera.version();
        rv = parseFloat(sver);
    }
    return rv;
}
var __userAgent = navigator.userAgent;
var __isIE =  navigator.appVersion.match(/MSIE/) != null;
var __IEVersion = __getIEVersion();
var __isIENew = __isIE && __IEVersion >= 8;
var __isIEOld = __isIE && !__isIENew;

var __isFireFox = __userAgent.match(/firefox/i) != null;
var __isFireFoxOld = __isFireFox && ((__userAgent.match(/firefox\/2./i) != null) || (__userAgent.match(/firefox\/1./i) != null));
var __isFireFoxNew = __isFireFox && !__isFireFoxOld;

var __isWebKit =  navigator.appVersion.match(/WebKit/) != null;
var __isChrome =  navigator.appVersion.match(/Chrome/) != null;
var __isOpera =  window.opera != null;
var __operaVersion = __getOperaVersion();
var __isOperaOld = __isOpera && (__operaVersion < 10);

function __parseBorderWidth(width) {
    var res = 0;
    if (typeof(width) == "string" && width != null && width != "" ) {
        var p = width.indexOf("px");
        if (p >= 0) {
            res = parseInt(width.substring(0, p));
        }
        else {
     		//do not know how to calculate other values (such as 0.5em or 0.1cm) correctly now
    		//so just set the width to 1 pixel
            res = 1; 
        }
    }
    return res;
}


//returns border width for some element
function __getBorderWidth(element) {
	var res = new Object();
	res.left = 0; res.top = 0; res.right = 0; res.bottom = 0;
	if (window.getComputedStyle) {
		//for Firefox
		var elStyle = window.getComputedStyle(element, null);
		res.left = parseInt(elStyle.borderLeftWidth.slice(0, -2));  
		res.top = parseInt(elStyle.borderTopWidth.slice(0, -2));  
		res.right = parseInt(elStyle.borderRightWidth.slice(0, -2));  
		res.bottom = parseInt(elStyle.borderBottomWidth.slice(0, -2));  
	}
	else {
		//for other browsers
		res.left = __parseBorderWidth(element.style.borderLeftWidth);
		res.top = __parseBorderWidth(element.style.borderTopWidth);
		res.right = __parseBorderWidth(element.style.borderRightWidth);
		res.bottom = __parseBorderWidth(element.style.borderBottomWidth);
	}
   
	return res;
}


//returns the absolute position of some element within document
function getElementAbsolutePos(elemID) {
	var element;
	if (typeof(elemID) == "string")	{
		element = document.getElementById(elemID);
	}
	else {
		element = elemID;
	}

	var res = new Object();
	res.x = 0; res.y = 0;
	if (element !== null) {
        if (__isIENew) {
	    	res.x = element.scrollLeft;
		    res.y = element.scrollTop;
		}
		else {
	    	res.x = element.offsetLeft;
		    res.y = element.offsetTop;
		}
    	
		var offsetParent = element.offsetParent;
		var parentNode = element.parentNode;
		var borderWidth = null;

		while (offsetParent != null) {
			res.x += offsetParent.offsetLeft;
			res.y += offsetParent.offsetTop;
			
			var parentTagName = offsetParent.tagName.toLowerCase();	

			if ((__isIEOld && parentTagName != "table") || (__isFireFoxNew && parentTagName == "td")) {		    
				borderWidth = __getBorderWidth(offsetParent);
				res.x += borderWidth.left;
				res.y += borderWidth.top;
			}
		    
			if (offsetParent != document.body && offsetParent != document.documentElement) {
				res.x -= offsetParent.scrollLeft;
				res.y -= offsetParent.scrollTop;
			}


			//next lines are necessary to support FireFox problem with offsetParent
   			if (!__isIE && !__isOperaOld || __isIENew) {
    			while (offsetParent != parentNode && parentNode !== null) {
					res.x -= parentNode.scrollLeft;
					res.y -= parentNode.scrollTop;
					if (__isFireFoxOld && __isWebKit) {
						borderWidth = __getBorderWidth(parentNode);
						res.x += borderWidth.left;
						res.y += borderWidth.top;
					}
    				parentNode = parentNode.parentNode;
    			}    
			}

   			parentNode = offsetParent.parentNode;
    		offsetParent = offsetParent.offsetParent;
		}
	}
    return res;
}




/*
 * Copyright 2005 Matthew Eernisse (mde@fleegix.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Original code by Matthew Eernisse (mde@fleegix.org), March 2005
 * Additional bugfixes by Mark Pruett (mark.pruett@comcast.net), 12th July 2005
 * Multi-select added by Craig Anderson (craig@sitepoint.com), 24th August 2006
 *
 * Version 1.3
*/

/**
 * Serializes the data from all the inputs in a Web form
 * into a query-string style string.
 * @param docForm -- Reference to a DOM node of the form element
 * @param formatOpts -- JS object of options for how to format
 * the return string. Supported options:
 *    collapseMulti: (Boolean) take values from elements that
 *    can return multiple values (multi-select, checkbox groups)
 *    and collapse into a single, comman-delimited value
 *    (e.g., thisVar=asdf,qwer,zxcv)
 * @returns query-string style String of variable-value pairs
 */
function formData2QueryString(docForm, formatOpts) {
  
  var opts = formatOpts || {};
  var str = '';
  var formElem;
  var lastElemName = '';
  
  for (i = 0; i < docForm.elements.length; i++) {
    formElem = docForm.elements[i];
    
    switch (formElem.type) {
      // Text fields, hidden form elements
      case 'text':
      case 'hidden':
      case 'password':
      case 'textarea':
      case 'select-one':
        str += formElem.name + '=' + encodeURI(formElem.value) + '&'
        break;
        
      // Multi-option select
      case 'select-multiple':
        var isSet = false;
        for(var j = 0; j < formElem.options.length; j++) {
          var currOpt = formElem.options[j];
          if(currOpt.selected) {
            if (opts.collapseMulti) {
              if (isSet) {
                str += ',' + encodeURI(currOpt.value);
              }
              else {
                str += formElem.name + '=' + encodeURI(currOpt.value);
                isSet = true;
              }
            }
            else {
              str += formElem.name + '=' + encodeURI(currOpt.value) + '&';
            }
          }
        }
        if (opts.collapseMulti) {
          str += '&';
        }
        break;
      
      // Radio buttons
      case 'radio':
        if (formElem.checked) {
          str += formElem.name + '=' + encodeURI(formElem.value) + '&'
        }
        break;
        
      // Checkboxes
      case 'checkbox':
        if (formElem.checked) {
          // Collapse multi-select into comma-separated list
          if (opts.collapseMulti && (formElem.name == lastElemName)) {
            // Strip of end ampersand if there is one
            if (str.lastIndexOf('&') == str.length-1) {
              str = str.substr(0, str.length - 1);
            }
            // Append value as comma-delimited string
            str += ',' + encodeURI(formElem.value);
          }
          else {
            str += formElem.name + '=' + encodeURI(formElem.value);
          }
          str += '&';
          lastElemName = formElem.name;
        }
        break;
        
    }
  }
  // Remove trailing separator
  str = str.substr(0, str.length - 1);
  return str;
}








/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
    The global object JSON contains two methods.

    JSON.stringify(value) takes a JavaScript value and produces a JSON text.
    The value must not be cyclical.

    JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
    return false if there is an error.
*/
var JSON = function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            'boolean': function (x) {
                return String(x);
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            },
            object: function (x) {
                if (x) {
                    var a = [], b, f, i, l, v;
                    if (x instanceof Array) {
                        a[0] = '[';
                        l = x.length;
                        for (i = 0; i < l; i += 1) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v == 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a[a.length] = v;
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = ']';
                    } else if (x instanceof Object) {
                        a[0] = '{';
                        for (i in x) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v == 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a.push(s.string(i), ':', v);
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = '}';
                    } else {
                        return;
                    }
                    return a.join('');
                }
                return 'null';
            }
        };
    return {
        copyright: '(c)2005 JSON.org',
        license: 'http://www.JSON.org/license.html',
/*
    Stringify a JavaScript value, producing a JSON text.
*/
        stringify: function (v) {
            var f = s[typeof v];
            if (f) {
                v = f(v);
                if (typeof v == 'string') {
                    return v;
                }
            }
            return null;
        },
/*
    Parse a JSON text, producing a JavaScript value.
    It returns false if there is a syntax error.
*/
        parse: function (text) {
            try {
                return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
                        text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
                    eval('(' + text + ')');
            } catch (e) {
                return false;
            }
        }
    };
}();








/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

/*
 * Perform a simple self-test to see if the VM is working
 */
function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}







/*
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
 * in FIPS PUB 180-1
 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for details.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}

/*
 * Perform a simple self-test to see if the VM is working
 *
function sha1_vm_test()
{
  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}

/*
 * Calculate the SHA-1 of an array of big-endian words, and a bit length
 */
function core_sha1(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << (24 - len % 32);
  x[((len + 64 >> 9) << 4) + 15] = len;

  var w = Array(80);
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  var e = -1009589776;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
    var olde = e;

    for(var j = 0; j < 80; j++)
    {
      if(j < 16) w[j] = x[i + j];
      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
      e = d;
      d = c;
      c = rol(b, 30);
      b = a;
      a = t;
    }

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
    e = safe_add(e, olde);
  }
  return Array(a, b, c, d, e);

}

/*
 * Perform the appropriate triplet combination function for the current
 * iteration
 */
function sha1_ft(t, b, c, d)
{
  if(t < 20) return (b & c) | ((~b) & d);
  if(t < 40) return b ^ c ^ d;
  if(t < 60) return (b & c) | (b & d) | (c & d);
  return b ^ c ^ d;
}

/*
 * Determine the appropriate additive constant for the current iteration
 */
function sha1_kt(t)
{
  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
         (t < 60) ? -1894007588 : -899497514;
}

/*
 * Calculate the HMAC-SHA1 of a key and some data
 */
function core_hmac_sha1(key, data)
{
  var bkey = str2binb(key);
  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
  return core_sha1(opad.concat(hash), 512 + 160);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert an 8-bit or 16-bit string to an array of big-endian words
 * In 8-bit function, characters >255 have their hi-byte silently ignored.
 */
function str2binb(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
  return bin;
}

/*
 * Convert an array of big-endian words to a string
 */
function binb2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
  return str;
}

/*
 * Convert an array of big-endian words to a hex string.
 */
function binb2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of big-endian words to a base-64 string
 */
function binb2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}






/** class Sjaks
	- opdelen van content naar html en javascript
	- @params url (url pagina)
	- @params postval (POST string of form object)
	- @params callfunct (indien waarde 'id' dan moet args een html element ID zijn, hier kan ook een functie naam 
		gebruik eventueel externe functie javaEval(this.server.responseText); om in die functie de javascript uit te voeren)
	- @params string args (indien waarde 'id' bij callfunctie moet dit een html element zijn)
	- @params string varType
*/
function Sjaks(varType) {
	this.debug = true; /* debug alert */
	this.disableform = true; /* disable form elements on form post */
	this.callfunct = 'id';
	this.args = '';
	this.rtFunc = new Function();
	this.varType = varType;

	this.aState1 = new Function();
	this.aState2 = new Function();
	this.aState3 = new Function();
	this.aState4 = new Function();
};

Sjaks.prototype.doGet = function(url, rtFunc){
	if(rtFunc != null){
		this.rtFunc = rtFunc;
	}
	this.url = url;
	this.aState1(this.varType);
	this.init();
};

Sjaks.prototype.doPost = function(url, postval, rtFunc){
	if(rtFunc != null){
		this.rtFunc = rtFunc;
	}
	this.url = url;
	this.postval = postval;
	this.aState1(this.varType);
	this.init();
};

Sjaks.prototype.init = function() { 
	this.server = null;
	if (typeof this.postval == "object") {
		this.poststr = this.form();
	} else if (typeof this.postval != "string") {
		this.poststr = "";
	} else {
		this.poststr = this.postval;
		this.postval = "";
	};
	var argtypes = {'string':'', 'boolean':'', 'number':''};
	if (typeof this.args in argtypes) {
		this.callArgs = new Array(this.args);
	} else if (typeof this.args == "object") {
		this.callArgs = this.args; 
	} else {
		this.callArgs = new Array();
	};
	var XMLHTTPtype = new Array(
		'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0',
		'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP',
		'Microsoft.XMLHTTP');
	for (var i = 0; i < XMLHTTPtype.length; i++) {
		try {
			if (window.XMLHttpRequest) {
				this.server = new XMLHttpRequest(XMLHTTPtype[i]);
			} else if (window.ActiveXObject) {
				this.server = new ActiveXObject(XMLHTTPtype[i]);
			};
		} catch (e) {};	
		if (this.server != null) {
			break;
		};
	};
	if (this.server == null) {
		this.msg("XMLHTTP unsupported");
	};
	var self = this;
	this.server.onreadystatechange = function () {
		if (this.server.readyState == 2) { 
			this.aState2(this.varType);
		}
		if (this.server.readyState == 3) {
			this.aState3(this.varType);
		} 
		if (this.server.readyState == 4) { 
			this.aState4(this.varType);	
			if (this.server.status == 200 && this.server.responseText != null) {
				if (typeof this.postval == "object") {
					this.form(true);
				};
				if (typeof this.callfunct == "string") {
					try {
						callback = eval("this." + this.callfunct);
					} catch (e) {};
				} else {
					callback = (typeof this.callfunct == "function") ? this.callfunct : function () {};
				};
				callback.apply(this, this.callArgs);
			}; 
		};	
	}.bind(this);
	var reqmeth = (this.poststr != "") ? "POST" : "GET";
	this.server.open(reqmeth, this.url, true);
	this.server.setRequestHeader("If-Modified-Since", "Mon, 1 Jan 2000 00:00:00 GMT"); 
	if (this.poststr != "") {
		this.server.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
		this.server.setRequestHeader("Content-length", this.poststr.length); 
		this.server.setRequestHeader("Connection", "close");
		this.server.send(this.poststr);
	} else {
		this.server.send(null);
	};
};
Function.prototype.bind = function(object) { 
	var newbind = this; 
	return function() { 
		return newbind.apply(object); 
	};
};
Sjaks.prototype.abort = function(){
	if(this.server){
		this.aState4(this.varType);
		this.server.onreadystatechange = function(){};
		this.server.abort();
		this.server = null;
	}
};
Sjaks.prototype.msg = function(msg) { 
	if (this.debug === true) {
		alert(msg);
	};
	return false;
};
SjaksJsIDs = new Array();
Sjaks.prototype.js = function(ID) {
	if (typeof ID == "string") {
		for (var i in SjaksJsIDs) {
			if (i == ID) {
				try {
					document.getElementsByTagName('body')[0].removeChild(SjaksJsIDs[i]);
				} catch(e) {};
			};
		};
	};
	var input = this.server.responseText;
	var reg = /<script[^>]*>([\s\S]*?)<\/script>/gi;
	if (input.search(reg) != -1) {
		var reg1 = /<script?[^>]+>/gi;			
		var reg2 = /<\/script>/gi;				
		var reg3 = /<!--/;
		var reg4 = /\/\/-->/;
		jsparts = input.split(reg1);
		input = "";
		for (i =0; i < jsparts.length; i++) {
			if (jsparts[i].search(reg2) != -1) {
				jspart = jsparts[i].split(reg2);
				jspart[0] = jspart[0].replace(reg3, "");
				jspart[0] = jspart[0].replace(reg4, "");
				input += jspart[0];
			};
		};
	};
	try {
		DynaScript = document.createElement("script");
		if (typeof ID == "string") {
			SjaksJsIDs[ID] = DynaScript;
		};
		DynaScript.setAttribute("type", "text/javascript");
		DynaScript.text = "<!--\n" + input + "\n//-->";
		document.getElementsByTagName("body")[0].appendChild(DynaScript);
	} catch(e) {
		this.msg("Js error in Server response");
	};
};
Sjaks.prototype.id = function(ID) {
	if(this.args != '' && this.args != null){
alert('duh');
		var ObjID = null;
		if (typeof ID == "object") {
			var ObjID = ID;
		} else {
			if (document.getElementById && document.getElementById(ID)) {
				ObjID = document.getElementById(ID);
			} else if (document.all && document.all[''+ID+'']) {
				ObjID = document.all[''+ID+''];
			}
		}
		if (ObjID != null && typeof ObjID == "object") {
			var output = this.server.responseText;
			var reg = /<script[^>]*>([\s\S]*?)<\/script>/gi;
			if (output.search(reg) != -1) {
				this.js(ID);
			}
			output = output.replace(reg, "");
			var AsignVal = {'textarea':'', 'input':''};
			var AsignSrc = {'img':'', 'iframe':''};
			try {
				if (ObjID.tagName.toLowerCase() in AsignVal) {
					ObjID.value = output;
				} else if (ObjID.tagName.toLowerCase() in AsignSrc) {
					ObjID.src = output;
				} else {
					ObjID.innerHTML = output; 
				}
			} catch(e) {	
				this.msg("Toewijzen mislukt: " + ID);
			}
		} else {
			this.msg("Missing page Id: " + ID);
		}
	}else{
		var output = this.server.responseText;
		var reg = /<script[^>]*>([\s\S]*?)<\/script>/gi;
		if (output.search(reg) != -1) {
			this.js(ID);
		}
		output = output.replace(reg, "");
		var AsignVal = {'textarea':'', 'input':''};
		var AsignSrc = {'img':'', 'iframe':''};
		this.rtFunc(output);
	}
};
Sjaks.prototype.form = function(free) {
	var poststr = "";
	if (typeof this.postval == "object") {
		try {
			for (i = 0; i < this.postval.elements.length; i++) {
				if (this.postval.elements[i].name != "" && free !== true) {
					var pName = this.postval.elements[i].name;
					var pVal = this.postval.elements[i].value;
					pVal = pVal.replace(/\+/g,"%2B");
					pVal = pVal.replace(/\=/g,"%3D");
					pVal = pVal.replace(/\&/g,"%26");
					if (this.postval.elements[i].type == "radio") {
						if (this.postval.elements[i].checked === true) {
							poststr += pName + "=" + pVal;
							poststr += (this.postval.elements.length - 1 ==  i) ? "" : "&";
						};
					} else {
						if (this.postval.elements[i].type == "checkbox") {
							if (this.postval.elements[i].checked !== true) {
								pVal = "";
							};
						};
						poststr += pName + "=" + pVal;
						poststr += (this.postval.elements.length - 1 ==  i) ? "" : "&"; 
					};
				};
				if (this.disableform === true) {
					this.postval.elements[i].disabled = (free === true) ? false : true;
				};				
			};
		} catch(e) {
			this.msg("Form error");
		};
	};
	return poststr;
};




//-->
