
Object.extend(Event, {
	wheel:function (event){
		var delta = 0;
		if (!event) event = window.event;
		if (event.wheelDelta) {
			delta = event.wheelDelta/120; 
			if (window.opera) delta = -delta;
		} else if (event.detail) { delta = -event.detail/3;	}
		return Math.round(delta); //Safari Round
	}
});

var DFTools =
{	
	urls: {
		self: '',
		base: '',
		reportError: 'problemReport.php'
	},
	
	setupUrlBase: function()
	{
		$A(document.getElementsByTagName("script")).findAll( function(s) {
			return (s.src && s.src.match(/DFTools\.js(\?.*)?$/))
		}).each( function(s) {
			DFTools.urls.self = s.src;
			DFTools.urls.base = DFTools.urls.self.replace(/[^/]+\/DFTools\.js(\?.*)?$/,'')
		});
	},
	
	writeEmail: function(u,d,tld)
	{
		document.write('<a href="');
		document.write('mailto:');
		document.write(u);
		document.write('@');
		document.write(d + '.' + tld);
		document.write('">');
		document.write(u);
		document.write('@');
		document.write(d + '.' + tld);
		document.write('</a>');
	},
	
	isValidEmail: function(string)
	{
		return /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(string);
	},
	
	loadFlash: function(container)
	{
		
	},
	
	imagesLoaded: function(container)
	{
		container = $(container);
		
		if(!container)
			return false;
		
		var images = container.getElementsBySelector('img');
		
		return Try.these(
			function() { return images.pluck('complete').all(); },
			function() { alert("Can't be sure if imagews are loaded, assuming yes..."); return true; }
		);
	},
	
	/**
	 * Set the default text for fields, which will appear when the fields are empty and dissapear when
	 * they gain focus.
	 *
	 * This function takes a field or an array of fields and applies default text to them. This means
	 * that when the field is empty, the default text will appear and the field will get a class of
	 * .defaultText, allowing the text to change color or style. When the field gains focus, the default
	 * text and class are removed.
	 *
	 * You may pass either a single element, and element ID, or an array of elements / element IDs. If
	 * the text field is omitted, the text for each field will be pulled from the field's title attribute
	 *
	 * @param Array/Element fields
	 * @param string [text]
	 * @return value
	 */
	defaultFieldText: function()
	{
		var defaultFieldTextHash = $H({});
		
		var defaultText = '';
		
		var defaultFieldTextMethods = $H(
		{
			getDefaultText: function()
			{
				return defaultFieldTextHash.get(this.identify());
			},
			
			setDefaultText: function(text)
			{
				defaultFieldTextHash.set(this.identify(),text);
			},
			
			defaultTextUpdate: function()
			{
				val = $F(this);
				var defaultText = this.getDefaultText();
				
				if(!val.length || val == defaultText)
				{
					this.value = defaultText;
					this.addClassName('defaultText');
				}
				else
				{
					this.removeClassName('defaultText');
				}
			},
			
			defaultTextClear: function()
			{
				val = $F(this);
				var defaultText = this.getDefaultText();
				
				if(val == defaultText)
				{
					this.value = '';
				}
				this.removeClassName('defaultText');
			}
		});
		
		var applyDefaultFieldText = function(field)
		{
			field = $(field);
			
			if(field)
			{
				defaultFieldTextMethods.each(function (pair) { field[pair.key] = pair.value.bind(field); });
				
				field.setDefaultText(defaultText ? defaultText : field.title);
				
				field.observe('blur',field.defaultTextUpdate);
				field.observe('focus',field.defaultTextClear);
				
				field.defaultTextUpdate();
			}
		};
		
		var defaultFieldText = function(fields,text)
		{
			defaultText = text;
			
			if(!(fields instanceof Array)) { fields = [fields]; }
			
			fields = $A(fields);
		
			fields.each(applyDefaultFieldText);
		};
		
		return defaultFieldText;
	}(),
	
	reportError: function(error,module,data)
	{
		try
		{
			var post = {
				errorName: error.name,
				errorMsg: error.message,
				module: module ? module : 'Unknown',
				report: {
					browserName: BrowserDetect.name,
					browserOS: BrowserDetect.OS,
					browserVersion: BrowserDetect.version,
					location: window.location.toString()
				}
			};
			
			if(error.fileName) { post.fileName = error.fileName; }
			if(error.lineNumber) { post.lineNumber = error.lineNumber; }
			if(error.number) { post.errorNumber = error.number; }
			
			if(error.error_function) { post.report.errorFunction = error.error_function; }
			if(error.error_handler) { post.report.errorHandler = error.error_handler; }
			
			if(error.description) { post.report.errorDescription = error.description; }
			if(error.stack) { post.report.stack = error.stack; }
			
			if(window.innerHeight) {
				post.report.windowHeight = window.innerHeight;
				post.report.windowWidth = window.innerWidth;
			}
			
			if(typeof(window.pageXOffset) != 'undefinied') {
				post.report.pageXOffset = window.pageXOffset;
				post.report.pageYOffset = window.pageYOffset;
			}
			
			if(document.referrer) {
				post.report.referrer = document.referrer;
			}
			
			if(data)
				post.report.moduleData = data;
			
			post.report = Object.toJSON(post.report);
			
			
			new Ajax.Request(DFTools.urls.base+DFTools.urls.reportError,{method:'post', parameters: post});
		}
		catch (error_error)
		{
			// Damn, we just can't win. Error when reporting an error!
			// Just give up and ignore this error.
			
			if(console)
			{
				console.log("Error while reporting en error!!",error_error);
			}
		}
	}
}

var DF_UI = 
{
	MoveWindow: function (win,x,y)
	{
		var pos = win.getPosition();
		win.setPosition(pos[0]+x,pos[1]+y);
	}
}

var writeEmail = DFTools.writeEmail;

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: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			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: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			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.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

var WebKitDetect = {  };

// If the user agent is WebKit, returns true. Otherwise, returns false.
WebKitDetect.isWebKit = function isWebKit()
{
    return RegExp(" AppleWebKit/").test(navigator.userAgent);
}

// If the user agent is WebKit, returns an array of numbers matching the "." separated 
// fields in the WebKit version number, with an "isNightlyBuild" property specifying
// whether the user agent is a WebKit nightly build. Otherwise, returns null.
//
// Example: 418.10.1 => [ 418, 10, 1 ] isNightlyBuild: false
WebKitDetect.version = function version() 
{
    /* Some example strings: 
            Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3
            Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Safari/521.32
     */
     
    // grab (AppleWebKit/)(xxx.x.x)
    var webKitFields = RegExp("( AppleWebKit/)([^ ]+)").exec(navigator.userAgent);
    if (!webKitFields || webKitFields.length < 3)
        return null;
    var versionString = webKitFields[2];

    var isNightlyBuild = versionString.indexOf("+") != -1;

    // Remove '+' or any other stray characters
    var invalidCharacter = RegExp("[^\\.0-9]").exec(versionString);
    if (invalidCharacter)
        versionString = versionString.slice(0, invalidCharacter.index);
    
    var version = versionString.split(".");
    version.isNightlyBuild = isNightlyBuild;
    return version;
}

// If the user agent is a WebKit version greater than or equal to the version specified
// in the string minimumString, returns true. Returns false otherwise. minimumString 
// defaults to "".
//
// Example usage: WebKitDetect.versionIsAtLeast("418.10.1")
WebKitDetect.versionIsAtLeast = function versionIsAtLeast(minimumString)
{
    function toIntOrZero(s) 
    {
        var toInt = parseInt(s);
        return isNaN(toInt) ? 0 : toInt;
    }

    if (minimumString === undefined)
        minimumString = "";
    
    var minimum = minimumString.split(".");
    var version = WebKitDetect.version();

    if (!version)
        return false;
        
    if (version.isNightlyBuild)
        return true;

    for (var i = 0; i < minimum.length; i++) {
        var versionField = toIntOrZero(version[i]);
        var minimumField = toIntOrZero(minimum[i]);
        
        if (versionField > minimumField)
            return true;
        if (versionField < minimumField)
            return false;
    }

    return true;
}

WebKitDetect.isMobile = function isMobile()
{
    return WebKitDetect.isWebKit() && RegExp(" Mobile/").test(navigator.userAgent);
}

WebKitDetect.mobileDevice = function mobileDevice()
{
    if (!WebKitDetect.isMobile())
        return null;
        
    var fields = RegExp("(Mozilla/5.0 \\()([^;]+)").exec(navigator.userAgent);
    if (!fields || fields.length < 3)
        return null;
    return fields[2];
}

// Example: 1C28 => [ 1, C, 28 ]
WebKitDetect._mobileVersion = function _mobileVersion(versionString)
{
    var fields = RegExp("([0-9]+)([A-Z]+)([0-9]+)").exec(versionString);
    if (!fields || fields.length != 4)
        return null;
    return [ fields[1], fields[2], fields[3] ];
}

WebKitDetect.mobileVersion = function mobileVersion()
{
    // grab (Mobile/)(nxnnn)
    var fields = RegExp("( Mobile/)([^ ]+)").exec(navigator.userAgent);
    if (!fields || fields.length < 3)
        return null;
    var versionString = fields[2];
    
    return WebKitDetect._mobileVersion(versionString);
}

WebKitDetect.mobileVersionIsAtLeast = function mobileVersionIsAtLeast(minimumString)
{
    function toIntOrZero(s) 
    {
        var toInt = parseInt(s);
        return isNaN(toInt) ? 0 : toInt;
    }

    if (minimumString === undefined)
        minimumString = "";

    var minimum = WebKitDetect._mobileVersion(minimumString);
    var version = WebKitDetect.mobileVersion();

    if (!version)
        return false;
        
    var majorVersInt = toIntOrZero(version[0]);
    var majorMinInt = toIntOrZero(minimum[0]);
    if (majorVersInt > majorMinInt)
        return true;
    if (majorVersInt < majorMinInt)
        return false;
    
    var majorVersAlpha = version[1];
    var majorMinAlpha = minimum[1];
    if (majorVersAlpha > majorMinAlpha)
        return true;
    if (majorVersAlpha < majorMinAlpha)
        return false;
    
    var minorVersInt = toIntOrZero(version[2]);
    var minorMinInt = toIntOrZero(minimum[2]);
    if (minorVersInt > minorMinInt)
        return true;
    if (minorVersInt < minorMinInt)
        return false;
    
    return true;
}


/*
*
* Copyright (c) 2007 Andrew Tetlaw
* 
*/
var FastInit = {
	onload : function() {
		if (FastInit.done) { return; }
		FastInit.done = true;
		for(var x = 0, al = FastInit.f.length; x < al; x++) {
			FastInit.f[x]();
		}
	},
	addOnLoad : function() {
		var a = arguments;
		for(var x = 0, al = a.length; x < al; x++) {
			if(typeof a[x] === 'function') {
				if (FastInit.done ) {
					a[x]();
				} else {
					FastInit.f.push(a[x]);
				}
			}
		}
	},
	listen : function() {
		if (/WebKit|khtml/i.test(navigator.userAgent)) {
			FastInit.timer = setInterval(function() {
				if (/loaded|complete/.test(document.readyState)) {
					clearInterval(FastInit.timer);
					delete FastInit.timer;
					FastInit.onload();
				}}, 10);
		} else if (document.addEventListener) {
			document.addEventListener('DOMContentLoaded', FastInit.onload, false);
		} else if(!FastInit.iew32) {
			if(window.addEventListener) {
				window.addEventListener('load', FastInit.onload, false);
			} else if (window.attachEvent) {
				return window.attachEvent('onload', FastInit.onload);
			}
		}
	},
	f:[],done:false,timer:null,iew32:false
};
/*@cc_on @*/
/*@if (@_win32)
FastInit.iew32 = true;
document.write('<script id="__ie_onload" defer src="' + ((location.protocol == 'https:') ? '//0' : 'javascript:void(0)') + '"><\/script>');
document.getElementById('__ie_onload').onreadystatechange = function(){if (this.readyState == 'complete') { FastInit.onload(); }};
/*@end @*/
FastInit.listen();


