

/* if ( navigator.userAgent.substr( 0, 34 ) == 'Mozilla/4.0 (compatible; MSIE 6.0;'
	|| navigator.userAgent.substr( 0, 34 ) == 'Mozilla/4.0 (compatible; MSIE 7.0;'
	|| navigator.userAgent.substr( 0, 34 ) == 'Mozilla/4.0 (compatible; MSIE 8.0;'
	|| navigator.userAgent.match( /Firefox\/1\.5/ )
	|| navigator.userAgent.match(/Firefox\/2\./)
	|| navigator.userAgent.match(/Firefox\/3\./) 
	|| navigator.userAgent.substr( 0, 6 ) == 'Opera/' ) */
	
if ( document.getElementsByTagName && ( window.addEventListener || window.attachEvent ) )

(function(){


// ----- private -----------------------------------------------------------------------------

var attach = function( element, event, handler ) {
	if ( window.addEventListener )
		element.addEventListener( event, handler, false );
	else
		element.attachEvent( 'on' + event, handler );
};

var getRect = navigator.userAgent.match( /^Mozilla\/4.0 \(compatible; MSIE 8\.0;/ ) ? function( element, origin ) {
	var left = 0, top = 0; 
	for ( var one = element; one && one != origin; one = one.offsetParent ) {
		left += one.offsetLeft - one.scrollLeft;
		top += one.offsetTop - one.scrollTop;
	}
	return { left: left, top: top, width: element.offsetWidth, height: element.offsetHeight };
} : typeof window.ActiveXObject != 'undefined' ? function( element, origin ) {
	var left = 
		- ( parseInt( element.currentStyle.borderLeftWidth ) || 0 )
		- ( parseInt( element.currentStyle.paddingLeft ) || 0 )
		- ( parseInt( element.currentStyle.marginLeft ) || 0 );
	var top = 
		- ( parseInt( element.currentStyle.borderTopWidth ) || 0 )
		- ( parseInt( element.currentStyle.paddingTop ) || 0 )
		- ( parseInt( element.currentStyle.marginTop ) || 0 );
	for ( var one = element; one && one != origin; one = one.offsetParent ) {
		left += one.offsetLeft - one.scrollLeft
			+ ( parseInt( one.currentStyle.borderLeftWidth ) || 0 )
			+ ( parseInt( one.currentStyle.paddingLeft ) || 0 )
			+ ( parseInt( one.currentStyle.marginLeft ) || 0 );
		top += one.offsetTop - one.scrollTop
			+ ( parseInt( one.currentStyle.borderTopWidth ) || 0 )
			+ ( parseInt( one.currentStyle.paddingTop ) || 0 )
			+ ( parseInt( one.currentStyle.marginTop ) || 0 );
	}
	return { left: left, top: top, width: element.offsetWidth, height: element.offsetHeight };
} : function( element, origin ) {
	var cs = document.defaultView.getComputedStyle( element, null );
	var left = 
		- ( parseInt( cs.getPropertyValue( 'border-left-width') ) || 0 )
		- ( parseInt( cs.getPropertyValue( 'padding-left' ) ) || 0 )
		- ( parseInt( cs.getPropertyValue( 'margin-left' ) ) || 0 );
	var top = 
		- ( parseInt( cs.getPropertyValue( 'border-top-width' ) ) || 0 )
		- ( parseInt( cs.getPropertyValue( 'padding-top' ) ) || 0 )
		- ( parseInt( cs.getPropertyValue( 'margin-top' ) ) || 0 );
	for ( var one = element; one && one != origin; one = one.offsetParent ) {
		cs = document.defaultView.getComputedStyle( one, null );
		left += one.offsetLeft - one.scrollLeft
			+ ( parseInt( cs.getPropertyValue( 'border-left-width') ) || 0 )
			+ ( parseInt( cs.getPropertyValue( 'padding-left' ) ) || 0 )
			+ ( parseInt( cs.getPropertyValue( 'margin-left' ) ) || 0 );
		top += one.offsetTop - one.scrollTop
			+ ( parseInt( cs.getPropertyValue( 'border-top-width' ) ) || 0 )
			+ ( parseInt( cs.getPropertyValue( 'padding-top' ) ) || 0 )
			+ ( parseInt( cs.getPropertyValue( 'margin-top' ) ) || 0 );
	}
	return { left: left, top: top, width: element.offsetWidth, height: element.offsetHeight };
};

var cancelEvent = function( event ) {
	if ( event.preventDefault )
		event.preventDefault();
  if ( event.stopPropagation )
    event.stopPropagation();
  event.cancelBubble = true;
  event.returnValue = false;
	return false;
};

var onload = [];

var expression = function( input ) {
	return input.replace( /\$\{([-+*\/0-9\.\(\)]*)\}/g, function( outer, inner ) { return eval( inner ); } );
};

attach( window, 'load', function() {
	for ( var i = 0, one; one = onload[ i++ ]; )
		one();
	onload = null;
} );

document.write( '<style> .tools-js-not-supported { display: none; } .tools-js-scroller { overflow: hidden !important; } </style>' );

var tools = window.tools = {};

// ----- watermark --------------------------------------------------------------------------

var watermarkFocus = function( event ) {
	var input = event.srcElement || event.target;
	if ( !input.isWatermark ) 
		return;
	input.isWatermark = false;
	input.value = '';
	input.className = input.originalClassName;
};

var watermarkBlur = function( event ) {
	var input = event.srcElement || event.target;
	input.isWatermark = input.value == '' || input.value == input.watermark;
	if ( input.isWatermark ) {
		input.className = input.watermarkStyle || input.originalClassName;
		input.value = input.watermark;
	}
};

onload.push( function() {
	var inputs = document.getElementsByTagName( 'input' );
	for ( var input, i = 0; input = inputs[ i++ ]; ) {
		var watermark = input.getAttribute( 'watermark' ) || '';
		var watermarkStyle = input.getAttribute( 'watermarkStyle' ) || '';
		if ( watermark == '' && watermarkStyle == '' )
			continue;
		input.watermark = watermark;
		input.watermarkStyle = watermarkStyle;
		attach( input, 'focus', watermarkFocus );
		attach( input, 'blur', watermarkBlur );
		input.originalClassName = input.className;
		input.isWatermark = input.value == '';
		if ( input.isWatermark ) {
			input.value = input.watermark;
			input.className = input.watermarkStyle || input.originalClassName;
		}
	}
} );

// ----- validator --------------------------------------------------------------------------

var validatorSubmit = function( event ) {
	var form = typeof event == 'object' ? ( event.srcElement || event.target ) : this;
	var elements = form.elements, minlength, expression;
	for ( var element, i = 0; element = elements[ i++ ]; ) {
		var value = element.isWatermark ? '' : element.value;
		if ( element.getAttribute( 'requireSelected' ) ) {
			var found = false;
			for ( var one, j = 0; one = elements[ j++ ]; )
				found = found || one.name === element.name && one.checked;
			if ( found )
				continue;
			// problem found
		}	else if ( typeof ( minlength = parseInt( element.getAttribute( 'minlength' ), 10 ) ) == 'number' && value.length < minlength 
			|| element.type == 'checkbox' && element.getAttribute( 'requireChecked' ) && !element.checked ) {
			// problem found
		} else if ( ( expression = element.getAttribute( 'requiredPattern' ) ) && 
			! ( new RegExp( expression, element.getAttribute( 'requiredOptions' ) || '' ) ).test( value ) ) {
			// problem found
		} else
			continue;
		element.focus();
		var message = element.getAttribute( 'requiredMessage' ) || form.getAttribute( 'requiredMessage' ) 
			|| document.getElementsByTagName( 'body' )[ 0 ].getAttribute( 'requiredMessage' );
		if ( message )
			alert( message );
		if ( event.preventDefault )
			event.preventDefault(); 
		return false;
	}
	for ( var element, i = 0; element = elements[ i++ ]; )
		if ( element.isWatermark )
			element.value = '';
	return true;
};

onload.push( function() {
	var forms = document.getElementsByTagName( 'form' );
	for ( var form, i = 0; form = forms[ i++ ]; )
		attach( form, 'submit', validatorSubmit );
} );

// ----- confirmations ----------------------------------------------------------------------

var confirmClick = function( event ) {
	var link = typeof event == 'object' ? ( event.srcElement || event.target ) : this;
	if ( !confirm( link.getAttribute( 'confirmation' ) ) ) {
		if ( event.preventDefault )
			event.preventDefault();
		if ( event.stopPropagation )
			event.stopPropagation();
		event.cancelBubble = true;
		return ( event.returnValue = false );
	}
	return ( event.returnValue = true );
};

onload.push( function() {
	var links = document.getElementsByTagName( 'a' ), confirmedHref;
	for ( var link, i = 0; link = links[ i++ ]; )
		if ( link.getAttribute( 'confirmation' ) ) {
			attach( link, 'click', confirmClick );
			if ( ( confirmedHref = link.getAttribute( 'confirmation-href' ) ) )
				link.href = confirmedHref;
		}
} );

//----- font resizer -----------------------------------------------------------------------

var sizerTargets = [], sizerImages = [], sizerControl = null;

var sizerClick = function( event ) {
	var element = event.srcElement || ( event.target.nodeType == 3 ? event.target.parentNode : event.target );
	while ( element && !element.sizeDelta && !element.sizeValue )
		element = element.parentNode;
	if ( !element )
		return;
	var current = sizerControl.sizeCurrentFactor = element.sizeValue || Math.min( Math.max( sizerControl.sizeCurrentFactor
		+ element.sizeDelta, sizerControl.sizeMinFactor ), sizerControl.sizeMaxFactor );
	for ( var i = sizerTargets.length - 1; element = sizerTargets[ i-- ]; )
		element.style.fontSize = ( element.baseSize * current ) + 'px';
	for ( var i = sizerImages.length - 1; element = sizerImages[ i-- ]; )
		element.src = ( element.sizeValue ? element.sizeValue == current 
			: ( element.sizeDelta > 0 ? sizerControl.sizeMaxFactor : sizerControl.sizeMinFactor ) == current )
			? element.srcDisabled : element.srcEnabled;
	var date = new Date();
	date.setTime( date.getTime() + ( 90 * 24 * 60 * 60 * 1000 ) );
	document.cookie = 'user-font-size=' + current + '; expires=' + date.toGMTString() + '; path=/';
};

onload.push( function() {
	if ( !( sizerControl = document.getElementById( 'sizeController' ) ) )
		return;
	sizerControl.style.display = '';
	var min = sizerControl.sizeMinFactor = parseFloat( sizerControl.getAttribute( 'sizeMinFactor' ) || '0.8' );
	var max = sizerControl.sizeMaxFactor = parseFloat( sizerControl.getAttribute( 'sizeMaxFactor' ) || '1.4' );
	var current = sizerControl.sizeCurrentFactor = document.cookie.match( /user-font-size=([0-9]*\.[0-9]*)/ ) ? parseFloat( RegExp.$1 ) :
		Math.min( Math.max( parseFloat( sizerControl.getAttribute( 'sizeCurrentFactor' ) || '1.0' ), min ), max );
	var element = null, baseSize = null, sizeDelta = null;
	for ( var i = 0; ( element = document.getElementsByTagName( '*' )[ i ] ); i++ ) {
		if ( ( baseSize = element.getAttribute( 'baseSize' ) ) ) {
			element.baseSize = parseFloat( baseSize );
			element.style.fontSize = ( element.baseSize * current ) + 'px';
			sizerTargets.push( element );
		}
		if ( ( sizeDelta = element.getAttribute( 'sizeDelta' ) ) ) {
			element.sizeDelta = parseFloat( sizeDelta );
			attach( element, 'click', sizerClick );
			if ( element.tagName == 'IMG' ) {
				sizerImages.push( element );
				element.srcEnabled = element.getAttribute( 'srcEnabled' ) || element.src;
				element.srcDisabled = element.getAttribute( 'srcDisabled' ) || element.src;
				element.src = ( element.sizeDelta > 0 ? max : min ) == current ? element.srcDisabled : element.srcEnabled;
			}
		}
		if ( ( sizeValue = element.getAttribute( 'sizeValue' ) ) ) {
			element.sizeValue = parseFloat( sizeValue );
			attach( element, 'click', sizerClick );
			if ( element.tagName == 'IMG' ) {
				sizerImages.push( element );
				element.srcEnabled = element.getAttribute( 'srcEnabled' ) || element.src;
				element.srcDisabled = element.getAttribute( 'srcDisabled' ) || element.src;
				element.src = element.sizeValue == current ? element.srcDisabled : element.srcEnabled;
			}
		}
	}
} );

//----- switcher ---------------------------------------------------------------------------

tools.setters = {
	
	blend: function( array, controls, prefix ) {
		var time = parseFloat( controls.getAttribute( prefix + 'Transition' ) );
		var cancel = null;
		return function( oldIndex, newIndex ) {
			var animation = [];
			for ( var i = 0, one; one = array[ i++ ]; )
				if ( i == newIndex ) {
					one.style.display = '';
					one.style.opacity = '1.0';
					one.style.filter = '';
					one.style.zIndex = 0;
				} else if ( i == oldIndex ) {
					animation.push( { start: 0, duration: time, id: 'one', element: one, type: 'opacity', from: 1.0, to: 0.0 },
						              { start: 0, duration: time, id: 'one', element: one, type: 'display', from: '', to: 'none', mode: 'set' } );
					one.style.zIndex = 1;
				} else {
					one.style.display = 'none';
					one.style.opacity = '0.0';
					one.style.filter = 'alpha(opacity=0)';
					one.style.zIndex = 0;
				}
			if ( cancel )
				cancel();
			cancel = tools.animate( animation );
		};
	},

	style: function( array, controls, prefix ) {
		var attribute = controls.getAttribute( prefix + 'Attribute' );
		var onValue = controls.getAttribute( prefix + 'Selected' );
		var offValue = controls.getAttribute( prefix + 'Normal' );
		return function( oldIndex, newIndex ) {
			for ( var i = 0, one; one = array[ i++ ]; )
				one.style[ attribute ] = i == newIndex ? onValue : offValue;
		};
	},

	display: function( array ) {
		return function( oldIndex, newIndex ) {
			for ( var i = 0, one; one = array[ i++ ]; )
				one.style.display = i == newIndex ? '' : 'none';
		};
	},

	className: function( array, controls, prefix ) {
		var className = controls.getAttribute( prefix + 'Normal' ) || '';
		var selectedName = controls.getAttribute( prefix + 'Selected' ) || 'selected';
		return function( oldIndex, newIndex ) {
			for ( var i = 0, one; one = array[ i++ ]; )
				one.className = i == newIndex ? selectedName : className;
		};
	}

};

tools.switcher = function( controls, contents ) {
	var html = '', template = controls.getAttribute( 'switchTemplate' ), index = 1, count = 0;
	var contentsArray = [], controlsArray = [];
	for ( var i = 0, one; one = contents.childNodes[ i ++ ]; )
		if ( one.nodeType == 1 ) {
			contentsArray.push( one );
			count ++;
		}
	for ( var i = 0, one; one = contentsArray[ i ++ ]; ) {
		html += expression( template.replace( /\$index\$/g, '' + i ).replace( /\$count\$/g, '' + count )
			.replace( /\$title\$/g, one.getAttribute( 'switchTitle' ) || one.getAttribute( 'title' ) || '' ) );
		if ( one.style.display != 'none' )
			index = i;
	}
	controls.innerHTML = html; controls.style.display = '';
	for ( var current = 0, i = 0, one; one = controls.childNodes[ i ++ ]; )
		if ( one.nodeType == 1 ) {
			controlsArray.push( one );
			attach( one, 'click', click( ++ current ) );
		}
	var interval = parseFloat( controls.getAttribute( 'switchInterval' ) ) * 1000;
	var start = ( parseFloat( controls.getAttribute( 'switchStart' ) ) * 1000 ) || interval;
	var switchContent = tools.setters[ controls.getAttribute( 'switchContentMode' ) || 'display' ]( contentsArray, controls, 'switchContent' );
	var switchControls = tools.setters[ controls.getAttribute( 'switchControlsMode' ) || 'className' ]( controlsArray, controls, 'switchControls' );
	switchContent( index, index );
	switchControls( index, index );
	var contentsHover = false, controlsHover = false, timer = null;
	if ( interval ) {
		timer = window.setTimeout( timeout, start );
		attach( controls, 'mouseover', function() { controlsHover = this; } );
		attach( controls, 'mouseout', function() { if ( controlsHover == this ) controlsHover = null; } );
		attach( contents, 'mouseover', function() { contentsHover = this; } );
		attach( contents, 'mouseout', function() { if ( contentsHover == this ) contentsHover = null; } );
	}
	return;
	
	function click( index ) {
		return function() { 
			if ( interval )
				window.clearTimeout( timer );
			return select( index );
		}; 
	}
	
	function timeout() {
		select( contentsHover || controlsHover ? index : 1 + ( index % count ) );
	}
	
	function select( newIndex ) {
		switchContent( index, newIndex );
		switchControls( index, newIndex );
		index = newIndex;
		if ( interval )
			timer = window.setTimeout( timeout, interval );
		return false;
	}
};

onload.push( function() {
	for ( var i = 0, contents = null, controls; ( controls = document.getElementsByTagName( '*' )[ i++ ] ); )
		if ( ( contents = controls.getAttribute( 'switchContents' ) ) && ( contents = document.getElementById( contents ) ) )
			tools.switcher( controls, contents );
} );

//----- htmlstyle ---------------------------------------------------------------------------

var styleCounter = 0;

var styleClick = function( htmlClass, selection, store ) {
	var body = document.getElementsByTagName( 'body' )[ 0 ], html = document.getElementsByTagName( 'html' )[ 0 ];
	var baseStyle = html.className || '';
	if ( baseStyle.match( new RegExp( '(^|.*\\s)' + htmlClass + '-([\\S]+)($|\\s.*)' ) ) )
		html.className = RegExp.$1 + htmlClass + '-' + selection + RegExp.$3;
	else
		html.className = baseStyle + ' ' + htmlClass + '-' + selection;
	styleCounter ++;
	if ( body ) {
		var helpStyle = body.className || '';
		if ( helpStyle.match( new RegExp( '(^|.*\\s)tools-js-html-style-([\\S]+)($|\\s.*)' ) ) )
			body.className = RegExp.$1 + 'tools-js-html-style-' + styleCounter + RegExp.$3;
		else
			body.className = helpStyle + ' tools-js-html-style-' + styleCounter;
	}
	if ( store ) {
		var value = null; 
		if ( ! document.cookie.match( /(?:^|;\s*)htmlStyle=([^;\s]*)\s*(?:;|$)/ ) )
			value = htmlClass + ',' + selection;
		else {
			var styleMap = decodeURIComponent( RegExp.$1 );
			if ( styleMap.match( new RegExp( '(^|.*,)' + htmlClass + ',(?:[^,]*)($|,.*)' ) ) )
				value = RegExp.$1 + htmlClass + ',' + selection + RegExp.$2;
			else
				value = styleMap + ',' + htmlClass + ',' + selection;
		}
		var date = new Date();
		date.setTime( date.getTime() + ( 360 * 24 * 60 * 60 * 1000 ) );
		document.cookie = 'htmlStyle=' + encodeURIComponent( value ) + '; expires=' + date.toGMTString() + '; path=/';
	}
};

var styleIterateClick = function( htmlClass, styles ) {
	styles = styles.split( ' ' );
	var className = document.getElementsByTagName( 'html' )[ 0 ].className;
	if ( className.match( new RegExp( '(^|.*\\s)' + htmlClass + '-([\\S]+)($|\\s.*)' ) ) )
		for ( var i = 0, one; one = styles[ i++ ]; )
			if ( one == RegExp.$2 ) {
				if ( i < styles.length )
					return styleClick( htmlClass, styles[ i ], true );
				return;
			}
};

if ( document.cookie.match( /(?:^|;\s*)htmlStyle=([^;\s]*)\s*(?:;|$)/ ) ) {
	var styleMap = decodeURIComponent( RegExp.$1 ).split( ',' );
	for ( var i = 0, one; one = styleMap[ i++ ]; )
		styleClick( one, styleMap[ i++ ], false );
}

onload.push( function() {
	for ( var i = 0, htmlClass = null, one, two; ( one = document.getElementsByTagName( '*' )[ i++ ] ); )
		if ( ( htmlClass = one.getAttribute( 'htmlClass' ) ) )
			if ( ( two = one.getAttribute( 'htmlSelection' ) ) )
				attach( one, 'click', ( function( a, b ) { return function() { return styleClick( a, b, true ); }; } )( htmlClass, two ) );
			else if ( ( two = one.getAttribute( 'htmlIterate' ) ) )
				attach( one, 'click', ( function( a, b ) { return function() { return styleIterateClick( a, b ); }; } )( htmlClass, two ) );
} );

// ----- animate -----------------------------------------------------------------------------

tools.animate = function( animations ) {
	if ( ! animations || animations.length == 0 )
		return;
	var startTime = 0;
	var seen = {}, styles = '';
	for ( var i = 0, one; one = animations[ i++ ]; ) {
		one.start *= 1000; one.duration *= 1000;
		one.previous = seen[ one.id + '$' + one.type ];
		one.disabled = false;
		if ( typeof one.from == 'undefined' )
			one.from = one.to;
		seen[ one.id + '$' + one.type ] = one;
		if ( ! one.previous ) {
			one.previous = {};
			if ( onload )
				switch ( one.type ) {
					case 'top': styles += '#' + one.id + ' { top: ' + one.from.toFixed( 0 ) + 'px; }\n'; break;
					case 'left': styles += '#' + one.id + ' { left: ' + one.from.toFixed( 0 ) + 'px; }\n'; break;
					case 'right': styles += '#' + one.id + ' { right: ' + one.from.toFixed( 0 ) + 'px; }\n'; break;
					case 'bottom': styles += '#' + one.id + ' { bottom: ' + one.from.toFixed( 0 ) + 'px; }\n'; break;
					case 'width': styles += '#' + one.id + ' { width: ' + one.from.toFixed( 0 ) + 'px; }\n'; break;
					case 'height': styles += '#' + one.id + ' { height: ' + one.from.toFixed( 0 ) + 'px; }\n'; break;
					case 'z-index': styles += '#' + one.id + ' { z-index: ' + one.from.toFixed( 0 ) + '; }\n'; break;
					case 'opacity': styles += '#' + one.id + ' { opacity: ' + one.from.toFixed( 2 )
						+ '; filter: ' + ( one.from == 1 ? '' : 'alpha(opacity=' + ( one.from*100 ).toFixed(0) + ')' ) + ' }\n'; break;
				}
		}
	}
	if ( onload ) {
		document.write( '<style>\n' + styles + '</style>' );
		onload.push( start );
	} else
		start();
	return stop;
	
	function start() {
		for ( var i = 0, one; one = animations[ i++ ]; )
			one.element = one.element || document.getElementById( one.id );
		startTime = new Date().getTime();
		if ( onload )
			window.setTimeout( step, 0 );
		else
			step();
	}
	
	function step() {
		if ( ! animations )
			return;
		var now = new Date().getTime() - startTime, active = false, offset;
		for ( var i = 0, one; one = animations[ i++ ]; )
			if ( ! one.disabled )
				if ( ( offset = now - one.start ) >= 0 ) {
					var current = Math.min( offset / one.duration, 1 );
					switch ( one.mode ) {
						case 'set': current = current < 1 ? one.from : one.to; break;
						case 'cosine': current = one.from + ( one.to - one.from ) * ( 0.5 - Math.cos( current * Math.PI ) / 2 ); break;
						case 'exponential': current = one.from + ( one.to - one.from ) * ( 1.005 - Math.pow( 0.005, current ) ); break;
						case 'linear':
						default: current = one.from + ( one.to - one.from ) * current;
					}
					if ( current === one.current && offset > one.duration ) {
						one.disabled = true;
						continue;
					}
					active = true;
					if ( current !== one.current ) {
						one.current = current;
						one.previous.disabled = true;
						if ( current )
							switch ( one.type ) {
								case 'top': one.element.style.top = current.toFixed( 0 ) + 'px'; break;
								case 'left': one.element.style.left = current.toFixed( 0 ) + 'px'; break;
								case 'right': one.element.style.right = current.toFixed( 0 ) + 'px'; break;
								case 'buttom': one.element.style.buttom = current.toFixed( 0 ) + 'px'; break;
								case 'width': one.element.style.width = current.toFixed( 0 ) + 'px'; break;
								case 'height': one.element.style.height = current.toFixed( 0 ) + 'px'; break;
								case 'z-index': one.element.style.zIndex = current.toFixed( 0 ); break;
								case 'display': one.element.style.display = current; break;
								case 'opacity': one.element.style.opacity = current.toFixed( 2 );
									one.element.style.filter = current == 1 ? '' : 'alpha(opacity=' + ( current*100 ).toFixed(0) + ')'; break;
							}
					}
				}	else
					active = true;
		if ( active )
			window.setTimeout( step, 5 );
		else
			animations = null;
	}
	
	function stop() {
		animations = null;
	}
}

// ----- dropper -----------------------------------------------------------------------------

var expandTimer = function( div ) {
	if ( div.expanding ) {
		var max = div.expandableInnerContent.offsetHeight;
		var current = Math.min( div.expandableContent.offsetHeight + 10, max );
		div.expandableContent.style.height = current + 'px';
		if ( max == current )
			return;
	} else {
		var current = Math.max( div.expandableContent.offsetHeight - 10, 0 );
		div.expandableContent.style.height = current + 'px';
		if ( 0 == current )
			return;
	}
	window.setTimeout( ( function( a ) { return function() { expandTimer( a ); }; } )( div ), 10 );
};

var expandableClick = function( div, expand ) {
	div.expanding = expand;
	div.expandableExpand.style.display = expand ? 'none' : 'block';
	div.expandableCollapse.style.display = expand ? 'block' : 'none';
	window.setTimeout( ( function( a ) { return function() { expandTimer( a ); }; } )( div ), 10 );
};

tools.expandable = function( expandableStyle ) {
	document.write( '<style>\ndiv.' + expandableStyle + ' .expand { display: block; }\n' +
		'div.' + expandableStyle + ' .content { overflow: hidden; height: 0px; }\n</style>' );
	onload.push( function() {
		var divs = document.getElementsByTagName( 'div' ), pattern = new RegExp( '\\b' + expandableStyle + '\\b' );
		for ( var div, i = 0; div = divs[ i++ ]; )
			if ( pattern.test( div.className ) ) {
				var content = null, expand = null, collapse = null, innerContent = null;
				for ( var j = 0, one; one = div.childNodes[ j++ ]; )
					if ( /\bcontent\b/.test( one.className ) )
						content = one;
					else if ( /\bexpand\b/.test( one.className ) )
						expand = one;
					else if ( /\bcollapse\b/.test( one.className ) )
						collapse = one;
				for ( var j = 0, one; one = content.childNodes[ j++ ]; )
					if ( one.nodeType == 1 )
						innerContent = one;
				div.expandableContent = content;
				div.expandableExpand = expand;
				div.expandableCollapse = collapse;
				div.expandableInnerContent = innerContent;
				attach( expand, 'click', ( function( a ) { return function() { return expandableClick( a, true ); }; } )( div ) );
				attach( collapse, 'click', ( function( a ) { return function() { return expandableClick( a, false ); }; } )( div ) );
			}
	} );
};

// ----- autoscroller -----------------------------------------------------------------------------

var scrollHover = null, scrollHoverLeft = 0, scrollHoverTop = 0, scrollHoverWidth = 0, scrollHoverHeight = 0, scroller = [];

var scrollTimer = function() {
	for ( var i = 0; one = scroller[ i ++ ]; ) {
		if ( one == scrollHover )
			continue;
		if ( one.$delay-- > 0 )
			continue;
		one.$speed = Math.min( 4, Math.max( -4, one.$speed + one.$acceleration ) );
		if ( one.$speed > 0 && one.scrollWidth - one.offsetWidth - one.scrollLeft < 164 )
			one.$acceleration = -0.05;
		if ( one.$speed < 0 && one.scrollLeft < 164 )
			one.$acceleration = 0.05;
		one.scrollLeft = Math.round( one.scrollLeft + one.$speed );
	}
	if ( ! scrollHover )
		return;
	var deltaX = 0, deltaY = 0;
	if ( scrollHover.autoscroll != 'vertical' ) {
		if ( scrollHoverLeft < scrollHoverWidth * 1/4 )
			scrollHover.scrollLeft += ( scrollHoverLeft - scrollHoverWidth * 1/4 ) / 8;
		if ( scrollHoverLeft > scrollHoverWidth * 3/4 )
			scrollHover.scrollLeft += ( scrollHoverLeft - scrollHoverWidth * 3/4 ) / 8;
	}
	if ( scrollHover.autoscroll != 'horizonal' ) {
		if ( scrollHoverTop < scrollHoverHeight * 1/4 )
			scrollHover.scrollTop += ( scrollHoverTop - scrollHoverHeight * 1/4 ) / 8;
		if ( scrollHoverTop > scrollHoverHeight * 3/4 )
			scrollHover.scrollTop += ( scrollHoverTop - scrollHoverHeight * 3/4 ) / 8;
	}
};

var scrollMouseOver = function( event ) {
	var element = event.srcElement || event.target;
	while ( !element.autoscroll )
		if ( !( element = element.parentNode ) )
			return;
	scrollHover = element;
	var rect = getRect( element, document.body );
	scrollHoverLeft = event.clientX - rect.left - scrollHover.scrollLeft;
	scrollHoverWidth = rect.width;
	scrollHoverTop = event.clientY - rect.top - scrollHover.scrollTop;
	scrollHoverHeight = rect.height;
};

var scrollMouseOut = function( event ) {
	var element = event.srcElement || event.target;
	while ( !element.autoscroll )
		if ( !( element = element.parentNode ) )
			return;
	if ( scrollHover !== element )	
		return;
	scrollHover = null;
};

onload.push( function() {
	var found = false;
	var divs = document.getElementsByTagName( "div" );
	for ( var i = 0, one; one = divs[ i ++ ]; ) {
		if ( one.autoscroll = one.getAttribute( "autoscroll" ) ) {
			scroller.push( one );
			one.$delay = 50;
			one.$speed = 0;
			one.$acceleration = 0.05;
			found = true;
		}
		if ( one.mousescroll = one.getAttribute( "mousescroll" ) ) {
			attach( one, "mouseover", scrollMouseOver );
			attach( one, "mousemove", scrollMouseOver );
			attach( one, "mouseout", scrollMouseOut );
			found = true;
		}
	}
	if ( found )
		window.setInterval( scrollTimer, 40 );
} );

//----- table sort ---------------------------------------------------------------------------

tools.sortTable = function( cell, direction ) {
	while ( typeof cell.cellIndex == 'undefined' )
		if ( !( cell = cell.parentNode ) )
			return;
	if ( typeof direction == 'undefined' )
		direction = -1;
	var tbody = cell.parentNode.parentNode;
	var table = cell.parentNode.parentNode.parentNode;
	var column = cell.cellIndex;
	if ( table.sortedFor == column + 'x' + direction )
		direction = -direction;
	var rows = [];
	for ( var i = 1; i < table.rows.length; i++ )
		rows.push( table.rows[ i ] );
	rows.sort( function( a, b ) {
		return direction * ( parseInt( a.cells[ column ].getAttribute( 'intValue' ) ) -
			parseInt( b.cells[ column ].getAttribute( 'intValue' ) ) );
	} );
	for ( var i = 0; i < rows.length; i++ )
		tbody.appendChild( rows[ i ] );
	table.sortedFor = column + 'x' + direction;
};

//----- dropdowns ---------------------------------------------------------------------------

var dropDowns = [], dropTime = 0, dropTimer = function() {
	for ( var i = dropDowns.length, sub; sub = dropDowns[ --i ]; )
		if ( ! sub.$hoverTop && ! sub.$hoverSub ) {
			sub.style.visibility = 'hidden';
			dropDowns.splice( i, 1 );
		} else
			break;
};
var dropStartTimer = function() {
	window.clearTimeout( dropTime );
	dropTime = window.setTimeout( dropTimer, 500 );
}
var dropDown = function( top, sub, position, level ) {
	sub.$hoverSub = sub.$hoverTop = false;
	attach( top, 'mouseover', function() {
		var initial = sub.$initialPosition, initialParent = sub.$initialParent;
		if ( ! initial ) {
			initial = sub.$initialPosition = getRect( sub );
			initialParent = sub.$initialParent = getRect( sub.parentNode );
		}
		if ( dropDowns[ level ] == sub )
			return;
		var topRect = getRect( top );
		var subRect = getRect( sub );
		var parentRect = getRect( sub.parentNode );
		switch ( position ) {
			case 'downLeft':
				sub.style.left = ( topRect.left + topRect.width - subRect.width - initial.left + initialParent.left - parentRect.left ) + 'px';
				sub.style.top = ( topRect.top + topRect.height - initial.top + initialParent.top - parentRect.top ) + 'px'; break;
			case 'downRight':
				sub.style.left = ( topRect.left - initial.left + initialParent.left - parentRect.left ) + 'px';
				sub.style.top = ( topRect.top + topRect.height - initial.top + initialParent.top - parentRect.top ) + 'px'; break;
			case 'leftDown':
				sub.style.left = ( topRect.left - subRect.width - initial.left + initialParent.left - parentRect.left ) + 'px';
				sub.style.top = ( topRect.top - initial.top + initialParent.top - parentRect.top ) + 'px'; break;
			case 'rightDown':
				sub.style.left = ( topRect.left + topRect.width - initial.left + initialParent.left - parentRect.left ) + 'px';
				sub.style.top = ( topRect.top - initial.top + initialParent.top - parentRect.top ) + 'px'; break;
		}
		sub.style.visibility = '';
		sub.$hoverTop = true;
		for ( var i = level, one; one = dropDowns[ i++ ]; )
			one.style.visibility = 'hidden';
		dropDowns.splice( level, 100, sub );
	} );
	attach( top, 'mouseout', function() {
		sub.$hoverTop = false;
		dropStartTimer();
	} );
	attach( sub, 'mouseover', function() {
		sub.$hoverSub = true;
	} );
	attach( sub, 'mouseout', function() {
		if ( sub.$hoverSub ) {
			sub.$hoverSub = false;
			dropStartTimer();
		}
	} );
};

onload.push( function() {
	var divs = document.getElementsByTagName( 'div' ), dropAnchor, set;
	for ( var k = 0, one; one = divs[ k++ ]; )
		if ( ( dropAnchor = one.getAttribute( 'dropAnchor' ) ) )
			dropDown( document.getElementById( dropAnchor ), one, 
				one.getAttribute( 'dropMode' ) || 'downRight', parseInt( one.getAttribute( 'dropLevel' ), 10 ) || 0 );
		else if ( ( set = one.getAttribute( 'dropSetFor' ) ) ) {
			set = document.getElementById( set );
			var mode = one.getAttribute( 'dropMode' ) || 'downRight', level = parseInt( one.getAttribute( 'dropLevel' ), 10 ) || 0;
			for ( var i = 0, j = 0, top, sub; top = set.childNodes[ i++ ]; )
				if ( top.nodeType == 1 ) {
					while ( ( sub = one.childNodes[ j++ ] ) && sub.nodeType != 1 );
					dropDown( top, sub, sub.getAttribute( 'dropMode' ) || mode, level );
				}
		}
} );

//----- custom scrollbars ---------------------------------------------------------------------------

var scrollbars = [];
tools.scrollbar = function( handle, target ) {
	handle.parentNode.style.display = 'block';
	handle.parentNode.style.visibility = '';
	target.style.overflow = 'hidden';
	handle.$isHandle = true;
	var scrollbar = handle.parentNode;
	var scrollbarRect = getRect( scrollbar );
	var handleRect = getRect( handle );
	handleRect.left -= scrollbarRect.left;
	handleRect.top -= scrollbarRect.top;
	var dragging = null;
	var innerWidth = scrollbarRect.width - handleRect.width;
	var innerHeight = scrollbarRect.height - handleRect.height;
	attach( handle, 'mousedown', function( event ) {
		if ( dragging )
			return;
		var element = event.srcElement || event.target;
		if ( element.$isHandle ) {
			dragging = { startLeft: handleRect.left, startTop: handleRect.top, clientX: event.clientX, clientY: event.clientY };
			return cancelEvent( event );
		}
	} );
	attach( document.body, 'mouseup', function( event ) {
		if ( dragging ) {
			dragging = null;
			return cancelEvent( event );
		}
	} );
	attach( scrollbar, 'mousemove', function( event ) {
		if ( ! dragging )
			return;
		handleRect.left = Math.max( 0, Math.min( scrollbarRect.width - handleRect.width, dragging.startLeft + event.clientX - dragging.clientX ) );
		handleRect.top = Math.max( 0, Math.min( scrollbarRect.height - handleRect.height, dragging.startTop + event.clientY - dragging.clientY ) );
		handle.style.left = handleRect.left + 'px';
		handle.style.top = handleRect.top + 'px';
		var scrollWidth = target.scrollWidth - target.offsetWidth, scrollHeight = target.scrollHeight - target.offsetHeight;
		if ( innerWidth > 0 && scrollWidth > 0 )
			target.scrollLeft = Math.max( 0, Math.min( scrollWidth, Math.round( scrollWidth * handleRect.left / innerWidth ) ) );
		if ( innerHeight > 0 && target.scrollHeight > target.offsetHeight  )
			target.scrollTop = Math.max( 0, Math.min( scrollHeight, Math.round( scrollHeight * handleRect.top / innerHeight ) ) );
		return cancelEvent( event );
	} );
	var scrollWidth = target.scrollWidth - target.offsetWidth, scrollHeight = target.scrollHeight - target.offsetHeight;
	if ( innerWidth > 0 && scrollWidth > 0 )
		target.scrollLeft = Math.max( 0, Math.min( scrollWidth, Math.round( scrollWidth * handleRect.left / innerWidth ) ) );
	if ( innerHeight > 0 && target.scrollHeight > target.offsetHeight  )
		target.scrollTop = Math.max( 0, Math.min( scrollHeight, Math.round( scrollHeight * handleRect.top / innerHeight ) ) );
	scrollbars.push( target.$updateScrollbar = function() {
		if ( ! dragging ) {
			if ( innerWidth > 0 && target.scrollWidth > target.offsetWidth )
				handleRect.left = Math.max( 0, Math.min( scrollbarRect.width - handleRect.width, Math.round( target.scrollLeft * innerWidth / ( target.scrollWidth - target.offsetWidth ) ) ) );
			else 
				handleRect.left = Math.round( innerWidth / 2 );
			if ( innerHeight > 0 && target.scrollHeight > target.offsetHeight  )
				handleRect.top = Math.max( 0, Math.min( scrollbarRect.height - handleRect.height, Math.round( target.scrollTop * innerHeight / ( target.scrollHeight - target.offsetHeight ) ) ) );
			else 
				handleRect.top = Math.round( innerHeight / 2 );
			handle.style.left = handleRect.left + 'px';
			handle.style.top = handleRect.top + 'px';
		}
	} );
	attach( target, 'scroll', target.$updateScrollbar );
	if ( scrollbars.length == 1 )
		window.setInterval( function() {
			for ( var i = 0, one; one = scrollbars[ i++ ]; )
				one();
		}, 333 );
};

onload.push( function() {
	var divs = document.getElementsByTagName( 'div' ), element;
	for ( var i = 0, one; one = divs[ i++ ]; )
		if ( ( element = one.getAttribute( 'scrollHandleFor' ) ) )
			tools.scrollbar( one, document.getElementById( element ) );
} );


})();

