

/* 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();
} );

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

// ----- 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 ---------------------------------------------------------------------------

var switchStart = function( controls, contents ) {
	var html = '', template = controls.getAttribute( 'switchTemplate' ), index = 1, count = 0;
	for ( var i = 0, one; one = contents.childNodes[ i++ ]; )
		if ( one.nodeType == 1 )
			count ++;
	if ( count <= 1 )
		return;
	for ( var current = 0, i = 0, one; one = contents.childNodes[ i++ ]; )
		if ( one.nodeType == 1 ) {
			html += expression( template.replace( /\$index\$/g, '' + ( ++ current ) ).replace( /\$count\$/g, '' + count )
				.replace( /\$title\$/g, one.getAttribute( 'switchTitle' ) || one.getAttribute( 'title' ) || '' ) );
			if ( one.style.display != 'none' )
				index = current;
		}
	controls.innerHTML = html; controls.style.display = '';
	var className = controls.getAttribute( 'switchClass' ) || '', selectedName = controls.getAttribute( 'switchSelected' ) || 'selected';
	for ( var current = 0, i = 0, one; one = controls.childNodes[ i++ ]; )
		if ( one.nodeType == 1 ) {
			one.className = ++ current == index ? selectedName : className;
			attach( one, 'click', ( function( a ) { return function() { return click( a ); }; } )( current ) );
		}
	var interval = parseFloat( controls.getAttribute( 'switchInterval' ) ) * 1000 || 5000;
	var start = ( parseFloat( controls.getAttribute( 'switchStart' ) ) * 1000 ) || interval;
	var over = null;
	attach( controls, 'mouseover', function() { over = this; } );
	attach( controls, 'mouseout', function() { if ( over == this ) over = null; } );
	attach( contents, 'mouseover', function() { over = this; } );
	attach( contents, 'mouseout', function() { if ( over == this ) over = null; } );
	var call = function() { return click(); };
	var timeout = start ? window.setTimeout( call, start ) : 0;
	
	function click( to ) {
		var clicked = typeof to == 'number';
		index = clicked ? to : over ? index : 1 + ( index % count );
		for ( var current = 0, i = 0, one; one = contents.childNodes[ i++ ]; )
			if ( one.nodeType == 1 )
				one.style.display = ++ current == index ? '' : 'none';
		for ( var current = 0, i = 0, one; one = controls.childNodes[ i++ ]; )
			if ( one.nodeType == 1 )
				one.className = ++ current == index ? selectedName : className;
		if ( interval ) {
			if ( clicked )
				window.clearTimeout( timeout );
			timeout = window.setTimeout( call, clicked ? start : 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 ) ) )
			switchStart( 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 -----------------------------------------------------------------------------

var startTime = 0, animations = [];

var animateStep = function() {
	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 = 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;
					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 'opacity': one.element.style.opacity = current.toFixed( 2 );
							one.element.style.filter = current == 1 ? '' : 'alpha(opacity=' + ( current*100 ).toFixed(0) + ')'; break;
						case 'display': one.element.style.display = current; break;
					}
				}
			}	else
				active = true;
	if ( active )
		window.setTimeout( animateStep, 5 );
	else
		animations = null;
};

window.toolsAnimate = function( parameter ) {
	animations = parameter;
	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;
		seen[ one.id + '$' + one.type ] = one;
		if ( ! one.previous ) {
			one.previous = {};
			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 'opacity': styles += '#' + one.id + ' { opacity: ' + one.from.toFixed( 2 )
					+ '; filter: ' + ( one.from == 1 ? '' : 'alpha(opacity=' + ( one.from*100 ).toFixed(0) + ')' ) + ' }\n'; break;
				case 'display': styles += '#' + one.id + ' { display: ' + one.from + '; }\n'; break;
			}
		}
	}
	document.write( '<style>\n' + styles + '</style>' );
	onload.push( function() {
		for ( var i = 0, one; one = animations[ i++ ]; )
			one.element = document.getElementById( one.id );
		startTime = new Date().getTime();
		window.setTimeout( animateStep, 0 );
	} );
};

window.toolsAnimateSkip = function() {
	startTime = 0;	
};

// ----- 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 );
};

window.toolsExpandable = 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 ( one.nodeType == 1 ) {
						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;
						else for ( var k = 0, two; two = one.childNodes[ k++ ]; )
							if ( /\bcontent\b/.test( two.className ) )
								content = two;
							else if ( /\bexpand\b/.test( two.className ) )
								expand = two;
							else if ( /\bcollapse\b/.test( two.className ) )
								collapse = two;
					}
				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 && !element.$mousescroll )
		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 && !element.$mousescroll )
		if ( !( element = element.parentNode ) )
			return;
	if ( scrollHover !== element )	
		return;
	scrollHover = null;
};

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

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

window.toolsSortTable = 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';
			sub.$top.className = sub.$topClassName;
			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;
	sub.$top = top;
	attach( top, 'mouseover', function( event ) {
		var initial = sub.$initialPosition, initialParent = sub.$initialParent;
		if ( ! initial ) {
			initial = sub.$initialPosition = getRect( sub );
			initialParent = sub.$initialParent = getRect( sub.parentNode );
			sub.$topClassName = top.className;
			sub.$topClassDropped = top.getAttribute( 'dropClass' ) || sub.$topClassName;
		}
		sub.$hoverTop = true;
		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 = '';
		top.className = sub.$topClassDropped;
		for ( var i = level, one; one = dropDowns[ i++ ]; ) {
			one.style.visibility = 'hidden';
			one.$top.className = one.$topClassName;
		}
		dropDowns.splice( level, 100, sub );
	} );
	attach( top, 'mouseout', function( event ) {
		if ( ! sub.$hoverTop )
			return;
		sub.$hoverTop = false;
		dropStartTimer();
	} );
	attach( sub, 'mouseover', function( event ) {
		sub.$hoverSub = true;
	} );
	attach( sub, 'mouseout', function() {
		if ( ! sub.$hoverSub )
			return;
		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 );
					if ( sub )
						dropDown( top, sub, sub.getAttribute( 'dropMode' ) || mode, level );
				}
		}
} );

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

var scrollbars = [];
var scrollbar = function( handle, target ) {
	if ( handle.parentNode.style.display == 'none' )
		handle.parentNode.style.display = 'block';
	else if ( handle.parentNode.parentNode.style.display == 'none' )
		handle.parentNode.parentNode.style.display = 'block';
	target.style.overflow = 'hidden';
	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;
		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 );
};
onload.push( function() {
	var divs = document.getElementsByTagName( 'div' ), element;
	for ( var i = 0, one; one = divs[ i++ ]; )
		if ( ( element = one.getAttribute( 'scrollHandleFor' ) ) )
			scrollbar( one, document.getElementById( element ) );
	if ( scrollbars.length > 0 )
		window.setInterval( function() {
			for ( var i = 0, one; one = scrollbars[ i++ ]; )
				one();
		}, 333 );
} );


})();