/* Date/Time Format v0.2; MIT-style license
By Steven Levithan <http://stevenlevithan.com> */

Date.prototype.format = function(mask) {
	var d = this; // Needed for the replace() closure
	
	// If preferred, zeroise() can be moved out of the format() method for performance and reuse purposes
	var zeroize = function (value, length) {
		if (!length) length = 2;
		value = String(value);
		for (var i = 0, zeros = ''; i < (length - value.length); i++) {
			zeros += '0';
		}
		return zeros + value;
	};
	
	return mask.replace(/"[^"]*"|'[^']*'|\b(?:d{1,4}|m{1,4}|yy(?:yy)?|([hHMs])\1?|TT|tt|[lL])\b/g, function($0) {
		switch($0) {
			case 'd':	return d.getDate();
			case 'dd':	return zeroize(d.getDate());
			case 'ddd':	return ['Sun','Mon','Tue','Wed','Thr','Fri','Sat'][d.getDay()];
			case 'dddd':	return ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'][d.getDay()];
			case 'm':	return d.getMonth() + 1;
			case 'mm':	return zeroize(d.getMonth() + 1);
			case 'mmm':	return ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][d.getMonth()];
			case 'mmmm':	return ['January','February','March','April','May','June','July','August','September','October','November','December'][d.getMonth()];
			case 'yy':	return String(d.getFullYear()).substr(2);
			case 'yyyy':	return d.getFullYear();
			case 'h':	return d.getHours() % 12 || 12;
			case 'hh':	return zeroize(d.getHours() % 12 || 12);
			case 'H':	return d.getHours();
			case 'HH':	return zeroize(d.getHours());
			case 'M':	return d.getMinutes();
			case 'MM':	return zeroize(d.getMinutes());
			case 's':	return d.getSeconds();
			case 'ss':	return zeroize(d.getSeconds());
			case 'l':	return zeroize(d.getMilliseconds(), 3);
			case 'L':	var m = d.getMilliseconds();
					if (m > 99) m = Math.round(m / 10);
					return zeroize(m);
			case 'tt':	return d.getHours() < 12 ? 'am' : 'pm';
			case 'TT':	return d.getHours() < 12 ? 'AM' : 'PM';
			// Return quoted strings with the surrounding quotes removed
			default:	return $0.substr(1, $0.length - 2);
		}
	});
};


//Element.prototype.setWidth = function(w)
//{
//	this.style.width = w;
//}

/* JScrollingSlides: Josh's Scrolling Slideshow Class */

JScrollingSlides = Class.create();
var JScrollingSlide_count = 0;
JScrollingSlides.prototype = 
{
	initialize: function(containerDiv,options)
	{
		this.containerDiv = $(containerDiv);
		
		this.debug = options['debug']?true:false;
		
		this.id = JScrollingSlide_count++;
		this.idPre = "jscrollslides_"+this.id;
		
		var thisObj = this;
		var func = function(e) { thisObj._initializeAfterLoaded(options); };
		Event.observe(window, 'load', func);
	},
	
	_failToLoad: function(message)
	{
		if(typeof(message) == "undefined" || !message || !message.length)
			message = "The slideshow could not be loaded.";
		
		this.containerDiv.update(message);
		this.running = false;
	},
	
	_initializeAfterLoaded: function(options)
	{
		// First check to see if we meet the requirements
		if(options['require_imageComplete'])
		{
			// if we need the complete property of images, WebKit < 523 doesn't have it.
			if(WebKitDetect.isWebKit() && !WebKitDetect.versionIsAtLeast("423"))
			{
				this._failToLoad("This slideshow requires Safari 3 or Firefox.");
				return false;
			}
		}
		
		// We need to delay loading until all of the images in our source list have loaded.
		this.slides = new Array();
		var sourceList = $(options['sourceList']);
		if(sourceList)
		{
			if(!DFTools.imagesLoaded(sourceList))
			{
				// If the images aren't loaded yet, set this function to run 0.5 seconds later, and return false.
				window.setTimeout(function(){this._initializeAfterLoaded(options);}.bind(this),500);
				return false;
			}
			this._loadSlidesFromList(sourceList);
		}
		
		var dimensions = Element.getDimensions(this.containerDiv);
		this.viewerWidth = dimensions.width;
		this.viewerHeight = dimensions.height;
		
		if(this.debug)
		{
			alert("Viewer Window: "+this.containerDiv+"\n"
				 +"   Width: "+dimensions.width+"\n"
				 +"   Height: "+dimensions.height+"\n"
				 +"   CSS Width: "+this.containerDiv.style.width+"\n"
				 +"   CSS Height: "+this.containerDiv.style.height+"\n"
				 +"   offsetWidth: "+this.containerDiv.offsetWidth+"\n"
				 +"   offsetHeight: "+this.containerDiv.offsetHeight+"\n"
				 +"   clientWidth: "+this.containerDiv.clientWidth+"\n"
				 +"   clientHeight: "+this.containerDiv.clientHeight+"\n"
				  );
		}
		
		this.containerDiv.style.position = "relative";
		this.containerDiv.style.overflow = "hidden";
		
		
		this.debug = options['debug']?true:false;
		this.slideSpacing = options['slideSpacing']?options['slideSpacing']:5;
		this.delay = options['delay']?options['delay']:250;
		this.speed = options['speed']?options['speed']:10;
		
		if(typeof(options['allowScroll']) == "undefined" || options['allowScroll'])
		{
			this._observeMouseEvents();
		}
		
		this._setup();
		
		this.start();
	},
	
	_setup: function()
	{
		this.containerDiv.innerHTML='';
		this.sliders = new Array();
		this.sliderWidths = new Array();
		this.sliderPositions = new Array();
		var divName,divCode;
		
		for(var i=0;i<2;i++)
		{
			divName = this.idPre+"_scroll_"+i;
			divCode = "<div id=\""+divName+"\" style=\"position:absolute;visibility:hidden;\"></div>";
			new Insertion.Top(this.containerDiv,divCode);
			$(divName).style.left = "0px";
			$(divName).style.top = "0px";
			if(this.debug)
			{
				$(divName).style.border = "1px solid #333";
				$(divName).style.visibility = "visible";
			}
			this.sliders[i] = $(divName);
			this.sliderWidths[i] = 0;
			this.sliderPositions[i] = 0;
		}
		
		this._fillSliderDivs();
	},
	
	_fillSliderDivs: function()
	{
		var divCode,divStyle,divId;
		var left = 0, totalWidth = 0,slideListCount = 0;
		var finalFirstItem = -1, slideOneWidth = 0;
		var slider = this.sliders[0];
		
		while(totalWidth < 2*this.viewerWidth)
		{
			if(slideListCount > 100)
			{
				// Something is wrong. Bail out!
				var minw = 2*this.viewerWidth;
				var realw = this.masterListDivWidth;
				alert("Slideshow creation failed. We were trying to make the master list div at least "+minw+
						"px wide, it is only "+realw+"px wide, and we're bailing out after 100 tries.");
				return false;
			}
			
			// Add every slide to the master list DIV.
			for(var i=0;i<this.slides.length;i++)
			{
				divId = this.idPre+"_slide_"+i;
				divStyle = "position:absolute;top:0px;left:"+left+"px;white-space:nowrap;";
				divCode = "<div id=\""+divId+"\" style=\""+divStyle+"\">"+this.slides[i]+"</div>";
				new Insertion.Top(slider,divCode);
				var dimensions = Element.getDimensions($(divId));
				left += dimensions.width + this.slideSpacing; 
				totalWidth += dimensions.width + this.slideSpacing;
				
				if(left >= this.viewerWidth && slider == this.sliders[0])	// this item has pushed us past the middle!
				{
					finalFirstItem = i + slideListCount*this.slides.length;
					this.sliderWidths[0] = left;
					left = 0;
					slider = this.sliders[1];
				}
			}
			slideListCount++;
		}
		this.sliderWidths[1] = left;
		
		this.sliderPositions[0] = this.viewerWidth;
		this.sliderPositions[1] = this.sliderPositions[0] + this.sliderWidths[0];
		
		if(this.debug)
		{
			alert("Viewer width: " + this.viewerWidth + "\n" +
				  "Slider 1 width: " + this.sliderWidths[0] + "\n" +
				  "Slider 1 position: " + this.sliderPositions[0] + "\n" +
				  "Slider 2 width: " + this.sliderWidths[1] + "\n" +
				  "Slider 2 Position: " + this.sliderPositions[1] + "\n" +
				  "Slide List Count: " + slideListCount + "\n");
		}
		
		this._placeSliders();
		
		for(var i=0;i<2;i++)
		{
			this.sliders[i].style.width=this.sliderWidths[i]+"px";
			this.sliders[i].style.height=(this.viewerHeight-5)+"px";
			this.sliders[i].style.visibility="visible";
		}
	},
	
	_loadSlidesFromList: function(list)
	{
		var listItems = list.getElementsByTagName("LI");
		var item;
		
		for(var i = 0; i < listItems.length; i++)
		{
			item = listItems.item(i);
			if(item.nodeName == "LI")
			{
				this.slides.push(item.innerHTML);
			}
		}
	},
	
	_placeSliders: function()
	{
		this.sliders[0].style.left = this.sliderPositions[0] + 'px';
		this.sliders[1].style.left = this.sliderPositions[1] + 'px';
	},
	
	_normalizeSliders: function()
	{
		if(this.speed >= 0 && this.sliderPositions[0] <= -1*this.sliderWidths[0])
			this.sliderPositions[0] = this.sliderPositions[1] + this.sliderWidths[1];
		if(this.speed >= 0 && this.sliderPositions[1] <= -1*this.sliderWidths[1])
			this.sliderPositions[1] = this.sliderPositions[0] + this.sliderWidths[0];
		if(this.running && this.speed < 0 && this.sliderPositions[0] > this.viewerWidth && this.sliderPositions[1] > this.viewerWidth)
		{
			this.sliderPositions[1] = -1* this.sliderWidths[1] + 1;
			this.sliderPositions[0] = this.sliderPositions[1] - this.sliderWidths[0];
		}
		if(this.running && this.speed < 0 && this.sliderPositions[0] > this.viewerWidth)
			this.sliderPositions[0] = this.sliderPositions[1] - this.sliderWidths[0];
		if(this.running && this.speed < 0 && this.sliderPositions[1] > this.viewerWidth)
			this.sliderPositions[1] = this.sliderPositions[0] - this.sliderWidths[1];
	},
	
	_queueNext: function()
	{
		var thisObj = this;
		var func = function() { thisObj.run(); };
		window.setTimeout(func,this.delay);
	},
	
	_observeMouseEvents: function()
	{
		var thisObj = this;
		var func = function(e) { thisObj.mouseOver(e); };
		Event.observe(this.containerDiv, 'mouseover', func);
		var func = function(e) { thisObj.mouseOut(e); };
		Event.observe(this.containerDiv, 'mouseout', func);
		var func = function(e) { thisObj.mouseMove(e); };
		Event.observe(this.containerDiv, 'mousemove', func);
		this._updateContainerPosition();
	},
	
	_updateContainerPosition: function()
	{
		Position.prepare();
		this.containerPosition = Position.cumulativeOffset(this.containerDiv);
	},
	
	mouseOver: function(e)
	{
		this._updateContainerPosition();
		this.saveSpeed = this.speed;
		this.speed = 0;
		
		/*var thisObj = this;
		var mouseOver = 
			function(e)
			{
				thisObj.mouseMove(e);
			};
			
		Event.observe(this.containerDiv, 'mousemove', mouseOver);*/
		
		
		//var func = function(e) { Event.stopObserving(this.containerDiv, 'mousemove', mouseOver); Event.stopObserving(this.containerDiv, 'mouseout', func); };
		//Event.observe(this.containerDiv, 'mouseout', func);
	},
	
	mouseOut: function(e)
	{
		this.speed= this.saveSpeed;
	},
	
	mouseMove: function(e)
	{
		var perc = ((e.clientX-this.containerPosition[0])/(.005*this.viewerWidth)) - 100;
		this.speed = (this.saveSpeed*perc/25)^3;
		if(Math.abs(perc) < 10)
			this.speed = 0;
		//window.status = "Mouse Move: clientX="+e.clientX+", perc="+perc+"%";
	},
	
	run: function()
	{
		if(this.running)
		{
			this.slide(this.speed);
			this._queueNext();
		}
		if (false && this.runs < 10)
		{
			alert("run called on "+this+", runs = "+this.runs+", running = "+this.running+"\n"+
				  "Slider 1 width: " + this.sliderWidths[0] + "\n" +
				  "Slider 1 position: " + this.sliderPositions[0] + "\n" +
				  "Slider 2 width: " + this.sliderWidths[1] + "\n" +
				  "Slider 2 Position: " + this.sliderPositions[1] + "\n");
			this.runs++;
		}
		//else
		//{
		//	alert("this.runs = "+this);
		//}
	},
	
	start: function()
	{
		this.running = true;
		this.runs = 0;
		this._queueNext();
	},
	
	slide: function(amt)
	{
		this.sliderPositions[0] -= amt;
		this.sliderPositions[1] -= amt;
		this._normalizeSliders();
		this._placeSliders();
	}
}

JPopinDiv = Class.create();
var JPopinDiv_count = 0;
JPopinDiv.prototype = 
{
	initialize: function(xPos,yPos,initialText,options)
	{
		this.id = JPopinDiv_count++;
		
		this.div_id= 'jpopin_'+this.id+'_div';
		this.topDiv_id= 'jpopin_'+this.id+'_top_div';
		this.midDiv_id= 'jpopin_'+this.id+'_mid_div';
		this.midLeftDiv_id= 'jpopin_'+this.id+'_midLeft_div';
		this.tabDiv_id= 'jpopin_'+this.id+'_tab_div';
		
		this.contentDiv_id= 'jpopin_'+this.id+'_left_div';
		
		this.xPos = xPos;
		this.yPos = yPos;
		
		this.zIndex = options['zIndex'] ? options['zIndex'] : 200;
		
		this.width = options['width'] ? options['width'] : 150;
		this.height = options['height'] ? options['height'] : 150;
		
		this.parentElement = options['parentElement'] ? $(options['parentElement']) : document.body;
		if(!this.parentElement) this.parentElement = document.body;
		
		this.tab = (options['tab']) ? options['tab'] : true;
		this.tabY = parseInt(options['tabY'] ? options['tabY'] : this.height/6);
		
		this.ltab = (options['ltab']) ? options['ltab'] : true;
		this.ltabY = parseInt(options['ltabY'] ? options['ltabY'] : -9999);
		
		var divCode;
		
		new Insertion.Bottom(this.parentElement,'<div id="'+this.div_id+'" style="position:absolute;left:'+this.xPos+'px;top:'+this.yPos+'px;display:none;z-index:'+this.zIndex+';"></div>');
		
		/* Top Divs */
  		new Insertion.Bottom(this.div_id,'<div class="jpopin_tl"></div>');
  		new Insertion.Bottom(this.div_id,'<div id="'+this.topDiv_id+'" class="jpopin_leftFlow" style="top: 0px;"></div>');
  		new Insertion.Bottom(this.topDiv_id,'<div class="jpopin_top" style="width:'+this.width+'px;"></div>');
  		new Insertion.Bottom(this.topDiv_id,'<div class="jpopin_tr" style="left:'+this.width+'px;"></div>');
  		
  		/* Mid Divs */
  		new Insertion.Bottom(this.div_id,'<div class="jpopin_left" style="height:'+this.height+'px;"></div>');
  		new Insertion.Bottom(this.div_id,'<div id="'+this.midDiv_id+'" class="jpopin_midFlow"></div>');
  		new Insertion.Bottom(this.midDiv_id,'<div id="'+this.midLeftDiv_id+'" class="jpopin_leftFlow"></div>');
  		
  		divCode  = '<div id='+this.contentDiv_id+' class="jpopin_content" style="width:'+this.width+'px;height:'+this.height+'px;';
  		if(options['contentDivStyle']) divCode += options['contentDivStyle'];
  		divCode += '"></div>';
  		new Insertion.Bottom(this.midLeftDiv_id,divCode);
  		new Insertion.Bottom(this.contentDiv_id,initialText);
  		
  		new Insertion.Bottom(this.midLeftDiv_id,'<div class="jpopin_right" style="left:'+this.width+'px;height:'+this.height+'px;"></div>');
  		
  		/* Bottom Divs */
  		new Insertion.Bottom(this.midDiv_id,'<div class="jpopin_bl" style="top:'+this.height+'px;"></div>');
  		new Insertion.Bottom(this.midLeftDiv_id,'<div class="jpopin_bottom" style="top:'+this.height+'px;width:'+this.width+'px;"></div>');
  		new Insertion.Bottom(this.midLeftDiv_id,'<div class="jpopin_br" style="top:'+this.height+'px;left:'+this.width+'px;"></div>');
  		
  		if(this.tab)
  		{
	  		new Insertion.Bottom(this.midLeftDiv_id,'<div id="'+this.tabDiv_id+'" class="jpopin_tab" style="left:'+this.width+'px;top:'+this.tabY+'px;"></div>');
  		}
  		if(this.ltab)
  		{
	  		new Insertion.Bottom(this.midLeftDiv_id,'<div id="'+this.tabDiv_id+'" class="jpopin_ltab" style="top:'+this.ltabY+'px;"></div>');
  		}
	},
	
	show: function()
	{
		Element.show(this.div_id);
	},
	
	hide: function()
	{
		Element.hide(this.div_id);
	}
}



/* JSlideShow: Josh's Slideshow Class */

JSlideShow = Class.create();
var JSlideShow_count = 0;
JSlideShow.prototype = 
{
	initialize: function(containerDiv,options)
	{
		this.containerDiv = $(containerDiv);
		
		this.debug = options['debug']?true:false;
		this.autoplay = (typeof options['autoplay'] != 'undefined')?options['autoplay']:false;
		
		this._setupComplete = false;
		
		this.slideSlots = new Array();
		this.slideCSlots = new Array();
		
		var thisObj = this;
		var func = function(e) { thisObj._initializeAfterLoaded(options); };
		Event.observe(window, 'load', func);
	},
	
	_initializeAfterLoaded: function(options)
	{
		this.id = JScrollingSlide_count++;
		this.idPre = "jslideshow_"+this.id;
		
		this.effectQueueName = this.idPre+"queue";
		
		var dimensions = Element.getDimensions(this.containerDiv);
		this.viewerWidth = dimensions.width;
		this.viewerHeight = dimensions.height;
		
		if(this.debug)
		{
			alert("Viewer Window: "+this.containerDiv+"\n"
				 +"   Width: "+dimensions.width+"\n"
				 +"   Height: "+dimensions.height+"\n"
				 +"   CSS Width: "+this.containerDiv.style.width+"\n"
				 +"   CSS Height: "+this.containerDiv.style.height+"\n"
				 +"   offsetWidth: "+this.containerDiv.offsetWidth+"\n"
				 +"   offsetHeight: "+this.containerDiv.offsetHeight+"\n"
				 +"   clientWidth: "+this.containerDiv.clientWidth+"\n"
				 +"   clientHeight: "+this.containerDiv.clientHeight+"\n"
				  );
		}
		
		this.containerDiv.style.position = "relative";
		this.containerDiv.style.overflow = "hidden";
		
		this.slides = new Array();
		if($(options['sourceList']))
			this._loadSlidesFromList($(options['sourceList']));
		
		//this.debug = options['debug']?true:false;
		this.delay = options['delay']?options['delay']*1000:4000;
		this.fadeDuration = options['fadeDuration']?options['fadeDuration']:3;
		
		this.bottomZ = options['bottomZ']?options['bottomZ']:10;
		
		this.fadeStyle = options['fadeStyle']?options['fadeStyle']:'crossfade'; // Options are 'crossfade' or 'straight'
		
		this.onShow = options['onShow']?options['onShow']:null;
		
		this._setup();
		
		if(options['slideslotStyle'])
			this.setSlideslotStyle(options['slideslotStyle']);
		
		if(this.autoplay)
			this.start();
	},
	
	
	_loadSlidesFromList: function(list)
	{
		var listItems = list.getElementsByTagName("LI");
		var item;
		
		for(var i = 0; i < listItems.length; i++)
		{
			item = listItems.item(i);
			if(item.nodeName == "LI")
			{
				this.slides.push(item);
			}
		}
	},
	
	
	_setup: function()
	{
		this.containerDiv.innerHTML='';
		this.slideSlots = new Array();
		this.slideCSlots = new Array();
		var divName,divCode;
		
		for(var i=0;i<2;i++)
		{
			divName = this.idPre+"_slot_"+i;
			divCName = this.idPre+"_slot_contents_"+i;
			divCode = "<div id=\""+divName+"\" style=\"position:absolute;width:"+
						this.viewerWidth+"px;text-align:center;display:none;\"><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"height:100%;width:100%;\"><tr><td style=\"height:100%;vertical-align:middle;text-align:center;\"><div id=\""+divCName+"\"></div></td></tr></table></div>";
			new Insertion.Top(this.containerDiv,divCode);
			$(divName).style.left = "0px";
			$(divName).style.top = "0px";
			if(this.debug)
			{
				$(divName).style.border = "1px solid "+(i<1?'#ff0000':'#0000ff');
				$(divName).style.display = "block";
			}
			this.slideSlots[i] = $(divName);
			this.slideCSlots[i] = $(divCName);
		}
		
		this.pos = 0;
		this.active = 0;
		
		this.runs = 0;
		this.queues = 0;
		
		this.effects = new Array();
		
		this._fillSlideSlots();
	},
	
	_fillSlideSlots: function()
	{
		var slideHtml = '';
		if(this.slides[this.pos] && this.slides[this.pos].innerHTML)
			slideHtml = this.slides[this.pos].innerHTML;
			
		this.slideCSlots[0].innerHTML = slideHtml;
		
		var nextSlide = this.slides.length ? (this.pos+1)%this.slides.length : 0;
		
		if(this.slides[nextSlide] && this.slides[nextSlide].innerHTML)
			slideHtml = this.slides[nextSlide].innerHTML;
			
		this.slideCSlots[1].innerHTML = slideHtml;
	},
	
	_queueNext: function()
	{
		var func;
		var thisObj = this;
		
		if(this.queues == 0)
		{
			// Nothing in queue, let's queue er up!
			func = function() { thisObj.queues--; thisObj.run(); };
			window.setTimeout(func,this.delay);
			this.queues++;
		}
		else
		{
			// we've been asked to add  to queue but queue is filled
			// so do nothing.
//			func = function() { thisObj.queues--; thisObj.run(); };
		}
	},
	
	setSlideslotStyle: function(propertyList)
	{
		Element.setStyle(this.slideSlots[0], propertyList);
		Element.setStyle(this.slideSlots[1], propertyList);
		return true;
	},
	
	run: function()
	{
		if(this.running)
		{
			this.runs++;
			this.advance(1);
			this._queueNext();
		}
	},
	
	start: function()
	{
		this.running = true;
		
//		new Effect.Appear(this.slideSlots[this.active], {duration: this.fadeDuration});
		new Element.show(this.slideSlots[this.active]);
		
		this._queueNext();
	},
	
	advance: function(n)
	{
		if(this.slides.length < 2)
		{
			if(this.debug)	alert(this.id+': advance called but slides.length==0!');
			return false;
		}
		
		var active = this.active;
		var inactive = (this.active+1)%2;
		var pos = this.pos;
		var next = (this.pos+1)%this.slides.length;
		
		this.slideCSlots[inactive].innerHTML = this.slides[next].innerHTML;
		this.slideSlots[inactive].style.zIndex = this.bottomZ+1;
		this.slideSlots[active].style.zIndex = this.bottomZ;
//		this.slideSlots[inactive].style.display = 'block'
//		this.slideSlots[active].style.display = 'block';
		
		if(this.effects[0])
			this.effects[0].cancel();
		if(this.effects[1])
			this.effects[1].cancel();

		this.effects[0] = new Effect.Fade(this.slideSlots[active], {duration: this.fadeDuration, queue: {scope: this.effectQueueName}});
		this.effects[1] = new Effect.Appear(this.slideSlots[inactive], {duration: this.fadeDuration, queue: {scope: this.effectQueueName}});
		
		if($(this.debug))
		{
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": add content for slide "+next+"<br>");
//			new Insertion.Top(this.debug,"SlideSlot "+active+": hide<br>");
//			new Insertion.Top(this.debug,"SlideSlot "+inactive+": show<br>");
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": set Zindex "+(this.bottomZ+1)+"<br>");
			new Insertion.Top(this.debug,"SlideSlot "+active+": set Zindex "+(this.bottomZ)+"<br>");
			new Insertion.Top(this.debug,"SlideSlot "+active+": Fade<br>");
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": Appear<br>");
			new Insertion.Top(this.debug,"<br>");
		}
		
		this.active = inactive;
		this.pos = next;
		
		if(this.onShow)
			this.onShow(next,this);
		
		return true;
	},
	
	_clearEffectQueue: function()
	{
		if(this.effects[0])
			this.effects[0].cancel();
		if(this.effects[1])
			this.effects[1].cancel();
		
		var q = Effect.Queues.get(this.effectQueueName);
		q.effects.each(function(e) { e.cancel() } );
		if($(this.debug))
		{
			alert(q);
			alert(q.length);
		}
	},
	
	show: function(i)
	{
		var active = this.active;
		var inactive = (this.active+1)%2;
		this.lastPos = this.pos;
		var next = i%this.slides.length;
		
		this._clearEffectQueue();
		
		
		this.slideSlots[active].style.opacity = '1.0';
		Element.show(this.slideSlots[active]);
		Element.hide(this.slideSlots[inactive]);
		this.slideSlots[inactive].style.opacity = '1.0';
		
		this.slideCSlots[inactive].innerHTML = this.slides[next].innerHTML;
		this.slideSlots[inactive].style.zIndex = this.bottomZ+1;
		this.slideSlots[active].style.zIndex = this.bottomZ;
		
		this.running = false;
		
		Element.show(this.slideSlots[active]);
		Element.hide(this.slideSlots[inactive]);
		
		if(this.effects[0])
			this.effects[0].cancel();
		if(this.effects[1])
			this.effects[1].cancel();

		this.effects[0] = new Effect.Fade(this.slideSlots[active], {duration: this.fadeDuration, queue: {scope: this.effectQueueName}});
		this.effects[1] = new Effect.Appear(this.slideSlots[inactive], {duration: this.fadeDuration, queue: {scope: this.effectQueueName}});
		
		if($(this.debug))
		{
			new Insertion.Top(this.debug,"--show("+i+")--<br>");
			new Insertion.Top(this.debug,"Cleared Effect Queue<br>");
			new Insertion.Top(this.debug,"SlideSlot "+active+": show<br>");
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": hide<br>");
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": add content for slide "+next+"<br>");
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": set Zindex "+(this.bottomZ+1)+"<br>");
			new Insertion.Top(this.debug,"SlideSlot "+active+": set Zindex "+(this.bottomZ)+"<br>");
			new Insertion.Top(this.debug,"SlideSlot "+active+": Fade<br>");
			new Insertion.Top(this.debug,"SlideSlot "+inactive+": Appear<br>");
			new Insertion.Top(this.debug,"<br>");
		}
		
		this.active = inactive;
		this.pos = next;
		
		if(this.onShow)
			this.onShow(next,this);
	}
}

DFDataGrid = Class.create();
DFDataGrid.prototype = 
{
	initialize: function(containerDiv,data,options)
	{
		this.containerDiv = $(containerDiv);
		
		options = $H(options);
		
		this.debug = options['debug']?true:false;
		
		this._setupComplete = false;
		
		this.data = new $A(data);
		this.dataView = false;
		
		this._setOptions(options);
		
		var thisObj = this;
		var func = function(e) { window.setTimeout(function(){thisObj._initializeAfterLoaded();},500); };
		Event.observe(window, 'load', func);
		
		this._setContainerStyles();
		
		this._setContainerLoading();
		
		this.headerDiv = false;
		this.headerTable = false;
	},
	
	_setContainerLoading: function()
	{
		if(this.loadingDiv == undefined || !this.loadingDiv)
		{
			var html = "<h2 class=\"dataTable_loadingMessage\">Loading Data...</h2><div class=\"dataTable\" style=\"display:none;\"></div>";
			new Insertion.Top(this.containerDiv,html);
			
			el = $$('#'+this.containerDiv.id+' h2.dataTable_loadingMessage');
			this.loadingDiv = el[0];
		}
		
		this.containerDiv.setStyle(
			{
				cursor: 'wait'
			}
		);
	},
	
	_clearContainerLoading: function()
	{
		this.containerDiv.setStyle(
			{
				cursor: 'default'
			}
		);
	},
	
	defaultOptions: function()
	{
		return $H(
		{
			hidePrefix:			'_',
			resizeDivPrefix:	'dataTable_resize',
			
			resizeWidth:		5,
			defaultColWidth:	200,
			
			colWidths:			[],
			colNames:			{},
			colTypes:			{},
			filterCols:			true,
			filterboxFuncs:		{},
			
			filterIcon:			'/images/filter.png',
			filterboxClass:		'dataTable_filterBox',
			
			sort:				false,
			sortInv:			false,
			
			filter:				false
		});
	},
	
	_setOptions: function(options)
	{
		var defaults = this.defaultOptions();
		
		var thisObj = this;
		
		defaults.each(function(v){ thisObj[v.key] = (typeof(options[v.key]) == 'undefined') ? v.value : options[v.key] });
		
		this.colWidths = $A(this.colWidths);
		this.colNames = $H(this.colNames);
		this.filterFuncs = $H(this.filterFuncs);
		
		if(this.filterCols !== true)
			this.filterCols = $A(this.filterCols);
	},
	
	colName: function(index)
	{
		if(typeof(index) == 'number')
			index = this._cols[index];
		
		if(typeof(index) == 'undefined')
			return false;
		
		if(typeof(this.colNames[index]) == 'undefined' || !this.colNames[index])
			return index;
		
		return this.colNames[index];
	},
	
	_setContainerStyles: function()
	{
		this.containerDiv.setStyle(
			{
				overflow: 'auto',
				backgroundColor: '#fff'
			}
		);
		this.containerDiv.makePositioned();
	},
	
	_initializeAfterLoaded: function()
	{
		this._parseData();
		
		this._doFilterAndSort();
		
		this.refresh();
	},
	
	_parseData: function()
	{
		this._cols = $A();
		
		var thisObj = this;
		
		// Go through each row of data and see what columns we have available.
		this.data.each(function(row)
		{
			var cols = Object.keys(row);
			var prefixLen = thisObj.hidePrefix.length;
			cols = cols.reject(function(e){ return e.substring(0,prefixLen) == thisObj.hidePrefix });
			cols = thisObj._cols.concat(cols).uniq();
			thisObj._cols = cols;
			
		});
		
		// Now, make sure we st up each column properly
		
		this._cols.each(function(col)
		{
			if(typeof(thisObj.colTypes[col]) == 'undefined' || !thisObj.colTypes[col])
			{
				thisObj.colTypes[col] = 'text';
			}
		});
	},
	
	sortBy: function(col,invert)
	{
		if(invert==undefined)
		{
			if(this.sort == col)
			{
				this.sortInv = !this.sortInv;
			}
			else
			{
				this.sort = col;
				this.sortInv = false;
			}
		}
		else
		{
			this.sort = col;
			this.sortInv = invert;
		}
		
		var headers = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_header a');
		
		headers.invoke('removeClassName','sort');
		
		this.filterAndSort();
	},
	
	filterBy: function(col,regexp)
	{
		if(typeof(this.filter)=='undefined' || !this.filter)
			this.filter = $H({});
		
		this.filter[col] = regexp;
		
		this.filterAndSort();
	},
	
	_passesFilter: function(row)
	{
		if(typeof(this.filter)=='undefined' || !this.filter)
			return true;
		
		return this.filter.all(function(test)
			{
				return (row[test.key].toString().indexOf(test.value.toString()) != -1);
			});
	},
	
	_doFilterAndSort: function()
	{
		var thisObj = this;
		
		this._setContainerLoading();
		
		this.dataView = $R(0,this.data.length-1);
		
		if(this.filter)
		{
			this.dataView = this.dataView.select(function(n){ return thisObj._passesFilter(thisObj.data[n]); })
		}
		
		if(this.sort)
		{
			this.dataView = this.dataView.sortBy(function(n)
			{
				return thisObj.data[n][thisObj.sort];
			});
		}
		
		this.dataView = $A(this.dataView);
		
		if(this.sortInv)
			this.dataView.reverse();
	},
	
	filterAndSort: function()
	{
		this._doFilterAndSort();
		
		this.refresh(false);
	},
	
	refresh: function(refreshHeader)
	{
		this._setContainerLoading();
		
		var el;
		
		this._cells = $A();
		
		el = $$('#'+this.containerDiv.id+' div.dataTable');
		this.tableDiv = el[0];
		
		if(refreshHeader != false)
			this._buildHeader();
		
		this._buildGrid();
		this._fillGrid();
		
		this._updateColWidths();
		
		this._addResizeHooks();
		
		this.loadingDiv.hide();
		this.tableDiv.show();
		
		this._updateColWidths();
		
//		Position.clone(this.headerDiv,this.headerHoverDiv,{offsetLeft: 2, offsetTop: 2});
//		this.headerHoverDiv.update(this.headerDiv.innerHTML);
//		this.headerHoverDiv.show();
//		this.headerDiv.setStyle({visibility: 'hidden'});
		
		this._clearContainerLoading();
	},
	
	_observeFilter: function(filterIcon,col)
	{
		var thisObj = this;
		
		if(typeof(thisObj.filterboxFuncs[col]) == 'undefined')
			thisObj.filterboxFuncs[col] = this.defaultFilterboxFunction.bindAsEventListener(this);
		
		filterIcon.observe('click',thisObj.filterboxFuncs[col]);
	},
	
	_observeFilterHide: function(e,box,col)
	{
		if(typeof(box) != 'undefined' && box)
			new Effect.BlindUp(box);
		
		if(typeof(col) != 'undefined' && col)
			this._observeFilter(e.target,col);
		
		return false;
	},
	
	_buildHeader: function()
	{
		var thisObj = this;
		
		var html, header;
		
		// Create the header div and header UL:
		
		var html = "<div class=\"dataTable_header\" style=\"position:relative;top:0px;z-index:5;\"><table class=\"dataTable_header\"><tr></tr></table></div>";
		
		new Insertion.Bottom(this.tableDiv,html);
		
		header = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_header');
		this.headerDiv = header[0];
		
		header = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_header table.dataTable_header');
		this.headerTable = header[0];
		this.headerRow = header[0].down().down();
		
		this.containerDiv.observe('scroll',function(e){thisObj.headerDiv.style.top=(thisObj.containerDiv.scrollTop)+'px';})
		
		var c = 0;
		
		this._cols.each(function(col)
		{
			var e_odd = (c%2)?'odd':'even';
			
			var colHeader = "<a href=\"#\" onclick=\"return false;\">"+thisObj.colName(col)+"</a>";
			
			html = "<td class=\"col"+c+" "+e_odd+"\"><div>"+colHeader+"</div></td>";
			html += "<td class=\"dataTable_resize\"><div class=\""+thisObj.resizeDivPrefix+c+"\">&nbsp;</div></td>";
			new Insertion.Bottom(thisObj.headerRow,html);
			
			var link = thisObj.headerRow.down('td',c*2).down().down();
			link.observe('click', function(e){ thisObj.sortBy(col); $(this).addClassName('sort'); });
			
			
			if(thisObj.filterCols === true || thisObj.filterCols.indexOf(col) != -1)
			{
				colHeader = "<img src=\""+thisObj.filterIcon+"\">";
				new Insertion.After(link,colHeader);
				var filterIcon = link.next();
				
				thisObj._observeFilter(filterIcon,col);
			}
			
			c++;
		});
				
		new Insertion.Top(document.body,'<div class="dataTable_header" style="position: absolute;border: none;z-index: 2;"></div>');
		header = $(document.body).down();
		this.headerHoverDiv = header;
	},
	
	_buildGrid: function()
	{
		var thisObj = this;
		
		var html, el;
		
		// Destroy the existing grid div if it exists:
		
		if(this.gridDiv != undefined)
		{
			if(this.gridDiv)
			{
				el = $(this.gridDiv);
				if(el && el != undefined)
					el.remove();
			}
		}
		
		// Create the grid div:
		
		var html = "<div class=\"dataTable_grid\"><table class=\"dataTable_grid\"><tbody><tr class=\"dataTable_preRow\"></tr><tr class=\"dataTable_postRow\"></tr></tbody></table></div>";
		
		new Insertion.Bottom(this.tableDiv,html);
		
		el = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_grid');
		this.gridDiv = el[0];
		
		el = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_grid table.dataTable_grid');
		this.gridTable = el[0];
		
		el = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_grid table.dataTable_grid tbody tr');
		this.gridPreRow = el[0];
		this.gridPostRow = el[1];
	},
	
	_fillGrid: function()
	{
		var thisObj = this;
		
		var el = this.gridPostRow;			// el is now the tbody.
		
		this.dataView.each(function(n)
		{
			var html = "<tr>";
			
			var row = this.data[n];
			
			var c = 0;
			
			thisObj._cols.each(function(col)
			{
				var e_odd = (c%2)?'odd':'even';
				html += "<td class=\"col"+c+" "+e_odd+"\"><div>"+row[col]+"</div></td>";
				html += "<td class=\"dataTable_resize\"><div class=\""+thisObj.resizeDivPrefix+c+"\">&nbsp;</div></td>";
				c++;
			});
			
			html +'</tr>';
			
			new Insertion.Before(el,html);
		});
	},
	
	_getResizeCells: function()
	{
		//var resizeCells = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_grid table.dataTable_grid tbody tr td.dataTable_resize');
		var resizeCells = $$('#'+this.containerDiv.id+' td.dataTable_resize');
		
		return resizeCells;
	},
	
	_getDataCells: function(col)
	{
		if(!this._cells)
			this._cells = $A();
		
		if(!this._cells[col])
		{
			//this._cells[col] = $$('#'+this.containerDiv.id+' div.dataTable div.dataTable_grid table.dataTable_grid tbody tr td.col'+col);
			this._cells[col] = $$('#'+this.containerDiv.id+' td.col'+col + ' div');
		}
		
		return this._cells[col];
	},
	
	_addResizeHooks: function()
	{
		var thisObj = this;
		
		var resizeCells = this._getResizeCells();
		
		var resizeDragHandler = function(a){thisObj.resizeDragHandler(a)};
		
//		resizeCells.invoke('observe','mouseDown',thisObj.resizeDragHandler);
		resizeCells.each(function(resize){
			var div = resize.down();
//			new Draggable(div); 
			new Draggable(div,{
							constraint:'horizontal',
							change:resizeDragHandler,
							revert: true}); 
		});	
	},
	
	_updateColWidths: function(col)
	{
		var thisObj = this;
		
		var totalWidth = 0;
		
		totalWidth = this.colWidths.inject(0,function(acc,n){return acc+n});
		
		totalWidth += this.resizeWidth * this._cols.length;
		
		this.headerTable.setWidth(totalWidth+'px');
		this.gridTable.setWidth(totalWidth+'px');
		
		var c = 0;
		
		if(col==undefined)
		{
			this._cols.each(function(col)
			{
				var cells;
	
				cells = thisObj._getDataCells(c);
				
				if(typeof(thisObj.colWidths[c]) == 'undefined')
					thisObj.colWidths[c] = thisObj.defaultColWidth;
				
//				cells.invoke('setStyle',{width: thisObj.colWidths[c]+'px'});
				cells.invoke('setWidth',thisObj.colWidths[c]+'px');
				
				c++;
			});
		}
		else
		{
			var cells = this._getDataCells(col);
			cells.invoke('setWidth',this.colWidths[col]+'px');
		}
		
		var resizeCells = this._getResizeCells();
		resizeCells.invoke('setWidth',this.resizeWidth+'px');;
		resizecells = null;
	},
	
	getColNum: function(element)
	{
		var colNum = element.classNames().toArray();
//		var colNum = element.className;
		colNum = colNum[0].substr(this.resizeDivPrefix.length);
		
		return colNum;
	},
	
	resizeDragHandler: function(drag)
	{
		var colNum, colPos, sliderPos, diff;
		
		diff = drag.currentDelta();
		diff = diff[0];
		
		colNum = this.getColNum(drag.element);
		
		this.colWidths[colNum] += diff;
		
		this._updateColWidths(colNum);
	},
	
	resizeFinishHandler: function(e)
	{
		alert("Resize");
	},
	
	defaultFilterboxFunction: function(event)
	{
		var thisObj = this;
		
		if(event.type == 'click')
		{
			// We're responding to the filter icon click.
			// Determine the coumn and column number
			var colNum = this.getColNum(event.target.up().up().next().down());
			var col = this._cols[colNum];
			
			// Tell the filterIcon to stop observing clicks, otherwise we may get called multiple times
			event.target.stopObserving('click',this.filterboxFuncs[col]);
			
			// Create a filter box
			var filterBox = this.newFilterbox(col);
			
			// Display it
			new Effect.BlindDown(filterBox);
			
			event.target.observeFilterHide = this._observeFilterHide.bindAsEventListener(this,filterBox,col);
			
			// Tell the filter icon to observe clicks which will close the box
			event.target.observe('click',event.target.observeFilterHide );
		}
		else if (event.type == 'submit')
		{
			// We're responding to the form submission
			// Find our form and box
			var filterBoxForm = event.target, filterBox = event.target.up();
			
			// Determine col number and reference
			var colNum = $F(filterBoxForm['col']), col = false;
			
			if(typeof(colNum) == 'undefined' || !(col = this._cols[colNum]) || typeof(col) == undefined)
			{
				alert('Column number was not present in form. Please contact a developer.');
				new Effect.Fade(filterBox);
				return false;
			}
			
			// Mark the grid as loading so users know what's going on
			this._setContainerLoading();
			
			// Find the filter icon
			
			var filterIcon = Try.these(
				function() { return thisObj.headerRow.down('td',colNum*2).down().down().next(); },
				function() { console.log("Couldn't find the filter icon!!!"); return false; },
				function() { return false; }
			) || false;
			
			// Hide the filter box
			new Effect.BlindUp(filterBox);
			
			// Now, make the filter icon observe the show filter box filter event again
			if(filterIcon)
			{
				filterIcon.stopObserving('click',filterIcon.observeFilterHide);
				this._observeFilter(filterIcon,col);
			}
			
			// Determine the column data type
			var type = this.colTypes[col];
			
			if(typeof(type) == 'undefined' || !type)
				type = 'text';
			
			// Now, filter by that type
			switch(type)
			{
				case 'text':
				default:
					this.filterBy(col,$F(filterBoxForm['filter']));
					break;
			}
			
			// Make sure the "loading" message is cleared
			
			this._clearContainerLoading();
			
			return false;
		}
	},
	
	newFilterbox: function(col)
	{
		var thisObj = this;
		
		var type = this.colTypes[col];
		
		var colNum = this._cols.indexOf(col);
		
		if(typeof(type) == 'undefined' || !type)
			type = 'text';
		
		var html,box,boxForm,headerCell,el,i;
		
		html = "<div class=\""+this.filterboxClass+"\" style=\"position:absolute;display:none;z-index: 10;\"></div>";
		
		new Insertion.Bottom(this.containerDiv,html);
		
		box = this.containerDiv.immediateDescendants();
		box = box[box.length-1];
		
		headerCell = this.headerDiv.down('td.col'+colNum);
		
		Position.clone(headerCell,box,{setWidth:false,setHeight:false,offsetLeft: 0, offsetTop: headerCell.clientHeight});
		
		box.setStyle({backgroundColor: headerCell.getStyle('backgroundColor')});
		
		//new Insertion.Bottom(box,"<p><b>Filter</b>: "+this.colName(col)+"</p>");
		new Insertion.Bottom(box,"<form onsubmit=\"return false;\"></form>");
		
		boxForm = box.down('form');
		
		boxForm.observe('submit',function(e){return thisObj.defaultFilterboxFunction(e);});
		
		var val = '';
		
		if(this.filter && typeof(this.filter[col]) != 'undefined')
			val = this.filter[col];
		
		switch(type)
		{
			case 'number':
				new Insertion.Bottom(boxForm,"<p>Filter: <select name=\"filter\"><option>--Select--</option></select></p>");
				el = $(boxForm['filter']);
				el.down().value='';
				this.uniqVals(col).each(function(v){new Insertion.Bottom(el,"<option>"+v+"</option>");});
				i = $A(el.options).pluck('value').indexOf(val);
				if(i!=-1)
					el.selectedIndex=i;
				new Insertion.Bottom(boxForm,"<input type=\"hidden\" name=\"col\" value=\""+colNum+"\">");
				new Insertion.Bottom(boxForm,"<input type=\"submit\" value=\"Go\">");
				break;
				
			case 'enum':
				new Insertion.Bottom(boxForm,"<p>Filter: <select name=\"filter\"><option>--Select--</option></select></p>");
				el = $(boxForm['filter']);
				el.down().value='';
				this.uniqVals(col).each(function(v){new Insertion.Bottom(el,"<option>"+v+"</option>");});
				i = $A(el.options).pluck('value').indexOf(val);
				if(i!=-1)
					el.selectedIndex=i;
				new Insertion.Bottom(boxForm,"<input type=\"hidden\" name=\"col\" value=\""+colNum+"\">");
				new Insertion.Bottom(boxForm,"<input type=\"submit\" value=\"Go\">");
				break;
			
			case 'text':
			default:
				new Insertion.Bottom(boxForm,"<p>Filter: <input type=\"text\" name=\"filter\" value=\""+val+"\"></p>");
				new Insertion.Bottom(boxForm,"<input type=\"hidden\" name=\"col\" value=\""+colNum+"\">");
				new Insertion.Bottom(boxForm,"<input type=\"submit\" value=\"Go\">");
				break;
		}
		
		return box;
	},
		
	uniqVals: function(col)
	{
		if(typeof(this._uniqVals) == 'undefined')
			this._uniqVals = $H({});
		
		if(typeof(this._uniqVals[col]) == 'undefined')
		{
			this._uniqVals[col] = $A(this.data.pluck(col)).uniq().sort();
		}
		
		return this._uniqVals[col];
	}
}


var DFThemeObject = Class.create();

DFThemeObject.FixedDiv = Class.create();
DFThemeObject.FixedDiv.prototype =
{
    initialize: function(options)
	{
		options = $H(options);
		
		this.div = false;
		
		this.pos = $H({});
		
		this._setOptions(options);
		
		this._createDiv();
	},
	
	defaultOptions: function()
	{
		return $H(
		{
			cssClass:		'DFFixed',
			innerHTML:		'&nbsp;',
			bodyHack:		true
		});
	},
	
	_setOptions: function(options)
	{
		var defaults = this.defaultOptions();
		
		var thisObj = this;
		
		defaults.each(function(v){ thisObj[v.key] = (typeof(options[v.key]) == 'undefined') ? v.value : options[v.key] });
	},
	
	_createDiv: function()
	{
		var html,className, body = $(document.body);
		
		className = this.cssClass;
		html = '<div class="'+this.cssClass+'">'+this.innerHTML+'</div>';
		new Insertion.Top(body,html);
		this.div = body.down();
		this._setDivStyle(this.div);
	},
	
	_setDivStyle: function(div)
	{
		var style = $H({position: 'fixed'});
		
		if(BrowserDetect.browser == "Explorer" && parseInt(BrowserDetect.version) < 7)
			style.position = 'absolute';
		
		div.setStyle(style);
	},
	
	setPos: function(side,px)
	{
		var style = $H({});
		
		if(BrowserDetect.browser == "Explorer" && parseInt(BrowserDetect.version) < 7)
		{
			if(this.bodyHack)
			{
				style[side] = px+'px';
				this.div.setStyle(style);
			}
			else
			{
				/*switch(side)
				{
					case 'top': style[side] = 'expression( ('+px+' + (tempVar=document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop))+\'px\' )'; break;
					case 'right': style[side] = px+'px'; break;
					case 'bottom': style[side] = 'expression( ('+px+' + (tempVar=document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop))+\'px\' )'; break;
					case 'left': style[side] = px+'px'; break;
				}*/
				
				switch(side)
				{
					case 'top': this.div.style.setExpression(side, '('+px+' + (tempVar=document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop))+\'px\''); break;
					case 'right': style[side] = px+'px'; break;
					case 'bottom': this.div.style.setExpression('top', "__DFThemeObject__FixedDiv_setBottom(" + px + ',' + this.div.uniqueID + ")"); break;
					case 'left': style[side] = px+'px'; break;
				}
				
				
				if(style.size())
					this.div.setStyle(style);
				
				//alert(side + ' style: ' + this.div.style[side]);
				
				
				//Event.observe(window,'scroll',function(){alert('scroll');this.setPos(side,px);}.bindAsEventListener(this));
			}
		}
		else
		{
			style[side] = px+'px';
			this.div.setStyle(style);
		}
	}
}

function __DFThemeObject__FixedDiv_setBottom(dist,obj)
{
	return dist - obj.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) 
			+ ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop );
}


DFThemeObject.SiteEdge = Class.create();
DFThemeObject.SiteEdge.prototype =
{
    initialize: function(options)
	{
		options = $H(options);
		
		this.divs = $H({top:		false,
						 right:		false,
						 bottom:	false,
						 left:		false});
		this.divTOs = $H({top:			false,
						   right:		false,
						   bottom:		false,
						   left:		false});
		
		this._setOptions(options);
		
		//var thisObj = this;
		//this._initialized = false;
		//this._initfunc = function(e) { window.setTimeout(function(){thisObj._initializeAfterLoaded();},500); };
		
		//Event.observe(window, 'load', this._initializeAfterLoaded.bindAsEventListener(this));
		
		
		if(BrowserDetect.browser == "Explorer" && parseInt(BrowserDetect.version) >= 7)
			this._initializeAfterLoaded();
		else
			FastInit.addOnLoad(this._initializeAfterLoaded.bindAsEventListener(this));
	},
	
	_initializeAfterLoaded: function(e)
	{
		this._createDivs();
		
		if(this.addBodyMargin)
			this._addBodyMargin();
			
		this._setContentSize();
		Event.observe(window,'resize',this._setContentSize.bind(this));
	},
	
	defaultOptions: function()
	{
		return $H(
		{
			cssClassPrefix:		'SiteEdge',
			
			addBodyMargin:		true,
			extraBodyMargin:	{top: 0, right: 0, bottom: 0, left: 0},
			divContents:		{top: '&nbsp;', right: '&nbsp;', bottom: '&nbsp;', left: '&nbsp;'},
			
			contentWidth:		undefined,
			contentHeight:		undefined,
			
			debugDiv:			false,
			backgroundOffset:	false,
			
			callbacks:			{}
		});
	},
	
	_setOptions: function(options)
	{
		var defaults = this.defaultOptions();
		
		var thisObj = this;
		
		defaults.each(function(v){ thisObj[v.key] = (typeof(options[v.key]) == 'undefined') ? v.value : options[v.key] });
		
		this.callbacks = $H(this.callbacks);
		
		var divHashOpts = $A(['extraBodyMargin','divContents'])
		
		divHashOpts.each(function(opt)
		{
			this[opt] = $H(this[opt]);
		
			this.divs.keys().each(function(k)
			{
				if(typeof(this[opt][k]) == 'undefined') this[opt][k]=defaults[opt][k];
			}.bind(this));
		}.bind(this));
	},
	
	_createDivs: function()
	{
		var html,className, body = $(document.body);
		
		var sides = this.divs.keys();
		
		sides.each(function(side)
		{
			className = this.cssClassPrefix+'_'+side;
			html = '<div class="'+this.cssClassPrefix+' '+className+'">'+this.divContents[side]+'</div>';
			//new Insertion.Top(body,html);
			this.divTOs[side] = new DFThemeObject.FixedDiv({cssClass: this.cssClassPrefix+' '+className, innerHTML: this.divContents[side]});
			this.divs[side] = body.down('.'+className);
			this._setDivStyle(this.divs[side],side);
		}.bind(this));
	},
	
	_setDivStyle: function(div,side)
	{
		switch(side)
		{
			case 'top':
				div.setStyle({
					width: '100%'
				});
				this.divTOs[side].setPos('left',0);
				this.divTOs[side].setPos('top',0);
				break;
				
			case 'right':
				div.setStyle({
					top: '0px',
					right: '0px',
					height: '100%'
				});
				this.divTOs[side].setPos('right',0);
				this.divTOs[side].setPos('top',0);
				break;
			
			case 'bottom':
				div.setStyle({
					bottom: '0px',
					left: '0px',
					width: '100%'
				});
				this.divTOs[side].setPos('left',0);
				this.divTOs[side].setPos('bottom',0);
				break;
			
			case 'left':
				div.setStyle({
					top: '0px',
					left: '0px',
					height: '100%'
				});
				this.divTOs[side].setPos('left',0);
				this.divTOs[side].setPos('top',0);
				break;
		}
		
		if(this.debugDiv)
		{
			new Insertion.Bottom(this.debugDiv,'<p>'+side+' div style: position:'+div.getStyle('position')+', top:'+div.getStyle('top')+'</p>');
		}
	},
	
	_addBodyMargin: function()
	{
		var size, body, style;
		
		//alert('In _addBodyMargin');
		
		body = $(document.body);
		style = $H({});
		
		if(!body) return false;
		
		this.divs.each(function(div)
		{
			if(div.value)
			{
				size = false;
				cssName = 'margin'+div.key.charAt(0).toUpperCase() + div.key.substring(1);
				
				switch(div.key)
				{
					case 'top':
					case 'bottom': size = div.value.getHeight(); break;
						
					case 'top':
					case 'bottom': size = div.value.getWidth(); break;
				}
				
				style[cssName] = (size+this.extraBodyMargin[div.key])+'px';
			}
		}.bind(this));
		
		body.setStyle(style);
	},
	
	_setContentSize: function()
	{
		var size, diff, body, style;
		
		//alert('In _setContentSize');
		
		body = $(document.body);
		
		if(!body) return false;
		
		size = Try.these(
				function() { if(BrowserDetect.browser == 'Safari') throw 'next';
								return [document.documentElement.clientWidth,document.documentElement.clientHeight]; },
				function() { return [window.innerWidth,window.innerHeight]; },
				function() { return [document.body.clientWidth,document.body.clientHeight]; });
		
		if(typeof(this.contentWidth) != 'undefined')
		{
			diff = size[0] - this.contentWidth;
			
			style = {width: (diff/2)+'px'};
			this.divs.left.setStyle(style);
			this.divs.right.setStyle(style);
			
			
			if(this.debugDiv)
			{
				new Insertion.Bottom(this.debugDiv,'<p>Resize: window width:'+size[0]+', diff:'+diff+'</p>');
			}
		}
		
		//alert('set widths');
		
		if(typeof(this.contentHeight) != 'undefined')
		{
			diff = size[1] - this.contentHeight;
			style = {paddingTop: Math.max(Math.floor(diff/2),0)+'px'};
			//alert('set style: '+style.paddingTop);
			this.divs.top.setStyle(style);
			//alert('test');
			style = {marginTop: Math.floor(diff/2)+'px',marginBottom: (diff/2)+'px'};
			this.divs.left.setStyle(style);
			this.divs.right.setStyle(style);
			style = {paddingBottom: Math.max(Math.floor(diff/2),0)+'px'};
			this.divs.bottom.setStyle(style);
			
			
			
			if(this.debugDiv)
			{
				new Insertion.Bottom(this.debugDiv,'<p>Resize: window height:'+size[1]+', diff:'+diff+'</p>');
			}
			
			if(this.backgroundOffset)
			{
				var offset = (size[1]-this.divs.bottom.getHeight()+this.backgroundOffset)*-1;
				this.divs.bottom.setStyle({backgroundPosition: "0px " + (offset)+ "px"}); 
			}
		}
		
		this._addBodyMargin();
		
		if(!this._haveSetContentSize)
		{
			// Setting the size for the first time often adds scroll bars. So we need
			// to recalculate everything again!
			
			this._haveSetContentSize=true;
			this._setContentSize();
		}
		
		if(typeof(this.callbacks.setContentSize) == 'function')
			this.callbacks.setContentSize();
	}
	
}

DFThemeObject.CustomScrollbar = Class.create( 
{
	initialize: function(containerDiv,options)
	{
		this.containerDiv = $(containerDiv);
		
		options = $H(options);
		
		this._setOptions(options);
		
		//if(BrowserDetect.browser == "Explorer" && parseInt(BrowserDetect.version) >= 7)
		//	this._initializeAfterLoaded();
		//else
		//	FastInit.addOnLoad(this._initializeAfterLoaded.bindAsEventListener(this));
		
		Event.observe(window,'load',this._initializeAfterLoaded.bindAsEventListener(this));
	},
	
	_initializeAfterLoaded: function(e)
	{
		this._createDivs();
		
		if(this.addBodyMargin)
			this._addBodyMargin();
			
		this._setContentSize();
		Event.observe(window,'resize',this._setContentSize.bind(this));
	},
	
	defaultOptions: function()
	{
		return $H(
		{
			cssClassPrefix:		'customScrollbar',
			minThumbHeight:		10,
			maxThumbHeight:		9999,
			
			scrollbarWidth : 10,
			scrollbarMargin : 5,
			arrowSpeed : 20,
			wheelSpeed : 20,
			showArrows : false,
			arrowSize : 0,
			animateTo : false,
			dragMinHeight : 10,
			dragMaxHeight : 99999,
			animateInterval : 100,
			animateStep: 3,
			maintainPosition: true,
			
			arrowImages: {up: '/images/up.gif', down: '/images/down.gif'}
		});
	},
	
	
	updateThumbHeight: function()
	{	
		this._contentHeight = this._contentDiv.getHeight();
		this._containerHeight = this.containerDiv.getHeight();
		this._trothHeight = this._troth.getHeight();
		
		this._thumbHeight = 0;
		
		if(this._contentHeight < this._containerHeight)
		{
			this._scrollDiv.hide();
			this.enabled = false;
			return true;
		}
		else
		{
			this.enabled = true;
			this._scrollDiv.show();
		}
		
		if(this._contentHeight)
			this._thumbHeight = Math.round((this._trothHeight * this._containerHeight) / this._contentHeight);
		
		if(this._thumbHeight < this.minThumbHeight)
			this._thumbHeight = this.minThumbHeight;
			
		if(this._thumbHeight > this.maxThumbHeight)
			this._thumbHeight = this.maxThumbHeight;
		
		this._thumb.setStyle({
			height: this._thumbHeight +"px"
		});
		
		this.setContainerStyle();
	},
		
	setContainerStyle: function()
	{
		this.containerDiv.setStyle({
			overflow: 'hidden'
		});
	},
	
	_setOptions: function(options)
	{
		var defaults = this.defaultOptions();
		
		var thisObj = this;
		
		defaults.each(function(v){ thisObj[v.key] = (options.get(v.key) == 'undefined') ? v.value : options.get(v.key) });
	},
	
	_initializeAfterLoaded: function()
	{
		// Make sure the container is positioned so we can absolutly position within it.
		Element.makePositioned(this.containerDiv);
		
		// The existing container will now contain two DIVs, one for the content and one for the scroll bar
		// We will create those divs now:
		
		this._createContentDiv();
		this._createScrollDiv();
		this._createThumb();
		this.setContainerStyle();
		this._addEventListeners();
		
		window.setTimeout(this.updateThumbHeight.bind(this),500);
	},
	
	_createContentDiv: function()
	{
		// create a new div to hold the content:
		
		this._contentDiv = $(document.createElement("div"));
		this._contentDiv.hide();
		this._contentDiv.addClassName(this.cssClassPrefix + "_content");
		this._setContentBoxStyle(this._contentDiv);
		this._contentDiv.update(this.containerDiv.innerHTML);
		this.containerDiv.update('');
		this.containerDiv.appendChild(this._contentDiv);
		this._contentDiv.show();
	},
	
	_createScrollDiv: function()
	{
		// create a new div to hold the scroll bar:
		
		this._scrollDiv = $(document.createElement("div"));
		this._scrollDiv.hide();
		this._scrollDiv.addClassName(this.cssClassPrefix + "_scrollDiv");
		this._setScrollDivStyle(this._scrollDiv);
		this.containerDiv.appendChild(this._scrollDiv);
		
		// Inside that div we need an up arrow, a down arrow, and a troth for the thumb
		this._arrows = {};
		this._arrows.up = $(document.createElement("div"));
		this._arrows.down = $(document.createElement("div"));
		this._troth = $(document.createElement("div"));
		this._troth.addClassName(this.cssClassPrefix + "_troth");
		this._scrollDiv.appendChild(this._arrows.up);
		this._scrollDiv.appendChild(this._troth);
		this._scrollDiv.appendChild(this._arrows.down);
		this._updateArrows();
		
		// Now show the scrollbar div
		// We have to show it now because otherwise we can't set our troth height
		this._scrollDiv.show();
		
		// We have our arrows so setup our troth
		
		var trothHeight, upHeight, downHeight;
		
		trothHeight = this.containerDiv.getHeight();
		upHeight = this._arrows.up.getHeight();
		downHeight = this._arrows.down.getHeight();
		
		trothHeight -= upHeight + downHeight;
		
		this._troth.setStyle({
			position: 'absolute',
			top: upHeight + 'px',
			left: '0px',
			height: trothHeight + 'px',
			width: this.scrollbarWidth + 'px'
		})
	},
	
	_createThumb: function()
	{
		if(this._thumb)
			this._thumb.remove();
		
		this._thumb = $(document.createElement("div"));
		this._thumb.hide();
		this._thumb.addClassName(this.cssClassPrefix+"_thumb");
		this._troth.appendChild(this._thumb);
		this._thumb.show();
		this.updateThumbHeight();
		
		var change = this._slide.bind(this);
		
		// Now add the behavior to the thumb...
		var sliderOpts = {
			axis:	'vertical',
			range: $R(0,this._contentHeight - this._containerHeight),
			onSlide: change,
			onChange: change
		}
		this._slider = new Control.Slider(this._thumb, this._troth, sliderOpts)
	},
	
	_setContentBoxStyle: function(el)
	{
		var dims;
		
		dims = this.containerDiv.getDimensions();
		
		dims.width -= this.scrollbarWidth;
		
		el.setStyle({
			position: 'absolute',
			left: '0px',
			top: '0px',
			width: dims.width + 'px'
		});
	},
	
	_setScrollDivStyle: function(el)
	{	
		el.setStyle({
			position: 'absolute',
			right: '0px',
			top: '0px',
			height: '100%',
			width: this.scrollbarWidth + 'px'
		});
	},
	
	_updateArrows: function()
	{
		var arrows = $H(this._arrows).keys();
		
		arrows.each(function(a)
		{
			var style = {
				position: 'absolute',
				left: '0px'
			};
			
			switch(a)
			{
				case 'up':		style.top = '0px'; break;
				case 'down':	style.bottom = '0px'; break;
			}
			
			this._arrows[a].setStyle(style);
			this._arrows[a].addClassName(this.cssClassPrefix + "_arrow");
			this._arrows[a].addClassName(this.cssClassPrefix + "_"+a+"Arrow");
			this._arrows[a].update("<a href=\"#\" onclick=\"return false;\"><img src=\""+this.arrowImages[a]+"\" border=\"0\"></a>");
			
		}.bind(this));
	},
	
	scroll: function(n)
	{
		if(!this.enabled)
			return false;
		
		//new Effect.Move(this._thumb, {x: 0, y: -1 * n, mode: 'relative'});
		this._slider.setValue(this._slider.value + n);
	},
	
	_slide: function(n)
	{
		if(!this.enabled)
			return false;
		
		var pos = -1 * n;
		this._contentDiv.setStyle({
			top: pos + 'px'
		});
	},
	
	_addEventListeners: function()
	{
		var func;
		
		func = function(e)
		{
			var dist = this.wheelSpeed * Event.wheel(e) * -1;
			this.scroll(dist);
		}.bind(this);
		
		Event.observe(this.containerDiv, "mousewheel", func, false);
		Event.observe(this.containerDiv, "DOMMouseScroll", func, false); // Firefox
		
		
		func = function(e){this.scroll(this.arrowSpeed * -1);}.bind(this);		
		Event.observe(this._arrows.up, "mousedown", func, false);
		
		func = function(e){this.scroll(this.arrowSpeed);}.bind(this);
		Event.observe(this._arrows.down, "mousedown", func, false);
	}
	
});

DFThemeObject.DropdownMenu = Class.create(Enumerable,
{	
	MenuItem: function(opts)
	{
		this.name = opts.name ? opts.name : 'menuItem_'+DFThemeObject.DropdownMenu.menuItemCount++;
		this.text = opts.text ? opts.text : '';
		this.href = opts.href ? opts.href : '#';
		
		this.handler = typeof(opts.handler) == 'function' ? opts.handler : false;
	},
	
	defaultOptions: function()
	{
		return $H(
		{
			cssPrefix:		'dropdown_',
			source:			false,
			applyTo:		false,
			xOffset:		0,
			yOffset:		0,
			hideDelay:		500
		});
	},
	
	initialize: function(options)
	{
		/********** Private Members **********/
		var myItems = $A();
		
		/********** Privileged Methods **********/
		
		this.itemCount = function()
		{
			return myItems.length;
		};
		
		this.getItem = function(n)
		{
			return myItems[n];
		};
		
		this.setItem = function(n,newItem)
		{
			return myItems[n] = newItem;
		};
		
		this.addItem = function(menuItem)
		{
			myItems.push(menuItem);
		};
		
		this.removeItem = function(n)
		{
			myItems[n] = null;
		};
		
		this.removeItem = function(n)
		{
			myItems[n] = null;
		};
		
		this._each = myItems._each.bind(myItems);
		
		
		/********** Initialize **********/
		
		this.rendered = false;
		
		this.visible = false;
		
		this.showing = this.hiding = this.locked = false;
		
		options = $H(options);
		
		this._setOptions(options);
		
		this._els = {};
		
		//FastInit.addOnLoad(this._initializeAfterLoaded.bindAsEventListener(this));
		Event.observe(window,'load',this._initializeAfterLoaded.bindAsEventListener(this));
	},
	
	
	/********** Public Properties **********/
	
	domIdPrefix: 'DFThemeObject_DropdownMenu_',
	
	/********** Public Methods **********/
	
	buildMenu: function()
	{
		if(!this.rendered)
		{
			this._createMenu();
			this.rendered = true;
		}
	},
	
	show: function()
	{
		if(!this.locked)
		{
			this.showing = true;
			this.buildMenu();
			this._els.container.show();
			this.visible = true;
			this.showing = false;
		}
	},
	
	hide: function()
	{
		this.hiding = true;
		
		window.setTimeout(this._hide.bind(this),this.hideDelay);
	},
	
	apply: function(el)
	{
		this._stopObserving();
		
		if(el)
			this.applyTo = $(el);
		
		this.reposition();
		
		this._startObserving();
	},
	
	reposition: function()
	{
		var el;
		
		if(this.applyTo && (el=$(this.applyTo)))
		{
			var yOffset = this.yOffset;
			yOffset += el.getHeight();
			try {
				this._els.container.absolutize();
				Element.clonePosition(this._els.container,el,{setLeft:true,setTop:true,setWidth:false,setHeight:false,offsetLeft:this.xOffset,offsetTop:yOffset});
			} catch(e) { }
			try {
				this._els.container.absolutize();
				Element.clonePosition(this._els.container,el,{setLeft:true,setTop:true,setWidth:false,setHeight:false,offsetLeft:this.xOffset,offsetTop:yOffset});
			} catch(e) { }
		}
	},
	
	/********** Personal Methods **********/
	
	_setOptions: function(options)
	{
		var defaults = this.defaultOptions();
		
		defaults.each(function(v){ this[v.key] = (typeof(options.get(v.key)) == 'undefined') ? v.value : options.get(v.key) },this);
	},
	
	_initializeAfterLoaded: function(e)
	{
		this._createDivs();
		
		//Event.observe(window,'resize',this._setContentSize.bind(this));
		
		this._loadMenu();
		
		this.buildMenu();
		
		this.apply();
	},
	
	_createDivs: function()
	{
		// Create our container, outer and inner DIVs:
		this._els.container = new Element('div',{'class':this.cssPrefix+'container'}).setStyle({position:'absolute',overflow:'visible'});
		this._els.outer = new Element('div',{'class':this.cssPrefix+'outer'});
		this._els.inner = new Element('div',{'class':this.cssPrefix+'inner'});
		
		this._els.outer.appendChild(new Element('div'));
		
		this._els.outer.down().appendChild(this._els.inner);
		this._els.container.appendChild(this._els.outer);
		
		this._els.container.hide();
		
		document.body.appendChild(this._els.container);
	},
	
	_loadMenu: function()
	{
		var source = this.source ? this.source : false;
		
		if(typeof(source) == 'string')
		{
			// We're being asked to load via AJAX.
		}
		else if(typeof(source) == 'object')
		{
			// We're being asked to load via an array.
			source = $A(source);
			source.each(function(item)
			{
				this.addItem(new this.MenuItem(item));
			},this);
		}
	},
	
	_createMenu: function()
	{
		// Create our menu OL:
		this._els.list = new Element('ol');
		
		this.each(function(menuItem)
		{
			var link = new Element('a',{href:menuItem.href}).update(menuItem.text);
			
			var div = new Element('div',{id: this.domIdPrefix+menuItem.name});
			div.appendChild(link);
			
			var item = new Element('li');
			item.appendChild(div);
			
			if(menuItem.handler)
				link.observe('click',menuItem.handler.bindAsEventHandler(menuItem,this));
			
			this._els.list.appendChild(item);
		},this);
		
		this._els.inner.appendChild(this._els.list);
	},
	
	_stopObserving: function() {},
	
	_startObserving: function()
	{
		var observers = $H();
		
		observers.set('applyTo_mouseover',this.show.bind(this));
		observers.set('applyTo_mouseout',this.hide.bind(this));
		
		var lock = function(){this.locked = true;}.bind(this);
		var unlock = function(){this.locked = false;this.hide();}.bind(this);
		
		observers.set('outer_mouseover',lock);
		observers.set('outer_mouseout',unlock);
		
		observers.each(function(pair)
		{
			var parts = pair.key.split("_",2);
			
			var el = parts[0] == 'applyTo' ? $(this.applyTo) : this._els[parts[0]];
			
			if(el)
				el.observe(parts[1],pair.value);
			
		},this);
		
		this._stopObserving = function()
		{
			observers.each(function(pair)
			{
				var parts = pair.key.split("_",2);
				
				var el = parts[0] == 'applyTo' ? $(this.applyTo) : this._els[parts[0]];
				
				if(el)
					el.stopObserving(parts[1],pair.value);
				
			},this);
		}.bind(this);
	},
	
	_hide: function()
	{
		if(!this.showing && !this.locked)
		{
			this._els.container.hide();
			this.visible = false;
		}	
	}
});


DFThemeObject.DropdownMenu.menuItemCount = 0;

var DFCountdown = Class.create();
DFCountdown.prototype =
{
	initialize: function(date,div,options)
	{
		this.date = new Date(date);
		this.div = $(div);
		
		this.setup();
		
		if(this.div)
		{
			this._p = new PeriodicalExecuter(this.update.bind(this), 1);
		}
	},
	
	setup: function()
	{
		this.units = $H({});
		this.units.second = 1000;
		this.units.minute = this.units.second*60;
		this.units.hour = this.units.minute*60;
		this.units.day = this.units.hour*24;
	},
	
	date:	false,
	div:	false,
	_p:		false,
	sep:	'&nbsp;:&nbsp;',
	
	update: function()
	{
		var now = new Date();
		var diff = this.date.getTime() - now.getTime();
		
		var diff_w = diff;
		
		var units = $H({});
		
		units.day = Math.floor(diff_w/this.units.day);
		diff_w -= units.day * this.units.day;
		units.hour = Math.floor(diff_w/this.units.hour);
		diff_w -= units.hour * this.units.hour;
		units.minute = Math.floor(diff_w/this.units.minute);
		diff_w -= units.minute * this.units.minute;
		units.second = Math.floor(diff_w/this.units.second);
		
		this.countdown = "";
		
		units.each(function(u)
		{
			var num = (u.value<10?'0':'') + u.value;
			
			if(this.countdown.length || u.value)
				this.countdown += num + this.sep;	
		}.bind(this));
		
		if(this.countdown.length)
			this.countdown = this.countdown.substr(0,this.countdown.length - this.sep.length);
		
		this.div.update(this.countdown);
	}
	
}

var DFColorPicker = Class.create();
DFColorPicker.prototype = 
{
	initialize: function(options)
	{
		options = $H(options);
		
		this.loaded = false;
		
		this._setOptions(options);
		
		$(document.body).insert(new Element('link',{href:"/_skel/dfstdlib/stylesheets/colorpicker.css",rel:"stylesheet",type:"text/css"}));
	},
	
	_maxValue:{'h':360,'s':100,'v':100},
	HSV:{0:360,1:100,2:100},
	_hSV:165,
	_wSV:162,
	_hH:163,
	_slideHSV:{0:360,1:100,2:100},
	_zINDEX:15,
	_stop:1,
	_tX:0,
	_tY:0,
	_oo:0,
	
	defaultOptions: function()
	{
		return $H(
		{
			cssClassPrefix: 'colorPicker_',
			
			x: 0,
			y: 0,
			z: 999,
			
			containerDiv: false
		});
	},
	
	load: function()
	{
		if(!this.loaded)
		{
			this._createElement();
			this._addEventListeners();
			
			this._loadSV();
	
			this._parentDiv.down('div.'+this.cssClassPrefix+'SVslide').setStyle({top:(80/100*170-7)+'px'});
			this._HSVupdate([0,0,20]);
			
			this.loaded=true;
		}
	},
	
	show: function()
	{
		this.load();
		this.containerDiv.show();
	},
	
	hide: function()
	{
		this.load();
		this.containerDiv.hide();
	},
	
	_setOptions: function(options)
	{
		var defaults = this.defaultOptions();
		
		var thisObj = this;
		
		defaults.each(function(v){ thisObj[v.key] = (typeof(options.get(v.key)) == 'undefined') ? v.value : optionsget(v.key) });
	},
	
	_createElement: function()
	{
		if(!this.containerDiv)
		{
			this.containerDiv = new Element('div', {'class': this.cssClassPrefix+'container', 'style':"position:absolute;left:"+this.x+"px;top:"+this.y+"px;z-index:"+this.z+";display:none;"});
			$(document.body).insert(this.containerDiv);
		}
		
		this._parentDiv = new Element('div', {'class': this.cssClassPrefix+'parent'});
		
		this._parentDiv.appendChild(new Element('div',{'class':this.cssClassPrefix+'plugCUR'}) );
		this._parentDiv.appendChild(new Element('div',{'class':this.cssClassPrefix+'plugHEX'}).update('FFFFFF') );
		this._parentDiv.appendChild(new Element('div',{'class':this.cssClassPrefix+'plugCLOSE'}).update('X') );
		
		this._parentDiv.insert("<br>");
		
		this._parentDiv.appendChild(new Element('div',{'class':this.cssClassPrefix+'SV',title:"Saturation + Value"}).insert(
										new Element('div',{'class':this.cssClassPrefix+'SVslide',style:"top:-4px;left:-4px;"}).update("<br>") 
									));
									
		this._parentDiv.appendChild(new Element('div',{'class':this.cssClassPrefix+'H',title:"Hue"}).insert(
										new Element('div',{'class':this.cssClassPrefix+'Hslide',style:"top:-7px;left:-8px;"}).update("<br>") 
									).insert(
										new Element('div',{'class':this.cssClassPrefix+'Hmodel'})
									));
									
		this.containerDiv.insert(this._parentDiv);
	},

	
	_addEventListeners: function()
	{
		Event.observe(this._parentDiv, "mousedown", this._HSVslide.bindAsEventListener(this,'drag',this._parentDiv), false);
		
		Event.observe(this._parentDiv.down('div.'+this.cssClassPrefix+'plugHEX'), "mousedown", this._plugHEXmousedown.bindAsEventListener(this), false);
		
		Event.observe(this._parentDiv.down('div.'+this.cssClassPrefix+'plugCLOSE'), "click", this.hide.bindAsEventListener(this), false);
		
		Event.observe(this._parentDiv.down('div.'+this.cssClassPrefix+'SV'), "click", this._HSVslide.bindAsEventListener(this,'SVslide',this._parentDiv), false);
		
		Event.observe(this._parentDiv.down('div.'+this.cssClassPrefix+'H'), "click", this._HSVslide.bindAsEventListener(this,'Hslide',this._parentDiv), false);
		
	},
	
	_plugHEXmousedown: function(e)
	{
		this._stop=0;
		setTimeout(function(){this._stop=1}.bind(this),100);
	},
	
	_absPos: function(o) 
	{
		var r={x:o.offsetLeft,y:o.offsetTop}; if(o.offsetParent) { var v=this._absPos(o.offsetParent); r.x+=v.x; r.y+=v.y; } return(r);
	},
	
	_agent: function(v)
	{
		return(Math.max(navigator.userAgent.toLowerCase().indexOf(v),0));
	},
	
	_within: function(v,a,z)
	{
		return((v>=a && v<=z)?true:false);
	},
	
	_XY: function(e,v)
	{
		var z=this._agent('msie')?[event.clientX+document.body.scrollLeft,event.clientY+document.body.scrollTop]:[e.pageX,e.pageY]; return(z[this._zero(v)]);
	},
	
	_XYwin:function(v)
	{
		var z=this._agent('msie')?[document.body.clientHeight,document.body.clientWidth]:[window.innerHeight,window.innerWidth]; return(!isNaN(v)?z[v]:z);
	},
	
	_zero: function(v)
	{
		v=parseInt(v); return(!isNaN(v)?v:0);
	},
	
	_HSVslide: function(e,d,o)
	{
		var tXY = function(e) { this._tY=this._XY(e,1)-ab.y; this._tX=this._XY(e)-ab.x; }.bindAsEventListener(this);
		function mkHSV(a,b,c) { return(Math.min(a,Math.max(0,Math.ceil((parseInt(c)/b)*a)))); }
		
		var ckHSV = function(a,b) { if(this._within(a,0,b)) return(a); else if(a>b) return(b); else if(a<0) return('-'+this._oo); }.bind(this);
		
		this._draghandler = function(e)
		{
			if(!this._stop)
			{
				if(d!='drag') this._XY(e);
				
				if(d=='SVslide')
				{
					var left = ckHSV(this._tX-this._oo,this._wSV);
					console.log("left: "+left);
					ds.setStyle({left:+left+'px'});
					ds.setStyle({top:ckHSV(this._tY-this._oo,this._wSV)+'px'});
					
					this._slideHSV[1]=mkHSV(100,this._wSV,ds.style.left);
					this._slideHSV[2]=100-mkHSV(100,this._wSV,ds.style.top);
					
					this._HSVupdate();
				}
				else if(d=='Hslide')
				{
					var ck=ckHSV(this._tY-this._oo,this._hH), j, r='hsv', z={};
					
					ds.setStyle({top:(ck-5)+'px'});
					this._slideHSV[0]=mkHSV(360,this._hH,ck);
					
					for(var i=0; i<=r.length-1; i++)
					{
						j=r.substr(i,1);
						z[i]= (j=='h') ? this._maxValue[j]-mkHSV(this._maxValue[j],this._hH,ck) : HSV[i];
					}
					
					this._HSVupdate(z);
					
					this._parentDiv.down('div.'+this.cssClassPrefix+'SV').setStyle({backgroundColor:'#'+this._hsv2hex([this.HSV[0],100,100])});
					
				}
				else if(d=='drag')
				{
					ds.setStyle({left:this._XY(e)+oX-eX+'px'});
					ds.setStyle({top:this._XY(e,1)+oY-eY+'px'});
				}
			}
		}.bindAsEventListener(this);
		
		this._cancelDragHandler = function()
		{
			this._stop=1;
			$(document).stopObserving('mousemove',this._draghandler);
			$(document).stopObserving('mouseup',this._cancelDragHandler);
		}.bindAsEventListener(this);
	
		if(this._stop)
		{
			this._stop='';
			var ds = $( d!='drag' ? this._parentDiv.down('div.'+this.cssClassPrefix+d) : o);
	
			if(d=='drag')
			{
				var oX=parseInt(ds.style.left), oY=parseInt(ds.style.top), eX=this._XY(e), eY=this._XY(e,1);
				$(o).setStyle({zIndex:this._zINDEX++});
			}
			else
			{
				var ab=this._absPos($(o));
				
				this._oo=(d=='Hslide')?2:4;
				
				ab.x+=10;
				ab.y+=22;
				if(d=='SVslide')
					this._slideHSV[0]=this.HSV[0];
			}
	
			$(document).observe('mousemove',this._draghandler);
			$(document).observe('mouseup',this._cancelDragHandler);
			
			this._draghandler(e);
	
		}
	},
	
	
	
	_HSVupdate: function(v)
	{
		v=this._hsv2hex(this.HSV=v?v:this._slideHSV);
		
		this._parentDiv.down('div.'+this.cssClassPrefix+'plugHEX').update(v);
		this._parentDiv.down('div.'+this.cssClassPrefix+'plugCUR').setStyle({background:'#'+v});
		
		return(v);
	
	},
	
	_loadSV: function()
	{
		var z='';
		for(var i=this._hSV; i>=0; i--)
			z+="<div style=\"BACKGROUND: #"+this._hsv2hex([Math.round((360 / this._hSV)*i),100,100])+";\"><br></div>"
			
		this._parentDiv.down('div.'+this.cssClassPrefix+'Hmodel').update(z);
	},
	
	_toHex: function(v) { v=Math.round(Math.min(Math.max(0,v),255)); return("0123456789ABCDEF".charAt((v-v%16)/16)+"0123456789ABCDEF".charAt(v%16)); },
	
	_rgb2hex: function(r) { return(this._toHex(r[0])+this._toHex(r[1])+this._toHex(r[2])); },
	
	_hsv2hex: function(h) { return(this._rgb2hex(this._hsv2rgb(h))); },

	_hsv2rgb: function(r) { // easyrgb.com/math.php?MATH=M21#text21
	
		var R,B,G,S=r[1]/100,V=r[2]/100,H=r[0]/360;
	
		if(S>0) { if(H>=1) H=0;
	
			H=6*H; F=H-Math.floor(H);
			A=Math.round(255*V*(1.0-S));
			B=Math.round(255*V*(1.0-(S*F)));
			C=Math.round(255*V*(1.0-(S*(1.0-F))));
			V=Math.round(255*V); 
	
			switch(Math.floor(H)) {
	
				case 0: R=V; G=C; B=A; break;
				case 1: R=B; G=V; B=A; break;
				case 2: R=A; G=V; B=C; break;
				case 3: R=A; G=B; B=V; break;
				case 4: R=C; G=A; B=V; break;
				case 5: R=V; G=A; B=B; break;
	
			}
	
			return([R?R:0,G?G:0,B?B:0]);
	
		}
		else return([(V=Math.round(V*255)),V,V]);
	
	}
	
};


FastInit.addOnLoad(DFTools.setupUrlBase);
